Skip to content

Instantly share code, notes, and snippets.

@g-cassie
Last active August 29, 2015 14:27
Show Gist options
  • Save g-cassie/001e126838d3f1db0a6f to your computer and use it in GitHub Desktop.
Save g-cassie/001e126838d3f1db0a6f to your computer and use it in GitHub Desktop.
# this uses the models setout in this gist: https://gist.github.com/g-cassie/6b9b0f29371677f48659
from projects.models import Project, User, UserProjectAccess
class UserProjectChildProfile(permissions.Profile):
# ProjectChild refers to any model that has a ForeignKey to Project
def __init__(self, request):
self.user = request.user
def get_queryset_filters(self, request, queryset):
# allows you to return Q objects to filter down a queryset
# this is how you can control what objects a user can see
# we don't modify queryset directly because there may be multiple
# permission profiles that the user falls into
# e.g. if a user is an admin for their organization they can see all their orgs stuff
# they might also be able to see projects in another organization that they were invited to
return queryset.filter(project__users=self.user)
def can_create(self, serializer):
# a final permissions check once a serializer has been validated
# allows you to prevent users from creating objects with specific attributes
# e.g. cannot create an object in a project they do not have access to
try:
a = UserProjectAccess.objects.get(project=serializer.validated_data['project'], user=self.user)
except UserProjectAccess.DoesNotExist:
return False
return a.role in [UserProjectAccess.EDITOR, UserProjectAccess.ADMIN]
def can_edit(self, serializer, obj):
# same idea as can_create
# we get the actual obj being modified as well as the serializer about to be saved
# e.g. user cannot move an object into a project they do not belong to
try:
a = UserProjectAccess.objects.get(project=serializer.validated_data['project'], user=self.user)
except UserProjectAccess.DoesNotExist:
return False
return a.role in [UserProjectAccess.EDITOR, UserProjectAccess.ADMIN]
## another example, user cannot set is_trashed=True if they are not an admin
if obj.is_trashed == False and serializer.validated_data['is_trashed'] == True:
return a.role == UserProjectAccess.ADMIN
def can_delete(self, obj):
# similar idea to can_create but we get the actual
# e.g. user can only delete objects they created
return obj.creator == self.user
class AdminProjectChildProfile(permissions.Profile):
def get_queryset_filters(self, request):
return Q(project__organizations=user.organization)
def can_delete(self, obj):
# admins can always delete
# if multiple profiles are available, you just need one profile to return True on a "can_" function
# and the request will be permitted.
# i.e. admins can always delete even if UserProjectChildProfile.can_delete returns False
return True
class ProjectChildViewSet(viewsets.ModelViewSet):
permission_profiles = [AdminProjectChildProfile, UserProjectChildProfile]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment