90 lines
2.9 KiB
Python
90 lines
2.9 KiB
Python
# Provide permissions handling
|
|
# we don't import models at module level in order to avoid migration problems
|
|
from django.utils.translation import gettext_lazy as _
|
|
from django.contrib.auth.models import Group, Permission
|
|
from django.contrib.contenttypes.models import ContentType
|
|
|
|
from .models import Program
|
|
|
|
|
|
__all__ = ("PagePermissions", "program")
|
|
|
|
|
|
class PagePermissions:
|
|
"""Handles obj permissions initialization of page subclass."""
|
|
|
|
model = None
|
|
# TODO: move values to subclass
|
|
groups = ({"label": _("editors"), "field": "editors_group_id", "perms": ["update"]},)
|
|
"""Groups informations initialized."""
|
|
groups_name_format = "{obj.title}: {group_label}"
|
|
"""Format used for groups name."""
|
|
perms_name_format = "{obj.title}: can {perm}"
|
|
"""Format used for permission name (displayed to humans)."""
|
|
perms_codename_format = "{obj._meta.label_lower}_{obj.pk}_{perm}"
|
|
"""Format used for permissions codename."""
|
|
|
|
def __init__(self, model):
|
|
self.model = model
|
|
|
|
def can(self, user, perm, obj):
|
|
"""Return True wether if user can edit Program or its children."""
|
|
from .models.page import ChildPage
|
|
|
|
if isinstance(obj, ChildPage):
|
|
obj = obj.parent_subclass
|
|
|
|
if not isinstance(obj, self.model):
|
|
return False
|
|
|
|
if user.is_superuser:
|
|
return True
|
|
|
|
perm = self.perms_codename_format.format(self=self, perm=perm, obj=obj)
|
|
return user.has_perm(perm)
|
|
|
|
def init(self, obj, model=None):
|
|
"""Initialize permissions for the provided obj.
|
|
|
|
Return True if group or permission have been created (`obj` has
|
|
thus been saved).
|
|
"""
|
|
updated = False
|
|
created_groups = []
|
|
|
|
# init groups
|
|
for infos in self.groups:
|
|
group = getattr(obj, infos["field"])
|
|
if not group:
|
|
group, created = self.init_group(obj, infos)
|
|
setattr(obj, infos["field"], group.pk)
|
|
updated = True
|
|
created and created_groups.append((group, infos))
|
|
|
|
if updated:
|
|
obj.save()
|
|
|
|
# init perms
|
|
for group, infos in created_groups:
|
|
self.init_perms(obj, group, infos)
|
|
|
|
return updated
|
|
|
|
def init_group(self, obj, infos):
|
|
name = self.groups_name_format.format(obj=obj, group_label=infos["label"])
|
|
return Group.objects.get_or_create(name=name)
|
|
|
|
def init_perms(self, obj, group, infos):
|
|
# TODO: avoid multiple database hits
|
|
for name in infos["perms"]:
|
|
perm, _ = Permission.objects.get_or_create(
|
|
codename=self.perms_codename_format.format(obj=obj, perm=name),
|
|
content_type=ContentType.objects.get_for_model(obj),
|
|
defaults={"name": self.perms_name_format.format(obj=obj, perm=name)},
|
|
)
|
|
if perm not in group.permissions.all():
|
|
group.permissions.add(perm)
|
|
|
|
|
|
program = PagePermissions(Program)
|