Skip to content

Commit 918e781

Browse files
committed
Implement cyberstorm view for updating teams
Implement APIView for updating teams. Currently support only dontation_link over PATCH request. Add URl and update tests. Refs. TS-2314
1 parent 02a2547 commit 918e781

File tree

4 files changed

+177
-4
lines changed

4 files changed

+177
-4
lines changed

django/thunderstore/api/cyberstorm/tests/test_team.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,3 +322,137 @@ def test_team_member_add_api_view__when_adding_a_member__fails_because_user_is_n
322322
.count()
323323
== 0
324324
)
325+
326+
327+
@pytest.mark.django_db
328+
def test_team_update_succeeds(
329+
api_client: APIClient,
330+
user: UserType,
331+
team: Team,
332+
):
333+
TeamMemberFactory(team=team, user=user, role="owner")
334+
api_client.force_authenticate(user)
335+
336+
new_donation_link = "https://example.com"
337+
338+
response = api_client.patch(
339+
f"/api/cyberstorm/team/{team.name}/update/",
340+
json.dumps({"donation_link": new_donation_link}),
341+
content_type="application/json",
342+
)
343+
344+
expected_response = {"donation_link": new_donation_link}
345+
assert response.status_code == 200
346+
347+
assert response.json() == expected_response
348+
assert Team.objects.get(pk=team.pk).donation_link == new_donation_link
349+
350+
351+
@pytest.mark.django_db
352+
def test_team_update_fails_user_not_authenticated(
353+
api_client: APIClient,
354+
team: Team,
355+
):
356+
new_donation_link = "https://example.com"
357+
358+
response = api_client.patch(
359+
f"/api/cyberstorm/team/{team.name}/update/",
360+
json.dumps({"donation_link": new_donation_link}),
361+
content_type="application/json",
362+
)
363+
364+
expected_response = {"detail": "Authentication credentials were not provided."}
365+
366+
assert response.status_code == 401
367+
assert response.json() == expected_response
368+
assert Team.objects.get(pk=team.pk).donation_link is None
369+
370+
371+
@pytest.mark.django_db
372+
def test_team_update_fails_validation(
373+
api_client: APIClient,
374+
user: UserType,
375+
team: Team,
376+
):
377+
TeamMemberFactory(team=team, user=user, role="owner")
378+
api_client.force_authenticate(user)
379+
380+
new_bad_donation_link = "example.com"
381+
382+
response = api_client.patch(
383+
f"/api/cyberstorm/team/{team.name}/update/",
384+
json.dumps({"donation_link": new_bad_donation_link}),
385+
content_type="application/json",
386+
)
387+
388+
expected_response = {"donation_link": ["Enter a valid URL."]}
389+
390+
assert response.status_code == 400
391+
assert response.json() == expected_response
392+
393+
394+
@pytest.mark.django_db
395+
def test_team_update_fail_user_not_owner(
396+
api_client: APIClient,
397+
user: UserType,
398+
team: Team,
399+
):
400+
TeamMemberFactory(team=team, user=user, role="member")
401+
api_client.force_authenticate(user)
402+
403+
new_donation_link = "https://example.com"
404+
405+
response = api_client.patch(
406+
f"/api/cyberstorm/team/{team.name}/update/",
407+
json.dumps({"donation_link": new_donation_link}),
408+
content_type="application/json",
409+
)
410+
411+
expected_response = {"non_field_errors": ["Must be an owner to edit team info"]}
412+
413+
assert response.status_code == 403
414+
assert response.json() == expected_response
415+
assert Team.objects.get(pk=team.pk).donation_link is None
416+
417+
418+
@pytest.mark.django_db
419+
def test_team_update_fail_team_does_not_exist(
420+
api_client: APIClient,
421+
user: UserType,
422+
):
423+
api_client.force_authenticate(user)
424+
425+
new_donation_link = "https://example.com"
426+
427+
response = api_client.patch(
428+
"/api/cyberstorm/team/FakeTeam/update/",
429+
json.dumps({"donation_link": new_donation_link}),
430+
content_type="application/json",
431+
)
432+
433+
expected_response = {"detail": "Not found."}
434+
435+
assert response.status_code == 404
436+
assert response.json() == expected_response
437+
438+
439+
@pytest.mark.django_db
440+
def test_team_update_fail_user_not_team_member(
441+
api_client: APIClient,
442+
user: UserType,
443+
team: Team,
444+
):
445+
api_client.force_authenticate(user)
446+
447+
new_donation_link = "https://example.com"
448+
449+
response = api_client.patch(
450+
f"/api/cyberstorm/team/{team.name}/update/",
451+
json.dumps({"donation_link": new_donation_link}),
452+
content_type="application/json",
453+
)
454+
455+
expected_response = {"non_field_errors": ["Must be a member to access team"]}
456+
457+
assert response.status_code == 403
458+
assert response.json() == expected_response

