Cleanup unused permissions

This commit is contained in:
FinnStutzenstein 2019-07-23 12:52:28 +02:00
parent e28f0f6685
commit c2a73c5146
2 changed files with 42 additions and 0 deletions

View File

@ -26,6 +26,7 @@ class CoreAppConfig(AppConfig):
from . import serializers # noqa
from .signals import (
autoupdate_for_many_to_many_relations,
cleanup_unused_permissions,
delete_django_app_permissions,
get_permission_change_data,
permission_change,
@ -60,6 +61,9 @@ class CoreAppConfig(AppConfig):
post_permission_creation.connect(
delete_django_app_permissions, dispatch_uid="delete_django_app_permissions"
)
post_permission_creation.connect(
cleanup_unused_permissions, dispatch_uid="cleanup_unused_permissions"
)
permission_change.connect(
get_permission_change_data, dispatch_uid="core_get_permission_change_data"
)

View File

@ -1,4 +1,7 @@
import logging
import sys
from collections import defaultdict
from typing import Dict, List
from django.apps import apps
from django.contrib.auth.models import Permission
@ -30,6 +33,41 @@ def delete_django_app_permissions(sender, **kwargs):
Permission.objects.filter(content_type__in=contenttypes).delete()
def cleanup_unused_permissions(sender, **kwargs):
"""
Deletes all permissions, that are not defined in any model meta class
"""
# Maps the content type id to codenames of perms for this content type.
content_type_codename_mapping: Dict[int, List[str]] = defaultdict(list)
# Maps content type ids to the content type.
content_type_id_mapping = {}
# Collect all perms from all apps.
for model in apps.get_models():
content_type = ContentType.objects.get_for_model(
model, for_concrete_model=False
)
content_type_id_mapping[content_type.id] = content_type
for perm in model._meta.permissions:
content_type_codename_mapping[content_type.id].append(perm[0])
# Cleanup perms per content type.
logger = logging.getLogger("openslides.core.migrations")
for content_type_id, codenames in content_type_codename_mapping.items():
app_label = content_type_id_mapping[content_type_id].app_label
unused_perms = Permission.objects.filter(
content_type__pk=content_type_id
).exclude(codename__in=codenames)
if unused_perms.exists():
verbose_permissions = ", ".join(
[f"{app_label}.{perm.codename}" for perm in unused_perms.all()]
)
logger.info(f"cleaning unused permissions: {verbose_permissions}")
unused_perms.delete()
def get_permission_change_data(sender, permissions, **kwargs):
"""
Yields all necessary Cachables if the respective permissions change.