1

I have a project in which there are workspaces, and each workspace can have any number of users. Users can also belong to multiple workspaces, so there's a many-to-many relationship between them.

Now, I have workspace creation and membership working, but I'm having trouble setting the permissions so that only the workspace members can see the workspace. I've tried with a custom object-level permission, but it doesn't seem to work.

The workspace model looks like this:

class Workspace(models.Model):
    name = models.CharField(max_length=100)
    users = models.ManyToManyField(User, related_name='workspaces')

The view looks like this:

class WorkspaceViewSet(viewsets.ModelViewSet):
    queryset = Workspace.objects.all().order_by('name')
    serializer_class = WorkspaceSerializer
    permission_classes = [permissions.IsAuthenticated|BelongsInWorkspace]

The serializer is like this:

class WorkspaceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Workspace
        fields = ('name', 'users')

    def create(self, validated_data):
        instance = super(WorkspaceSerializer, self)
        instance.users.add(self.context['request'].user)
        return instance

And finally, the custom permission I'm trying to use here:

class BelongsInWorkspace(BasePermission):
    def has_permission(self, request, view):
        return True

    def has_object_permission(self, request, view, obj):
        return obj.users.filter(pk=request.user).exists()
manabreak
  • 5,415
  • 7
  • 39
  • 96

1 Answers1

1

I would highly recommend django-guardian to handle this problem. Django-guardian allows for straightforward, object-level permission management.

To handle your problem, all you would need to do is add a Meta class to your workspace model, where you can create custom permissions.

 class Workspace(models.Model):
    name = models.CharField(max_length=100)
    users = models.ManyToManyField(User, related_name='workspaces')

    class Meta:
        default_permissions = ('add', 'change', 'delete')
        permissions = (
                ('access_workspace', 'Access workspace'),
                )

Assign either a user or a group that permission, attached to a specific workspace.

assign_perm('access_workspace', user, workspace)

#This will return True if the user has been properly assigned the permission
user.has_perm('access_workspace', workspace)

Then to get all workspaces a user has access to, you would just need to call get_objects_for_user() in your view

queryset = get_objects_for_user(self.request.user, 'project.access_workspace')
SourPatchAdult
  • 179
  • 2
  • 9