Skip to content

Commit

Permalink
Check who can access /providers/{id}/edit
Browse files Browse the repository at this point in the history
  • Loading branch information
tortila committed Sep 27, 2023
1 parent 0c9fd30 commit 0eb49ca
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 24 deletions.
56 changes: 56 additions & 0 deletions apps/accounts/tests/test_provider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import pytest

from django.urls import reverse
from waffle.testutils import override_flag
from apps.greencheck.factories import UserFactory


@pytest.mark.django_db
@override_flag("provider_request", active=True)
def test_edit_view_accessible_by_user_with_required_perms(
client, hosting_provider_with_sample_user, sample_hoster_user
):
# given: existing hosting provider with assigned user
# when: accessing its edit view by that user
client.force_login(sample_hoster_user)
response = client.get(
reverse("provider_edit", args=[str(hosting_provider_with_sample_user.id)])
)

# then: page for the correct provider request is rendered
assert response.status_code == 200


@pytest.mark.django_db
@override_flag("provider_request", active=True)
def test_edit_view_accessible_by_admins(
client, hosting_provider_with_sample_user, greenweb_staff_user
):
# given: existing hosting provider with assigned user
# when: accessing its edit view by GWF staff
client.force_login(greenweb_staff_user)
response = client.get(
reverse("provider_edit", args=[str(hosting_provider_with_sample_user.id)])
)

# then: page for the correct provider request is rendered
assert response.status_code == 200


@pytest.mark.django_db
@override_flag("provider_request", active=True)
def test_edit_view_inaccessible_by_unauthorized_users(
client, hosting_provider_with_sample_user
):
# given: existing hosting provider with assigned user
# when: accessing its edit view by another user
another_user = UserFactory.build()
another_user.save()

client.force_login(another_user)
response = client.get(
reverse("provider_edit", args=[str(hosting_provider_with_sample_user.id)])
)

# then: user is redirected to the provider portal
assert response.status_code == 302
2 changes: 1 addition & 1 deletion apps/accounts/tests/test_provider_portal.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def test_provider_portal_home_view_filters_out_removed_requests(client):
# and to visit as that user
user = removed_request.created_by

# given: 1 approved verification request
# given: 1 pending verification request
pending_request = ProviderRequestFactory.create(
created_by=user, status=ProviderRequestStatus.PENDING_REVIEW
)
Expand Down
71 changes: 48 additions & 23 deletions apps/accounts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
ProviderRequestEvidence,
ProviderRequestIPRange,
)
from .permissions import manage_provider
from .utils import send_email

import logging
Expand Down Expand Up @@ -283,32 +284,56 @@ class Steps(Enum):

def dispatch(self, request, *args, **kwargs):
"""
Overwrite method from TemplateView to decide for which users
to render a 404 page
This view is re-used for 3 different use cases:
- /requests/new to submit a new verification request
- /requests/{request_id}/edit to edit an existing request
- /providers/{provider_id}/edit to edit an existing provider
This method catches all the cases in which users should be stopped
(e.g. lack of permissions or nonexistent objects) by raising exceptions
and using HTTP redirects.
It will proceed (by calling the same method on the parent class)
if no issue was found.
"""
request_id = kwargs.get("request_id")
provider_id = kwargs.get("provider_id")

# all users can access this view to create a new request
if not request_id:
return super().dispatch(request, *args, **kwargs)

# edit view can be only accessed for existing PRs
try:
pr = ProviderRequest.objects.get(id=request_id)
except ProviderRequest.DoesNotExist:
raise Http404("Page not found")

if pr.status != ProviderRequestStatus.OPEN:
messages.error(
self.request, "This verification request cannot be edited at this time"
)
return HttpResponseRedirect(
reverse("provider_request_detail", args=[pr.pk])
)

# only admins and creators can access for editing existing requests
if not request.user.is_admin and request.user.id != pr.created_by.id:
raise Http404("Page not found")
if provider_id:
# edit view can be only accessed for existing Providers
try:
hp = Hostingprovider.objects.get(id=provider_id)
except Hostingprovider.DoesNotExist:
raise Http404("Page not found")

# only users with object-level perms for provider can access its edit view
if (
not request.user.has_perm(manage_provider.full_name, hp)
and not request.user.is_admin
):
messages.error(
self.request,
"You don't have the required permission to edit this listing",
)
return HttpResponseRedirect(reverse("provider_portal_home"))
elif request_id:
# edit view can be only accessed for existing PRs
try:
pr = ProviderRequest.objects.get(id=request_id)
except ProviderRequest.DoesNotExist:
raise Http404("Page not found")

# only OPEN requests are editable
if pr.status != ProviderRequestStatus.OPEN:
messages.error(
self.request,
"This verification request cannot be edited at this time",
)
return HttpResponseRedirect(
reverse("provider_request_detail", args=[pr.pk])
)
# only admins and creators can access for editing existing requests
if not request.user.is_admin and request.user.id != pr.created_by.id:
raise Http404("Page not found")

return super().dispatch(request, *args, **kwargs)

Expand Down

0 comments on commit 0eb49ca

Please sign in to comment.