from __future__ import unicode_literals, absolute_import import itertools import logging from django.apps import apps from django.utils.encoding import force_text logger = logging.getLogger(__name__) class ModelPermission(object): _functions = {} _inheritances = {} _registry = {} @classmethod def deregister(cls, model): cls._registry.pop(model, None) # TODO: Find method to revert the add_to_class('acls'...) # delattr doesn't work. @classmethod def register(cls, model, permissions): from django.contrib.contenttypes.fields import GenericRelation cls._registry.setdefault(model, []) for permission in permissions: cls._registry[model].append(permission) AccessControlList = apps.get_model( app_label='acls', model_name='AccessControlList' ) model.add_to_class( name='acls', value=GenericRelation(AccessControlList) ) @classmethod def get_classes(cls, as_content_type=False): ContentType = apps.get_model( app_label='contenttypes', model_name='ContentType' ) if as_content_type: content_type_dictionary = ContentType.objects.get_for_models( *cls._registry.keys() ) content_type_ids = [ content_type.pk for content_type in content_type_dictionary.values() ] return ContentType.objects.filter(pk__in=content_type_ids) else: return cls._registry.keys() @classmethod def get_for_class(cls, klass, as_choices=False): if as_choices: results = [] for namespace, permissions in itertools.groupby(cls.get_for_class(klass=klass, as_choices=False), lambda entry: entry.namespace): permission_options = [ (force_text(permission.pk), permission) for permission in permissions ] results.append( (namespace, permission_options) ) return results else: return cls._registry.get(klass, ()) @classmethod def get_for_instance(cls, instance): StoredPermission = apps.get_model( app_label='permissions', model_name='StoredPermission' ) permissions = [] class_permissions = cls.get_for_class(klass=type(instance)) if class_permissions: permissions.extend(class_permissions) pks = [ permission.stored_permission.pk for permission in set(permissions) ] return StoredPermission.objects.filter(pk__in=pks) @classmethod def get_function(cls, model): return cls._functions[model] @classmethod def get_inheritance(cls, model): return cls._inheritances[model] @classmethod def register_function(cls, model, function): cls._functions[model] = function @classmethod def register_inheritance(cls, model, related): cls._inheritances[model] = related