From e3430f91ce3f843ca629ac3da45b8cd7076d8d86 Mon Sep 17 00:00:00 2001 From: Oksamies Date: Sun, 7 Jan 2024 22:50:06 +0200 Subject: [PATCH] Add EditTeamMemberAPIView --- .../api/cyberstorm/tests/test_team.py | 87 +++++++++++++++++++ .../api/cyberstorm/views/__init__.py | 2 + .../thunderstore/api/cyberstorm/views/team.py | 46 ++++++++++ django/thunderstore/api/urls.py | 6 ++ 4 files changed, 141 insertions(+) diff --git a/django/thunderstore/api/cyberstorm/tests/test_team.py b/django/thunderstore/api/cyberstorm/tests/test_team.py index 589a59b9b..6f1c674dc 100644 --- a/django/thunderstore/api/cyberstorm/tests/test_team.py +++ b/django/thunderstore/api/cyberstorm/tests/test_team.py @@ -134,6 +134,93 @@ def test_team_membership_permission__when_fetching_team__is_case_insensitive( assert response.status_code == 200 +@pytest.mark.django_db +def test_team_members_edit__when_changing_role__succeeds( + api_client: APIClient, + user: UserType, + team: Team, +): + TeamMemberFactory(team=team, user=user, role="owner") + api_client.force_authenticate(user) + just_a_member = TeamMemberFactory(team=team, role="owner") + + response = api_client.post( + f"/api/cyberstorm/team/{team.name}/members/edit/", + json.dumps({"username": just_a_member.user.username, "role": "member"}), + content_type="application/json", + ) + + response_json = response.json() + assert response.status_code == 200 + assert response_json["team_name"] == team.name + assert response_json["username"] == just_a_member.user.username + assert response_json["role"] == "member" + assert TeamMember.objects.get(pk=just_a_member.pk).role == "member" + + +@pytest.mark.django_db +def test_team_members_edit__when_changing_role__fails_because_user_is_not_in_the_team( + api_client: APIClient, + user: UserType, + team: Team, +): + TeamMemberFactory(team=team, user=user, role="owner") + api_client.force_authenticate(user) + another_team = TeamFactory() + member_in_another_team = TeamMemberFactory(team=another_team, role="owner") + + response = api_client.post( + f"/api/cyberstorm/team/{team.name}/members/edit/", + json.dumps( + {"username": member_in_another_team.user.username, "role": "member"} + ), + content_type="application/json", + ) + + assert response.status_code == 404 + response_json = response.json() + assert response_json["detail"] == "Not found." + + +@pytest.mark.django_db +def test_team_members_edit__when_changing_role__fails_because_team_does_not_exist( + api_client: APIClient, + user: UserType, +): + api_client.force_authenticate(user) + + response = api_client.post( + f"/api/cyberstorm/team/GhostTeam/members/edit/", + json.dumps({"username": user.username, "role": "member"}), + content_type="application/json", + ) + + assert response.status_code == 404 + response_json = response.json() + assert response_json["detail"] == "Not found." + + +@pytest.mark.django_db +def test_team_members_edit__when_changing_role__fails_because_user_is_not_authenticated( + api_client: APIClient, + user: UserType, + team: Team, +): + TeamMemberFactory(team=team, user=user, role="owner") + just_a_member = TeamMemberFactory(team=team, role="owner") + + response = api_client.post( + f"/api/cyberstorm/team/{team.name}/members/edit/", + json.dumps({"username": just_a_member.user.username, "role": "member"}), + content_type="application/json", + ) + + assert response.status_code == 401 + response_json = response.json() + assert response_json["detail"] == "Authentication credentials were not provided." + assert TeamMember.objects.get(pk=just_a_member.pk).role == "owner" + + @pytest.mark.django_db def test_team_member_list_api_view__for_member__returns_only_real_users( api_client: APIClient, diff --git a/django/thunderstore/api/cyberstorm/views/__init__.py b/django/thunderstore/api/cyberstorm/views/__init__.py index cef2ebfa2..3b216d6e4 100644 --- a/django/thunderstore/api/cyberstorm/views/__init__.py +++ b/django/thunderstore/api/cyberstorm/views/__init__.py @@ -12,6 +12,7 @@ from .package_rating import PackageRatingRateAPIView from .package_version_list import PackageVersionListAPIView from .team import ( + EditTeamMemberAPIView, RemoveTeamMemberAPIView, TeamAPIView, TeamCreateAPIView, @@ -40,4 +41,5 @@ "PackageListingEditCategoriesAPIView", "TeamCreateAPIView", "RemoveTeamMemberAPIView", + "EditTeamMemberAPIView", ] diff --git a/django/thunderstore/api/cyberstorm/views/team.py b/django/thunderstore/api/cyberstorm/views/team.py index 7ae6df4d1..7b1af9f75 100644 --- a/django/thunderstore/api/cyberstorm/views/team.py +++ b/django/thunderstore/api/cyberstorm/views/team.py @@ -22,6 +22,7 @@ from thunderstore.repository.forms import ( AddTeamMemberForm, CreateTeamForm, + EditTeamMemberForm, RemoveTeamMemberForm, ) from thunderstore.repository.models.team import Team, TeamMember @@ -190,6 +191,51 @@ def post(self, request: HttpRequest, team_name: str): raise ValidationError(form.errors) +class CyberstormEditTeamMemberRequestSerialiazer(serializers.Serializer): + username = serializers.CharField() + role = serializers.ChoiceField( + choices=EditTeamMemberForm.base_fields["role"].choices + ) + + +class CyberstormEditTeamMemberResponseSerialiazer(serializers.Serializer): + username = serializers.CharField(source="user") + role = serializers.ChoiceField( + choices=EditTeamMemberForm.base_fields["role"].choices + ) + team_name = serializers.CharField(source="team") + + +class EditTeamMemberAPIView(APIView): + @conditional_swagger_auto_schema( + request_body=CyberstormEditTeamMemberRequestSerialiazer, + responses={200: CyberstormEditTeamMemberResponseSerialiazer}, + operation_id="cyberstorm.team.members.edit", + tags=["cyberstorm"], + ) + def post(self, request: HttpRequest, team_name: str): + serializer = CyberstormEditTeamMemberRequestSerialiazer(data=request.data) + serializer.is_valid(raise_exception=True) + team_member = get_object_or_404( + TeamMember, + user__username__iexact=request.data["username"], + team__name__iexact=team_name, + ) + form = EditTeamMemberForm( + user=request.user, + instance=team_member, + data=serializer.validated_data, + ) + + if form.is_valid(): + team_member = form.save() + return Response( + CyberstormEditTeamMemberResponseSerialiazer(team_member).data + ) + else: + raise ValidationError(form.errors) + + class TeamServiceAccountListAPIView(CyberstormAutoSchemaMixin, TeamRestrictedAPIView): serializer_class = CyberstormServiceAccountSerializer filter_backends = [StrictOrderingFilter] diff --git a/django/thunderstore/api/urls.py b/django/thunderstore/api/urls.py index 6b98d33bf..13392fd49 100644 --- a/django/thunderstore/api/urls.py +++ b/django/thunderstore/api/urls.py @@ -4,6 +4,7 @@ CommunityAPIView, CommunityFiltersAPIView, CommunityListAPIView, + EditTeamMemberAPIView, PackageDeprecateAPIView, PackageListingAPIView, PackageListingByCommunityListAPIView, @@ -134,4 +135,9 @@ RemoveTeamMemberAPIView.as_view(), name="cyberstorm.team.members.remove", ), + path( + "team//members/edit/", + EditTeamMemberAPIView.as_view(), + name="cyberstorm.team.members.edit", + ), ]