Skip to content

Commit

Permalink
more robust approach to permission handling in loader tag
Browse files Browse the repository at this point in the history
  • Loading branch information
chris committed Dec 8, 2009
1 parent 298173f commit c3b3987
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 15 deletions.
48 changes: 48 additions & 0 deletions djtracker/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from django.contrib.auth.models import User, Group
from django.core.urlresolvers import reverse

from djtracker.utils import check_perms

class UserProfile(models.Model):
"""
Extension of User to allow for more detailed information about a
Expand All @@ -22,6 +24,40 @@ def __unicode__(self):
def get_absolute_url(self):
return ("project_user", (), {'username': self.user.username})

def get_allowed_project_ids(request, user=None, permission='view'):
"""
returns a list of project ids which request.user is allowed to see
"""
project_ids = []
perm_index = ['view', 'edit', 'comment'].index(permission)
# need to reference Project indirectly to avoid circular import reference
for project in models.get_model('djtracker','project').objects.all():
perms = check_perms(request, project, user)
if perms[perm_index]:
project_ids.append(project.id)
return project_ids

class PermissionFilterManager(models.Manager):
"""
a manager which adds a special permission filter. usage:
in queries, replace
model_class.objects.all()
with
model_class.objects.filter_allowed(request)
"""
def __init__(self, by='project__id__in', *args, **kwargs):
"""
``by`` determines on which attribute to filter (default: project)
"""
self._by = by
super(PermissionFilterManager, self).__init__(*args, **kwargs)

def filter_allowed(self, request, permission='view'):
project_ids = get_allowed_project_ids(request, permission)
if self._by:
return self.filter(**{self._by: project_ids})

class Project(models.Model):
"""
Projects are the central location of where everything comes together. An
Expand Down Expand Up @@ -109,6 +145,8 @@ def __unicode__(self):
def get_absolute_url(self):
return ("project_index", (), {'project_slug': self.slug})

objects = PermissionFilterManager(by='id__in')

class Milestone(models.Model):
"""
Goal to be reached
Expand All @@ -130,6 +168,8 @@ def get_absolute_url(self):
return ("project_milestone", (), {'project_slug': self.project.slug,
'modi_slug': self.slug})

objects = PermissionFilterManager()

class Component(models.Model):
"""
Components are items that are part of a project. For instance I have a
Expand All @@ -150,6 +190,8 @@ def get_absolute_url(self):
return ("project_component", (), {'project_slug': self.project.slug,
'modi_slug': self.slug})

objects = PermissionFilterManager()

class Version(models.Model):
"""
This will be FKed to projects. This will allow creation of issues
Expand All @@ -170,6 +212,8 @@ def get_absolute_url(self):
return ("project_version", (), {'project_slug': self.project.slug,
'modi_slug': self.slug})

objects = PermissionFilterManager()

class Status(models.Model):
"""
Status dictate what status an issue is in, such as open, closed, etc
Expand Down Expand Up @@ -267,6 +311,8 @@ def get_absolute_url(self):
return ("project_issue", (), {'project_slug': self.project.slug,
'issue_id': self.id})

objects = PermissionFilterManager()

class FileUpload(models.Model):
"""
File uploads will be FKed to specific issues. This will allow for
Expand All @@ -286,6 +332,8 @@ def get_absolute_url(self):
return ("project_issue_file", (), {'project_slug': self.issue.project.slug,
'file_id': self.id})

objects = PermissionFilterManager(by='issue__project__id__in')

class IssueFilter(models.Model):
"""
This allows users to save their favorite view filters
Expand Down
21 changes: 6 additions & 15 deletions djtracker/templatetags/get_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,15 @@ def render(self, context):
except:
raise TemplateSyntaxError, "Failed to retrieve model"

object_list = model.objects.all()
if request and hasattr(model.objects, 'filter_allowed'):
object_list = model.objects.filter_allowed(request)
else:
object_list = model.objects.all()

object_list = object_list.order_by(self.sort)
if object_list.count() > self.count:
object_list = object_list[:self.count]
project_ids = []
for x in object_list:
if hasattr(x, "allow_anon_viewing") and request:
can_view, can_edit, can_comment = utils.check_perms(request, x)
if can_view:
project_ids.append(x.id)
object_list = model.objects.filter(id__in=project_ids)
issue_ids = []
for x in object_list:
if hasattr(x, "assigned_to") and request:
can_view, can_edit, can_comment = utils.check_perms(request, x.project)
if can_view:
issue_ids.append(x.id)
object_list = model.objects.filter(id__in=issue_ids)

context.update({self.var_name: object_list})
return ''

Expand Down

0 comments on commit c3b3987

Please sign in to comment.