Skip to content

Commit f2a2960

Browse files
authored
Merge pull request #928 from thunderstore-io/12-05-Add_AddTeamMember_APIView
Add AddTeamMember APIView
2 parents f716447 + 3cc16ca commit f2a2960

File tree

4 files changed

+141
-3
lines changed

4 files changed

+141
-3
lines changed

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

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import json
2+
13
import pytest
24
from django.contrib.auth import get_user_model
35
from rest_framework.test import APIClient
@@ -223,3 +225,74 @@ def test_team_service_accounts_api_view__for_member__sorts_results(
223225
assert result[0]["name"] == alice.first_name
224226
assert result[1]["name"] == bob.first_name
225227
assert result[2]["name"] == charlie.first_name
228+
229+
230+
@pytest.mark.django_db
231+
def test_team_add_member__when_adding_a_member__succeeds(
232+
api_client: APIClient,
233+
team: Team,
234+
user: UserType,
235+
):
236+
teamMember = TeamMemberFactory(team=team, role="owner")
237+
api_client.force_authenticate(teamMember.user)
238+
239+
response = api_client.post(
240+
f"/api/cyberstorm/team/{team.name}/members/add/",
241+
json.dumps({"username": user.username, "role": "owner"}),
242+
content_type="application/json",
243+
)
244+
245+
assert response.status_code == 200
246+
response_json = response.json()
247+
assert response_json["username"] == user.username
248+
assert response_json["role"] == "owner"
249+
assert response_json["team"] == team.name
250+
251+
252+
@pytest.mark.django_db
253+
def test_team_add_member__when_adding_a_member__fails_because_team_doesnt_exist(
254+
api_client: APIClient,
255+
team: Team,
256+
user: UserType,
257+
):
258+
teamMember = TeamMemberFactory(team=team, role="owner")
259+
api_client.force_authenticate(teamMember.user)
260+
261+
response = api_client.post(
262+
"/api/cyberstorm/team/FakeTeam/members/add/",
263+
json.dumps({"username": user.username, "role": "owner"}),
264+
content_type="application/json",
265+
)
266+
267+
assert response.status_code == 404
268+
assert response.json()["detail"] == "Not found."
269+
270+
271+
@pytest.mark.django_db
272+
def test_team_add_member__when_adding_a_member__fails_because_user_is_already_in_team(
273+
api_client: APIClient,
274+
team: Team,
275+
user: UserType,
276+
):
277+
teamMember = TeamMemberFactory(team=team, role="owner")
278+
api_client.force_authenticate(teamMember.user)
279+
280+
response1 = api_client.post(
281+
f"/api/cyberstorm/team/{team.name}/members/add/",
282+
json.dumps({"username": user.username, "role": "owner"}),
283+
content_type="application/json",
284+
)
285+
286+
assert response1.status_code == 200
287+
288+
response2 = api_client.post(
289+
f"/api/cyberstorm/team/{team.name}/members/add/",
290+
json.dumps({"username": user.username, "role": "owner"}),
291+
content_type="application/json",
292+
)
293+
294+
assert response2.status_code == 400
295+
assert (
296+
"Team Member with this User and Team already exists."
297+
in response2.json()["__all__"]
298+
)

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
NamespacePackageListAPIView,
1010
PackageDependantsListAPIView,
1111
)
12-
from .team import TeamDetailAPIView, TeamMembersAPIView, TeamServiceAccountsAPIView
12+
from .team import (
13+
AddTeamMemberAPIView,
14+
TeamDetailAPIView,
15+
TeamMembersAPIView,
16+
TeamServiceAccountsAPIView,
17+
)
1318

