From a36a130998b4fe4b651c482cf4b935601de9941b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 22 Mar 2013 17:52:18 +0100 Subject: [PATCH] Working on permissions and groups generation --- greenmine/base/permissions.py | 65 -------------------------------- greenmine/profile/models.py | 9 ++++- greenmine/profile/services.py | 23 +++++++++++ greenmine/profile/sigdispatch.py | 10 ++++- greenmine/scrum/admin.py | 12 ++---- greenmine/scrum/api.py | 10 +---- greenmine/scrum/models.py | 54 +++----------------------- greenmine/scrum/sigdispatch.py | 19 ++-------- greenmine/urls.py | 1 - 9 files changed, 53 insertions(+), 150 deletions(-) delete mode 100644 greenmine/base/permissions.py create mode 100644 greenmine/profile/services.py diff --git a/greenmine/base/permissions.py b/greenmine/base/permissions.py deleted file mode 100644 index e09e7efd..00000000 --- a/greenmine/base/permissions.py +++ /dev/null @@ -1,65 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import absolute_import - -# FIXME: move this file to base. - -from greenmine.profile.models import Role -from greenmine.scrum.models import ProjectUserRole - - -def get_role(name): - """ - Helper method for a get role object - finding by name. - """ - return Role.objects.get(slug=name) - - -def has_perm(user, project, loc, perm, pur=None): - """ - Checks if a user has a concrete permission on - a project. - """ - - if not pur: - try: - pur = ProjectUserRole.objects.get(project=project, user=user) - except ProjectUserRole.DoesNotExist: - return False - - return getattr(pur.role, '%s_%s' % (loc.lower(), perm.lower()), False) - - -def has_perms(user, project, perms=[]): - """ - Check a group of permissions in a single call. - """ - - if user.is_superuser: - return True - - if project.owner == user: - return True - - try: - pur, valid = ProjectUserRole.objects\ - .get(project=project, user=user), True - except ProjectUserRole.DoesNotExist: - return False - - for pitem in perms: - if len(pitem) != 2: - continue - - loc, locperms = pitem - if not isinstance(locperms, (list, tuple)): - locperms = [locperms] - - valid = False not in [has_perm(user, project, loc, locperm, pur=pur) - for locperm in locperms] - - if not valid: - break - - return valid diff --git a/greenmine/profile/models.py b/greenmine/profile/models.py index 850ee31e..4f950b8e 100644 --- a/greenmine/profile/models.py +++ b/greenmine/profile/models.py @@ -2,7 +2,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ -from django.contrib.auth.models import Permission +from django.contrib.auth.models import Permission, Group class Profile(models.Model): @@ -26,5 +26,12 @@ class Role(models.Model): permissions = models.ManyToManyField(Permission, verbose_name=_('permissions'), blank=True) + def __unicode__(self): + return unicode(self.name) + +if not hasattr(Group, 'role'): + field = models.ForeignKey(Role, blank=False, null=False, related_name='groups') + field.contribute_to_class(Group, 'role') + from . import sigdispatch diff --git a/greenmine/profile/services.py b/greenmine/profile/services.py new file mode 100644 index 00000000..e5509fe7 --- /dev/null +++ b/greenmine/profile/services.py @@ -0,0 +1,23 @@ +from django.contrib.auth.models import Group + +from greenmine.scrum.models import Project + +class RoleGroupsService(object): + def replicate_role_on_all_projects(self, role): + for group in role.groups.all(): + self._replicate_role_permissions_on_group(role, group) + for project in Project.objects.all(): + self._replicate_role_on_project_if_needed(role, project) + + def _replicate_role_permissions_on_group(self, role, group): + group.permissions.clear() + for permission in role.permissions.all(): + group.permissions.add(permission) + group.save() + + def _replicate_role_on_project_if_needed(self, role, project): + if project.groups.filter(role=role).count() == 0: + group = Group(name="p%d-r%d" % (project.pk, role.pk), role=role) + group.save() + role.groups.add(group) + self._replicate_role_permissions_on_group(role, group) diff --git a/greenmine/profile/sigdispatch.py b/greenmine/profile/sigdispatch.py index 5027c0e7..be79a2a4 100644 --- a/greenmine/profile/sigdispatch.py +++ b/greenmine/profile/sigdispatch.py @@ -6,7 +6,8 @@ from django.db.models.signals import post_save from django.dispatch import receiver from django.contrib.auth.models import User -from .models import Profile +from .models import Profile, Role +from .services import RoleGroupsService @receiver(post_save, sender=User) @@ -16,3 +17,10 @@ def user_post_save(sender, instance, created, **kwargs): """ if created and not Profile.objects.filter(user=instance).exists(): Profile.objects.create(user=instance) + +@receiver(post_save, sender=Role) +def role_post_save(sender, instance, created, **kwargs): + """ + Recalculate projects groups + """ + RoleGroupsService().replicate_role_on_all_projects(instance) diff --git a/greenmine/scrum/admin.py b/greenmine/scrum/admin.py index 8d97c49f..96f63725 100644 --- a/greenmine/scrum/admin.py +++ b/greenmine/scrum/admin.py @@ -1,11 +1,13 @@ # -*- coding: utf-8 -*- from django.contrib import admin -from greenmine.scrum.models import Project, ProjectExtras, ProjectUserRole, \ +from guardian.admin import GuardedModelAdmin + +from greenmine.scrum.models import Project, ProjectExtras, \ Milestone, UserStory, Change, ChangeAttachment, Task -class ProjectAdmin(admin.ModelAdmin): +class ProjectAdmin(GuardedModelAdmin): list_display = ["name", "owner"] admin.site.register(Project, ProjectAdmin) @@ -17,12 +19,6 @@ class ProjectExtrasAdmin(admin.ModelAdmin): admin.site.register(ProjectExtras, ProjectExtrasAdmin) -class ProjectUserRoleAdmin(admin.ModelAdmin): - list_display = ["project", "user", "role"] - -admin.site.register(ProjectUserRole, ProjectUserRoleAdmin) - - class MilestoneAdmin(admin.ModelAdmin): list_display = ["name", "project", "owner"] diff --git a/greenmine/scrum/api.py b/greenmine/scrum/api.py index 709b7257..b60c990a 100644 --- a/greenmine/scrum/api.py +++ b/greenmine/scrum/api.py @@ -3,7 +3,7 @@ from tastypie.resources import ModelResource from tastypie.authentication import SessionAuthentication from tastypie.authorization import DjangoAuthorization -from greenmine.scrum.models import Project, ProjectUserRole, \ +from greenmine.scrum.models import Project, \ Milestone, UserStory, Change, ChangeAttachment, Task @@ -15,14 +15,6 @@ class ProjectResource(ModelResource): authorization = DjangoAuthorization() -class ProjectUserRoleResource(ModelResource): - class Meta: - queryset = ProjectUserRole.objects.all() - resource_name = 'projectuserrole' - authentication = SessionAuthentication() - authorization = DjangoAuthorization() - - class MilestoneResource(ModelResource): class Meta: queryset = Milestone.objects.all() diff --git a/greenmine/scrum/models.py b/greenmine/scrum/models.py index 29052bc2..8149691b 100644 --- a/greenmine/scrum/models.py +++ b/greenmine/scrum/models.py @@ -23,11 +23,6 @@ class ProjectManager(models.Manager): def get_by_natural_key(self, slug): return self.get(slug=slug) - def can_view(self, user): - queryset = ProjectUserRole.objects.filter(user=user)\ - .values_list('project', flat=True) - return Project.objects.filter(pk__in=queryset) - class ProjectExtras(models.Model): task_parser_re = models.CharField(max_length=1000, blank=True, null=True, default=None) @@ -60,12 +55,10 @@ class Project(models.Model): modified_date = models.DateTimeField(auto_now_add=True) owner = models.ForeignKey("auth.User", related_name="projects") - participants = models.ManyToManyField('auth.User', - related_name="projects_participant", - through="ProjectUserRole", + groups = models.ManyToManyField('auth.Group', + related_name="projects", null=True, blank=True) - public = models.BooleanField(default=True) markup = models.CharField(max_length=10, choices=MARKUP_TYPE, default='md') extras = models.OneToOneField("ProjectExtras", related_name="project", null=True, default=None) @@ -143,8 +136,7 @@ class Project(models.Model): @property def all_participants(self): - qs = ProjectUserRole.objects.filter(project=self) - return User.objects.filter(id__in=qs.values_list('user__pk', flat=True)) + return User.objects.filter(group__in=self.groups) @property def default_milestone(self): @@ -161,44 +153,6 @@ class Project(models.Model): super(Project, self).save(*args, **kwargs) - def add_user(self, user, role): - from greenmine.base import permissions - return ProjectUserRole.objects.create( - project=self, - user=user, - role=permissions.get_role(role), - ) - - -class ProjectUserRole(models.Model): - project = models.ForeignKey("Project", related_name="user_roles") - user = models.ForeignKey("auth.User", related_name="user_roles") - role = models.ForeignKey("profile.Role", related_name="user_roles") - - mail_milestone_created = models.BooleanField(default=True) - mail_milestone_modified = models.BooleanField(default=False) - mail_milestone_deleted = models.BooleanField(default=False) - mail_userstory_created = models.BooleanField(default=True) - mail_userstory_modified = models.BooleanField(default=False) - mail_userstory_deleted = models.BooleanField(default=False) - mail_task_created = models.BooleanField(default=True) - mail_task_assigned = models.BooleanField(default=False) - mail_task_deleted = models.BooleanField(default=False) - mail_question_created = models.BooleanField(default=False) - mail_question_assigned = models.BooleanField(default=True) - mail_question_deleted = models.BooleanField(default=False) - mail_document_created = models.BooleanField(default=True) - mail_document_deleted = models.BooleanField(default=False) - mail_wiki_created = models.BooleanField(default=False) - mail_wiki_modified = models.BooleanField(default=False) - mail_wiki_deleted = models.BooleanField(default=False) - - def __repr__(self): - return u"" % (self.id) - - class Meta: - unique_together = ('project', 'user') - class MilestoneManager(models.Manager): def get_by_natural_key(self, name, project): @@ -317,8 +271,10 @@ class UserStory(models.Model): client_requirement = models.BooleanField(default=False) team_requirement = models.BooleanField(default=False) + order = models.PositiveSmallIntegerField("Order") class Meta: + ordering = ['order'] unique_together = ('ref', 'project') def __repr__(self): diff --git a/greenmine/scrum/sigdispatch.py b/greenmine/scrum/sigdispatch.py index 9e6c24c9..01ee5efb 100644 --- a/greenmine/scrum/sigdispatch.py +++ b/greenmine/scrum/sigdispatch.py @@ -7,7 +7,6 @@ from django.template.loader import render_to_string from django.contrib.auth.models import User -from greenmine.scrum.models import ProjectUserRole from greenmine.base import signals from greenmine.base.utils.auth import set_token from greenmine.base.mail.tasks import send_mail, send_bulk_mail @@ -38,11 +37,7 @@ def mail_recovery_password(sender, user, **kwargs): @receiver(signals.mail_milestone_created) def mail_milestone_created(sender, milestone, user, **kwargs): - participants_ids = ProjectUserRole.objects\ - .filter(user=user, mail_milestone_created=True, project=milestone.project)\ - .values_list('user__pk', flat=True) - - participants = User.objects.filter(pk__in=participants_ids) + participants = milestone.project.all_participants() emails_list = [] subject = ugettext("Greenmine: sprint created") @@ -61,11 +56,7 @@ def mail_milestone_created(sender, milestone, user, **kwargs): @receiver(signals.mail_userstory_created) def mail_userstory_created(sender, us, user, **kwargs): - participants_ids = ProjectUserRole.objects\ - .filter(user=user, mail_userstory_created=True, project=us.project)\ - .values_list('user__pk', flat=True) - - participants = User.objects.filter(pk__in=participants_ids) + participants = us.milestone.project.all_participants() emails_list = [] subject = ugettext("Greenmine: user story created") @@ -85,11 +76,7 @@ def mail_userstory_created(sender, us, user, **kwargs): @receiver(signals.mail_task_created) def mail_task_created(sender, task, user, **kwargs): - participants_ids = ProjectUserRole.objects\ - .filter(user=user, mail_task_created=True, project=task.project)\ - .values_list('user__pk', flat=True) - - participants = User.objects.filter(pk__in=participants_ids) + participants = task.us.milestone.project.all_participants() emails_list = [] subject = ugettext("Greenmine: task created") diff --git a/greenmine/urls.py b/greenmine/urls.py index a22e478a..31c41295 100644 --- a/greenmine/urls.py +++ b/greenmine/urls.py @@ -16,7 +16,6 @@ from wiki.api import * v1_api = Api(api_name='gm') v1_api.register(ProjectResource()) -v1_api.register(ProjectUserRoleResource()) v1_api.register(MilestoneResource()) v1_api.register(UserStoryResource()) v1_api.register(ChangeResource())