From 9e35eb7fcdf9b7eda5d17f83504e27290e0a0b7c Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 19:20:23 +0200 Subject: [PATCH 01/16] fail and success util functions --- src/api/__init__.py | 1 + src/api/utils.py | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 src/api/utils.py diff --git a/src/api/__init__.py b/src/api/__init__.py index 10ff23f..e8628ce 100644 --- a/src/api/__init__.py +++ b/src/api/__init__.py @@ -15,3 +15,4 @@ import api.models import api.endpoints import api.views +import api.utils diff --git a/src/api/utils.py b/src/api/utils.py new file mode 100644 index 0000000..afb7158 --- /dev/null +++ b/src/api/utils.py @@ -0,0 +1,7 @@ +from flask import jsonify + +def fail(msg, code=400): + return jsonify({"status": "failed", "msg": msg}), int(code) + +def success(data, code=200): + return jsonify({"status": "success", "data": data}), int(code) \ No newline at end of file From dbb6fa5d35e1bd0ed8cbdc12005d04cc1e61c854 Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 19:21:26 +0200 Subject: [PATCH 02/16] more detailed return types in update, delete and get user. issue #72 --- src/api/controllers/userController.py | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index ee6aebc..9709a46 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -1,5 +1,8 @@ from api.models import db, User, UserHasProject, UserLink, UserFeedback from api import app +from api.utils import fail, success +from flask_jwt_extended import get_jwt_identity +from flask import jsonify class UserController: session = db.session() @@ -20,31 +23,18 @@ def update_user(self, id, **kwargs): user = User.query.filter_by(id=id).first() if user == None: - return None + return fail("user not found", 404) for key, value in kwargs.items(): if not hasattr(user, key): - return None - - for key, value in kwargs.items(): - setattr(user, key, value) - - db.session.commit() - - return user - - def update_user(self, id, **kwargs): - user = User.query.filter_by(id=id).first() - - if user == None: - return user + return fail("forbidden attribute", 401) for key, value in kwargs.items(): setattr(user, key, value) db.session.commit() - return user + return success(user.as_dict()) def get_user(self, **kwargs): user = User.query.filter_by(**kwargs).first() @@ -68,12 +58,12 @@ def delete_user(self, id): user = User.query.filter_by(id=id).first() if user == None: - return None + return fail("user not found", 404) db.session.delete(user) db.session.commit() - return user + return success(user.as_dict()) # User Link def create_link(self, user_id, **kwargs): From 0d473bdd5faf8f77d57789f427e091a1fedc178e Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 19:21:45 +0200 Subject: [PATCH 03/16] controller method to create user from jwt --- src/api/controllers/userController.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index 9709a46..ce211a7 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -138,4 +138,10 @@ def delete_feedback(self, user_id, feedback_id): return feedback + def get_user_from_jwt(self): + user = self.get_user(id=get_jwt_identity()) + if user is None: + return fail("User not found") + return success(user.as_dict()) + userController = UserController() From 9733ca3fd936b4f34a13ef91288aef13d02ce25d Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 21:17:55 +0200 Subject: [PATCH 04/16] refactored user update route as per issues #69 and #71 + better code for forbidden attributes (403 forbidden) --- src/api/controllers/userController.py | 2 +- src/api/views/userView.py | 53 +++++++++++++++++---------- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index ce211a7..d683574 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -27,7 +27,7 @@ def update_user(self, id, **kwargs): for key, value in kwargs.items(): if not hasattr(user, key): - return fail("forbidden attribute", 401) + return fail("forbidden attribute", 403) for key, value in kwargs.items(): setattr(user, key, value) diff --git a/src/api/views/userView.py b/src/api/views/userView.py index db662af..d5db028 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -1,5 +1,7 @@ from flask import request, jsonify, session, Flask, redirect, session, url_for +from flask_jwt_extended import get_jwt_identity, jwt_required from api import app +from api.utils import fail, success from api.controllers import userController from os import environ @@ -81,41 +83,54 @@ def create_user(): else: return jsonify(user.as_dict()), 201 -@app.route("/users/", methods=['PUT']) -def update_user(id): +@app.route("/user", methods=['PUT']) +@jwt_required +def update_user(): """ Update user - Updates user with `id` using the data in request body + Updates authenticated user with the data in request body --- tags: - User parameters: - - in: path - name: id - type: integer - required: true - description: Id of user to update - in: body name: User required: true - description: User object containing data to update + description: User attributes to update. Any combination of attributes is valid schema: - $ref: "#/definitions/User" + id: UserUpdate + properties: + name: + type: string + description: (Optional) Name of the user + bio: + type: string + description: (Optional) Biography of the user + languages: + type: string + description: (Optional) List of programming languages the user uses + interests: + type: string + description: (Optional) Interests of the user + location: + type: string + description: (Optional) Location of the user + occupation: + type: string + description: (Optional) Formal occupation, eg. student at X or works at Y responses: 200: description: User updated successfully - 400: - description: Failed to update user + 403: + description: Forbidden Parameters used + 404: + description: User the token belonged to doesn't exist anymore """ - if 'id' in request.get_json(): - return "Failed to update user. Request body can not specify user's id.", 501 - user = userController.update_user(id, **request.get_json()) + if 'id' in request.get_json(): + return fail("Failed to update user. Request body can not specify user's id.", 403) - if user == None: - return "Failed to update user.", 400 - else: - return jsonify(user.as_dict()), 200 + return userController.update_user(get_jwt_identity(), **request.get_json()) @app.route("/users/", methods=['GET']) def get_user(id): From 3f1f191a1290b39b2cb6fe13ad9eb023b2764583 Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 21:38:54 +0200 Subject: [PATCH 05/16] refactor user get route as per #69 and #71 --- src/api/views/userView.py | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/api/views/userView.py b/src/api/views/userView.py index d5db028..31c32fc 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -132,32 +132,22 @@ def update_user(): return userController.update_user(get_jwt_identity(), **request.get_json()) -@app.route("/users/", methods=['GET']) -def get_user(id): +@app.route("/user", methods=['GET']) +@jwt_required +def get_user(): """ Get user - Retreives user with `id` + Retreives authenticated user --- tags: - User - parameters: - - in: path - name: id - type: integer - required: true - description: Id of the user to retrieve responses: 200: description: User object 404: - description: User not found + description: User the token belonged to doesn't exist anymore """ - user = userController.get_user(id=id) - - if user: - return jsonify(user.as_dict()), 200 - else: - return "", 404 + return userController.get_user_from_jwt() @app.route("/users", methods=['GET']) def get_all_users(): From 703abc028632626743dfbde6a10f08fc05e6488c Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 21:42:22 +0200 Subject: [PATCH 06/16] with the /user route this can be removed #56 --- src/api/views/oauthView.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/api/views/oauthView.py b/src/api/views/oauthView.py index dd2857c..a954c15 100644 --- a/src/api/views/oauthView.py +++ b/src/api/views/oauthView.py @@ -81,10 +81,3 @@ def register_callback(blueprint): redirect_token = f"?state={session.pop('state')}&token={access_token}" return redirect(session.pop('redirect') + redirect_token) -# Actually deprecated -# should be /user in userview but I'll leave it until Routes branch adds and merges it -@app.route("/getcurrentuser", methods=["GET"]) -@jwt_required -def getCurrentUser(): - current_user = userController.get_user(id=get_jwt_identity()) - return jsonify(current_user.as_dict()), 200 From e80aec0c67535f993c733f5aa1f81562d618cdc4 Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 21:42:42 +0200 Subject: [PATCH 07/16] refactor user delete as per #69 and #71 --- src/api/views/userView.py | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/src/api/views/userView.py b/src/api/views/userView.py index 31c32fc..8a4d6a0 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -167,37 +167,23 @@ def get_all_users(): return jsonify(users), 200 -@app.route("/users/", methods=['DELETE']) -def delete_user(id): +@app.route("/user", methods=['DELETE']) +@jwt_required +def delete_user(): """ Delete user - Deletes user with `id` + Deletes authenticated user --- tags: - User - parameters: - - in: path - name: id - type: integer - required: true - description: Id of the user to delete responses: 200: description: User deleted successfully - 401: - description: Not allowed to delete the specified user 404: - description: User not found + description: User the token belonged to doesn't exist anymore """ - if int(current_user.id) == int(id): - user = userController.delete_user(id) - - if user: - return "", 200 - else: - return "", 404 - else: - return "You cannot delete an other user", 401 + + return userController.delete_user(get_jwt_identity()) # User Link @app.route("/users//links", methods=['POST']) From c611268ae66779d7d7a94f60b2d028a862e5990d Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 21:44:20 +0200 Subject: [PATCH 08/16] remove create user route users should only be created through the /register routine --- src/api/views/userView.py | 77 --------------------------------------- 1 file changed, 77 deletions(-) diff --git a/src/api/views/userView.py b/src/api/views/userView.py index 8a4d6a0..fa6145a 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -6,83 +6,6 @@ from os import environ # User -@app.route("/users", methods=['POST']) -def create_user(): - """ - Create user - --- - tags: - - User - parameters: - - in: body - name: User - required: true - description: User object containing data for creation - schema: - $ref: "#/definitions/User" - definitions: - - schema: - id: User - properties: - id: - type: integer - description: Id of the user. This property will be assigned a value returned by the database - name: - type: string - description: Name of the user - bio: - type: string - description: Biography of the user - languages: - type: string - description: List of programming languages the user uses - interests: - type: string - description: Interests of the user - location: - type: string - description: Location of the user - occupation: - type: string - description: Formal occupation, eg. student at X or works at Y - projects: - type: array - description: List of projects - items: - $ref: "#/definitions/Project" - links: - type: array - description: List of links - items: - $ref: "#/definitions/UserLink" - project_feedbacks: - type: array - description: List of feedbacks given to projects - items: - $ref: "#/definitions/ProjectFeedback" - user_feedbacks: - type: array - description: List of feedbacks given to users - items: - $ref: "#/definitions/UserFeedback" - received_feedbacks: - type: array - description: List of received feedbacks from users - items: - $ref: "#/definitions/UserFeedback" - responses: - 201: - description: User created successfully - 400: - description: Failed to create user - """ - user = userController.create_user(**request.get_json()) - - if user == None: - return "Failed to create user.", 400 - else: - return jsonify(user.as_dict()), 201 - @app.route("/user", methods=['PUT']) @jwt_required def update_user(): From 060c58e18229ab3da1d2854b52d5b03acbd5b369 Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 22:10:33 +0200 Subject: [PATCH 09/16] don't jsonify response by default. some routes might need to operate on the results --- src/api/utils.py | 7 +++++-- src/api/views/userView.py | 8 ++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/api/utils.py b/src/api/utils.py index afb7158..93bb477 100644 --- a/src/api/utils.py +++ b/src/api/utils.py @@ -1,7 +1,10 @@ from flask import jsonify def fail(msg, code=400): - return jsonify({"status": "failed", "msg": msg}), int(code) + return {"status": "failed", "msg": msg}, int(code) def success(data, code=200): - return jsonify({"status": "success", "data": data}), int(code) \ No newline at end of file + return {"status": "success", "data": data}, int(code) + +def jsonify_response(data, code): + return jsonify(data), code \ No newline at end of file diff --git a/src/api/views/userView.py b/src/api/views/userView.py index fa6145a..6c14490 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -1,7 +1,7 @@ from flask import request, jsonify, session, Flask, redirect, session, url_for from flask_jwt_extended import get_jwt_identity, jwt_required from api import app -from api.utils import fail, success +from api.utils import fail, success, jsonify_response from api.controllers import userController from os import environ @@ -53,7 +53,7 @@ def update_user(): if 'id' in request.get_json(): return fail("Failed to update user. Request body can not specify user's id.", 403) - return userController.update_user(get_jwt_identity(), **request.get_json()) + return jsonify_response(*userController.update_user(get_jwt_identity(), **request.get_json())) @app.route("/user", methods=['GET']) @jwt_required @@ -70,7 +70,7 @@ def get_user(): 404: description: User the token belonged to doesn't exist anymore """ - return userController.get_user_from_jwt() + return jsonify_response(*userController.get_user_from_jwt()) @app.route("/users", methods=['GET']) def get_all_users(): @@ -106,7 +106,7 @@ def delete_user(): description: User the token belonged to doesn't exist anymore """ - return userController.delete_user(get_jwt_identity()) + return jsonify_response(*userController.delete_user(get_jwt_identity())) # User Link @app.route("/users//links", methods=['POST']) From 17dc72aa47a830fd8f57d56e3678e99323c561f7 Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 22:43:16 +0200 Subject: [PATCH 10/16] augmented controller return types now returns a tuple of data, msg and code best compromise for easy controller returns while still being able to access the raw data. the tuple can be wrapped in the wrap_response() method #72 --- src/api/controllers/userController.py | 26 ++++++++++++-------------- src/api/utils.py | 14 ++++++-------- src/api/views/userView.py | 8 ++++---- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index d683574..fc396e1 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -1,6 +1,5 @@ from api.models import db, User, UserHasProject, UserLink, UserFeedback from api import app -from api.utils import fail, success from flask_jwt_extended import get_jwt_identity from flask import jsonify @@ -14,32 +13,35 @@ def create_user(self, **kwargs): self.session.add(user) self.session.commit() - return user + return user, "OK", 200 except: self.session.rollback() - return None + return None, "Forbidden Attributes", 403 def update_user(self, id, **kwargs): user = User.query.filter_by(id=id).first() if user == None: - return fail("user not found", 404) + return None, "user not found", 404 for key, value in kwargs.items(): if not hasattr(user, key): - return fail("forbidden attribute", 403) + return None, "forbidden attribute", 403 for key, value in kwargs.items(): setattr(user, key, value) db.session.commit() - return success(user.as_dict()) + return user, "OK", 200 def get_user(self, **kwargs): user = User.query.filter_by(**kwargs).first() - return user + if user is None: + return None, "User Not Found", 404 + + return user, "OK", 200 def get_all_users(self, **kwargs): all_users = User.query.all() @@ -58,13 +60,12 @@ def delete_user(self, id): user = User.query.filter_by(id=id).first() if user == None: - return fail("user not found", 404) + return None, "user not found", 404 db.session.delete(user) db.session.commit() - return success(user.as_dict()) - + return user, "OK", 200 # User Link def create_link(self, user_id, **kwargs): try: @@ -139,9 +140,6 @@ def delete_feedback(self, user_id, feedback_id): return feedback def get_user_from_jwt(self): - user = self.get_user(id=get_jwt_identity()) - if user is None: - return fail("User not found") - return success(user.as_dict()) + return self.get_user(id=get_jwt_identity()) userController = UserController() diff --git a/src/api/utils.py b/src/api/utils.py index 93bb477..c81853c 100644 --- a/src/api/utils.py +++ b/src/api/utils.py @@ -1,10 +1,8 @@ from flask import jsonify -def fail(msg, code=400): - return {"status": "failed", "msg": msg}, int(code) - -def success(data, code=200): - return {"status": "success", "data": data}, int(code) - -def jsonify_response(data, code): - return jsonify(data), code \ No newline at end of file +def wrap_response(data, msg, code): + obj = {"msg": msg} + if not data is None: + obj["data"] = data.as_dict() + return jsonify(obj), code + \ No newline at end of file diff --git a/src/api/views/userView.py b/src/api/views/userView.py index 6c14490..9699dd0 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -1,7 +1,7 @@ from flask import request, jsonify, session, Flask, redirect, session, url_for from flask_jwt_extended import get_jwt_identity, jwt_required from api import app -from api.utils import fail, success, jsonify_response +from api.utils import wrap_response from api.controllers import userController from os import environ @@ -53,7 +53,7 @@ def update_user(): if 'id' in request.get_json(): return fail("Failed to update user. Request body can not specify user's id.", 403) - return jsonify_response(*userController.update_user(get_jwt_identity(), **request.get_json())) + return wrap_response(*userController.update_user(get_jwt_identity(), **request.get_json())) @app.route("/user", methods=['GET']) @jwt_required @@ -70,7 +70,7 @@ def get_user(): 404: description: User the token belonged to doesn't exist anymore """ - return jsonify_response(*userController.get_user_from_jwt()) + return wrap_response(*userController.get_user_from_jwt()) @app.route("/users", methods=['GET']) def get_all_users(): @@ -106,7 +106,7 @@ def delete_user(): description: User the token belonged to doesn't exist anymore """ - return jsonify_response(*userController.delete_user(get_jwt_identity())) + return wrap_response(*userController.delete_user(get_jwt_identity())) # User Link @app.route("/users//links", methods=['POST']) From 4ca53f07dde88a3b2b9f03d2b7df6b6ecb0e3673 Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 22:44:03 +0200 Subject: [PATCH 11/16] augmented login and register now returns a msg and code in case of an error --- src/api/views/oauthView.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/api/views/oauthView.py b/src/api/views/oauthView.py index a954c15..d6c89c5 100644 --- a/src/api/views/oauthView.py +++ b/src/api/views/oauthView.py @@ -62,11 +62,13 @@ def login_callback(blueprint): if blueprint.name == "github": resp = github.get("/user").json() id = resp["id"] - user = userController.get_user(github_id=id) + user, msg, code = userController.get_user(github_id=id) redirect_token = f"?state={session.pop('state', '{}')}" if user: access_token = create_access_token(identity=user) redirect_token += f"&token={access_token}" + else: + redirect_token += f"&msg={msg}&code={code}" return redirect(session.pop("redirect") + redirect_token) @@ -74,10 +76,16 @@ def register_callback(blueprint): if blueprint.name == "github": resp = github.get("/user").json() id = resp["id"] - user = userController.get_user(github_id=id) - if not user: - user = userController.create_user(github_id=id, name=session.pop('username', "Anton")) + user, msg, code = userController.get_user(github_id=id) + redirect_token = f"?state={session.pop('state')}" + if user is None: + user, msg, code = userController.create_user(github_id=id, name=session.pop('username', "Anton")) + + if user is None: + redirect_token += f"&msg={msg}&code={code}" + else: access_token = create_access_token(identity=user) - redirect_token = f"?state={session.pop('state')}&token={access_token}" + redirect_token += f"&token={access_token}" + return redirect(session.pop('redirect') + redirect_token) From 92968d539c9dd34f669de0d2814593f3f64490db Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 23:15:14 +0200 Subject: [PATCH 12/16] 400 is more sensible for this as per description 403 is for requests that are technically valid but the server refuses to process --- src/api/controllers/userController.py | 6 +++--- src/api/views/userView.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index fc396e1..3405c21 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -16,7 +16,7 @@ def create_user(self, **kwargs): return user, "OK", 200 except: self.session.rollback() - return None, "Forbidden Attributes", 403 + return None, "Forbidden Attributes", 400 def update_user(self, id, **kwargs): user = User.query.filter_by(id=id).first() @@ -26,7 +26,7 @@ def update_user(self, id, **kwargs): for key, value in kwargs.items(): if not hasattr(user, key): - return None, "forbidden attribute", 403 + return None, "forbidden attribute", 400 for key, value in kwargs.items(): setattr(user, key, value) @@ -40,7 +40,7 @@ def get_user(self, **kwargs): if user is None: return None, "User Not Found", 404 - + return user, "OK", 200 def get_all_users(self, **kwargs): diff --git a/src/api/views/userView.py b/src/api/views/userView.py index 9699dd0..08f3abf 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -44,14 +44,14 @@ def update_user(): responses: 200: description: User updated successfully - 403: - description: Forbidden Parameters used + 400: + description: Bad Request. Forbidden Parameters used 404: description: User the token belonged to doesn't exist anymore """ if 'id' in request.get_json(): - return fail("Failed to update user. Request body can not specify user's id.", 403) + return wrap_response(None, "Failed to update user. Request body can not specify user's id.", 400) return wrap_response(*userController.update_user(get_jwt_identity(), **request.get_json())) From 6d2e079ca8950752070b13181d260ecc14c9eff1 Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 23:15:48 +0200 Subject: [PATCH 13/16] use app context to create access token for the tests unfortunately this breaks create_project test --- tests/api/__init__.py | 8 +++++++- tests/conftest.py | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/api/__init__.py b/tests/api/__init__.py index a15adcc..d28be6a 100644 --- a/tests/api/__init__.py +++ b/tests/api/__init__.py @@ -10,7 +10,7 @@ - call these functions form any test case. """ - +from flask_jwt_extended import create_access_token from tests import db, Project, User, UserLink, ProjectLink, UserFeedback def create_project_for_test_cases(data): @@ -27,6 +27,12 @@ def create_project_link_for_test_cases(data): return new_project_link.as_dict() +def create_access_token_for_test_cases(data): + new_user = User(**data) + db.session.add(new_user) + db.session.commit() + return create_access_token(identity=new_user) + def create_user_for_test_cases(data): new_user = User(**data) db.session.add(new_user) diff --git a/tests/conftest.py b/tests/conftest.py index 3c9fffd..5927238 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,4 +25,5 @@ def client(): pass with app.test_client() as test_client: - yield test_client + with app.app_context(): + yield test_client From fba088e2eafd391df8a01ed87e5f60d08e344468 Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 23:16:43 +0200 Subject: [PATCH 14/16] fix update user route --- tests/api/views/test_userView.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/tests/api/views/test_userView.py b/tests/api/views/test_userView.py index c4df5f9..928e716 100644 --- a/tests/api/views/test_userView.py +++ b/tests/api/views/test_userView.py @@ -1,6 +1,6 @@ from tests.conftest import client from tests import db, User, UserLink, UserFeedback -from tests.api import create_user_for_test_cases, create_user_link_for_test_cases, create_user_feedback_for_test_cases +from tests.api import create_user_for_test_cases, create_user_link_for_test_cases, create_user_feedback_for_test_cases, create_access_token_for_test_cases class TestUserView(object): @@ -22,19 +22,16 @@ def test_create_user(self, client): assert response.status_code == 400 def test_update_user(self, client): - user_id = create_user_for_test_cases(self.valid_data)["id"] - - response = client.post('/users/1', json={}) - assert response.status_code == 400 + token = create_access_token_for_test_cases(self.valid_data) - # notice: Should we respond to update_user request without json data with status code 200? - # response = client.post('/users/{}'.format(user_id), json={}) - # assert response.status_code == 400 + #for now we will allow empty body. + response = client.put('/user', headers={"Authorization": f"Bearer {token}"}, json={}) + assert response.status_code == 200 - response = client.post('/users/{}'.format(user_id), json={"name": "Updated Name"}) + response = client.put('/user', headers={"Authorization": f"Bearer {token}"}, json={"name": "Updated Name"}) assert response.status_code == 200 - assert response.get_json()['name'] == "Updated Name" + assert response.get_json()['data']['name'] == "Updated Name" def test_delete_user(self, client): user_id = None From 7960115b37c4d201be71fa86f6766520d0ed07af Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 23:17:11 +0200 Subject: [PATCH 15/16] remove create user test which doesn't have a corresponding route --- tests/api/views/test_userView.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/api/views/test_userView.py b/tests/api/views/test_userView.py index 928e716..0cddb27 100644 --- a/tests/api/views/test_userView.py +++ b/tests/api/views/test_userView.py @@ -14,12 +14,6 @@ class TestUserView(object): 'occupation': 'cashier' } - def test_create_user(self, client): - response = client.post('/users', json=self.valid_data) - assert response.status_code == 201 - - response = client.post('/users', json={}) - assert response.status_code == 400 def test_update_user(self, client): token = create_access_token_for_test_cases(self.valid_data) From 1ed3c5cf41bf8d9bf86f2c8380e9c120b74f3e93 Mon Sep 17 00:00:00 2001 From: Adenylatcyclase Date: Thu, 25 Jun 2020 23:28:53 +0200 Subject: [PATCH 16/16] amall improvements to utility + get and delete user --- tests/api/__init__.py | 6 +++++- tests/api/views/test_userView.py | 34 +++++++++++++++++++------------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/tests/api/__init__.py b/tests/api/__init__.py index d28be6a..bd7fb7c 100644 --- a/tests/api/__init__.py +++ b/tests/api/__init__.py @@ -20,6 +20,10 @@ def create_project_for_test_cases(data): return new_project.as_dict() +def delete_user_for_test_cases(user): + db.session.delete(user) + db.session.commit() + def create_project_link_for_test_cases(data): new_project_link = ProjectLink(**data) db.session.add(new_project_link) @@ -31,7 +35,7 @@ def create_access_token_for_test_cases(data): new_user = User(**data) db.session.add(new_user) db.session.commit() - return create_access_token(identity=new_user) + return create_access_token(identity=new_user), new_user def create_user_for_test_cases(data): new_user = User(**data) diff --git a/tests/api/views/test_userView.py b/tests/api/views/test_userView.py index 0cddb27..b82ae93 100644 --- a/tests/api/views/test_userView.py +++ b/tests/api/views/test_userView.py @@ -1,6 +1,7 @@ from tests.conftest import client from tests import db, User, UserLink, UserFeedback -from tests.api import create_user_for_test_cases, create_user_link_for_test_cases, create_user_feedback_for_test_cases, create_access_token_for_test_cases +from tests.api import create_user_for_test_cases, create_user_link_for_test_cases, create_user_feedback_for_test_cases +from tests.api import delete_user_for_test_cases, create_access_token_for_test_cases class TestUserView(object): @@ -16,7 +17,7 @@ class TestUserView(object): def test_update_user(self, client): - token = create_access_token_for_test_cases(self.valid_data) + token, _ = create_access_token_for_test_cases(self.valid_data) #for now we will allow empty body. response = client.put('/user', headers={"Authorization": f"Bearer {token}"}, json={}) @@ -28,24 +29,29 @@ def test_update_user(self, client): assert response.get_json()['data']['name'] == "Updated Name" def test_delete_user(self, client): - user_id = None - response = client.delete('/users/{}'.format(user_id)) - assert response.status_code == 404 + token, _ = create_access_token_for_test_cases(self.valid_data) - user_id = create_user_for_test_cases(self.valid_data)["id"] - response = client.delete('/users/{}'.format(user_id)) + response = client.delete('/user', headers={"Authorization": f"Bearer {token}"}) assert response.status_code == 200 - def test_get_user(self, client): - user_id = None - response = client.get('/users/{}'.format(user_id)) + response = client.delete('/user', headers={"Authorization": f"Bearer {token}"}) assert response.status_code == 404 + - user = create_user_for_test_cases(self.valid_data) - user_id = user["id"] - response = client.get('/users/{}'.format(user_id)) + def test_get_user(self, client): + token, user = create_access_token_for_test_cases(self.valid_data) + + response = client.get('/user', headers={"Authorization": f"Bearer {token}"}) assert response.status_code == 200 - assert response.get_json() == user + assert response.get_json() == {"data": user.as_dict(), "msg": "OK"} + + delete_user_for_test_cases(user) + + response = client.get('/user', headers={"Authorization": f"Bearer {token}"}) + assert response.status_code == 404 + + + def test_get_all_users(self, client): create_user_for_test_cases(self.valid_data)