1419
__all__ = [
1520
"CommunityDetailAPIView",
@@ -23,6 +28,7 @@
2328
"PackageVersionReadmeAPIView",
2429
"PackageVersionsAPIView",
2530
"TeamDetailAPIView",
31+
"AddTeamMemberAPIView",
2632
"TeamMembersAPIView",
2733
"TeamServiceAccountsAPIView",
2834
]

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

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
from django.contrib.auth import get_user_model
12
from django.db.models import Q, QuerySet
2-
from rest_framework.exceptions import PermissionDenied
3+
from rest_framework import serializers
4+
from rest_framework.exceptions import PermissionDenied, ValidationError
35
from rest_framework.generics import ListAPIView, RetrieveAPIView, get_object_or_404
46
from rest_framework.permissions import IsAuthenticated
57
from rest_framework.request import Request
8+
from rest_framework.response import Response
9+
from rest_framework.views import APIView
610

711
from thunderstore.account.models.service_account import ServiceAccount
812
from thunderstore.api.cyberstorm.serializers import (
@@ -11,9 +15,15 @@
1115
CyberstormTeamSerializer,
1216
)
1317
from thunderstore.api.ordering import StrictOrderingFilter
14-
from thunderstore.api.utils import CyberstormAutoSchemaMixin
18+
from thunderstore.api.utils import (
19+
CyberstormAutoSchemaMixin,
20+
conditional_swagger_auto_schema,
21+
)
22+
from thunderstore.repository.forms import AddTeamMemberForm
1523
from thunderstore.repository.models.team import Team, TeamMember
1624

25+
User = get_user_model()
26+
1727

1828
class TeamDetailAPIView(CyberstormAutoSchemaMixin, RetrieveAPIView):
1929
serializer_class = CyberstormTeamSerializer
@@ -52,6 +62,49 @@ def get_queryset(self) -> QuerySet[TeamMember]:
5262
)
5363

5464

65+
class CyberstormTeamAddMemberRequestSerialiazer(serializers.Serializer):
66+
username = serializers.CharField()
67+
role = serializers.ChoiceField(
68+
choices=AddTeamMemberForm.base_fields["role"].choices
69+
)
70+
71+
72+
class CyberstormTeamAddMemberResponseSerialiazer(serializers.Serializer):
73+
username = serializers.CharField(source="user")
74+
role = serializers.CharField()
75+
team = serializers.CharField()
76+
77+
78+
class AddTeamMemberAPIView(APIView):
79+
@conditional_swagger_auto_schema(
80+
request_body=CyberstormTeamAddMemberRequestSerialiazer,
81+
responses={200: CyberstormTeamAddMemberResponseSerialiazer},
82+
operation_id="cyberstorm.team.members.add",
83+
tags=["cyberstorm"],
84+
)
85+
def post(self, request, team_name, format=None):
86+
team = get_object_or_404(Team, name__iexact=team_name)
87+
serializer = CyberstormTeamAddMemberRequestSerialiazer(data=request.data)
88+
serializer.is_valid(raise_exception=True)
89+
90+
form = AddTeamMemberForm(
91+
user=request.user,
92+
data={
93+
**serializer.validated_data,
94+
"team": team.pk,
95+
"user": serializer.validated_data["username"],
96+
},
97+
)
98+
99+
if form.is_valid():
100+
team_member = form.save()
101+
return Response(
102+
CyberstormTeamAddMemberResponseSerialiazer(team_member).data
103+
)
104+
else:
105+
raise ValidationError(form.errors)
106+
107+
55108
class TeamServiceAccountsAPIView(CyberstormAutoSchemaMixin, TeamRestrictedAPIView):
56109
serializer_class = CyberstormServiceAccountSerializer
57110
filter_backends = [StrictOrderingFilter]

django/thunderstore/api/urls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from django.urls import path
22

33
from thunderstore.api.cyberstorm.views import (
4+
AddTeamMemberAPIView,
45
CommunityDetailAPIView,
56
CommunityFiltersAPIView,
67
CommunityListAPIView,
@@ -62,6 +63,11 @@
6263
TeamMembersAPIView.as_view(),
6364
name="cyberstorm.team.members",
6465
),
66+
path(
67+
"team/<str:team_name>/members/add/",
68+
AddTeamMemberAPIView.as_view(),
69+
name="cyberstorm.team.members.add",
70+
),
6571
path(
6672
"team/<str:team_id>/service-accounts/",
6773
TeamServiceAccountsAPIView.as_view(),

0 commit comments

Comments
 (0)