# coding=utf-8 from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals from django.core.exceptions import ObjectDoesNotExist from rapid.models import Application, Profile __author__ = 'marcos.medeiros' # noinspection PyProtectedMember from rapid.registry import _caller_urls_module class Permission(object): """ A permission for an registry entry. """ def __init__(self, model, instances): self.model = model self.instances = instances def all_instances(model): """ Shortcut function for granting permission over all instances of a model. For that use, create a permission with this function at its "instances" attribute. """ def i(request): if model(request): return {} else: return None return i def apply_instances_permission(model, perm): """ Returns the set of objects that a resolved permission has access to. :param model: ModelData of the model that'll be filtered :param perm: Resolved permission (that is, the result of evaluating permission.instances(request)) """ if perm is None: return [] if hasattr(perm, 'keys'): return model.default_manager().filter(**perm) if hasattr(perm, '__iter__'): return perm if hasattr(perm, 'all'): return perm return [] def has_instance(model, perm, instance): """ Verifies if an object instance access is permitted :param model: ModelData of the desired model :param perm: Resolved permission (that is, the result of evaluating permission.instances(request)) :param instance: Instance that'll be verified. """ p = apply_instances_permission(model, perm) if hasattr(p, 'filter'): return p.filter(pk=instance.pk).exists() if hasattr(p, '__iter__'): return bool([f for f in p if f.pk == instance.pk]) return False def to_profile(profile_name): """ Grants permission over the model and all instances to the given profile(s) of the application the model is being registered. :param profile_name: Name or list of names of profiles that'll receive the permission. """ app = Application.objects.get(python_name=_caller_urls_module()) # Should never fail if hasattr(profile_name, "__iter__"): profiles = [pf.pk for pf in Profile.objects.filter(name__in=profile_name, application=app).all()] def m(request): if not request.user.is_authenticated(): return False up = [p.pk for p in request.user.profile_set] for p in up: if p in profiles: return True return False else: profile = None try: profile = Profile.objects.get(name=profile_name, application=app) except ObjectDoesNotExist: # Profile is not registered yet. May happen after a deploy. return False def m(request): if not request.user.is_authenticated(): return False up = [p.pk for p in request.user.profile_set.all()] if profile in up: return True return False return Permission(m, all_instances(m)) def to_staff(): """ Grants permission over the model and all instances to every user with is_staff set. """ def m(request): if request.user.is_authenticated() and request.user.is_staff: return True return False return Permission(m, all_instances(m)) def to_all(): """ Grants permission over the model and all instances to all users. """ # noinspection PyUnusedLocal def m(request): return True return Permission(m, all_instances(m)) def to_superusers(): """ Grants permission over the model and all instances to every user with superuser set. """ def m(request): if request.user.is_authenticated() and request.user.is_superuser: return True return False return Permission(m, all_instances(m)) def to_application_managers(python_name): """ Grants permission over the model and all instances to the manager of the given application :param python_name: Name of the desired application main module """ app = [ap.pk for ap in Application.objects.filter(python_name=python_name).all()] def m(request): if not request.user.is_authenticated(): return False up = [a.pk for a in request.user.managed_applications.all()] if app in up: return True return False return Permission(m, all_instances(m))