django/thunderstore/api/cyberstorm/views/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
TeamMemberAddAPIView,
2525
TeamMemberListAPIView,
2626
TeamServiceAccountListAPIView,
27+
UpdateTeamAPIView,
2728
)
2829

2930
__all__ = [
@@ -49,4 +50,5 @@
4950
"UpdatePackageListingCategoriesAPIView",
5051
"RejectPackageListingAPIView",
5152
"ApprovePackageListingAPIView",
53+
"UpdateTeamAPIView",
5254
]

django/thunderstore/api/cyberstorm/views/team.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from django.core.exceptions import ValidationError as DjangoValidationError
21
from django.db.models import Q, QuerySet
32
from rest_framework import status
43
from rest_framework.exceptions import PermissionDenied, ValidationError
@@ -16,8 +15,13 @@
1615
CyberstormTeamAddMemberResponseSerializer,
1716
CyberstormTeamMemberSerializer,
1817
CyberstormTeamSerializer,
18+
CyberstormTeamUpdateSerializer,
19+
)
20+
from thunderstore.api.cyberstorm.services.team import (
21+
create_team,
22+
disband_team,
23+
update_team,
1924
)
20-
from thunderstore.api.cyberstorm.services import team as team_services
2125
from thunderstore.api.ordering import StrictOrderingFilter
2226
from thunderstore.api.utils import (
2327
CyberstormAutoSchemaMixin,
@@ -66,7 +70,7 @@ def post(self, request, *args, **kwargs):
6670
serializer = CyberstormCreateTeamSerializer(data=request.data)
6771
serializer.is_valid(raise_exception=True)
6872
team_name = serializer.validated_data["name"]
69-
team = team_services.create_team(user=request.user, team_name=team_name)
73+
team = create_team(user=request.user, team_name=team_name)
7074
return_data = CyberstormTeamSerializer(team).data
7175
return Response(return_data, status=status.HTTP_201_CREATED)
7276

@@ -135,5 +139,32 @@ class DisbandTeamAPIView(APIView):
135139
)
136140
def delete(self, request, *args, **kwargs):
137141
team_name = kwargs["team_name"]
138-
team_services.disband_team(user=request.user, team_name=team_name)
142+
disband_team(user=request.user, team_name=team_name)
139143
return Response(status=status.HTTP_204_NO_CONTENT)
144+
145+
146+
class UpdateTeamAPIView(APIView):
147+
permission_classes = [IsAuthenticated]
148+
serializer_class = CyberstormTeamUpdateSerializer
149+
http_method_names = ["patch"]
150+
151+
@conditional_swagger_auto_schema(
152+
operation_id="cyberstorm.team.update",
153+
tags=["cyberstorm"],
154+
request_body=CyberstormTeamUpdateSerializer,
155+
responses={status.HTTP_200_OK: serializer_class},
156+
)
157+
def patch(self, request, team_name, *args, **kwargs):
158+
team = get_object_or_404(Team.objects.exclude(is_active=False), name=team_name)
159+
160+
serializer = self.serializer_class(data=request.data)
161+
serializer.is_valid(raise_exception=True)
162+
163+
updated_team = update_team(
164+
agent=request.user,
165+
team=team,
166+
donation_link=serializer.validated_data["donation_link"],
167+
)
168+
169+
return_data = self.serializer_class(instance=updated_team).data
170+
return Response(return_data, status=status.HTTP_200_OK)

django/thunderstore/api/urls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
TeamMemberListAPIView,
2424
TeamServiceAccountListAPIView,
2525
UpdatePackageListingCategoriesAPIView,
26+
UpdateTeamAPIView,
2627
)
2728

2829
cyberstorm_urls = [
@@ -126,6 +127,11 @@
126127
TeamAPIView.as_view(),
127128
name="cyberstorm.team",
128129
),
130+
path(
131+
"team/<str:team_name>/update/",
132+
UpdateTeamAPIView.as_view(),
133+
name="cyberstorm.team.update",
134+
),
129135
path(
130136
"team/<str:team_name>/disband/",
131137
DisbandTeamAPIView.as_view(),

0 commit comments

Comments
 (0)