Limiting access to data through user permissions?

8 views
Skip to first unread message

Will Meyers

unread,
Jul 10, 2020, 12:04:19 PM7/10/20
to Django users

Just need some help getting over a wall I've hit.

I have a web application that whenever a user signs up, is assigned a License. This License has CustomPermissions attached to it telling what values of a field within a materialized view they have access to. I have an API that needs to filter data requested against the User who requested it based on the User's license. I drafted some example models below that outlines my problem.

class CustomPermission(models.Model):
    name = models.CharField(max_length=255)
    field = models.CharField(max_length=255)
    value = models.CharField(max_length=255)

class License(models.Model):
    name = models.CharField(max_length=255)
    permissions = models.ManyToManyField(CustomPermissions)
    ...

class User(AbstractBaseUser):
    license = models.ForeignKey(License, on_delete=models.CASCADE)
    ...

This works fine if I'm only filtering columns with text values. I can just do

...
user = request.user
permissions = user.license.permissions.values_list('field', 'value')
return queryset.objects.filter(**{field: value for field, value in permissions})

This issue is that I cannot filter against other datatypes (datetimes for example). If I wanted to limit access to data published in the last 90 days for example, there's no way to represent that in this model.

To solve this I was thinking of using a sparse table for the CustomPermission model. Something like

class CustomPermission(models.Model):
    name = models.CharField(max_length=255)
    field = models.CharField(max_length=255)
    operation = models.CharField(max_length='32')
    text_value = models.CharField(max_length=255, null=True, blank=True)
    date_value = models.DateField(null=True, blank=True)

Where operation would be equal to '__gt', '__lt', ... things like that. I can then just do something similar as before

...
user = request.user
permissions = user.license.permissions.values_list('field', 'operation', 'text_value', 'date_value')
return queryset.objects.filter(**{fld + op: txt_val or dat_val for fld, op, txt_val, dat_val in permissions})

But this does not feel right, and can get messy quickly. Any suggestions?

Reply all
Reply to author
Forward
0 new messages