Skip to content

Commit ae1f556

Browse files
committed
Use service layer function in form views
Utilize the remove team member service layer function in the form views. Remove logic from the form as this logic has now moved to the service layer and update the tests accordingly. The form is now only intended for validating POST data to the view. Refs. TS-2315
1 parent 5f2bb6d commit ae1f556

File tree

3 files changed

+29
-117
lines changed

3 files changed

+29
-117
lines changed

django/thunderstore/repository/forms/team.py

-10
Original file line numberDiff line numberDiff line change
@@ -93,16 +93,6 @@ def __init__(self, user: Optional[UserType], *args, **kwargs):
9393
super().__init__(*args, **kwargs)
9494
self.user = user
9595

96-
def clean_membership(self):
97-
membership = self.cleaned_data["membership"]
98-
if membership.user != self.user:
99-
membership.team.ensure_user_can_manage_members(self.user)
100-
membership.team.ensure_member_can_be_removed(membership)
101-
return membership
102-
103-
def save(self):
104-
self.cleaned_data["membership"].delete()
105-
10696

10797
class EditTeamMemberForm(forms.ModelForm):
10898
class Meta:

django/thunderstore/repository/tests/test_team_forms.py

+1-98
Original file line numberDiff line numberDiff line change
@@ -179,87 +179,9 @@ def test_form_add_team_member(
179179
assert form.errors
180180

181181

182-
@pytest.mark.django_db
183-
@pytest.mark.parametrize("remover_type", TestUserTypes.options())
184-
@pytest.mark.parametrize("removed_type", TestUserTypes.options())
185-
@pytest.mark.parametrize("remover_role", TeamMemberRole.options() + [None])
186-
@pytest.mark.parametrize("removed_role", TeamMemberRole.options() + [None])
187-
def test_form_remove_team_member(
188-
remover_type: str, removed_type: str, remover_role: str, removed_role: str
189-
) -> None:
190-
remover_type_valid_map = {
191-
TestUserTypes.no_user: False,
192-
TestUserTypes.unauthenticated: False,
193-
TestUserTypes.regular_user: True,
194-
TestUserTypes.deactivated_user: False,
195-
TestUserTypes.service_account: False,
196-
TestUserTypes.site_admin: True,
197-
TestUserTypes.superuser: True,
198-
}
199-
removed_type_valid_map = {
200-
**remover_type_valid_map,
201-
**{TestUserTypes.deactivated_user: True},
202-
}
203-
remover_role_valid_map = {
204-
None: False,
205-
TeamMemberRole.member: False,
206-
TeamMemberRole.owner: True,
207-
}
208-
removed_role_valid_map = {
209-
None: False,
210-
TeamMemberRole.member: True,
211-
TeamMemberRole.owner: True,
212-
}
213-
remover_valid = all(
214-
(
215-
remover_type_valid_map[remover_type],
216-
remover_role_valid_map[remover_role],
217-
)
218-
)
219-
removed_valid = all(
220-
(
221-
removed_type_valid_map[removed_type],
222-
removed_role_valid_map[removed_role],
223-
)
224-
)
225-
226-
remover = TestUserTypes.get_user_by_type(remover_type)
227-
removed = TestUserTypes.get_user_by_type(removed_type)
228-
team = Team.create(name="Test")
229-
230-
if remover is not None and remover.is_authenticated and remover_role is not None:
231-
TeamMember.objects.create(
232-
team=team,
233-
user=remover,
234-
role=remover_role,
235-
)
236-
237-
if removed is not None and removed.is_authenticated and removed_role is not None:
238-
membership = TeamMember.objects.create(
239-
team=team,
240-
user=removed,
241-
role=removed_role,
242-
).pk
243-
else:
244-
membership = None
245-
246-
form = RemoveTeamMemberForm(
247-
user=remover,
248-
data={"membership": membership},
249-
)
250-
should_be_valid = all((remover_valid, removed_valid))
251-
if should_be_valid:
252-
assert form.is_valid() is True
253-
assert form.save() is None
254-
assert TeamMember.objects.filter(pk=membership).exists() is False
255-
else:
256-
assert form.is_valid() is False
257-
assert form.errors
258-
259-
260182
@pytest.mark.django_db
261183
@pytest.mark.parametrize("role", TeamMemberRole.options())
262-
def test_form_remove_team_member_works_on_self(role: str) -> None:
184+
def test_form_remove_team_member_valid_membership_roles(role: str) -> None:
263185
user = UserFactory()
264186
team = Team.create(name="Test")
265187
TeamMember.objects.create(
@@ -277,25 +199,6 @@ def test_form_remove_team_member_works_on_self(role: str) -> None:
277199
data={"membership": membership.pk},
278200
)
279201
assert form.is_valid() is True
280-
assert form.save() is None
281-
assert TeamMember.objects.filter(pk=membership.pk).exists() is False
282-
283-
284-
@pytest.mark.django_db
285-
def test_form_remove_team_member_last_owner() -> None:
286-
user = UserFactory()
287-
team = Team.create(name="Test")
288-
last_owner = TeamMember.objects.create(
289-
user=user,
290-
team=team,
291-
role=TeamMemberRole.owner,
292-
)
293-
form = RemoveTeamMemberForm(
294-
user=user,
295-
data={"membership": last_owner.pk},
296-
)
297-
assert form.is_valid() is False
298-
assert "Cannot remove last owner from team" in str(repr(form.errors))
299202

300203

301204
@pytest.mark.django_db

django/thunderstore/repository/views/team_settings.py

+28-9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
CreateServiceAccountForm,
1717
DeleteServiceAccountForm,
1818
)
19+
from thunderstore.api.cyberstorm.services.team import remove_team_member
1920
from thunderstore.core.mixins import RequireAuthenticationMixin
2021
from thunderstore.core.utils import capture_exception
2122
from thunderstore.frontend.views import SettingsViewMixin
@@ -26,7 +27,6 @@
2627
DonationLinkTeamForm,
2728
EditTeamMemberForm,
2829
RemoveTeamMemberForm,
29-
TeamMemberRole,
3030
)
3131
from thunderstore.repository.models import Team, TeamMember, reverse
3232

