From 1625c7ef10343ba3faa641defa977c9111189d31 Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 7 Dec 2024 23:13:01 +0100 Subject: [PATCH] APi & Client - get users followed by user on username completion --- fittrackee/tests/users/test_users_api.py | 96 +++++++++++++++++++ fittrackee/users/users.py | 17 +++- .../src/components/Comment/CommentEdition.vue | 1 + 3 files changed, 111 insertions(+), 3 deletions(-) diff --git a/fittrackee/tests/users/test_users_api.py b/fittrackee/tests/users/test_users_api.py index c2ad5964b..c22429cc5 100644 --- a/fittrackee/tests/users/test_users_api.py +++ b/fittrackee/tests/users/test_users_api.py @@ -573,6 +573,38 @@ def test_it_gets_users_list_regardless_suspended_status( 'total': 3, } + def test_it_gets_following_user_when_profile_is_hidden( + self, + app: Flask, + user_1_admin: User, + user_2: User, + user_3: User, + ) -> None: + user_2.hide_profile_in_users_directory = True + user_3.hide_profile_in_users_directory = True + user_1_admin.send_follow_request_to(user_2) + user_2.approves_follow_request_from(user_1_admin) + db.session.commit() + client, auth_token = self.get_test_client_and_auth_token( + app, user_1_admin.email + ) + + response = client.get( + '/api/users?with_following=true', + headers=dict(Authorization=f'Bearer {auth_token}'), + ) + + data = json.loads(response.data.decode()) + assert response.status_code == 200 + assert data['status'] == 'success' + assert len(data['data']['users']) == 2 + assert data['data']['users'][0] == jsonify_dict( + user_1_admin.serialize(current_user=user_1_admin) + ) + assert data['data']['users'][1] == jsonify_dict( + user_2.serialize(current_user=user_1_admin) + ) + def test_it_gets_all_users( self, app: Flask, @@ -1583,6 +1615,38 @@ def test_it_gets_users_list_without_inactive_hidden_or_suspended_users( 'total': 2, } + def test_it_gets_following_user_when_profile_is_hidden( + self, + app: Flask, + user_1_moderator: User, + user_2: User, + user_3: User, + ) -> None: + user_2.hide_profile_in_users_directory = True + user_3.hide_profile_in_users_directory = True + user_1_moderator.send_follow_request_to(user_2) + user_2.approves_follow_request_from(user_1_moderator) + db.session.commit() + client, auth_token = self.get_test_client_and_auth_token( + app, user_1_moderator.email + ) + + response = client.get( + '/api/users?with_following=true', + headers=dict(Authorization=f'Bearer {auth_token}'), + ) + + data = json.loads(response.data.decode()) + assert response.status_code == 200 + assert data['status'] == 'success' + assert len(data['data']['users']) == 2 + assert data['data']['users'][0] == jsonify_dict( + user_1_moderator.serialize(current_user=user_1_moderator) + ) + assert data['data']['users'][1] == jsonify_dict( + user_2.serialize(current_user=user_1_moderator) + ) + class TestGetUsersAsUser(ApiTestCaseMixin): @pytest.mark.parametrize( @@ -1638,6 +1702,38 @@ def test_it_gets_users_list_without_inactive_hidden_or_suspended_users( 'total': 2, } + def test_it_gets_following_user_when_profile_is_hidden( + self, + app: Flask, + user_1: User, + user_2: User, + user_3: User, + ) -> None: + user_2.hide_profile_in_users_directory = True + user_3.hide_profile_in_users_directory = True + user_1.send_follow_request_to(user_2) + user_2.approves_follow_request_from(user_1) + db.session.commit() + client, auth_token = self.get_test_client_and_auth_token( + app, user_1.email + ) + + response = client.get( + '/api/users?with_following=true', + headers=dict(Authorization=f'Bearer {auth_token}'), + ) + + data = json.loads(response.data.decode()) + assert response.status_code == 200 + assert data['status'] == 'success' + assert len(data['data']['users']) == 2 + assert data['data']['users'][0] == jsonify_dict( + user_1.serialize(current_user=user_1) + ) + assert data['data']['users'][1] == jsonify_dict( + user_2.serialize(current_user=user_1) + ) + def test_it_gets_users_list_with_workouts( self, app: Flask, diff --git a/fittrackee/users/users.py b/fittrackee/users/users.py index 78027d828..6c3b6f101 100644 --- a/fittrackee/users/users.py +++ b/fittrackee/users/users.py @@ -3,7 +3,7 @@ from typing import Any, Dict, Optional, Tuple, Union from flask import Blueprint, current_app, request, send_file -from sqlalchemy import asc, desc, exc, func, nullslast +from sqlalchemy import and_, asc, desc, exc, func, nullslast, or_ from fittrackee import appLog, db, limiter from fittrackee.emails.tasks import ( @@ -213,6 +213,8 @@ def get_users(auth_user: User) -> Dict: :query string order_by: sorting criteria: ``username``, ``created_at``, ``workouts_count``, ``role``, ``is_active`` (default: ``username``) + :query boolean with_following: returns hidden users followed by user if + true :query boolean with_hidden_users: returns hidden users if true (only if authenticated user has administration rights - for users administration) @@ -256,16 +258,25 @@ def get_users(auth_user: User) -> Dict: with_suspended_users = _get_value_depending_on_user_rights( params, 'with_suspended', auth_user ) + with_following = params.get('with_following', 'false').lower() + following_user_ids = ( + auth_user.get_following_user_ids() if with_following == 'true' else [] + ) + users_pagination = ( User.query.filter( User.username.ilike('%' + query + '%') if query else True, ( True if with_inactive == 'true' else User.is_active == True # noqa ), - ( + or_( True if with_hidden_users == 'true' - else User.hide_profile_in_users_directory == False # noqa + else User.hide_profile_in_users_directory == False, # noqa + and_( + User.id.in_(following_user_ids), + User.hide_profile_in_users_directory == True, # noqa + ), ), ( True diff --git a/fittrackee_client/src/components/Comment/CommentEdition.vue b/fittrackee_client/src/components/Comment/CommentEdition.vue index 26237ec17..80fbb9067 100644 --- a/fittrackee_client/src/components/Comment/CommentEdition.vue +++ b/fittrackee_client/src/components/Comment/CommentEdition.vue @@ -151,6 +151,7 @@ store.dispatch(USERS_STORE.ACTIONS.GET_USERS, { per_page: 5, q: usernameQuery, + with_following: 'true', }) } function updateText(textareaData: ICustomTextareaData) {