diff --git a/app/api/dao/user.py b/app/api/dao/user.py index 15d6f4e0d..349215374 100644 --- a/app/api/dao/user.py +++ b/app/api/dao/user.py @@ -150,6 +150,7 @@ def get_user_by_username(username: str): def list_users( user_id: int, search_query: str = "", + skill: str = "", page: int = DEFAULT_PAGE, per_page: int = DEFAULT_USERS_PER_PAGE, is_verified=None, @@ -159,6 +160,7 @@ def list_users( Arguments: user_id: The ID of the user to be listed. search_query: The search query for name of the users to be found. + skill: The skill of the user to be listed. 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 @@ -168,14 +170,18 @@ def list_users( """ - users_list = ( - UserModel.query.filter( - UserModel.id != user_id, - not is_verified or UserModel.is_email_verified, - func.lower(UserModel.name).contains(search_query.lower()) - | func.lower(UserModel.username).contains(search_query.lower()), + users_list_query = UserModel.query.filter( + UserModel.id != user_id, + not is_verified or UserModel.is_email_verified, + func.lower(UserModel.name).contains(search_query.lower()) + | func.lower(UserModel.username).contains(search_query.lower()), + ) + if skill: + users_list_query = users_list_query.filter( + func.lower(UserModel.skills) == func.lower(skill) ) - .order_by(UserModel.id) + users_list = ( + users_list_query.order_by(UserModel.id) .paginate( page=page, per_page=per_page, diff --git a/app/api/resources/user.py b/app/api/resources/user.py index cb546535f..db991f74a 100644 --- a/app/api/resources/user.py +++ b/app/api/resources/user.py @@ -56,6 +56,7 @@ class UserList(Resource): "list_users", params={ "search": "Search query", + "skills": "Search based on skill", "page": "specify page of users (default: 1)", "per_page": "specify number of users per page (default: 10)", }, @@ -93,7 +94,13 @@ def get(cls): ) user_id = get_jwt_identity() - return DAO.list_users(user_id, request.args.get("search", ""), page, per_page) + return DAO.list_users( + user_id, + request.args.get("search", ""), + request.args.get("skills", None), + page, + per_page, + ) @users_ns.route("users/") @@ -260,6 +267,7 @@ class VerifiedUser(Resource): "get_verified_users", params={ "search": "Search query", + "skills": "Search based on skill", "page": "specify page of users", "per_page": "specify number of users per page", }, @@ -298,7 +306,12 @@ def get(cls): user_id = get_jwt_identity() return DAO.list_users( - user_id, request.args.get("search", ""), page, per_page, is_verified=True + user_id, + request.args.get("search", ""), + request.args.get("skills", None), + page, + per_page, + is_verified=True, ) diff --git a/app/database/models/user.py b/app/database/models/user.py index 90cd11979..ae7ebb7b2 100644 --- a/app/database/models/user.py +++ b/app/database/models/user.py @@ -59,7 +59,16 @@ class UserModel(db.Model): need_mentoring = db.Column(db.Boolean) available_to_mentor = db.Column(db.Boolean) - def __init__(self, name, username, password, email, terms_and_conditions_checked): + def __init__( + self, + name, + username, + password, + email, + terms_and_conditions_checked, + need_mentoring=False, + available_to_mentor=False, + ): """Initialises userModel class with name, username, password, email, and terms_and_conditions_checked.""" # required fields @@ -78,8 +87,8 @@ def __init__(self, name, username, password, email, terms_and_conditions_checked # optional fields - self.need_mentoring = False - self.available_to_mentor = False + self.need_mentoring = need_mentoring + self.available_to_mentor = available_to_mentor def json(self): """Returns Usermodel object in json format.""" diff --git a/requirements.txt b/requirements.txt index 7ac2d2f31..a706a505a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,4 @@ gunicorn==20.0.4 psycopg2-binary==2.8.6 python-dotenv==0.18.0 six==1.11.0 -pre-commit +pre-commit \ No newline at end of file diff --git a/tests/users/test_dao_filter_by_skill.py b/tests/users/test_dao_filter_by_skill.py new file mode 100644 index 000000000..eaf70491a --- /dev/null +++ b/tests/users/test_dao_filter_by_skill.py @@ -0,0 +1,74 @@ +import unittest + +from flask import json +from http import HTTPStatus +from tests.base_test_case import BaseTestCase +from app.database.models.user import UserModel +from app.database.sqlalchemy_extension import db +from tests.test_data import user1, user2, user3 +from tests.test_utils import get_test_request_header + + +class TestFilterUsersBySkill(BaseTestCase): + def setUp(self): + super().setUp() + + # Insert data of the first entry + self.first_user = UserModel(**user1) + self.first_user.is_email_verified = True + self.first_user.skills = "Problem Solving" + + db.session.add(self.first_user) + db.session.commit() + + # Insert data of the second entry + self.second_user = UserModel(**user2) + self.second_user.is_email_verified = True + self.second_user.skills = "Problem Solving" + + db.session.add(self.second_user) + db.session.commit() + + # Insert data of the third entry + self.third_user = UserModel(**user3) + self.third_user.is_email_verified = True + self.third_user.skills = "Critical thinking" + + db.session.add(self.third_user) + db.session.commit() + + def test_filter_users_by_skill_problem_solving(self): + + auth_header = get_test_request_header(self.admin_user.id) + expected_response = "Problem Solving" + + actual_response = self.client.get( + "/users/verified?skills=Problem Solving", + headers=auth_header, + content_type="application/json", + ) + + self.assertEqual(HTTPStatus.OK, actual_response.status_code) + + for data in json.loads(actual_response.data): + self.assertEqual(expected_response, data["skills"]) + + def test_filter_users_by_skill_critical(self): + + auth_header = get_test_request_header(self.admin_user.id) + expected_response = "Critical thinking" + + actual_response = self.client.get( + "/users/verified?skills=Critical thinking", + headers=auth_header, + content_type="application/json", + ) + + self.assertEqual(HTTPStatus.OK, actual_response.status_code) + + for data in json.loads(actual_response.data): + self.assertEqual(expected_response, data["skills"]) + + +if __name__ == "__main__": + unittest.main()