mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-20 17:56:11 +02:00
Merge remote-tracking branch 'origin/main' into nl/2669-max-width-adjustment-for-wide-screens
This commit is contained in:
commit
04f0b6f8f4
4 changed files with 128 additions and 8 deletions
|
@ -12,10 +12,11 @@
|
||||||
<div id="main-content">
|
<div id="main-content">
|
||||||
<h1 id="domain-requests-header">Domain requests</h1>
|
<h1 id="domain-requests-header">Domain requests</h1>
|
||||||
<div class="grid-row grid-gap">
|
<div class="grid-row grid-gap">
|
||||||
<div class="mobile:grid-col-12 tablet:grid-col-6">
|
|
||||||
<p class="margin-y-0">Domain requests can only be modified by the person who created the request.</p>
|
|
||||||
</div>
|
|
||||||
{% if has_edit_request_portfolio_permission %}
|
{% if has_edit_request_portfolio_permission %}
|
||||||
|
<div class="mobile:grid-col-12 tablet:grid-col-6">
|
||||||
|
<p class="margin-y-0">Domain requests can only be modified by the person who created the request.</p>
|
||||||
|
</div>
|
||||||
<div class="mobile:grid-col-12 tablet:grid-col-6">
|
<div class="mobile:grid-col-12 tablet:grid-col-6">
|
||||||
{% comment %}
|
{% comment %}
|
||||||
IMPORTANT:
|
IMPORTANT:
|
||||||
|
@ -29,6 +30,8 @@
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<p class="margin-y-0">Domain requests can only be modified by the person who created the request.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -859,3 +859,106 @@ class TestPortfolio(WebTest):
|
||||||
response = self.client.get(reverse("home"))
|
response = self.client.get(reverse("home"))
|
||||||
self.assertIsNone(self.client.session.get("portfolio"))
|
self.assertIsNone(self.client.session.get("portfolio"))
|
||||||
self.assertNotContains(response, "Hotel California")
|
self.assertNotContains(response, "Hotel California")
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
@override_flag("organization_feature", active=True)
|
||||||
|
@override_flag("organization_requests", active=True)
|
||||||
|
def test_org_user_can_delete_own_domain_request_with_permission(self):
|
||||||
|
"""Test that an org user with edit permission can delete their own DomainRequest with a deletable status."""
|
||||||
|
|
||||||
|
# Assign the user to a portfolio with edit permission
|
||||||
|
UserPortfolioPermission.objects.get_or_create(
|
||||||
|
user=self.user,
|
||||||
|
portfolio=self.portfolio,
|
||||||
|
roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER],
|
||||||
|
additional_permissions=[UserPortfolioPermissionChoices.EDIT_REQUESTS],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a domain request with status WITHDRAWN
|
||||||
|
domain_request = completed_domain_request(
|
||||||
|
name="test-domain.gov",
|
||||||
|
status=DomainRequest.DomainRequestStatus.WITHDRAWN,
|
||||||
|
portfolio=self.portfolio,
|
||||||
|
)
|
||||||
|
domain_request.creator = self.user
|
||||||
|
domain_request.save()
|
||||||
|
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
# Perform delete
|
||||||
|
response = self.client.post(reverse("domain-request-delete", kwargs={"pk": domain_request.pk}), follow=True)
|
||||||
|
|
||||||
|
# Check that the response is 200
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# Check that the domain request no longer exists
|
||||||
|
self.assertFalse(DomainRequest.objects.filter(pk=domain_request.pk).exists())
|
||||||
|
domain_request.delete()
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
@override_flag("organization_feature", active=True)
|
||||||
|
@override_flag("organization_requests", active=True)
|
||||||
|
def test_delete_domain_request_as_org_user_without_permission_with_deletable_status(self):
|
||||||
|
"""Test that an org user without edit permission cant delete their DomainRequest even if status is deletable."""
|
||||||
|
|
||||||
|
# Assign the user to a portfolio without edit permission
|
||||||
|
UserPortfolioPermission.objects.get_or_create(
|
||||||
|
user=self.user,
|
||||||
|
portfolio=self.portfolio,
|
||||||
|
roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER],
|
||||||
|
additional_permissions=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a domain request with status STARTED
|
||||||
|
domain_request = completed_domain_request(
|
||||||
|
name="test-domain.gov",
|
||||||
|
status=DomainRequest.DomainRequestStatus.STARTED,
|
||||||
|
portfolio=self.portfolio,
|
||||||
|
)
|
||||||
|
domain_request.creator = self.user
|
||||||
|
domain_request.save()
|
||||||
|
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
# Attempt to delete
|
||||||
|
response = self.client.post(reverse("domain-request-delete", kwargs={"pk": domain_request.pk}), follow=True)
|
||||||
|
|
||||||
|
# Check response is 403 Forbidden
|
||||||
|
self.assertEqual(response.status_code, 403)
|
||||||
|
|
||||||
|
# Check that the domain request still exists
|
||||||
|
self.assertTrue(DomainRequest.objects.filter(pk=domain_request.pk).exists())
|
||||||
|
domain_request.delete()
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
@override_flag("organization_feature", active=True)
|
||||||
|
@override_flag("organization_requests", active=True)
|
||||||
|
def test_org_user_cannot_delete_others_domain_requests(self):
|
||||||
|
"""Test that an org user with edit permission cannot delete DomainRequests they did not create."""
|
||||||
|
|
||||||
|
# Assign the user to a portfolio with edit permission
|
||||||
|
UserPortfolioPermission.objects.get_or_create(
|
||||||
|
user=self.user,
|
||||||
|
portfolio=self.portfolio,
|
||||||
|
roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER],
|
||||||
|
additional_permissions=[UserPortfolioPermissionChoices.EDIT_REQUESTS],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create another user and a domain request
|
||||||
|
other_user = User.objects.create(username="other_user")
|
||||||
|
domain_request = completed_domain_request(
|
||||||
|
name="test-domain.gov",
|
||||||
|
status=DomainRequest.DomainRequestStatus.STARTED,
|
||||||
|
portfolio=self.portfolio,
|
||||||
|
)
|
||||||
|
domain_request.creator = other_user
|
||||||
|
domain_request.save()
|
||||||
|
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
# Perform delete as self.user
|
||||||
|
response = self.client.post(reverse("domain-request-delete", kwargs={"pk": domain_request.pk}), follow=True)
|
||||||
|
|
||||||
|
# Check response is 403 Forbidden
|
||||||
|
self.assertEqual(response.status_code, 403)
|
||||||
|
|
||||||
|
# Check that the domain request still exists
|
||||||
|
self.assertTrue(DomainRequest.objects.filter(pk=domain_request.pk).exists())
|
||||||
|
domain_request.delete()
|
||||||
|
|
|
@ -796,6 +796,12 @@ class DomainRequestDeleteView(DomainRequestPermissionDeleteView):
|
||||||
if status not in valid_statuses:
|
if status not in valid_statuses:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Portfolio users cannot delete their requests if they aren't permissioned to do so
|
||||||
|
if self.request.user.is_org_user(self.request):
|
||||||
|
portfolio = self.request.session.get("portfolio")
|
||||||
|
if not self.request.user.has_edit_request_portfolio_permission(portfolio):
|
||||||
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
|
|
|
@ -25,9 +25,8 @@ def get_domain_requests_json(request):
|
||||||
paginator = Paginator(objects, 10)
|
paginator = Paginator(objects, 10)
|
||||||
page_number = request.GET.get("page", 1)
|
page_number = request.GET.get("page", 1)
|
||||||
page_obj = paginator.get_page(page_number)
|
page_obj = paginator.get_page(page_number)
|
||||||
|
|
||||||
domain_requests = [
|
domain_requests = [
|
||||||
serialize_domain_request(domain_request, request.user) for domain_request in page_obj.object_list
|
serialize_domain_request(request, domain_request, request.user) for domain_request in page_obj.object_list
|
||||||
]
|
]
|
||||||
|
|
||||||
return JsonResponse(
|
return JsonResponse(
|
||||||
|
@ -90,13 +89,22 @@ def apply_sorting(queryset, request):
|
||||||
return queryset.order_by(sort_by)
|
return queryset.order_by(sort_by)
|
||||||
|
|
||||||
|
|
||||||
def serialize_domain_request(domain_request, user):
|
def serialize_domain_request(request, domain_request, user):
|
||||||
# Determine if the request is deletable
|
|
||||||
is_deletable = domain_request.status in [
|
deletable_statuses = [
|
||||||
DomainRequest.DomainRequestStatus.STARTED,
|
DomainRequest.DomainRequestStatus.STARTED,
|
||||||
DomainRequest.DomainRequestStatus.WITHDRAWN,
|
DomainRequest.DomainRequestStatus.WITHDRAWN,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Determine if the request is deletable
|
||||||
|
if not user.is_org_user(request):
|
||||||
|
is_deletable = domain_request.status in deletable_statuses
|
||||||
|
else:
|
||||||
|
portfolio = request.session.get("portfolio")
|
||||||
|
is_deletable = (
|
||||||
|
domain_request.status in deletable_statuses and user.has_edit_request_portfolio_permission(portfolio)
|
||||||
|
) and domain_request.creator == user
|
||||||
|
|
||||||
# Determine action label based on user permissions and request status
|
# Determine action label based on user permissions and request status
|
||||||
editable_statuses = [
|
editable_statuses = [
|
||||||
DomainRequest.DomainRequestStatus.STARTED,
|
DomainRequest.DomainRequestStatus.STARTED,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue