Created
September 20, 2013 15:22
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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