Skip to content

Commit ec0341c

Browse files
authored
fix(user): PermissionError, 500, when deleting user (#8731)
1 parent 2e5f3a5 commit ec0341c

3 files changed

Lines changed: 79 additions & 1 deletion

File tree

api/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ All notable changes to the **Prowler API** are documented in this file.
1212
- Now the MANAGE_ACCOUNT permission is required to modify or read user permissions instead of MANAGE_USERS [(#8281)](https://github.com/prowler-cloud/prowler/pull/8281)
1313
- Now at least one user with MANAGE_ACCOUNT permission is required in the tenant [(#8729)](https://github.com/prowler-cloud/prowler/pull/8729)
1414

15+
### Fixed
16+
- 500 error when deleting user [(#8731)](https://github.com/prowler-cloud/prowler/pull/8731)
17+
1518
---
1619

1720
## [1.13.1] (Prowler 5.12.2)

api/src/backend/api/tests/test_views.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import jwt
1414
import pytest
1515
from allauth.socialaccount.models import SocialAccount, SocialApp
16+
from allauth.account.models import EmailAddress
1617
from botocore.exceptions import ClientError, NoCredentialsError
1718
from conftest import (
1819
API_JSON_CONTENT_TYPE,
@@ -325,6 +326,78 @@ def test_users_destroy_invalid_user(self, authenticated_client, create_test_user
325326
assert response.status_code == status.HTTP_400_BAD_REQUEST
326327
assert User.objects.filter(id=another_user.id).exists()
327328

329+
def test_users_destroy_cascades_allauth_and_memberships(
330+
self, authenticated_client, create_test_user
331+
):
332+
# Create related admin-side objects (email + SocialAccount)
333+
EmailAddress.objects.create(
334+
user=create_test_user,
335+
email=create_test_user.email,
336+
primary=True,
337+
verified=True,
338+
)
339+
SocialAccount.objects.create(
340+
user=create_test_user, provider="fake-provider", uid="uid-fake-provider"
341+
)
342+
343+
# Sanity check pre-conditions
344+
assert EmailAddress.objects.filter(user=create_test_user).exists()
345+
assert SocialAccount.objects.filter(user=create_test_user).exists()
346+
assert Membership.objects.filter(user=create_test_user).exists()
347+
assert UserRoleRelationship.objects.filter(user=create_test_user).exists()
348+
349+
# Delete current user
350+
response = authenticated_client.delete(
351+
reverse("user-detail", kwargs={"pk": str(create_test_user.id)})
352+
)
353+
assert response.status_code == status.HTTP_204_NO_CONTENT
354+
355+
# Assert user and related objects are gone
356+
assert not User.objects.filter(id=create_test_user.id).exists()
357+
assert not EmailAddress.objects.filter(user_id=create_test_user.id).exists()
358+
assert not SocialAccount.objects.filter(user_id=create_test_user.id).exists()
359+
assert not Membership.objects.filter(user_id=create_test_user.id).exists()
360+
assert not UserRoleRelationship.objects.filter(
361+
user_id=create_test_user.id
362+
).exists()
363+
364+
def test_users_destroy_with_saml_configuration_and_memberships(
365+
self, authenticated_client, create_test_user, saml_setup
366+
):
367+
# Ensure SAML configuration exists for tenant (from saml_setup fixture)
368+
domain = saml_setup["domain"]
369+
config = SAMLConfiguration.objects.get(email_domain=domain)
370+
371+
# Attach a SAML SocialAccount to the user
372+
SocialAccount.objects.create(
373+
user=create_test_user, provider="saml", uid="uid-saml"
374+
)
375+
376+
# Sanity check pre-conditions
377+
assert SocialAccount.objects.filter(
378+
user=create_test_user, provider="saml"
379+
).exists()
380+
assert Membership.objects.filter(user=create_test_user).exists()
381+
assert UserRoleRelationship.objects.filter(user=create_test_user).exists()
382+
383+
# Delete current user
384+
response = authenticated_client.delete(
385+
reverse("user-detail", kwargs={"pk": str(create_test_user.id)})
386+
)
387+
assert response.status_code == status.HTTP_204_NO_CONTENT
388+
389+
# Assert user-related rows are removed
390+
assert not User.objects.filter(id=create_test_user.id).exists()
391+
assert not SocialAccount.objects.filter(user_id=create_test_user.id).exists()
392+
assert not Membership.objects.filter(user_id=create_test_user.id).exists()
393+
assert not UserRoleRelationship.objects.filter(
394+
user_id=create_test_user.id
395+
).exists()
396+
397+
# Tenant-level SAML configuration should remain intact
398+
assert SAMLConfiguration.objects.filter(id=config.id).exists()
399+
assert SocialApp.objects.filter(provider="saml", client_id=domain).exists()
400+
328401
@pytest.mark.parametrize(
329402
"attribute_key, attribute_value, error_field",
330403
[

api/src/backend/api/v1/views.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,9 @@ def destroy(self, request, *args, **kwargs):
811811
if kwargs["pk"] != str(self.request.user.id):
812812
raise ValidationError("Only the current user can be deleted.")
813813

814-
return super().destroy(request, *args, **kwargs)
814+
user = self.get_object()
815+
user.delete(using=MainRouter.admin_db)
816+
return Response(status=status.HTTP_204_NO_CONTENT)
815817

816818
@extend_schema(
817819
parameters=[

0 commit comments

Comments
 (0)