Skip to content

Commit

Permalink
fix permissions for API user endpoint (#1256)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeriox authored Apr 4, 2024
1 parent bb987b8 commit 273cdd0
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 6 deletions.
23 changes: 23 additions & 0 deletions ephios/api/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from rest_framework.permissions import DjangoModelPermissions, DjangoObjectPermissions


class ViewPermissionsMixin:
# DjangoModelPermissions and DjangoObjectPermissions only check permissions for write/unsafe operations.
# This mixin adds permissions for read/safe operations.
perms_map = {
"GET": ["%(app_label)s.view_%(model_name)s"],
"OPTIONS": [],
"HEAD": [],
"POST": ["%(app_label)s.add_%(model_name)s"],
"PUT": ["%(app_label)s.change_%(model_name)s"],
"PATCH": ["%(app_label)s.change_%(model_name)s"],
"DELETE": ["%(app_label)s.delete_%(model_name)s"],
}


class ViewPermissions(ViewPermissionsMixin, DjangoModelPermissions):
pass


class ViewObjectPermissions(ViewPermissionsMixin, DjangoObjectPermissions):
pass
9 changes: 3 additions & 6 deletions ephios/api/views/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@
from rest_framework.filters import SearchFilter
from rest_framework.generics import RetrieveAPIView
from rest_framework.mixins import RetrieveModelMixin
from rest_framework.permissions import DjangoObjectPermissions
from rest_framework.relations import SlugRelatedField
from rest_framework.schemas.openapi import AutoSchema
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from rest_framework_guardian.filters import ObjectPermissionsFilter

from ephios.api.filters import ParticipationFilterSet, ParticipationPermissionFilter
from ephios.api.permissions import ViewPermissions
from ephios.api.views.events import ParticipationSerializer
from ephios.core.models import LocalParticipation, Qualification, UserProfile
from ephios.core.services.qualification import collect_all_included_qualifications
Expand Down Expand Up @@ -78,23 +77,21 @@ def get_object(self):
class UserViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = UserProfileSerializer
queryset = UserProfile.objects.all()
permission_classes = [IsAuthenticatedOrTokenHasScope, DjangoObjectPermissions]
permission_classes = [IsAuthenticatedOrTokenHasScope, ViewPermissions]
required_scopes = ["CONFIDENTIAL_READ"]
search_fields = ["display_name", "email"]

filter_backends = [
DjangoFilterBackend,
SearchFilter,
ObjectPermissionsFilter,
]


class UserByMailView(RetrieveModelMixin, GenericViewSet):
serializer_class = UserProfileSerializer
queryset = UserProfile.objects.all()
permission_classes = [IsAuthenticatedOrTokenHasScope, DjangoObjectPermissions]
permission_classes = [IsAuthenticatedOrTokenHasScope, ViewPermissions]
required_scopes = ["CONFIDENTIAL_READ"]
filter_backends = [ObjectPermissionsFilter]
lookup_url_kwarg = "email"
lookup_field = "email"
lookup_value_regex = "[^/]+" # customize to allow dots (".") in the lookup value
Expand Down
10 changes: 10 additions & 0 deletions tests/api/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,13 @@ def test_api_user_profile_by_email(django_app, superuser):
user=superuser,
)
assert superuser.email in response


def test_manager_can_view_users(django_app, groups, manager):
response = django_app.get(reverse("api:userprofile-list"), user=manager)
assert manager.email in response


def test_volunter_cannot_view_users(django_app, groups, volunteer):
response = django_app.get(reverse("api:userprofile-list"), user=volunteer, expect_errors=True)
assert response.status_code == 403

0 comments on commit 273cdd0

Please sign in to comment.