Working on permissions and groups generation
parent
e0e41c7c95
commit
a36a130998
|
@ -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
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
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):
|
class Profile(models.Model):
|
||||||
|
@ -26,5 +26,12 @@ class Role(models.Model):
|
||||||
permissions = models.ManyToManyField(Permission,
|
permissions = models.ManyToManyField(Permission,
|
||||||
verbose_name=_('permissions'), blank=True)
|
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
|
from . import sigdispatch
|
||||||
|
|
|
@ -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)
|
|
@ -6,7 +6,8 @@ from django.db.models.signals import post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.contrib.auth.models import User
|
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)
|
@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():
|
if created and not Profile.objects.filter(user=instance).exists():
|
||||||
Profile.objects.create(user=instance)
|
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)
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from django.contrib import admin
|
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
|
Milestone, UserStory, Change, ChangeAttachment, Task
|
||||||
|
|
||||||
|
|
||||||
class ProjectAdmin(admin.ModelAdmin):
|
class ProjectAdmin(GuardedModelAdmin):
|
||||||
list_display = ["name", "owner"]
|
list_display = ["name", "owner"]
|
||||||
|
|
||||||
admin.site.register(Project, ProjectAdmin)
|
admin.site.register(Project, ProjectAdmin)
|
||||||
|
@ -17,12 +19,6 @@ class ProjectExtrasAdmin(admin.ModelAdmin):
|
||||||
admin.site.register(ProjectExtras, ProjectExtrasAdmin)
|
admin.site.register(ProjectExtras, ProjectExtrasAdmin)
|
||||||
|
|
||||||
|
|
||||||
class ProjectUserRoleAdmin(admin.ModelAdmin):
|
|
||||||
list_display = ["project", "user", "role"]
|
|
||||||
|
|
||||||
admin.site.register(ProjectUserRole, ProjectUserRoleAdmin)
|
|
||||||
|
|
||||||
|
|
||||||
class MilestoneAdmin(admin.ModelAdmin):
|
class MilestoneAdmin(admin.ModelAdmin):
|
||||||
list_display = ["name", "project", "owner"]
|
list_display = ["name", "project", "owner"]
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ from tastypie.resources import ModelResource
|
||||||
from tastypie.authentication import SessionAuthentication
|
from tastypie.authentication import SessionAuthentication
|
||||||
from tastypie.authorization import DjangoAuthorization
|
from tastypie.authorization import DjangoAuthorization
|
||||||
|
|
||||||
from greenmine.scrum.models import Project, ProjectUserRole, \
|
from greenmine.scrum.models import Project, \
|
||||||
Milestone, UserStory, Change, ChangeAttachment, Task
|
Milestone, UserStory, Change, ChangeAttachment, Task
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,14 +15,6 @@ class ProjectResource(ModelResource):
|
||||||
authorization = DjangoAuthorization()
|
authorization = DjangoAuthorization()
|
||||||
|
|
||||||
|
|
||||||
class ProjectUserRoleResource(ModelResource):
|
|
||||||
class Meta:
|
|
||||||
queryset = ProjectUserRole.objects.all()
|
|
||||||
resource_name = 'projectuserrole'
|
|
||||||
authentication = SessionAuthentication()
|
|
||||||
authorization = DjangoAuthorization()
|
|
||||||
|
|
||||||
|
|
||||||
class MilestoneResource(ModelResource):
|
class MilestoneResource(ModelResource):
|
||||||
class Meta:
|
class Meta:
|
||||||
queryset = Milestone.objects.all()
|
queryset = Milestone.objects.all()
|
||||||
|
|
|
@ -23,11 +23,6 @@ class ProjectManager(models.Manager):
|
||||||
def get_by_natural_key(self, slug):
|
def get_by_natural_key(self, slug):
|
||||||
return self.get(slug=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):
|
class ProjectExtras(models.Model):
|
||||||
task_parser_re = models.CharField(max_length=1000, blank=True, null=True, default=None)
|
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)
|
modified_date = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
owner = models.ForeignKey("auth.User", related_name="projects")
|
owner = models.ForeignKey("auth.User", related_name="projects")
|
||||||
participants = models.ManyToManyField('auth.User',
|
groups = models.ManyToManyField('auth.Group',
|
||||||
related_name="projects_participant",
|
related_name="projects",
|
||||||
through="ProjectUserRole",
|
|
||||||
null=True,
|
null=True,
|
||||||
blank=True)
|
blank=True)
|
||||||
|
|
||||||
public = models.BooleanField(default=True)
|
public = models.BooleanField(default=True)
|
||||||
markup = models.CharField(max_length=10, choices=MARKUP_TYPE, default='md')
|
markup = models.CharField(max_length=10, choices=MARKUP_TYPE, default='md')
|
||||||
extras = models.OneToOneField("ProjectExtras", related_name="project", null=True, default=None)
|
extras = models.OneToOneField("ProjectExtras", related_name="project", null=True, default=None)
|
||||||
|
@ -143,8 +136,7 @@ class Project(models.Model):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def all_participants(self):
|
def all_participants(self):
|
||||||
qs = ProjectUserRole.objects.filter(project=self)
|
return User.objects.filter(group__in=self.groups)
|
||||||
return User.objects.filter(id__in=qs.values_list('user__pk', flat=True))
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def default_milestone(self):
|
def default_milestone(self):
|
||||||
|
@ -161,44 +153,6 @@ class Project(models.Model):
|
||||||
|
|
||||||
super(Project, self).save(*args, **kwargs)
|
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"<Project-User-Relation-%s>" % (self.id)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
unique_together = ('project', 'user')
|
|
||||||
|
|
||||||
|
|
||||||
class MilestoneManager(models.Manager):
|
class MilestoneManager(models.Manager):
|
||||||
def get_by_natural_key(self, name, project):
|
def get_by_natural_key(self, name, project):
|
||||||
|
@ -317,8 +271,10 @@ class UserStory(models.Model):
|
||||||
|
|
||||||
client_requirement = models.BooleanField(default=False)
|
client_requirement = models.BooleanField(default=False)
|
||||||
team_requirement = models.BooleanField(default=False)
|
team_requirement = models.BooleanField(default=False)
|
||||||
|
order = models.PositiveSmallIntegerField("Order")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
ordering = ['order']
|
||||||
unique_together = ('ref', 'project')
|
unique_together = ('ref', 'project')
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|
|
@ -7,7 +7,6 @@ from django.template.loader import render_to_string
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
from greenmine.scrum.models import ProjectUserRole
|
|
||||||
from greenmine.base import signals
|
from greenmine.base import signals
|
||||||
from greenmine.base.utils.auth import set_token
|
from greenmine.base.utils.auth import set_token
|
||||||
from greenmine.base.mail.tasks import send_mail, send_bulk_mail
|
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)
|
@receiver(signals.mail_milestone_created)
|
||||||
def mail_milestone_created(sender, milestone, user, **kwargs):
|
def mail_milestone_created(sender, milestone, user, **kwargs):
|
||||||
participants_ids = ProjectUserRole.objects\
|
participants = milestone.project.all_participants()
|
||||||
.filter(user=user, mail_milestone_created=True, project=milestone.project)\
|
|
||||||
.values_list('user__pk', flat=True)
|
|
||||||
|
|
||||||
participants = User.objects.filter(pk__in=participants_ids)
|
|
||||||
|
|
||||||
emails_list = []
|
emails_list = []
|
||||||
subject = ugettext("Greenmine: sprint created")
|
subject = ugettext("Greenmine: sprint created")
|
||||||
|
@ -61,11 +56,7 @@ def mail_milestone_created(sender, milestone, user, **kwargs):
|
||||||
|
|
||||||
@receiver(signals.mail_userstory_created)
|
@receiver(signals.mail_userstory_created)
|
||||||
def mail_userstory_created(sender, us, user, **kwargs):
|
def mail_userstory_created(sender, us, user, **kwargs):
|
||||||
participants_ids = ProjectUserRole.objects\
|
participants = us.milestone.project.all_participants()
|
||||||
.filter(user=user, mail_userstory_created=True, project=us.project)\
|
|
||||||
.values_list('user__pk', flat=True)
|
|
||||||
|
|
||||||
participants = User.objects.filter(pk__in=participants_ids)
|
|
||||||
|
|
||||||
emails_list = []
|
emails_list = []
|
||||||
subject = ugettext("Greenmine: user story created")
|
subject = ugettext("Greenmine: user story created")
|
||||||
|
@ -85,11 +76,7 @@ def mail_userstory_created(sender, us, user, **kwargs):
|
||||||
|
|
||||||
@receiver(signals.mail_task_created)
|
@receiver(signals.mail_task_created)
|
||||||
def mail_task_created(sender, task, user, **kwargs):
|
def mail_task_created(sender, task, user, **kwargs):
|
||||||
participants_ids = ProjectUserRole.objects\
|
participants = task.us.milestone.project.all_participants()
|
||||||
.filter(user=user, mail_task_created=True, project=task.project)\
|
|
||||||
.values_list('user__pk', flat=True)
|
|
||||||
|
|
||||||
participants = User.objects.filter(pk__in=participants_ids)
|
|
||||||
|
|
||||||
emails_list = []
|
emails_list = []
|
||||||
subject = ugettext("Greenmine: task created")
|
subject = ugettext("Greenmine: task created")
|
||||||
|
|
|
@ -16,7 +16,6 @@ from wiki.api import *
|
||||||
|
|
||||||
v1_api = Api(api_name='gm')
|
v1_api = Api(api_name='gm')
|
||||||
v1_api.register(ProjectResource())
|
v1_api.register(ProjectResource())
|
||||||
v1_api.register(ProjectUserRoleResource())
|
|
||||||
v1_api.register(MilestoneResource())
|
v1_api.register(MilestoneResource())
|
||||||
v1_api.register(UserStoryResource())
|
v1_api.register(UserStoryResource())
|
||||||
v1_api.register(ChangeResource())
|
v1_api.register(ChangeResource())
|
||||||
|
|
Loading…
Reference in New Issue