Ajoute la gestion des groupes
This commit is contained in:
parent
20d0f1fba9
commit
0fa182cb4a
8 changed files with 602 additions and 58 deletions
|
@ -1,12 +1,14 @@
|
|||
from django.db import models
|
||||
from django.contrib.auth.models import Group as DjangoGroup
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db.models.signals import post_save, m2m_changed
|
||||
from django.contrib.auth.models import Group as DjangoGroup
|
||||
from django.db import models
|
||||
from django.db.models.signals import m2m_changed, post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class WikiGroup(models.Model):
|
||||
""" A structured user group, used to grant permissions on sub-wikis
|
||||
"""A structured user group, used to grant permissions on sub-wikis
|
||||
|
||||
This model contains a structured group of users, in the sense that a group contains
|
||||
both users and other groups, allowing a DAG group structure.
|
||||
|
@ -20,8 +22,8 @@ class WikiGroup(models.Model):
|
|||
"""
|
||||
|
||||
class CyclicStructureException(Exception):
|
||||
""" Exception raised when a new edge introduces a cycle in the groups'
|
||||
structure """
|
||||
"""Exception raised when a new edge introduces a cycle in the groups'
|
||||
structure"""
|
||||
|
||||
def __init__(self, from_group, to_group):
|
||||
self.from_group = from_group
|
||||
|
@ -40,22 +42,48 @@ class WikiGroup(models.Model):
|
|||
related_name="included_in_groups",
|
||||
blank=True,
|
||||
)
|
||||
users = models.ManyToManyField(get_user_model(), blank=True)
|
||||
users = models.ManyToManyField(User, blank=True)
|
||||
managers = models.ManyToManyField(User, related_name="managed_groups", blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.django_group)
|
||||
|
||||
def get_all_users(self):
|
||||
""" Get the queryset of all the users in this group, including recursively
|
||||
included users """
|
||||
"""Get the queryset of all the users in this group, including recursively
|
||||
included users"""
|
||||
users_set = self.users.all()
|
||||
for subgroup in self.includes_groups.all():
|
||||
users_set = users_set.union(subgroup.get_all_users())
|
||||
return users_set
|
||||
|
||||
def is_manager(self, user):
|
||||
"""Checks wether the user is a manager of this group or any subgroup"""
|
||||
|
||||
# Base case: the user is an explicit manager
|
||||
if user in self.managers.all():
|
||||
return True
|
||||
|
||||
for subgroup in self.includes_groups.all():
|
||||
# If the user is a manager of a subgroup
|
||||
if subgroup.is_manager(user):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_all_groups(self):
|
||||
"""Returns the set of metagroups i.e. self plus the list of groups including
|
||||
this group recursively"""
|
||||
|
||||
groups = {self}
|
||||
|
||||
for metagroup in self.included_in_groups.all():
|
||||
groups |= metagroup.get_all_groups()
|
||||
|
||||
return groups
|
||||
|
||||
def propagate_update(self, already_notified=None):
|
||||
""" Commits itself to the Django group, and calls this method on every group in
|
||||
`included_in_groups` """
|
||||
"""Commits itself to the Django group, and calls this method on every group in
|
||||
`included_in_groups`"""
|
||||
|
||||
# Check that we did not already propagate the update signal to this group
|
||||
if already_notified is None:
|
||||
|
@ -69,20 +97,20 @@ class WikiGroup(models.Model):
|
|||
metagroup.propagate_update(already_notified=already_notified)
|
||||
|
||||
def commit_to_django_group(self):
|
||||
""" Writes this model's data to the related Django group """
|
||||
"""Writes this model's data to the related Django group"""
|
||||
|
||||
self.django_group.user_set.set(self.get_all_users())
|
||||
|
||||
def group_in_cycle(self, with_children):
|
||||
""" Checks whether this group would be in a group cycle if it had
|
||||
"""Checks whether this group would be in a group cycle if it had
|
||||
`with_children` as child nodes. This assumes that the graph currently stored is
|
||||
acyclic.
|
||||
|
||||
Returns `None` if no cycle is found, else retuns a child from `with_children`
|
||||
causing the cycle to appear. """
|
||||
causing the cycle to appear."""
|
||||
|
||||
def do_dfs(cur_node, visited_nodes):
|
||||
""" DFS to check whether we find `self` again """
|
||||
"""DFS to check whether we find `self` again"""
|
||||
if cur_node.pk in visited_nodes:
|
||||
return False
|
||||
if cur_node.pk == self.pk:
|
||||
|
@ -103,7 +131,7 @@ class WikiGroup(models.Model):
|
|||
|
||||
@receiver(post_save, sender=WikiGroup, dispatch_uid="on_wiki_group_changed")
|
||||
def on_wiki_group_changed(sender, instance, **kwargs):
|
||||
""" Commit the related WikiGroups to Django Group upon model change """
|
||||
"""Commit the related WikiGroups to Django Group upon model change"""
|
||||
instance.propagate_update()
|
||||
|
||||
|
||||
|
@ -113,8 +141,8 @@ def on_wiki_group_changed(sender, instance, **kwargs):
|
|||
dispatch_uid="on_wiki_group_includes_changed",
|
||||
)
|
||||
def on_wiki_group_includes_changed(sender, instance, action, **kwargs):
|
||||
""" Commit the related WikiGroups to Django Group upon change of the set of
|
||||
included other groups """
|
||||
"""Commit the related WikiGroups to Django Group upon change of the set of
|
||||
included other groups"""
|
||||
if action in ["post_add", "post_remove", "post_clear"]:
|
||||
instance.propagate_update()
|
||||
|
||||
|
@ -125,7 +153,7 @@ def on_wiki_group_includes_changed(sender, instance, action, **kwargs):
|
|||
dispatch_uid="on_wiki_group_users_changed",
|
||||
)
|
||||
def on_wiki_group_users_changed(sender, instance, action, **kwargs):
|
||||
""" Commit the related WikiGroups to Django Group upon change of included users """
|
||||
"""Commit the related WikiGroups to Django Group upon change of included users"""
|
||||
if action in ["post_add", "post_remove", "post_clear"]:
|
||||
instance.propagate_update()
|
||||
|
||||
|
@ -136,7 +164,7 @@ def on_wiki_group_users_changed(sender, instance, action, **kwargs):
|
|||
dispatch_uid="on_wiki_group_includes_check_acyclic",
|
||||
)
|
||||
def on_wiki_group_includes_check_acyclic(sender, instance, action, pk_set, **kwargs):
|
||||
""" Checks the acyclicity of the groups' graph before committing new edges.
|
||||
"""Checks the acyclicity of the groups' graph before committing new edges.
|
||||
|
||||
PLEASE NOTE that this check is only a fallback, and that forms should validate
|
||||
the acyclicity before committing anything.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue