Skip to content

Commit e3dad2b

Browse files
committed
Add RemoveTeamMemberAPIView
1 parent 18c615f commit e3dad2b

File tree

4 files changed

+146
-2
lines changed

4 files changed

+146
-2
lines changed

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

+84-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from thunderstore.account.factories import ServiceAccountFactory
88
from thunderstore.core.types import UserType
99
from thunderstore.repository.factories import TeamFactory, TeamMemberFactory
10-
from thunderstore.repository.models.team import Team
10+
from thunderstore.repository.models.team import Team, TeamMember
1111

1212
User = get_user_model()
1313

@@ -183,6 +183,89 @@ def test_team_member_list_api_view__for_member__sorts_results(
183183
assert result[4]["username"] == erin.username
184184

185185

186+
@pytest.mark.django_db
187+
def test_team_members_remove__when_removing_member__succeeds(
188+
api_client: APIClient,
189+
user: UserType,
190+
team: Team,
191+
):
192+
TeamMemberFactory(team=team, user=user, role="owner")
193+
api_client.force_authenticate(user)
194+
just_a_member = TeamMemberFactory(team=team, role="member")
195+
196+
response = api_client.post(
197+
f"/api/cyberstorm/team/{team.name}/members/remove/",
198+
json.dumps({"username": just_a_member.user.username}),
199+
content_type="application/json",
200+
)
201+
202+
assert response.status_code == 200
203+
response_json = response.json()
204+
assert response_json["team_name"] == team.name
205+
assert response_json["username"] == just_a_member.user.username
206+
207+
208+
@pytest.mark.django_db
209+
def test_team_members_remove__when_removing_member__fails_because_user_is_not_a_member_in_team(
210+
api_client: APIClient,
211+
user: UserType,
212+
team: Team,
213+
):
214+
TeamMemberFactory(team=team, user=user, role="owner")
215+
api_client.force_authenticate(user)
216+
another_team = TeamFactory()
217+
member_in_another_team = TeamMemberFactory(team=another_team, role="owner")
218+
219+
response = api_client.post(
220+
f"/api/cyberstorm/team/{team.name}/members/remove/",
221+
json.dumps({"username": member_in_another_team.user.username}),
222+
content_type="application/json",
223+
)
224+
225+
assert response.status_code == 404
226+
response_json = response.json()
227+
assert response_json["detail"] == "Not found."
228+
229+
230+
@pytest.mark.django_db
231+
def test_team_members_remove__when_removing_member__fails_because_team_does_not_exist(
232+
api_client: APIClient,
233+
user: UserType,
234+
):
235+
api_client.force_authenticate(user)
236+
237+
response = api_client.post(
238+
f"/api/cyberstorm/team/GhostTeam/members/remove/",
239+
json.dumps({"username": user.username}),
240+
content_type="application/json",
241+
)
242+
243+
assert response.status_code == 404
244+
response_json = response.json()
245+
assert response_json["detail"] == "Not found."
246+
247+
248+
@pytest.mark.django_db
249+
def test_team_members_remove__when_removing_member__fails_because_user_is_not_authenticated(
250+
api_client: APIClient,
251+
user: UserType,
252+
team: Team,
253+
):
254+
TeamMemberFactory(team=team, user=user, role="owner")
255+
just_a_member = TeamMemberFactory(team=team, role="member")
256+
257+
response = api_client.post(
258+
f"/api/cyberstorm/team/{team.name}/members/remove/",
259+
json.dumps({"username": just_a_member.user.username}),
260+
content_type="application/json",
261+
)
262+
263+
assert response.status_code == 401
264+
response_json = response.json()
265+
assert response_json["detail"] == "Authentication credentials were not provided."
266+
assert TeamMember.objects.filter(team=team, user=user).count() == 1
267+
268+
186269
@pytest.mark.django_db
187270
def test_team_service_account_list_api_view__for_member__returns_only_service_accounts(
188271
api_client: APIClient,

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

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from .package_rating import PackageRatingRateAPIView
1313
from .package_version_list import PackageVersionListAPIView
1414
from .team import (
15+
RemoveTeamMemberAPIView,
1516
TeamAPIView,
1617
TeamCreateAPIView,
1718
TeamMemberAddAPIView,
@@ -38,4 +39,5 @@
3839
"PackageDeprecateAPIView",
3940
"PackageListingEditCategoriesAPIView",
4041
"TeamCreateAPIView",
42+
"RemoveTeamMemberAPIView",
4143
]

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

+54-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@
1919
CyberstormAutoSchemaMixin,
2020
conditional_swagger_auto_schema,
2121
)
22-
from thunderstore.repository.forms import AddTeamMemberForm, CreateTeamForm
22+
from thunderstore.repository.forms import (
23+
AddTeamMemberForm,
24+
CreateTeamForm,
25+
RemoveTeamMemberForm,
26+
)
2327
from thunderstore.repository.models.team import Team, TeamMember
2428

2529

@@ -137,6 +141,55 @@ def post(self, request, team_name, format=None):
137141
raise ValidationError(form.errors)
138142

139143

144+
class CyberstormRemoveTeamMemberRequestSerialiazer(serializers.Serializer):
145+
username = serializers.CharField()
146+
147+
148+
class CyberstormRemoveTeamMemberResponseSerialiazer(serializers.Serializer):
149+
username = serializers.CharField()
150+
team_name = serializers.CharField()
151+
152+
153+
class RemoveTeamMemberAPIView(APIView):
154+
@conditional_swagger_auto_schema(
155+
request_body=CyberstormRemoveTeamMemberRequestSerialiazer,
156+
responses={200: CyberstormRemoveTeamMemberResponseSerialiazer},
157+
operation_id="cyberstorm.team.members.remove",
158+
tags=["cyberstorm"],
159+
)
160+
def post(self, request: HttpRequest, team_name: str):
161+
team = get_object_or_404(Team, name__iexact=team_name)
162+
163+
serializer = CyberstormRemoveTeamMemberRequestSerialiazer(data=request.data)
164+
serializer.is_valid(raise_exception=True)
165+
166+
team_member = get_object_or_404(
167+
TeamMember,
168+
user__username__iexact=serializer.validated_data["username"],
169+
team=team,
170+
)
171+
172+
membership = team.get_membership_for_user(team_member.user)
173+
174+
form = RemoveTeamMemberForm(
175+
user=request.user,
176+
data={"membership": membership},
177+
)
178+
179+
if form.is_valid():
180+
form.save()
181+
return Response(
182+
CyberstormRemoveTeamMemberResponseSerialiazer(
183+
{
184+
"username": serializer.validated_data["username"],
185+
"team_name": team_name,
186+
}
187+
).data
188+
)
189+
else:
190+
raise ValidationError(form.errors)
191+
192+
140193
class TeamServiceAccountListAPIView(CyberstormAutoSchemaMixin, TeamRestrictedAPIView):
141194
serializer_class = CyberstormServiceAccountSerializer
142195
filter_backends = [StrictOrderingFilter]

django/thunderstore/api/urls.py

+6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
PackageVersionChangelogAPIView,
1515
PackageVersionListAPIView,
1616
PackageVersionReadmeAPIView,
17+
RemoveTeamMemberAPIView,
1718
TeamAPIView,
1819
TeamCreateAPIView,
1920
TeamMemberAddAPIView,
@@ -128,4 +129,9 @@
128129
UserDeleteAPIView.as_view(),
129130
name="cyberstorm.current-user.delete",
130131
),
132+
path(
133+
"team/<str:team_name>/members/remove/",
134+
RemoveTeamMemberAPIView.as_view(),
135+
name="cyberstorm.team.members.remove",
136+
),
131137
]

0 commit comments

Comments
 (0)