Skip to content

Instantly share code, notes, and snippets.

@develmaycare
Created September 20, 2013 15:22
Show Gist options
  • Save develmaycare/6639176 to your computer and use it in GitHub Desktop.
Save develmaycare/6639176 to your computer and use it in GitHub Desktop.
This is an example of complex object-level permissions using django-guardian. This is from a real-world project, and the problem that I see is the large number of queries required to assign permissions. See https://gist.github.com/bogeymin/6639293 for an example of solving this in a somewhat unorthodox, but simple way.
class Project(models.Model):
added_by = models.ForeignKey(User, related_name="added_by_projects")
assigned_to = models.ForeignKey(User, related_name="assigned_to_projects")
owned_by = models.ForeignKey(User, related_name="owned_by_projects")
is_private = models.BooleanField()
all_access = models.BooleanField()
departments = models.ForeignKey(Department)
restrict_access_by_default = models.BooleanField()
team_members = models.ManyToManyField(User, related_name="team_projects")
class Meta:
# An "all" permission helps reduce the number of queries, but probably isn't desirable for every assignment.
permissions = (("all_for_project", "All Permissions for Project"),)
def save(self, *args, **kwargs):
super(Project, self).save(*args, **kwargs)
if self.is_private:
assign_perm(self.added_by, "all_for_project", self)
elif self.all_access:
try:
group = Group.object.get(name="Everyone")
assign_perm(group, 'all_for_project', self)
except Group.DoesNotExist:
# Would need to alert the user that the Everyone group does not exist.
pass
else:
assign_perm(self.added_by, 'all_for_project', self)
if self.assigned_to:
assign_perm(self.assigned_to, 'all_for_project', self)
if self.owned_by:
assign_perm(self.assigned_to, 'all_for_project', self)
# This is only a positive assignement -- what about groups that
# were previously assigned, but have been removed? Also, we could
# directly connect a Django group to a department via ForeignKey
# to eliminate the query for the department-group m2m.
if self.departments and self.restrict_access_to_departments:
for department in self.departments:
try:
group = DepartmentJoinGroup.objects.get(department=self.department).group
assign_perm(group, 'all_for_project', self)
except DepartmentJoinGroup.DoesNotExist:
pass
# This is only a positive assignment -- what about team members
# that were previously assigned, but have been removed from the
# team?
if self.team_members:
for user in self.team_members:
assign_perm(user, 'all_for_project', self)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment