From 9e16dec8846bfa9c04dcd1439a1b59d335a1f256 Mon Sep 17 00:00:00 2001 From: Rashika qureshi Date: Tue, 21 Jul 2020 14:41:12 +0530 Subject: [PATCH] Fix:updating an user with empty username and name gives an error message --- app/api/api_extension.py | 2 +- app/api/dao/task.py | 4 +- app/api/dao/user.py | 92 ++++++++++--------- app/api/models/admin.py | 2 +- app/api/models/mentorship_relation.py | 2 +- app/api/models/user.py | 2 +- app/api/resources/admin.py | 4 +- app/api/resources/common.py | 2 +- app/api/resources/mentorship_relation.py | 4 +- app/api/resources/user.py | 15 +-- app/api/validations/user.py | 1 - app/messages.py | 1 + requirements.txt | 2 +- tests/admin/test_api_list_admin_users.py | 2 +- tests/admin/test_api_remove_admin_user.py | 2 +- .../test_api_list_relations.py | 2 +- .../test_api_create_task_comment.py | 8 +- .../test_api_delete_task_comment.py | 2 +- .../test_api_get_task_comments.py | 6 +- .../test_api_modify_task_comment.py | 4 +- tests/tasks/test_api_list_tasks.py | 2 +- tests/tasks/test_dao_complete_task.py | 2 +- tests/tasks/test_dao_create_task.py | 2 +- tests/users/test_api_authentication.py | 2 +- tests/users/test_api_get_other_user.py | 60 ++++++++++++ tests/users/test_api_list_users.py | 2 +- tests/users/test_api_update_user.py | 57 ++++++++++++ 27 files changed, 202 insertions(+), 84 deletions(-) create mode 100644 tests/users/test_api_get_other_user.py diff --git a/app/api/api_extension.py b/app/api/api_extension.py index 9a32f1629..b8ffdc33c 100644 --- a/app/api/api_extension.py +++ b/app/api/api_extension.py @@ -1,4 +1,4 @@ -from flask_restplus import Api +from flask_restx import Api api = Api( title="Mentorship System API", diff --git a/app/api/dao/task.py b/app/api/dao/task.py index 0c264250a..e3b0af5ac 100644 --- a/app/api/dao/task.py +++ b/app/api/dao/task.py @@ -37,7 +37,7 @@ def create_task(user_id: int, mentorship_relation_id: int, data: Dict[str, str]) return messages.MENTORSHIP_RELATION_DOES_NOT_EXIST, HTTPStatus.NOT_FOUND if relation.state != MentorshipRelationState.ACCEPTED: - return messages.UNACCEPTED_STATE_RELATION, HTTPStatus.BAD_REQUEST + return messages.UNACCEPTED_STATE_RELATION, HTTPStatus.FORBIDDEN if (relation.mentor_id != user_id) and (relation.mentee_id != user_id): return messages.USER_NOT_INVOLVED_IN_THIS_MENTOR_RELATION, 403 @@ -142,7 +142,7 @@ def complete_task(user_id: int, mentorship_relation_id: int, task_id: int): return messages.TASK_DOES_NOT_EXIST, HTTPStatus.NOT_FOUND if task.get("is_done"): - return messages.TASK_WAS_ALREADY_ACHIEVED, HTTPStatus.BAD_REQUEST + return messages.TASK_WAS_ALREADY_ACHIEVED, HTTPStatus.FORBIDDEN else: relation.tasks_list.update_task( task_id=task_id, is_done=True, completed_at=datetime.now().timestamp() diff --git a/app/api/dao/user.py b/app/api/dao/user.py index f42ebc367..cec8a2790 100644 --- a/app/api/dao/user.py +++ b/app/api/dao/user.py @@ -2,7 +2,7 @@ from operator import itemgetter from http import HTTPStatus from typing import Dict -from flask_restplus import marshal +from flask_restx import marshal from sqlalchemy import func from app import messages @@ -34,12 +34,12 @@ class UserDAO: @staticmethod def create_user(data: Dict[str, str]): """Creates a new user. - + Creates a new user with provided data. - + Arguments: data: A list containing the user's name, username, password, and email, as well as recognition that they have read and agree to the Terms and Conditions. - + Returns: A tuple with two elements. The first element is a dictionary containing a key 'message' containing a string which indicates whether or not the user was created successfully. The second is the HTTP response code. """ @@ -73,13 +73,13 @@ def create_user(data: Dict[str, str]): @email_verification_required def delete_user(user_id: int): """ Deletes a user. - + Deletes the specified user and removes them from the directory, with checks to make sure that the user exists and is not the only administrator. - + Arguments: user_id: The ID of the user to be deleted. - - Returns: + + Returns: A tuple with two elements. The first element is a dictionary containing a key 'message' containing a string which indicates whether or not the user was created successfully. The second is the HTTP response code. """ @@ -102,15 +102,15 @@ def delete_user(user_id: int): @email_verification_required def get_user(user_id: int): """ Retrieves a user's profile information using a specified ID. - + Provides the user profile of the user whose ID matches the one specified. - + Arguments: user_id: The ID of the user to be searched. - + Returns: The UserModel class of the user whose ID was searched, containing the public information of their profile such as bio, location, etc. - + """ return UserModel.find_by_id(user_id) @@ -118,15 +118,15 @@ def get_user(user_id: int): @staticmethod def get_user_by_email(email: str): """ Retrieves a user's profile information using a specified email. - + Provides the user profile of the user whose email matches the one specified. - + Arguments: email: The email of the user to be searched. - + Returns: The UserModel class of the user whose email was searched, containing the public information of their profile such as bio, location, etc. - + """ return UserModel.find_by_email(email) @@ -134,15 +134,15 @@ def get_user_by_email(email: str): @staticmethod def get_user_by_username(username: str): """ Retrieves a user's profile information using a specified username. - + Provides the user profile of the user whose username matches the one specified. - + Arguments: username: The ID of the user to be searched. - + Returns: The UserModel class of the user whose username was searched, containing the public information of their profile such as bio, location, etc. - + """ return UserModel.find_by_username(username) @@ -150,17 +150,17 @@ def get_user_by_username(username: str): @staticmethod def list_users(user_id: int, search_query: str = "", page: int = DEFAULT_PAGE, per_page: int = DEFAULT_USERS_PER_PAGE, is_verified = None): """ Retrieves a list of verified users with the specified ID. - + Arguments: user_id: The ID of the user to be listed. search_query: The search query for name of the users to be found. is_verified: Status of the user's verification; None when provided as an argument. page: The page of users to be returned per_page: The number of users to return per page - + Returns: A list of users matching conditions and the HTTP response code. - + """ users_list = UserModel.query.filter( @@ -197,16 +197,16 @@ def list_users(user_id: int, search_query: str = "", page: int = DEFAULT_PAGE, p @email_verification_required def update_user_profile(user_id: int, data: Dict[str, str]): """ Updates the profile of a specified user with new data. - + Replaces old data items with new ones in the provided data list, with a check for overlap between users in username and a check that a user with the specified ID exists - + Arguments: user_id: The ID of the user whose data will be updated. data: A list containing the user's information such as name, bio, location, etc. - + Returns: A message that indicates whether the update was successful or not and a second element which is the HTTP response code. - + """ user = UserModel.find_by_id(user_id) @@ -214,6 +214,7 @@ def update_user_profile(user_id: int, data: Dict[str, str]): return messages.USER_DOES_NOT_EXIST, HTTPStatus.NOT_FOUND username = data.get("username", None) + if username: user_with_same_username = UserModel.find_by_username(username) @@ -223,8 +224,17 @@ def update_user_profile(user_id: int, data: Dict[str, str]): user.username = username - if "name" in data and data["name"]: - user.name = data["name"] + if "name" in data: + if data["name"]: + user.name = data["name"] + else: + return messages.NAME_FIELD_IS_MISSING,HTTPStatus.OK + + if "username" in data: + if data["username"]: + user.username = data["username"] + else: + return messages.USERNAME_FIELD_IS_MISSING,HTTPStatus.OK if "bio" in data: if data["bio"]: @@ -291,7 +301,7 @@ def update_user_profile(user_id: int, data: Dict[str, str]): if "available_to_mentor" in data: user.available_to_mentor = data["available_to_mentor"] - + user.save_to_db() return messages.USER_SUCCESSFULLY_UPDATED, HTTPStatus.OK @@ -300,16 +310,16 @@ def update_user_profile(user_id: int, data: Dict[str, str]): @email_verification_required def change_password(user_id: int, data: Dict[str, str]): """ Changes the user's password. - + Finds the user with the given ID, checks their current password, and then updates to the new one. - + Arguments: user_id: The ID of the user to be searched. data: The user's current and new password. - + Returns: A message that indicates whether the password change was successful or not and a second element which is the HTTP response code. - + """ current_password = data["current_password"] @@ -326,15 +336,15 @@ def change_password(user_id: int, data: Dict[str, str]): @staticmethod def confirm_registration(token: str): """ Determines whether a user's email registration has been confirmed. - + Determines whether a user's email registration was invalid, previously confirmed, or just confirmed. - + Arguments: token: Serialized and signed email address as a URL safe string. - + Returns: A message that indicates if the confirmation was invalid, already happened, or just happened, and the HTTP response code. - + """ email_from_token = confirm_token(token) @@ -354,15 +364,15 @@ def confirm_registration(token: str): @staticmethod def authenticate(username_or_email: str, password: str): """ User login process. - + The user can login with two options: -> username + password -> email + password - + Arguments: username_or_email: The username or email associated with the account being authenticated. password: The password associated with the account being authenticated. - + Returns: Returns authenticated user if username and password are valid, otherwise returns None. """ diff --git a/app/api/models/admin.py b/app/api/models/admin.py index dd7f6bc4c..a420a2293 100644 --- a/app/api/models/admin.py +++ b/app/api/models/admin.py @@ -1,4 +1,4 @@ -from flask_restplus import fields, Model +from flask_restx import fields, Model def add_models_to_namespace(api_namespace): diff --git a/app/api/models/mentorship_relation.py b/app/api/models/mentorship_relation.py index f6e2d18ad..cd3085241 100644 --- a/app/api/models/mentorship_relation.py +++ b/app/api/models/mentorship_relation.py @@ -1,4 +1,4 @@ -from flask_restplus import fields, Model +from flask_restx import fields, Model from app.utils.enum_utils import MentorshipRelationState diff --git a/app/api/models/user.py b/app/api/models/user.py index e7c47a2e6..bcf6d4ad2 100644 --- a/app/api/models/user.py +++ b/app/api/models/user.py @@ -1,4 +1,4 @@ -from flask_restplus import fields, Model +from flask_restx import fields, Model from app.api.models.mentorship_relation import ( list_tasks_response_body, mentorship_request_response_body_for_user_dashboard_body, diff --git a/app/api/resources/admin.py b/app/api/resources/admin.py index 7e50c3de6..842162900 100644 --- a/app/api/resources/admin.py +++ b/app/api/resources/admin.py @@ -1,5 +1,5 @@ from flask import request -from flask_restplus import Resource, Namespace, marshal +from flask_restx import Resource, Namespace, marshal from flask_jwt_extended import jwt_required, get_jwt_identity from http import HTTPStatus from app import messages @@ -108,7 +108,7 @@ def get(cls): A admin user with valid access token can view the list of all admins. The endpoint doesn't take any other input. A JSON array having an object for each admin user is returned. The array contains id, username, name, slack_username, bio, - location, occupation, organization, skills. + location, occupation, organization, skills. The current admin user's details are not returned. """ user_id = get_jwt_identity() diff --git a/app/api/resources/common.py b/app/api/resources/common.py index e68dbc54d..8b9c721e8 100644 --- a/app/api/resources/common.py +++ b/app/api/resources/common.py @@ -1,4 +1,4 @@ -from flask_restplus import reqparse +from flask_restx import reqparse auth_header_parser = reqparse.RequestParser() auth_header_parser.add_argument( diff --git a/app/api/resources/mentorship_relation.py b/app/api/resources/mentorship_relation.py index 1795d0468..5a1d49f9e 100644 --- a/app/api/resources/mentorship_relation.py +++ b/app/api/resources/mentorship_relation.py @@ -1,5 +1,5 @@ from flask import request -from flask_restplus import Resource, Namespace, marshal +from flask_restx import Resource, Namespace, marshal from flask_jwt_extended import jwt_required, get_jwt_identity from http import HTTPStatus from app import messages @@ -501,7 +501,7 @@ class CreateTask(Resource): @mentorship_relation_ns.doc("create_task_in_mentorship_relation") @mentorship_relation_ns.expect(auth_header_parser, create_task_request_body) @mentorship_relation_ns.response(HTTPStatus.CREATED, '%s'%messages.TASK_WAS_CREATED_SUCCESSFULLY) - @mentorship_relation_ns.response(HTTPStatus.BAD_REQUEST, '%s'%messages.UNACCEPTED_STATE_RELATION) + @mentorship_relation_ns.response(HTTPStatus.FORBIDDEN, '%s'%messages.UNACCEPTED_STATE_RELATION) @mentorship_relation_ns.response(HTTPStatus.UNAUTHORIZED, '%s\n%s\n%s'%( messages.TOKEN_HAS_EXPIRED, messages.TOKEN_IS_INVALID, diff --git a/app/api/resources/user.py b/app/api/resources/user.py index d7bbd1568..bdf5a0b62 100644 --- a/app/api/resources/user.py +++ b/app/api/resources/user.py @@ -8,7 +8,7 @@ create_refresh_token, get_jwt_identity, ) -from flask_restplus import Resource, marshal, Namespace +from flask_restx import Resource, marshal, Namespace from app import messages from app.api.validations.user import * @@ -72,8 +72,7 @@ class OtherUser(Resource): @jwt_required @users_ns.doc("get_user") @users_ns.expect(auth_header_parser) - @users_ns.response(HTTPStatus.CREATED, "Success.", public_user_api_model) - @users_ns.response(HTTPStatus.BAD_REQUEST, "%s" % messages.USER_ID_IS_NOT_VALID) + @users_ns.response(HTTPStatus.OK, "Success.", public_user_api_model) @users_ns.response( HTTPStatus.UNAUTHORIZED, "%s\n%s\n%s" @@ -91,19 +90,11 @@ def get(cls, user_id): A user with valid access token can view the details of another user. The endpoint takes "user_id" of such user has input. """ - # Validate arguments - if not OtherUser.validate_param(user_id): - return messages.USER_ID_IS_NOT_VALID, HTTPStatus.BAD_REQUEST - requested_user = DAO.get_user(user_id) if requested_user is None: return messages.USER_DOES_NOT_EXIST, HTTPStatus.NOT_FOUND else: - return marshal(requested_user, public_user_api_model), HTTPStatus.CREATED - - @staticmethod - def validate_param(user_id): - return isinstance(user_id, int) + return marshal(requested_user, public_user_api_model), HTTPStatus.OK @users_ns.route("user") diff --git a/app/api/validations/user.py b/app/api/validations/user.py index 00ee22479..de6804a38 100644 --- a/app/api/validations/user.py +++ b/app/api/validations/user.py @@ -213,7 +213,6 @@ def validate_update_profile_request_data(data): if "available_to_mentor" in data and data["available_to_mentor"] is None: return messages.FIELD_AVAILABLE_TO_MENTOR_IS_INVALID - return {} diff --git a/app/messages.py b/app/messages.py index 83f3f538d..cd5e1b1e4 100644 --- a/app/messages.py +++ b/app/messages.py @@ -48,6 +48,7 @@ DESCRIPTION_FIELD_IS_MISSING = {"message": "Description field is missing."} COMMENT_FIELD_IS_MISSING = {"message": "Comment field is missing."} USERNAME_FIELD_IS_EMPTY = {"message": f"The username field has to be longer than {USERNAME_MIN_LENGTH} characters and shorter than {USERNAME_MAX_LENGTH} characters."} +USER_AND_USERNAME_FIELD_IS_MISSING ={"message":"The name and username fields are missing."} # Admin USER_IS_ALREADY_AN_ADMIN = {"message": "User is already an Admin."} diff --git a/requirements.txt b/requirements.txt index 1ff48e47f..24cee1fcb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,7 +30,7 @@ Flask==1.0.2 Flask-JWT-Extended==3.10.0 Flask-Mail==0.9.1 Flask-Migrate==2.5.2 -flask-restplus==0.11.0 +flask-restx==0.2.0 Flask-SQLAlchemy==2.3.2 Flask-Testing==0.7.1 future==0.16.0 diff --git a/tests/admin/test_api_list_admin_users.py b/tests/admin/test_api_list_admin_users.py index accded029..621a05230 100644 --- a/tests/admin/test_api_list_admin_users.py +++ b/tests/admin/test_api_list_admin_users.py @@ -2,7 +2,7 @@ from datetime import datetime, timedelta from flask import json -from flask_restplus import marshal +from flask_restx import marshal from app import messages from app.api.models.admin import public_admin_user_api_model diff --git a/tests/admin/test_api_remove_admin_user.py b/tests/admin/test_api_remove_admin_user.py index 6b6238748..2bb706ff8 100644 --- a/tests/admin/test_api_remove_admin_user.py +++ b/tests/admin/test_api_remove_admin_user.py @@ -2,7 +2,7 @@ from datetime import datetime, timedelta from flask import json -from flask_restplus import marshal +from flask_restx import marshal from app import messages from app.api.models.admin import public_admin_user_api_model diff --git a/tests/mentorship_relation/test_api_list_relations.py b/tests/mentorship_relation/test_api_list_relations.py index fe02cde71..4cc00d091 100644 --- a/tests/mentorship_relation/test_api_list_relations.py +++ b/tests/mentorship_relation/test_api_list_relations.py @@ -2,7 +2,7 @@ import unittest from datetime import datetime, timedelta -from flask_restplus import marshal +from flask_restx import marshal from app.api.models.mentorship_relation import mentorship_request_response_body from app.database.models.tasks_list import TasksListModel diff --git a/tests/task_comments/test_api_create_task_comment.py b/tests/task_comments/test_api_create_task_comment.py index ac0d45ae3..c600470bd 100644 --- a/tests/task_comments/test_api_create_task_comment.py +++ b/tests/task_comments/test_api_create_task_comment.py @@ -19,7 +19,7 @@ def test_task_comment_creation_api_without_comment(self): auth_header = get_test_request_header(self.admin_user.id) expected_response = messages.COMMENT_FIELD_IS_MISSING actual_response = self.client.post( - f"mentorship_relation/{self.relation_id}/task/{self.task_id}" f"/comment", + f"mentorship_relation/{self.relation_id}/task/{self.task_id}/comment", follow_redirects=True, headers=auth_header, content_type="application/json", @@ -33,7 +33,7 @@ def test_task_comment_creation_api_with_comment_not_string(self): auth_header = get_test_request_header(self.admin_user.id) expected_response = messages.COMMENT_NOT_IN_STRING_FORMAT actual_response = self.client.post( - f"mentorship_relation/{self.relation_id}/task/{self.task_id}" f"/comment", + f"mentorship_relation/{self.relation_id}/task/{self.task_id}/comment", follow_redirects=True, headers=auth_header, content_type="application/json", @@ -51,7 +51,7 @@ def test_task_comment_creation_api_with_comment_too_long(self): ) } actual_response = self.client.post( - f"mentorship_relation/{self.relation_id}/task/{self.task_id}" f"/comment", + f"mentorship_relation/{self.relation_id}/task/{self.task_id}/comment", follow_redirects=True, headers=auth_header, content_type="application/json", @@ -96,7 +96,7 @@ def test_full_task_comment_creation_api(self): auth_header = get_test_request_header(self.admin_user.id) expected_response = messages.TASK_COMMENT_WAS_CREATED_SUCCESSFULLY actual_response = self.client.post( - f"mentorship_relation/{self.relation_id}/task/{self.task_id}" f"/comment", + f"mentorship_relation/{self.relation_id}/task/{self.task_id}/comment", follow_redirects=True, headers=auth_header, content_type="application/json", diff --git a/tests/task_comments/test_api_delete_task_comment.py b/tests/task_comments/test_api_delete_task_comment.py index 204ba371e..b2df2af48 100644 --- a/tests/task_comments/test_api_delete_task_comment.py +++ b/tests/task_comments/test_api_delete_task_comment.py @@ -96,7 +96,7 @@ def test_task_comment_deletion_api_with_comment_not_existing(self): auth_header = get_test_request_header(self.admin_user.id) expected_response = messages.TASK_COMMENT_DOES_NOT_EXIST actual_response = self.client.delete( - f"mentorship_relation/{self.relation_id}/task/{self.task_id}" f"/comment/0", + f"mentorship_relation/{self.relation_id}/task/{self.task_id}/comment/0", follow_redirects=True, headers=auth_header, content_type="application/json", diff --git a/tests/task_comments/test_api_get_task_comments.py b/tests/task_comments/test_api_get_task_comments.py index 51924cc8c..1eda14f1b 100644 --- a/tests/task_comments/test_api_get_task_comments.py +++ b/tests/task_comments/test_api_get_task_comments.py @@ -1,7 +1,7 @@ import json import unittest -from flask_restplus import marshal +from flask_restx import marshal from app import messages from app.api.dao.task_comment import TaskCommentDAO @@ -29,7 +29,7 @@ def setUp(self): def test_task_comment_listing_api_without_auth_header(self): expected_response = messages.AUTHORISATION_TOKEN_IS_MISSING actual_response = self.client.get( - f"mentorship_relation/{self.relation_id}/task/{self.task_id}" f"/comments/", + f"mentorship_relation/{self.relation_id}/task/{self.task_id}/comments/", follow_redirects=True, content_type="application/json", ) @@ -70,7 +70,7 @@ def test_task_comment_listing_api(self): task_comments_model, ) actual_response = self.client.get( - f"mentorship_relation/{self.relation_id}/task/{self.task_id}" f"/comments", + f"mentorship_relation/{self.relation_id}/task/{self.task_id}/comments", follow_redirects=True, headers=auth_header, ) diff --git a/tests/task_comments/test_api_modify_task_comment.py b/tests/task_comments/test_api_modify_task_comment.py index 538e33ec7..985ffd366 100644 --- a/tests/task_comments/test_api_modify_task_comment.py +++ b/tests/task_comments/test_api_modify_task_comment.py @@ -95,7 +95,7 @@ def test_task_comment_modification_api_with_relation_not_existing(self): auth_header = get_test_request_header(self.admin_user.id) expected_response = messages.MENTORSHIP_RELATION_DOES_NOT_EXIST actual_response = self.client.put( - f"mentorship_relation/0/task/{self.task_id}/comment/" f"{self.comment_id}", + f"mentorship_relation/0/task/{self.task_id}/comment/{self.comment_id}", follow_redirects=True, headers=auth_header, content_type="application/json", @@ -124,7 +124,7 @@ def test_task_comment_modification_api_with_comment_not_existing(self): auth_header = get_test_request_header(self.admin_user.id) expected_response = messages.TASK_COMMENT_DOES_NOT_EXIST actual_response = self.client.put( - f"mentorship_relation/{self.relation_id}/task/{self.task_id}" f"/comment/0", + f"mentorship_relation/{self.relation_id}/task/{self.task_id}/comment/0", follow_redirects=True, headers=auth_header, content_type="application/json", diff --git a/tests/tasks/test_api_list_tasks.py b/tests/tasks/test_api_list_tasks.py index 4b48bebc3..e713e5a6c 100644 --- a/tests/tasks/test_api_list_tasks.py +++ b/tests/tasks/test_api_list_tasks.py @@ -1,6 +1,6 @@ import unittest from flask import json -from flask_restplus import marshal +from flask_restx import marshal from app import messages from app.api.models.mentorship_relation import list_tasks_response_body diff --git a/tests/tasks/test_dao_complete_task.py b/tests/tasks/test_dao_complete_task.py index e7835d058..e49befd76 100644 --- a/tests/tasks/test_dao_complete_task.py +++ b/tests/tasks/test_dao_complete_task.py @@ -20,7 +20,7 @@ def test_achieve_not_achieved_task(self): def test_achieve_achieved_task(self): self.assertTrue(self.tasks_list_1.find_task_by_id(2).get("is_done")) - expected_response = messages.TASK_WAS_ALREADY_ACHIEVED, 400 + expected_response = messages.TASK_WAS_ALREADY_ACHIEVED, 403 actual_response = TaskDAO.complete_task( self.first_user.id, self.mentorship_relation_w_second_user.id, 2 ) diff --git a/tests/tasks/test_dao_create_task.py b/tests/tasks/test_dao_create_task.py index 5ca429a97..4170b8de6 100644 --- a/tests/tasks/test_dao_create_task.py +++ b/tests/tasks/test_dao_create_task.py @@ -40,7 +40,7 @@ def test_create_task_with_non_existing_mentorship_relation(self): def test_create_task_with_mentorship_relation_non_accepted_state(self): - expected_response = messages.UNACCEPTED_STATE_RELATION, 400 + expected_response = messages.UNACCEPTED_STATE_RELATION, 403 self.mentorship_relation_w_second_user.state = MentorshipRelationState.CANCELLED actual_response = TaskDAO.create_task( diff --git a/tests/users/test_api_authentication.py b/tests/users/test_api_authentication.py index d28b116b8..501f69976 100644 --- a/tests/users/test_api_authentication.py +++ b/tests/users/test_api_authentication.py @@ -2,7 +2,7 @@ from datetime import timedelta from flask import json -from flask_restplus import marshal +from flask_restx import marshal from app import messages from app.api.models.user import full_user_api_model diff --git a/tests/users/test_api_get_other_user.py b/tests/users/test_api_get_other_user.py new file mode 100644 index 000000000..c300a3196 --- /dev/null +++ b/tests/users/test_api_get_other_user.py @@ -0,0 +1,60 @@ +import unittest + +from flask import json +from flask_restplus import marshal +from http import HTTPStatus + +from app.api.models.user import public_user_api_model +from app.database.models.user import UserModel +from app.database.sqlalchemy_extension import db +from tests.base_test_case import BaseTestCase +from tests.test_data import user1, user2 +from tests.test_utils import get_test_request_header + + +class TestnGetOtherUserApi(BaseTestCase): + + def setUp(self): + super(TestnGetOtherUserApi, self).setUp() + + self.verified_user = UserModel( + name=user1["name"] + " Example", + email=user1["email"], + username=user1["username"], + password=user1["password"], + terms_and_conditions_checked=user1["terms_and_conditions_checked"], + ) + self.other_user = UserModel( + name=user2["name"], + email=user2["email"], + username=user2["username"], + password=user2["password"], + terms_and_conditions_checked=user2["terms_and_conditions_checked"], + ) + + self.verified_user.is_email_verified = True + self.verified_user.is_available = False + self.other_user.is_email_verified = True + self.other_user.is_available = False + db.session.add(self.verified_user) + db.session.add(self.other_user) + db.session.commit() + + def test_user_error_code_ok_for_other_user(self): + auth_header = get_test_request_header(self.admin_user.id) + expected_response = marshal(self.verified_user, public_user_api_model) + actual_response = self.client.get( + f"/users/{self.verified_user.id}", follow_redirects=True, headers=auth_header + ) + self.assertEqual(HTTPStatus.OK, actual_response.status_code) + self.assertEqual(expected_response, json.loads(actual_response.data)) + + def test_user_invalid_user_id_for_other_user(self): + auth_header = get_test_request_header(self.admin_user.id) + actual_response = self.client.get( + "/users/abc", follow_redirects=True, headers=auth_header + ) + self.assertEqual(HTTPStatus.NOT_FOUND, actual_response.status_code) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/users/test_api_list_users.py b/tests/users/test_api_list_users.py index 7a5ff15d0..1329e8a44 100644 --- a/tests/users/test_api_list_users.py +++ b/tests/users/test_api_list_users.py @@ -2,7 +2,7 @@ from datetime import datetime, timedelta from flask import json -from flask_restplus import marshal +from flask_restx import marshal from app import messages from app.api.models.user import public_user_api_model diff --git a/tests/users/test_api_update_user.py b/tests/users/test_api_update_user.py index 10797aabf..8618351a6 100644 --- a/tests/users/test_api_update_user.py +++ b/tests/users/test_api_update_user.py @@ -78,6 +78,63 @@ def test_update_username_not_taken(self): self.assertDictEqual(expected_response, json.loads(actual_response.data)) self.assertEqual(user1_new_username, self.first_user.username) + def test_update_missing_username(self): + + self.first_user = UserModel( + name=user1["name"], + email=user1["email"], + username=user1["username"], + password=user1["password"], + terms_and_conditions_checked=user1["terms_and_conditions_checked"], + ) + self.first_user.is_email_verified = True + + db.session.add(self.first_user) + db.session.commit() + + user1_new_username = "" + auth_header = get_test_request_header(self.first_user.id) + expected_response = messages.USERNAME_FIELD_IS_MISSING + actual_response = self.client.put( + "/user", + follow_redirects=True, + headers=auth_header, + data=json.dumps(dict(username=user1_new_username)), + content_type="application/json", + ) + + self.assertEqual(200, actual_response.status_code) + self.assertDictEqual(expected_response, json.loads(actual_response.data)) + + def test_update_missing_name(self): + + self.first_user = UserModel( + name=user1["name"], + email=user1["email"], + username=user1["username"], + password=user1["password"], + terms_and_conditions_checked=user1["terms_and_conditions_checked"], + ) + self.first_user.is_email_verified = True + + db.session.add(self.first_user) + db.session.commit() + + user1_new_username = "new_username" + user1_new_name = "" + auth_header = get_test_request_header(self.first_user.id) + expected_response = messages.NAME_FIELD_IS_MISSING + actual_response = self.client.put( + "/user", + follow_redirects=True, + headers=auth_header, + data=json.dumps(dict(name=user1_new_name)), + content_type="application/json", + ) + + self.assertEqual(200, actual_response.status_code) + self.assertDictEqual(expected_response, json.loads(actual_response.data)) + def test_update_username_invalid_length(self): self.first_user = UserModel(