Skip to content

Support for custom getter of delegated objects

Latest
Compare
Choose a tag to compare
@mesemus mesemus released this 01 Jun 04:53
· 7 commits to master since this release

This getter is usable for checking permissions of "create" methods, especially in combination with rest_framework_nested.

Real world example

In the example below, EducationAreaViewSet is nested inside the StudyProgrammeViewSet (study programme has many education areas). The url of the EducationAreaViewSet is:

/programmes/<programme_pk>/education-areas/...

We want all operations on EducationArea to be checked against the containing StudyProgramme.
To differentiate the actions (such as update) on EducationArea and on StudyProgramme in permission handlers defined on StudyProgramme we map all operations on EducationArea to a virtual 'edit_education_area' action and send this to StudyProgramme permissions instead. The mapping parameter can be a dict if one needs to differentiate the actions.

from rest_delegated_permissions import DelegatedPermission, kwargs_delegated_object_getter
from rest_framework_nested import routers
from angular_dynamic_forms import AngularFormMixin, autocomplete, AutoCompleteMixin

@perms.apply(permissions=[
    DelegatedPermission(perms, 'programmes', mapping='edit_education_area',
                        delegated_objects_getter=kwargs_delegated_object_getter(
                            {'programmes': 'programme_pk'}
                        )),
])
class EducationAreaViewSet(AutoCompleteMixin, AngularFormMixin, viewsets.ModelViewSet):
    # its 'programmes' m2m point to StudyProgramme model
    model = EducationArea     
    serializer_class = EducationAreaSerializer
    ...

@perms.apply(permissions=[
    OpenIDPermission('http://vscht.cz/openid#permission-studyprogrammes-edit',
                     perms={..., 'edit_education_area', ...}),
    OwnerPermission(owner_username_path='studyprogrammepersonrole__person__user__username',
                    extra_filter=Q(studyprogrammepersonrole__role__in=(
                            StudyProgrammePersonRole.GUARANTEE,
                            StudyProgrammePersonRole.COOPERATING
                    )),
                    perms={... 'edit_education_area' ...})
    AuthenticatedReadPermission()
])
class StudyProgrammeViewSet(...)
...

programmes_router = DefaultRouter()
programmes_router.register(r'programmes', StudyProgrammeViewSet)

education_area_router = routers.NestedSimpleRouter(programmes_router,
    r'accreditations/study_programme/programmes', lookup='programme')
education_area_router.register(r'education-areas', EducationAreaViewSet,
    base_name='study-programmes-education-areas')