authentic2-cut/src/authentic2_cut/utils.py

241 lines
7.7 KiB
Python

from authentic2.a2_rbac.models import (
ACTIVATE_OP,
ADD_OP,
ADMIN_OP,
CHANGE_OP,
DELETE_OP,
RESET_PASSWORD_OP,
SEARCH_OP,
VIEW_OP,
Operation,
)
from authentic2.a2_rbac.models import OrganizationalUnit as OU
from authentic2.a2_rbac.models import Permission, Role
from authentic2.a2_rbac.utils import get_operation
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
User = get_user_model()
CUT_VALIDATE_OP = Operation.register(name='Valider', slug='cut_validate')
CUT_FC_OP = Operation.register(name='Modifier liaison FC', slug='cut_fc')
ROLE_TEMPLATES = [
{
'name': 'Administrateur CUT - création',
'slug': '_a2-cut-create',
'operations': [ADD_OP],
'target': 'user_ct',
'scope': 'ou_usagers',
},
{
'name': 'Administrateur CUT - recherche',
'slug': '_a2-cut-search',
'operations': [SEARCH_OP],
'target': 'user_ct',
'scope': 'ou_usagers',
},
{
'name': 'Administrateur CUT - lecture',
'slug': '_a2-cut-view',
'operations': [VIEW_OP],
'target': 'user_ct',
'scope': 'ou_usagers',
},
{
'name': 'Administrateur CUT - modification',
'slug': '_a2-cut-change',
'operations': [CHANGE_OP],
'target': 'user_ct',
'scope': 'ou_usagers',
},
{
'name': 'Administrateur CUT - suppression',
'slug': '_a2-cut-delete',
'operations': [DELETE_OP],
'target': 'user_ct',
'scope': 'ou_usagers',
},
{
'name': 'Administrateur CUT - mot de passe',
'slug': '_a2-cut-passwords',
'operations': [RESET_PASSWORD_OP],
'target': 'user_ct',
'scope': 'ou_usagers',
},
{
'name': 'Administrateur CUT - suspension',
'slug': '_a2-cut-activate',
'operations': [ACTIVATE_OP],
'target': 'user_ct',
'scope': 'ou_usagers',
},
{
'name': 'Administrateur CUT - validation',
'slug': '_a2-cut-validate',
'operations': [CUT_VALIDATE_OP],
'target': 'user_ct',
'scope': 'ou_usagers',
},
{
'name': 'Administrateur CUT - fc',
'slug': '_a2-cut-fc',
'operations': [CUT_FC_OP, SEARCH_OP, VIEW_OP],
'target': 'user_ct',
'scope': 'ou_usagers',
},
{
'name': 'Administrateur CUT',
'slug': '_a2-cut-admin-usagers',
'role_parents': [
'_a2-cut-create',
'_a2-cut-search',
'_a2-cut-view',
'_a2-cut-change',
'_a2-cut-delete',
'_a2-cut-passwords',
'_a2-cut-activate',
'_a2-cut-validate',
'_a2-cut-fc',
],
},
{
'name': 'Utilisateurs',
'slug': '_a2-cut-admin-users',
'operations': [ADMIN_OP],
'target': 'user_ct',
'scope': 'self',
'child_of_ou': ['ou_territoire', '__prefix__'],
},
{
'name': 'Rôles',
'slug': '_a2-cut-admin-roles',
'operations': [ADMIN_OP],
'target': 'role_ct',
'scope': 'self',
'child_of_ou': ['ou_territoire', '__prefix__'],
},
{
'name': 'Administrateur lecteur',
'slug': '_a2-cut-admin-view-only',
'operations': [VIEW_OP],
'target': 'user_ct',
'scope': 'self',
'child_of_ou': ['ou_territoire', '__prefix__'],
},
{
'name': 'Administrateur',
'slug': '_a2-cut-admin',
'role_parents': ['_a2-cut-admin-users', '_a2-cut-admin-roles'],
'scope': 'no_scope',
},
]
def update_roles():
try:
default_ou = OU.objects.get(default=True)
except OU.DoesNotExist:
pass
else:
if default_ou.slug != 'usagers':
default_ou.default = False
default_ou.save()
ou_usagers, created = OU.objects.get_or_create(
slug='usagers', defaults={'name': 'Usagers', 'default': True}
)
if ou_usagers.default is False:
ou_usagers.default = True
ou_usagers.save()
ou_territoire, created = OU.objects.get_or_create(
name='Territoire',
slug='territoire',
defaults={
'name': 'Territoire',
},
)
ct_ct = ContentType.objects.get_for_model(ContentType)
user_ct = ContentType.objects.get_for_model(User)
role_ct = ContentType.objects.get_for_model(Role)
ou_ct = ContentType.objects.get_for_model(OU)
roles = {}
ous = OU.objects.all()
def handle_ou(ou, ou_usagers, ou_territoire, user_ct, role_ct, ou_ct, **kwargs):
ou_ct = ContentType.objects.get_for_model(OU)
if ou.slug == 'usagers':
return
for tpl in ROLE_TEMPLATES:
role, created = Role.objects.get_or_create(
slug=tpl['slug'], ou=ou, defaults={'name': tpl['name']}
)
roles[(ou, tpl['slug'])] = role
if tpl.get('operations'):
target_ct = vars()[tpl['target']]
if tpl['scope'] == 'self':
scope = ou
else:
scope = vars()[tpl['scope']]
permissions = []
for operation in tpl['operations']:
op = get_operation(operation)
permission, created = Permission.objects.get_or_create(
operation=op, ou=scope, target_ct=ct_ct, target_id=target_ct.pk
)
permissions.append(permission)
op = get_operation(VIEW_OP)
permission, created = Permission.objects.get_or_create(
operation=op, target_ct=ou_ct, target_id=scope.pk
)
permissions.append(permission)
role.permissions.set(permissions)
else:
role.permissions.clear()
# remove self administration
role.permissions.remove(*role.permissions.filter(target_ct=role_ct, target_id=role.pk))
child_of_ou = tpl.get('child_of_ou', [])
for child in child_of_ou:
child_ou = None
if child == '__prefix__':
# find the longest matching ou
candidates = [o for o in ous if o != ou and ou.slug.startswith(o.slug)]
candidates.sort(key=lambda o: len(o.slug), reverse=True)
if candidates:
child_ou = candidates[0]
elif ou.slug != child:
child_ou = vars()[child]
if child_ou:
child_role = Role.objects.get(ou=child_ou, slug=tpl['slug'])
role.add_child(child_role)
if 'role_parents' in tpl:
for role_parent in tpl['role_parents']:
role.add_parent(roles[(ou, role_parent)])
# Les administrateurs territoire doivent aussi administrer les collectivités
if tpl['name'] == 'Administrateur' and ou.slug == 'territoire':
op = get_operation(ADMIN_OP)
permission, created = Permission.objects.get_or_create(
operation=op, target_ct=ct_ct, target_id=ou_ct.pk
)
role.permissions.add(permission)
slugs = [tpl['slug'] for tpl in ROLE_TEMPLATES]
Role.objects.filter(slug__startswith='_a2-cut').exclude(slug__in=slugs).delete()
handle_ou(ou_territoire, **vars())
for ou in OU.objects.exclude(slug__in=['usagers', 'territoire']):
handle_ou(**vars())
def mime_type_from_buffer(buf):
import magic
if hasattr(magic, 'from_buffer'):
return magic.from_buffer(buf, mime=True)
else:
return magic.detect_from_content(buf).mime_type