|
51 | 51 | UserRoleRelationship, |
52 | 52 | ) |
53 | 53 | from api.rls import Tenant |
| 54 | +from api.v1.serializers import TokenSerializer |
54 | 55 | from api.v1.views import ComplianceOverviewViewSet, TenantFinishACSView |
55 | 56 |
|
56 | 57 |
|
@@ -4720,6 +4721,36 @@ def test_role_clear_relationships(self, authenticated_client, roles_fixture): |
4720 | 4721 | assert role.users.count() == 0 |
4721 | 4722 | assert role.provider_groups.count() == 0 |
4722 | 4723 |
|
| 4724 | + def test_cannot_remove_own_assignment_via_role_update( |
| 4725 | + self, authenticated_client, roles_fixture |
| 4726 | + ): |
| 4727 | + role = roles_fixture[0] |
| 4728 | + # Ensure the authenticated user is assigned to this role |
| 4729 | + user = User.objects.get(email=TEST_USER) |
| 4730 | + if not UserRoleRelationship.objects.filter(user=user, role=role).exists(): |
| 4731 | + UserRoleRelationship.objects.create( |
| 4732 | + user=user, role=role, tenant_id=role.tenant_id |
| 4733 | + ) |
| 4734 | + |
| 4735 | + # Attempt to update role users to exclude the current user |
| 4736 | + data = { |
| 4737 | + "data": { |
| 4738 | + "id": str(role.id), |
| 4739 | + "type": "roles", |
| 4740 | + "relationships": {"users": {"data": []}}, |
| 4741 | + } |
| 4742 | + } |
| 4743 | + response = authenticated_client.patch( |
| 4744 | + reverse("role-detail", kwargs={"pk": role.id}), |
| 4745 | + data=json.dumps(data), |
| 4746 | + content_type="application/vnd.api+json", |
| 4747 | + ) |
| 4748 | + assert response.status_code == status.HTTP_400_BAD_REQUEST |
| 4749 | + assert ( |
| 4750 | + "cannot remove their own role" |
| 4751 | + in response.json()["errors"][0]["detail"].lower() |
| 4752 | + ) |
| 4753 | + |
4723 | 4754 | def test_role_create_with_invalid_user_relationship( |
4724 | 4755 | self, authenticated_client, provider_groups_fixture |
4725 | 4756 | ): |
@@ -4841,16 +4872,135 @@ def test_partial_update_relationship( |
4841 | 4872 | roles_fixture[2].id, |
4842 | 4873 | } |
4843 | 4874 |
|
4844 | | - def test_destroy_relationship( |
4845 | | - self, authenticated_client, roles_fixture, create_test_user |
| 4875 | + def test_destroy_relationship_other_user( |
| 4876 | + self, authenticated_client, roles_fixture, create_test_user, tenants_fixture |
4846 | 4877 | ): |
| 4878 | + # Create another user in same tenant and assign a role |
| 4879 | + tenant = tenants_fixture[0] |
| 4880 | + other_user = User.objects.create_user( |
| 4881 | + name="other", |
| 4882 | + email="other_user@prowler.com", |
| 4883 | + password="TmpPass123@", |
| 4884 | + ) |
| 4885 | + Membership.objects.create(user=other_user, tenant=tenant) |
| 4886 | + UserRoleRelationship.objects.create( |
| 4887 | + user=other_user, role=roles_fixture[0], tenant_id=tenant.id |
| 4888 | + ) |
| 4889 | + |
| 4890 | + # Delete roles for the other user (allowed) |
4847 | 4891 | response = authenticated_client.delete( |
4848 | | - reverse("user-roles-relationship", kwargs={"pk": create_test_user.id}), |
| 4892 | + reverse("user-roles-relationship", kwargs={"pk": other_user.id}), |
4849 | 4893 | ) |
4850 | 4894 | assert response.status_code == status.HTTP_204_NO_CONTENT |
4851 | | - relationships = UserRoleRelationship.objects.filter(role=roles_fixture[0].id) |
| 4895 | + relationships = UserRoleRelationship.objects.filter(user=other_user.id) |
4852 | 4896 | assert relationships.count() == 0 |
4853 | 4897 |
|
| 4898 | + def test_cannot_delete_own_roles(self, authenticated_client, create_test_user): |
| 4899 | + # Attempt to delete own roles should be forbidden |
| 4900 | + response = authenticated_client.delete( |
| 4901 | + reverse("user-roles-relationship", kwargs={"pk": create_test_user.id}), |
| 4902 | + ) |
| 4903 | + assert response.status_code == status.HTTP_400_BAD_REQUEST |
| 4904 | + |
| 4905 | + def test_prevent_removing_last_manage_account_on_patch( |
| 4906 | + self, authenticated_client, roles_fixture, create_test_user, tenants_fixture |
| 4907 | + ): |
| 4908 | + # roles_fixture[1] has manage_account=False |
| 4909 | + limited_role = roles_fixture[1] |
| 4910 | + |
| 4911 | + # Ensure there is no other user with MANAGE_ACCOUNT in the tenant |
| 4912 | + tenant = tenants_fixture[0] |
| 4913 | + # Create a secondary user without MANAGE_ACCOUNT |
| 4914 | + user2 = User.objects.create_user( |
| 4915 | + name="limited_user", |
| 4916 | + email="limited_user@prowler.com", |
| 4917 | + password="TmpPass123@", |
| 4918 | + ) |
| 4919 | + Membership.objects.create(user=user2, tenant=tenant) |
| 4920 | + UserRoleRelationship.objects.create( |
| 4921 | + user=user2, role=limited_role, tenant_id=tenant.id |
| 4922 | + ) |
| 4923 | + |
| 4924 | + # Attempt to switch the only MANAGE_ACCOUNT user to a role without it |
| 4925 | + data = {"data": [{"type": "roles", "id": str(limited_role.id)}]} |
| 4926 | + response = authenticated_client.patch( |
| 4927 | + reverse("user-roles-relationship", kwargs={"pk": create_test_user.id}), |
| 4928 | + data=data, |
| 4929 | + content_type="application/vnd.api+json", |
| 4930 | + ) |
| 4931 | + assert response.status_code == status.HTTP_400_BAD_REQUEST |
| 4932 | + assert "MANAGE_ACCOUNT" in response.json()["errors"][0]["detail"] |
| 4933 | + |
| 4934 | + def test_allow_role_change_when_other_user_has_manage_account_on_patch( |
| 4935 | + self, authenticated_client, roles_fixture, create_test_user, tenants_fixture |
| 4936 | + ): |
| 4937 | + # roles_fixture[1] has manage_account=False, roles_fixture[0] has manage_account=True |
| 4938 | + limited_role = roles_fixture[1] |
| 4939 | + ma_role = roles_fixture[0] |
| 4940 | + |
| 4941 | + tenant = tenants_fixture[0] |
| 4942 | + # Create another user with MANAGE_ACCOUNT |
| 4943 | + user2 = User.objects.create_user( |
| 4944 | + name="ma_user", |
| 4945 | + email="ma_user@prowler.com", |
| 4946 | + password="TmpPass123@", |
| 4947 | + ) |
| 4948 | + Membership.objects.create(user=user2, tenant=tenant) |
| 4949 | + UserRoleRelationship.objects.create( |
| 4950 | + user=user2, role=ma_role, tenant_id=tenant.id |
| 4951 | + ) |
| 4952 | + |
| 4953 | + # Now changing the first user's roles to a non-MA role should succeed |
| 4954 | + data = {"data": [{"type": "roles", "id": str(limited_role.id)}]} |
| 4955 | + response = authenticated_client.patch( |
| 4956 | + reverse("user-roles-relationship", kwargs={"pk": create_test_user.id}), |
| 4957 | + data=data, |
| 4958 | + content_type="application/vnd.api+json", |
| 4959 | + ) |
| 4960 | + assert response.status_code == status.HTTP_204_NO_CONTENT |
| 4961 | + |
| 4962 | + def test_role_destroy_only_manage_account_blocked( |
| 4963 | + self, authenticated_client, tenants_fixture |
| 4964 | + ): |
| 4965 | + # Use a tenant without default admin role (tenant3) |
| 4966 | + tenant = tenants_fixture[2] |
| 4967 | + user = User.objects.get(email=TEST_USER) |
| 4968 | + # Add membership for this tenant |
| 4969 | + Membership.objects.create(user=user, tenant=tenant) |
| 4970 | + |
| 4971 | + # Create a single MANAGE_ACCOUNT role in this tenant |
| 4972 | + only_role = Role.objects.create( |
| 4973 | + name="only_ma", |
| 4974 | + tenant=tenant, |
| 4975 | + manage_users=True, |
| 4976 | + manage_account=True, |
| 4977 | + manage_billing=False, |
| 4978 | + manage_providers=False, |
| 4979 | + manage_integrations=False, |
| 4980 | + manage_scans=False, |
| 4981 | + unlimited_visibility=False, |
| 4982 | + ) |
| 4983 | + |
| 4984 | + # Switch token to this tenant |
| 4985 | + serializer = TokenSerializer( |
| 4986 | + data={ |
| 4987 | + "type": "tokens", |
| 4988 | + "email": TEST_USER, |
| 4989 | + "password": TEST_PASSWORD, |
| 4990 | + "tenant_id": str(tenant.id), |
| 4991 | + } |
| 4992 | + ) |
| 4993 | + serializer.is_valid(raise_exception=True) |
| 4994 | + access_token = serializer.validated_data["access"] |
| 4995 | + authenticated_client.defaults["HTTP_AUTHORIZATION"] = f"Bearer {access_token}" |
| 4996 | + |
| 4997 | + # Attempt to delete the only MANAGE_ACCOUNT role |
| 4998 | + response = authenticated_client.delete( |
| 4999 | + reverse("role-detail", kwargs={"pk": only_role.id}) |
| 5000 | + ) |
| 5001 | + assert response.status_code == status.HTTP_400_BAD_REQUEST |
| 5002 | + assert Role.objects.filter(id=only_role.id).exists() |
| 5003 | + |
4854 | 5004 | def test_invalid_provider_group_id(self, authenticated_client, create_test_user): |
4855 | 5005 | invalid_id = "non-existent-id" |
4856 | 5006 | data = {"data": [{"type": "provider-groups", "id": invalid_id}]} |
|
0 commit comments