Skip to content

Routes project link and feedback refactor #87

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 40 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
b95e0fc
Optionally can get JWT timeout time from environment file
petak5 Jun 29, 2020
2295466
Formatting fixes
petak5 Jun 29, 2020
27571b5
Don't create new DB session
petak5 Jun 29, 2020
1a7feea
Add info about setting JWT token timeout to README
petak5 Jun 29, 2020
38b6c99
Fixed and made more verbose JWT token timeout environment variable se…
petak5 Jun 29, 2020
23d8aec
Refactored create project route
petak5 Jun 29, 2020
5536927
Fix typos in response messages
petak5 Jul 3, 2020
f266f5e
Update project route refactor
petak5 Jul 3, 2020
beccc65
Get projects routes refactor
petak5 Jul 3, 2020
8f4a042
Delete project refactor
petak5 Jul 3, 2020
8716f16
Fix possible error with multiple parameters with the same name being …
petak5 Jul 3, 2020
90575b2
Add session rollback to create project controller when failed
petak5 Jul 3, 2020
bce06a1
Update project tests after routes refactor
petak5 Jul 3, 2020
6fc6801
Fixed delete project test
petak5 Jul 3, 2020
946bebc
Fix usage message for tests
petak5 Jul 4, 2020
2326e61
Remove get all users test
petak5 Jul 5, 2020
c6290ab
Create project link
petak5 Jul 5, 2020
312c6bf
Update project link
petak5 Jul 5, 2020
7f24957
Delete project link
petak5 Jul 5, 2020
8673dfa
Remove get all project links route and related code
petak5 Jul 5, 2020
002f832
Remove get all project feedbacks route
petak5 Jul 9, 2020
0434d6f
Create project feedback
petak5 Jul 9, 2020
4c54d7a
Delete project feedback
petak5 Jul 9, 2020
0937e9a
Rename user_id to author_id in ProjectFeedback
petak5 Jul 9, 2020
a25807f
Get link_id from path in delete project feedback route
petak5 Jul 9, 2020
056f7a0
Fix update project link route request body structure
petak5 Jul 9, 2020
af528e2
Fix create project link route request body structure
petak5 Jul 9, 2020
da079a9
Get project id from path in delete project route
petak5 Jul 9, 2020
93196a5
Change get project(s) routes to `/project/<id>` and `/project/all`
petak5 Jul 9, 2020
8915bbe
Merge branch 'routes_project_refactor' into routes_project_link_and_f…
petak5 Jul 9, 2020
691e7e6
Merge branch 'develop' into routes_project_refactor
petak5 Jul 9, 2020
2165bf0
Merge branch 'routes_project_refactor' into routes_project_link_and_f…
petak5 Jul 9, 2020
51f91a2
Merge branch 'develop' into routes_project_refactor
petak5 Jul 9, 2020
13c9edc
Fix changed get project(s) route URL path in test
petak5 Jul 9, 2020
837cce5
Fix changed delete project route URL path in test
petak5 Jul 9, 2020
bb9418d
Merge branch 'routes_project_refactor' into routes_project_link_and_f…
petak5 Jul 9, 2020
e149560
Fix create project link test
petak5 Jul 9, 2020
43db39b
Fix update project link test
petak5 Jul 9, 2020
6ad32de
Fix delete project link test
petak5 Jul 10, 2020
336a611
Add project feedback tests
petak5 Jul 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ Run the server:

