aircox/aircox/permissions.py
2024-05-04 04:09:45 +02:00

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)