diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f26880c064388fffaf104c01f95187ec9b14b381..9cbb3d861676a5dcfcf0f7c4d00393822f0a76c6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -207,6 +207,9 @@ staging_trigger_unified-api_redeployment: trigger: project: 'app/holi-unified-api' branch: 'main' + forward: + yaml_variables: false + pipeline_variables: false only: - main resource_group: unified-api-staging @@ -233,6 +236,9 @@ production_trigger_unified-api_redeployment: trigger: project: 'app/holi-unified-api' branch: 'production' + forward: + yaml_variables: false + pipeline_variables: false only: - production resource_group: unified-api-production diff --git a/init.sh b/init.sh index 9d9dd75ff7658445e6f6ac7196b88f75206d9dfc..9e656a01b9c34277868d1b1e166aabd621a00e03 100755 --- a/init.sh +++ b/init.sh @@ -7,6 +7,11 @@ brewInstall() { # only install, when not present, so it's not accidentally updat brew list "$1" &>/dev/null || brew install "$1" } +fail() { + echo -e >&2 "${RED}${1}${NOCOLOR}" + exit 1 +} + # install the Python virtualenv pyenv install -s "$(cat .python-version)" pyenv local "$(cat .python-version)" diff --git a/openbook_auth/schema/helpers.py b/openbook_auth/schema/helpers.py new file mode 100644 index 0000000000000000000000000000000000000000..10f362a9e3544433ec1719045be750ce9db4ba88 --- /dev/null +++ b/openbook_auth/schema/helpers.py @@ -0,0 +1,20 @@ +from django.db.models import Case, When + +from openbook_auth.models import User +from openbook_common.schema.types import Paged +from openbook_common.utils.model_loaders import get_connection_model + + +def get_ordered_user_connections(circle_id, offset, limit): + Connection = get_connection_model() + all_connections = Connection.objects.filter( + circles__id__isnull=False, target_connection__circles__id=circle_id + ).order_by("-created") + + connections_ids = list(all_connections.values_list("user_id", flat=True)) + + preserved_order = Case(*[When(id=pk, then=pos) for pos, pk in enumerate(connections_ids)]) + + user_connections = User.objects.select_related("profile").filter(id__in=connections_ids).order_by(preserved_order) + + return Paged.of(user_connections, offset, limit) diff --git a/openbook_auth/schema/queries.py b/openbook_auth/schema/queries.py index d0f17338f3daaa695da28bd7039eced690447355..3adb8ea4be36151d65566523a39225570003bb84 100644 --- a/openbook_auth/schema/queries.py +++ b/openbook_auth/schema/queries.py @@ -10,6 +10,7 @@ from django.db.models.functions import Concat from django.db.models.lookups import IContains from openbook_auth.models import User as UserModel, UserBlock as UserBlockModel +from openbook_auth.schema.helpers import get_ordered_user_connections from openbook_auth.schema.types import User, AuthenticatedUser from openbook_auth.utils import verify_authorized_user, check_max_limit from openbook_common.validators import string_not_empty @@ -116,6 +117,17 @@ class Query: return Paged.of(current_user.connected_users(), offset, limit) + @strawberry_django.field() + def my_connections(self, info, offset: int = 0, limit: int = 10) -> Paged[User]: + current_user = verify_authorized_user(info) + return get_ordered_user_connections(circle_id=current_user.connections_circle_id, offset=offset, limit=limit) + + @strawberry_django.field() + def connections_by_user_id(self, info, user_id: uuid.UUID, offset: int = 0, limit: int = 10) -> Paged[User]: + verify_authorized_user(info) + user = UserModel.objects.get(id=user_id) + return get_ordered_user_connections(circle_id=user.connections_circle_id, offset=offset, limit=limit) + @strawberry_django.field( deprecation_reason="This query is deprecated. Please switch to using the 'favorites' query instead." ) diff --git a/openbook_auth/tests/helpers.py b/openbook_auth/tests/helpers.py index 83974d20f37fe02b1f1356765e8fb1e4c4d521c9..052554c310c501c8cb30391dbaf88a1572d57582 100644 --- a/openbook_auth/tests/helpers.py +++ b/openbook_auth/tests/helpers.py @@ -112,3 +112,48 @@ def get_connected_users_raw(calling_user=None): """, context_value=benedict({"request": {"user": calling_user or AnonymousUser}}), ) + + +def get_my_connections(current_user=None): + response = get_my_connections_query(current_user) + assert response.errors is None + return response.data["myConnections"] + + +def get_my_connections_query(current_user=None): + return async_to_sync(schema.execute)( + """ + query { + myConnections { + totalResults + data { + id + } + } + } + """, + context_value=benedict({"request": {"user": current_user or AnonymousUser}}), + ) + + +def get_connections_by_user_id(user_id, current_user=None): + response = get_connections_by_user_id_query(user_id, current_user) + assert response.errors is None + return response.data["connectionsByUserId"] + + +def get_connections_by_user_id_query(user_id, current_user=None): + return async_to_sync(schema.execute)( + """ + query ConnectionsByUserId($userId: UUID!) { + connectionsByUserId(userId: $userId) { + totalResults + data { + id + } + } + } + """, + variable_values={"userId": str(user_id)}, + context_value=benedict({"request": {"user": current_user or AnonymousUser}}), + ) diff --git a/openbook_auth/tests/test_graphql.py b/openbook_auth/tests/test_graphql.py index 4b3b40c9a524c72809d84e7e3fd164d50bac297f..73c4af7384051766920f9b9d7e8f0bbe20c62edc 100644 --- a/openbook_auth/tests/test_graphql.py +++ b/openbook_auth/tests/test_graphql.py @@ -32,6 +32,10 @@ from openbook_auth.tests.helpers import ( get_users_by_chat_identities, get_connected_users, get_connected_users_raw, + get_my_connections, + get_my_connections_query, + get_connections_by_user_id, + get_connections_by_user_id_query, ) from openbook_common.tests.helpers import ( assert_is_unauthorized, @@ -1396,3 +1400,51 @@ class TestUsers: assert response.errors is None assert response.data["userSuggestions"]["totalResults"] == 25 assert len(response.data["userSuggestions"]["data"]) == 5 + + def test_my_connections(self): + user1 = make_user(name="First", last_name="User") + user2 = make_user(name="Second", last_name="User") + user3 = make_user(name="Third", last_name="User") + + connect_to_user(user1, user2) + connect_to_user(user2, user1) + connect_to_user(user1, user3) + connect_to_user(user3, user1) + + connected_users = get_my_connections(current_user=user1) + assert connected_users["totalResults"] == 2 + assert connected_users["data"][0]["id"] == str(user3.id) + assert connected_users["data"][1]["id"] == str(user2.id) + + def test_cannot_retrieve_my_connections_if_anonymous_user(self): + response = get_my_connections_query() + assert_is_unauthorized(response) + + def test_connections_by_user_id(self): + user1 = make_user(name="First", last_name="User") + user2 = make_user(name="Second", last_name="User") + user3 = make_user(name="Third", last_name="User") + + connect_to_user(user1, user2) + connect_to_user(user2, user1) + connect_to_user(user1, user3) + connect_to_user(user3, user1) + + connected_users = get_connections_by_user_id(user_id=user1.id, current_user=user2) + + assert connected_users["totalResults"] == 2 + assert connected_users["data"][0]["id"] == str(user3.id) + assert connected_users["data"][1]["id"] == str(user2.id) + + def test_cannot_retrieve_connections_by_user_id_if_anonymous_user(self): + user1 = make_user(name="First", last_name="User") + user2 = make_user(name="Second", last_name="User") + user3 = make_user(name="Third", last_name="User") + + connect_to_user(user1, user2) + connect_to_user(user2, user1) + connect_to_user(user1, user3) + connect_to_user(user3, user1) + + response = get_connections_by_user_id_query(user_id=user1.id) + assert_is_unauthorized(response)