Skip to content

Commit

Permalink
Fix:updating an user with empty username and name gives an error message
Browse files Browse the repository at this point in the history
  • Loading branch information
rashikaqureshi committed Aug 6, 2020
1 parent 99820ef commit 7c5a31b
Show file tree
Hide file tree
Showing 31 changed files with 219 additions and 101 deletions.
2 changes: 1 addition & 1 deletion app/api/api_extension.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flask_restplus import Api
from flask_restx import Api

api = Api(
title="Mentorship System API",
Expand Down
8 changes: 4 additions & 4 deletions app/api/dao/mentorship_relation.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,22 +182,22 @@ def accept_request(user_id: int, request_id: int):

# verify if request is in pending state
if request.state != MentorshipRelationState.PENDING:
return messages.NOT_PENDING_STATE_RELATION, HTTPStatus.BAD_REQUEST
return messages.NOT_PENDING_STATE_RELATION, HTTPStatus.FORBIDDEN

# verify if I'm the receiver of the request
if request.action_user_id == user_id:
return messages.CANT_ACCEPT_MENTOR_REQ_SENT_BY_USER, HTTPStatus.BAD_REQUEST
return messages.CANT_ACCEPT_MENTOR_REQ_SENT_BY_USER, HTTPStatus.FORBIDDEN

# verify if I'm involved in this relation
if not (request.mentee_id == user_id or request.mentor_id == user_id):
return messages.CANT_ACCEPT_UNINVOLVED_MENTOR_RELATION, HTTPStatus.BAD_REQUEST
return messages.CANT_ACCEPT_UNINVOLVED_MENTOR_RELATION, HTTPStatus.FORBIDDEN

my_requests = user.mentee_relations + user.mentor_relations

# verify if I'm on a current relation
for my_request in my_requests:
if my_request.state == MentorshipRelationState.ACCEPTED:
return messages.USER_IS_INVOLVED_IN_A_MENTORSHIP_RELATION, HTTPStatus.BAD_REQUEST
return messages.USER_IS_INVOLVED_IN_A_MENTORSHIP_RELATION, HTTPStatus.FORBIDDEN

mentee = request.mentee
mentor = request.mentor
Expand Down
4 changes: 2 additions & 2 deletions app/api/dao/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion app/api/dao/task_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def delete_comment(user_id, _id, task_id, relation_id):
return messages.TASK_COMMENT_DOES_NOT_EXIST, HTTPStatus.NOT_FOUND

if task_comment.user_id != user_id:
return messages.TASK_COMMENT_WAS_NOT_CREATED_BY_YOU_DELETE, HTTPStatus.BAD_REQUEST
return messages.TASK_COMMENT_WAS_NOT_CREATED_BY_YOU_DELETE, HTTPStatus.FORBIDDEN

if task_comment.task_id != task_id:
return messages.TASK_COMMENT_WITH_GIVEN_TASK_ID_DOES_NOT_EXIST, HTTPStatus.NOT_FOUND
Expand Down
92 changes: 51 additions & 41 deletions app/api/dao/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
"""
Expand Down Expand Up @@ -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.
"""

Expand All @@ -102,65 +102,65 @@ 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)

@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)

@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)

@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(
Expand Down Expand Up @@ -197,23 +197,24 @@ 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)
if not user:
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)

Expand All @@ -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"]:
Expand Down Expand Up @@ -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
Expand All @@ -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"]
Expand All @@ -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)
Expand All @@ -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.
"""
Expand Down
2 changes: 1 addition & 1 deletion app/api/models/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flask_restplus import fields, Model
from flask_restx import fields, Model


def add_models_to_namespace(api_namespace):
Expand Down
2 changes: 1 addition & 1 deletion app/api/models/mentorship_relation.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flask_restplus import fields, Model
from flask_restx import fields, Model

from app.utils.enum_utils import MentorshipRelationState

Expand Down
2 changes: 1 addition & 1 deletion app/api/models/user.py
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
4 changes: 2 additions & 2 deletions app/api/resources/admin.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion app/api/resources/common.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flask_restplus import reqparse
from flask_restx import reqparse

auth_header_parser = reqparse.RequestParser()
auth_header_parser.add_argument(
Expand Down
10 changes: 5 additions & 5 deletions app/api/resources/mentorship_relation.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -188,7 +188,7 @@ class AcceptMentorshipRelation(Resource):
HTTPStatus.OK, "%s" % messages.MENTORSHIP_RELATION_WAS_ACCEPTED_SUCCESSFULLY
)
@mentorship_relation_ns.response(
HTTPStatus.BAD_REQUEST,
HTTPStatus.FORBIDDEN,
"%s\n%s\n%s\n%s"
% (
messages.NOT_PENDING_STATE_RELATION,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -786,12 +786,12 @@ def put(cls, relation_id, task_id, comment_id):
@mentorship_relation_ns.doc(
responses={
HTTPStatus.OK: f"{messages.TASK_COMMENT_WAS_DELETED_SUCCESSFULLY}",
HTTPStatus.BAD_REQUEST: f"{messages.UNACCEPTED_STATE_RELATION}<br>"
f"{messages.TASK_COMMENT_WAS_NOT_CREATED_BY_YOU_DELETE}",
HTTPStatus.BAD_REQUEST: f"{messages.UNACCEPTED_STATE_RELATION}",
HTTPStatus.UNAUTHORIZED: f"{messages.TOKEN_HAS_EXPIRED}<br>"
f"{messages.TOKEN_IS_INVALID}<br>"
f"{messages.AUTHORISATION_TOKEN_IS_MISSING}<br>"
f"{messages.USER_NOT_INVOLVED_IN_THIS_MENTOR_RELATION}",
HTTPStatus.FORBIDDEN: f"{messages.TASK_COMMENT_WAS_NOT_CREATED_BY_YOU_DELETE}",
HTTPStatus.NOT_FOUND: f"{messages.USER_DOES_NOT_EXIST}<br>"
f"{messages.MENTORSHIP_RELATION_DOES_NOT_EXIST}<br>"
f"{messages.TASK_DOES_NOT_EXIST}<br>"
Expand Down
Loading

0 comments on commit 7c5a31b

Please sign in to comment.