@@ -111,17 +111,31 @@ def get_context_data(self, **kwargs):
111111
return context
112112

113113
def form_invalid(self, form):
114-
messages.error(
115-
self.request, "There was a problem performing the requested action"
116-
)
114+
error_msg = "There was a problem performing the requested action"
115+
messages.error(self.request, error_msg)
117116
capture_exception(ValidationError(form.errors))
118117
return super().form_invalid(form)
119118

120119
def form_valid(self, form):
120+
if "kick" in self.request.POST:
121+
return self._handle_kick_action(form)
122+
121123
form.save()
122124
messages.success(self.request, "Action performed successfully")
123125
return redirect(self.object.settings_url)
124126

127+
def _handle_kick_action(self, form):
128+
try:
129+
remove_team_member(
130+
agent=self.request.user,
131+
team_member=form.cleaned_data["membership"],
132+
)
133+
except ValidationError:
134+
return self.form_invalid(form)
135+
136+
messages.success(self.request, "Action performed successfully")
137+
return redirect(self.object.settings_url)
138+
125139

126140
class SettingsTeamAddMemberView(TeamDetailView, UserFormKwargs, FormView):
127141
template_name = "settings/team_add_member.html"
@@ -190,16 +204,21 @@ def get_context_data(self, **kwargs):
190204
context["can_leave"] = not self.object.is_last_owner(self.membership.user)
191205
return context
192206

193-
def form_invalid(self, form):
194-
messages.error(
195-
self.request, "There was a problem performing the requested action"
196-
)
207+
def form_invalid(self, form, error_msg=None):
208+
error_msg = "There was a problem performing the requested action"
209+
messages.error(self.request, error_msg)
197210
capture_exception(ValidationError(form.errors))
198211
return super().form_invalid(form)
199212

200213
@transaction.atomic
201214
def form_valid(self, form):
202-
form.save()
215+
try:
216+
remove_team_member(
217+
agent=self.request.user,
218+
team_member=form.cleaned_data["membership"],
219+
)
220+
except ValidationError:
221+
return self.form_invalid(form)
203222
return redirect(reverse("settings.teams"))
204223

205224

0 commit comments

Comments
 (0)