def has_module_perms(self, user, app_label): models = self.get_models(app_label) for model in models: manager = AccessManager(model) if manager.check_visible(model, self.FakeRequest(self, user)): return True return False
def create(self, validated_data): """Overriden to patch the object by the AccessManager-provided values""" ModelClass = self.Meta.model manager = AccessManager(ModelClass) data = manager.check_appendable(ModelClass, self.context['request']) if data is False: raise exceptions.PermissionDenied("Is not appendable") ret = super(AccessSerializerMixin, self).create(validated_data) if data: for k in data: v = data[k] fieldname = k if fieldname.endswith("_set"): fieldname = fieldname[:-4] field = ret._meta.get_field(fieldname) if isinstance(field, ForeignObjectRel): if isinstance(v, collections.Iterable) and not isinstance( v, string_types): fld = getattr(ret, k) for i in v: fld.add(i) elif getattr(ret, k) is None: setattr(ret, k, v) ret.save() return ret
def has_view_permission(self, request, obj=None): manager = AccessManager(self.model) if manager.check_visible(self.model, request) is False: return False if obj: return bool(manager.apply_visible(obj.__class__.objects.filter(id=obj.id), request)) return True
def get_field_queryset(self, db, db_field, request): # NOTE!!! Undocumented and may be changed in future versions! qs = super(AccessControlMixin, self).get_field_queryset(db, db_field, request) model = _get_field_rel_model(db_field) manager = AccessManager(model) if qs is None: qs = manager.get_queryset() return manager.apply_visible(qs, request)
def has_ability(self, user, model, ability, obj=None): manager = AccessManager(model) if obj and isinstance(obj, model): apply = getattr(manager, "apply_%s" % ability) return bool(apply(model.objects.filter(pk=obj.pk), self.FakeRequest(self, user))) check = getattr(manager, "check_%s" % ability) return check(model, self.FakeRequest(self, user)) is not False
def has_module_permission(self, request): if self.has_view_permission(request): return True for model in apps.get_app_config(self.model._meta.app_label).get_models(): if AccessManager(model).check_visible(model, request) is not False: return True return False
def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == "project": projects = AccessManager(Project).changeable(request) kwargs["queryset"] = projects return super(ProjectMemberAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
def field_choices(self, field, request, model_admin): model = _get_field_rel_model(field) if not model: return [item for item in super(RelatedFieldVisibleListFilter, self).field_choices(field, request, model_admin)] else: q = model.objects.all() return [(o.pk, text_type(o)) for o in AccessManager(model).apply_visible(q, request).distinct()]
def filter_queryset(self, request, queryset, view): """Returns queryset filtered by access rights or None""" ability = self.get_requested_ability(request, queryset, view) if not ability: return return AccessManager(self.get_queryset_model( request, queryset, view)).apply_able(ability, queryset, request)
def format_callback(obj): has_admin = obj.__class__ in self.admin_site._registry opts = obj._meta no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_text(obj)) # Trying to get admin change URL admin_url = None try: admin_url = reverse('%s:%s_%s_change' % (self.admin_site.name, opts.app_label, opts.model_name), None, (quote(obj._get_pk_val()),)) except NoReverseMatch: # Change url doesn't exist -- don't display link to edit pass # Collecting forbidden subobjects, compatible with Django or forced by the option if STRONG_DELETION_CONTROL or has_admin: if not obj.__class__._meta.auto_created: manager = AccessManager(obj.__class__) # filter out forbidden items if manager.check_deleteable(obj.__class__, request) is False: model_perms_needed.add(opts.verbose_name) if not manager.apply_deleteable(obj.__class__._default_manager.filter(pk=obj.pk), request): object_perms_needed.add(obj) if admin_url: # Display a link to the admin page. return format_html('{}: <a href="{}">{}</a>', capfirst(opts.verbose_name), admin_url, obj) else: # Don't display link to edit, because it either has no # admin or is edited inline. return no_edit_link
def save_related(self, request, form, formsets, change): if change and self.has_basic_change_permission(request, form.instance): return super(AccessControlMixin, self).save_related(request, form, formsets, change) if not change and self.has_add_permission(request): data = AccessManager(self.model).appendable(request) for k in data: v = data[k] fieldname = k if fieldname.endswith("_set"): fieldname = fieldname[:-4] field = form.instance._meta.get_field(fieldname) if isinstance(v, collections.Iterable) and not isinstance(v, string_types) and isinstance(field, ForeignObjectRel): fld = getattr(form.instance, k) for i in v: fld.add(i) return super(AccessControlMixin, self).save_related(request, form, formsets, change) raise PermissionDenied
def save_model(self, request, obj, form, change): if change and self.has_basic_change_permission(request, obj): return super(AccessControlMixin, self).save_model(request, obj, form, change) if not change and self.has_add_permission(request): data = AccessManager(self.model).appendable(request) for k in data: v = data[k] fieldname = k if fieldname.endswith("_set"): fieldname = fieldname[:-4] field = form.instance._meta.get_field(fieldname) if isinstance(v, collections.Iterable) and not isinstance(v, string_types) and isinstance(field, ForeignObjectRel): continue if getattr(obj, k) is None: setattr(obj, k, v) return super(AccessControlMixin, self).save_model(request, obj, form, change) raise PermissionDenied
def has_object_permission(self, request, view, obj): """ Overriden to determine permissions to the model instance """ queryset = self.get_view_queryset(request, view) if queryset is None: return False model = self.get_queryset_model(request, queryset, view) if not model: return False ability = self.get_requested_ability(request, queryset, view) if not ability: raise exceptions.MethodNotAllowed(request.method) return bool( AccessManager(model).apply_able(ability, queryset, request).filter(pk=obj.pk))
def has_permission(self, request, view): """ Overriden to determine permissions to the whole model """ # Workaround to ensure thet the AccessPermission is not applied # to the root view when using DefaultRouter. if getattr(view, '_ignore_model_permissions', False): return True queryset = self.get_view_queryset(request, view) if queryset is None: return False model = self.get_queryset_model(request, queryset, view) if not model: return False ability = self.get_requested_ability(request, queryset, view) if not ability: raise exceptions.MethodNotAllowed(request.method) return AccessManager(model).check_able(ability, model, request) is not False
def filter_queryset(self, term, queryset=None, request=None, *av, **kw): # the `request` parameter here appear from views.py queryset = AccessManager(queryset.model).apply_visible( queryset, request) return super(AccessSelect2WidgetMixin, self).filter_queryset(term, queryset=queryset, *av, **kw)
AccessManager.register_plugins({ Permission: ApplyAblePlugin(visible=lambda queryset, request: queryset.filter( Q(user=request.user) | Q(group__in=request.user.groups.all()))), User: CompoundPlugin( DjangoAccessPlugin(), ApplyAblePlugin( changeable=lambda queryset, request: queryset.filter( Q(id=request.user.id)), deleteable=lambda queryset, request: queryset.filter( Q(id=request.user.id)), ), ), Group: CompoundPlugin( DjangoAccessPlugin(), CheckAblePlugin( appendable=lambda model, request: {'user_set': [request.user]}), ApplyAblePlugin( visible=lambda queryset, request: queryset.filter(user=request.user ), changeable=lambda queryset, request: queryset.filter(user=request. user), deleteable=lambda queryset, request: queryset.filter(user=request. user), ), ) })
from access.managers import AccessManager from access.plugins import AccessPluginBase, CheckAblePlugin, ApplyAblePlugin, CompoundPlugin from django.contrib.auth.models import User from trans.models import Project, ProjectMember, Vehicle, Driver, Order AccessManager.register_plugins({ User: CompoundPlugin( CheckAblePlugin( appendable=(lambda model, request: {} if request.user.id and request.user.projects.filter( allow_manage=True) else False), ), ApplyAblePlugin(visible=( lambda queryset, request: queryset if request.user.projects.filter(allow_manage=True) else queryset. filter(projects__project__users__user=request.user.id).distinct( ) or queryset.filter(id=request.user.id).distinct()), changeable=(lambda queryset, request: queryset.filter( id=request.user.id).distinct()), deleteable=(lambda queryset, request: queryset.filter( id=request.user.id).distinct()))), }) AccessManager.register_plugins({ Project: CompoundPlugin( CheckAblePlugin(appendable=(lambda model, request: False), ), ApplyAblePlugin( visible=(lambda queryset, request: queryset.filter(
def has_add_permission(self, request, *av, **kw): # TODO: for Django 3.0 the *av = [obj] where the obj is a parent object r = AccessManager(self.model).appendable(request) is not False return r
def has_add_permission(self, request): r = AccessManager(self.model).appendable(request) is not False return r
def get_queryset(self, request): return AccessManager(self.model).visible(request)
AccessManager.register_plugins({ Permission: ApplyAblePlugin(visible=lambda queryset, request: queryset.filter( Q(user=request.user) | Q(group__in=request.user.groups.all()))), User: CompoundPlugin( CheckAblePlugin( appendable=lambda model, request: DjangoAccessPlugin( ).check_appendable(model, request), # deleteable=lambda model, request: DjangoAccessPlugin().check_deleteable(model, request), ), ApplyAblePlugin( changeable=lambda queryset, request: queryset.filter( Q(id=request.user.id)) if DjangoAccessPlugin().check_changeable(queryset.model, request) is False else (queryset.all() if request.user.is_superuser else queryset.all().exclude(is_superuser=True)), deleteable=lambda queryset, request: queryset.filter( Q(id=request.user.id)) if DjangoAccessPlugin().check_deleteable(queryset.model, request) is False else (queryset.all() if request.user.is_superuser else queryset.all().exclude(is_superuser=True)), )), Group: CompoundPlugin( DjangoAccessPlugin(), CheckAblePlugin( appendable=lambda model, request: {'user_set': [request.user]}), ApplyAblePlugin( visible=lambda queryset, request: queryset.filter(user=request.user ), changeable=lambda queryset, request: queryset.filter(user=request. user), deleteable=lambda queryset, request: queryset.filter(user=request. user), ), ) })