Your `.env` file should now look something like [example.env](https://github.com/ProgrammingBuddies/programmingbuddies-api/blob/develop/example.env)

- Optionally you can set the JWT token timeout
- `JWT_ACCESS_TOKEN_EXPIRES` - time in seconds

### Testing

- to run multiple tests just specify the directory which contains them for example `pipenv run pytest tests/`
Expand Down
170 changes: 102 additions & 68 deletions src/api/controllers/projectController.py
Original file line number Diff line number Diff line change
@@ -1,60 +1,79 @@
from api.models import db, Project, UserHasProject, ProjectLink, ProjectFeedback
from api.models import db, User, Project, UserHasProject, ProjectLink, ProjectFeedback

class ProjectController:
session = db.session()
session = db.session

# Project
def create_project(self, **kwargs):
def create_project(self, user_id, **kwargs):
try:
user = User.query.filter_by(id=user_id).first()

if user == None:
return None, "User not found", 404

project = Project(**kwargs)
self.session.add(project)

userHasProject = UserHasProject(role=1)
userHasProject.project = project
userHasProject.user = user

self.session.add(userHasProject)
self.session.commit()

return project
return project, "OK", 201
except:
return None
self.session.rollback()
return None, "Project creation failed", 400

def update_project(self, id, **kwargs):
project = Project.query.filter_by(id=id).first()
def update_project(self, user_id, **kwargs):
if 'user_id' in kwargs:
return None, "Failed to update project. Request body can not specify user's id.", 400

if project == None:
return None
if 'id' not in kwargs:
return None, "Failed to update project. Request body must specify project's id.", 400

for key, value in kwargs.items():
if not hasattr(project, key):
return None
user = User.query.filter_by(id=user_id).first()

for key, value in kwargs.items():
setattr(project, key, value)

db.session.commit()
if user == None:
return None, "User not found", 404

return project

def update_project(self, id, **kwargs):
project = Project.query.filter_by(id=id).first()
project = Project.query.filter_by(id=kwargs["id"]).first()

if project == None:
return project
return None, "Project not found", 404

# Note that we are updating the id too, but to the same id because we used it to query the user with it
for key, value in kwargs.items():
if not hasattr(project, key):
return None, f"Forbidden attribute '{key}'", 400

for key, value in kwargs.items():
setattr(project, key, value)

db.session.commit()

return project
return project, "OK", 200

def get_project(self, **kwargs):
project = Project.query.filter_by(**kwargs).first()

return project
if project:
return project, "OK", 200
else:
return None, "Project not found", 404

def get_all_projects(self, **kwargs):
all_projects = Project.query.all()

return all_projects
return all_projects, "OK", 200

def delete_project(self, user_id, id):

userHasProject = UserHasProject.query.filter_by(user_id=user_id, project_id=id).first()
# TODO: verify that the user owns the project (or has neccessary rights)
if not userHasProject:
return None, "Failed to delete project. Current user does not belong to specified project, or the project does not exist.", 404

def delete_project(self, id):
# Remove all project's links
for link in ProjectLink.query.filter_by(project_id=id).all():
db.session.delete(link)
Expand All @@ -66,84 +85,99 @@ def delete_project(self, id):
project = Project.query.filter_by(id=id).first()

if project == None:
return project
# TODO: db.session.rollback?
return None, "Project not found", 404

db.session.delete(project)
db.session.commit()

return project
return project, "OK", 200

# Project Link
def create_link(self, project_id, **kwargs):
def create_link(self, user_id, **kwargs):
try:
link = ProjectLink(project_id=project_id, **kwargs)
self.session.add(link)
self.session.commit()
if "project_id" in kwargs and "name" in kwargs and "url" in kwargs and len(kwargs) == 3:
if kwargs["project_id"] is None or kwargs["name"] is None or kwargs["url"] is None:
return None, "Arguments can't be empty", 400

return link
link = ProjectLink(**kwargs)
self.session.add(link)
self.session.commit()

return link, "OK", 201
else:
return None, "Forbidden attributes used in request. Only 'project_id', 'name' and 'url' allowed.", 400
except:
self.session.rollback()
return None

def update_link(self, project_id, link_id, **kwargs):
link = ProjectLink.query.filter_by(project_id=project_id, id=link_id).first()
return None, "Failed to create project link.", 400

if link == None:
return None
def update_link(self, user_id, **kwargs):
if "project_id" in kwargs and "id" in kwargs and len(kwargs) >= 2:
if kwargs["project_id"] is None or kwargs["id"] is None:
return None, "Arguments can't be empty", 400

for key, value in kwargs.items():
if not hasattr(link, key):
return None
link = ProjectLink.query.filter_by(project_id=kwargs["project_id"], id=kwargs["id"]).first()

for key, value in kwargs.items():
setattr(link, key, value)
if link == None:
return None, "Failed to update project link. Project link not found.", 404

db.session.commit()
for key, value in kwargs.items():
if not hasattr(link, key):
return None, f"Failed to update project link. Forbidden attribute '{key}'.", 400

return link
for key, value in kwargs.items():
setattr(link, key, value)

def get_all_links(self, project_id):
all_links = ProjectLink.query.filter_by(project_id=project_id).all()
db.session.commit()

return all_links
return link, "OK", 200
else:
return None, "Forbidden attributes used in request. Only 'project_id', 'id', 'name' and 'url' allowed.", 400

def delete_link(self, project_id, link_id):
link = ProjectLink.query.filter_by(project_id=project_id, id=link_id).first()
def delete_link(self, user_id, link_id):
link = ProjectLink.query.filter_by(id=link_id).first()

if link == None:
return None
return None, "Failed to delete project link. Project link not found.", 404

db.session.delete(link)
db.session.commit()

return link
return link, "OK", 200

# Project Feedback
def create_feedback(self, project_id, **kwargs):
def create_feedback(self, author_id, **kwargs):
if 'project_id' not in kwargs:
return None, "Failed to create feedback. Request body must specify feedback's project_id.", 400

try:
feedback = ProjectFeedback(project_id=project_id, **kwargs)
self.session.add(feedback)
self.session.commit()
if "project_id" in kwargs and "rating" in kwargs and "description" in kwargs and len(kwargs) == 3:
if kwargs["project_id"] is None or kwargs["rating"] is None or kwargs["description"] is None:
return None, "Arguments can't be empty", 400

return feedback
feedback = ProjectFeedback(author_id=author_id, **kwargs)
self.session.add(feedback)
self.session.commit()

return feedback, "OK", 201
else:
return None, "Forbidden attributes used in request. Only 'project_id', 'rating' and 'description' allowed.", 400
except:
self.session.rollback()
return None

def get_all_feedbacks(self, project_id):
all_feedbacks = ProjectFeedback.query.filter_by(project_id=project_id).all()
return None, "Failed to create project feedback.", 400

return all_feedbacks

def delete_feedback(self, project_id, feedback_id):
feedback = ProjectFeedback.query.filter_by(project_id=project_id, id=feedback_id).first()
def delete_feedback(self, author_id, feedback_id):
feedback = ProjectFeedback.query.filter_by(id=feedback_id).first()

if feedback == None:
return None
return None, "Failed to delete project feedback. Project feedback not found.", 404

if feedback.author_id != author_id:
return None, "Failed to delete project feedback. Cannot delete project feedback that you did not create.", 400

db.session.delete(feedback)
db.session.commit()

return feedback
return feedback, "OK", 200

projectController = ProjectController()
21 changes: 8 additions & 13 deletions src/api/controllers/userController.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from flask import jsonify

class UserController:
session = db.session()
session = db.session

# User
def create_user(self, **kwargs):
Expand All @@ -16,17 +16,17 @@ def create_user(self, **kwargs):
return user, "OK", 200
except:
self.session.rollback()
return None, "Forbidden Attributes", 400
return None, "Forbidden attributes", 400

def update_user(self, id, **kwargs):
user = User.query.filter_by(id=id).first()

if user == None:
return None, "user not found", 404
return None, "User not found", 404

for key, value in kwargs.items():
if not hasattr(user, key):
return None, "forbidden attribute", 400
return None, f"Forbidden attribute '{key}'", 400

for key, value in kwargs.items():
setattr(user, key, value)
Expand All @@ -39,15 +39,10 @@ def get_user(self, **kwargs):
user = User.query.filter_by(**kwargs).first()

if user is None:
return None, "User Not Found", 404
return None, "User not found", 404

return user, "OK", 200

def get_all_users(self, **kwargs):
all_users = User.query.all()

return all_users

def delete_user(self, id):
# Remove all user's links
for link in UserLink.query.filter_by(user_id=id).all():
Expand All @@ -60,7 +55,7 @@ def delete_user(self, id):
user = User.query.filter_by(id=id).first()

if user == None:
return None, "user not found", 404
return None, "User not found", 404

db.session.delete(user)
db.session.commit()
Expand All @@ -81,7 +76,7 @@ def create_link(self, user_id, **kwargs):
return None, "Forbidden attributes used in request. only name and url allowed.", 400
except:
self.session.rollback()
return None, "link creation failed", 500
return None, "Link creation failed", 500

def update_link(self, user_id, **kwargs):
if not 'id' in kwargs:
Expand All @@ -108,7 +103,7 @@ def get_all_links(self, user_id):
user = User.query.filter_by(id=user_id).first()
if user is None:
return None, "User not found", 404

return user.links, "OK", 200

def delete_link(self, user_id, **kwargs):
Expand Down
4 changes: 2 additions & 2 deletions src/api/models/projectFeedbackModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

class ProjectFeedback(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
project_id = db.Column(db.Integer, db.ForeignKey('project.id'))
rating = db.Column(db.Integer, nullable=False)
description = db.Column(db.String(255), nullable=True)

def as_dict(self):
obj_d = {
'id': self.id,
'user_id': self.user_id,
'author_id': self.author_id,
'project_id': self.project_id,
'rating': self.rating,
'description': self.description,
Expand Down
Loading