def _filter_fields_by_permissions(self, fields, permissions_kind): """ Filter serializer fields by permissions kind :param fields: serializer fields list :param permissions_kind: edit/view :return: fields allowed to interact with """ model = self.Meta.model targets_map = {Permission.get_target(model, field): field for field in fields} pk_fields = [] pk_target = Permission.get_target(model, 'pk') if pk_target in targets_map: pk_fields.append(targets_map.pop(pk_target)) pk_field = model_meta.get_field_info(model).pk pk_target = Permission.get_target(model, pk_field) if pk_target in targets_map: pk_fields.append(targets_map.pop(pk_target)) allowed_targets = Permission.apply_permissions(self.permissions, targets_map.keys(), permissions_kind) allowed_fields = list(map(lambda target: targets_map[target], allowed_targets)) if allowed_fields: allowed_fields.extend(pk_fields) return allowed_fields
def _filter_fields_by_permissions(self, fields, permissions_kind): """ Filter serializer fields by permissions kind :param fields: serializer fields list :param permissions_kind: edit/view :return: fields allowed to interact with """ model = self.Meta.model targets_map = { Permission.get_target(model, field): field for field in fields } pk_fields = [] pk_target = Permission.get_target(model, 'pk') if pk_target in targets_map: pk_fields.append(targets_map.pop(pk_target)) pk_field = model_meta.get_field_info(model).pk pk_target = Permission.get_target(model, pk_field) if pk_target in targets_map: pk_fields.append(targets_map.pop(pk_target)) allowed_targets = Permission.apply_permissions(self.permissions, targets_map.keys(), permissions_kind) allowed_fields = list( map(lambda target: targets_map[target], allowed_targets)) if allowed_fields: allowed_fields.extend(pk_fields) return allowed_fields
def has_perm(instance, user): target = Permission.get_target(instance, action) context = getattr(user, '_permission_context', []) permissions = Permission.objects.filter_by_context(context) \ .filter_by_targets([target]).filter(permission=Permission.PERMISSIONS.action) return bool( Permission.apply_permissions(permissions, [target], Permission.PERMISSIONS.action) )
def _update_permissions(self, role, perm, targets, perm_type, condition=None): if isinstance(role, (list, tuple)): for r in role: self._update_permissions(r, perm, targets, perm_type, condition) return if isinstance(targets, str): targets = [targets] condition = (condition or []) + [TPMModuleCondition() ] + self.user_roles[role] if self.verbosity >= 3: for target in targets: print(' {} {} permission for {} on {}\n' ' if {}.'.format( 'Add' if perm_type == 'allow' else 'Revoke', perm, role, target, condition, )) self.defined_permissions.extend([ Permission(target=target, permission=perm, permission_type=perm_type, condition=condition) for target in targets ])
def has_permission(self, request, view): targets = self.get_targets(request, view) context = view._collect_permission_context() permissions = Permission.objects.filter_by_context(context).filter_by_targets(targets) if request.method in SAFE_METHODS: permission_kind = Permission.PERMISSIONS.view else: permission_kind = Permission.PERMISSIONS.edit return bool(Permission.apply_permissions(permissions, targets, permission_kind))
def get_targets(self, request, view): model = view.get_queryset().model targets = [] for lookup_field in view.parent_lookup_field.split('__'): field = getattr(model, lookup_field).field parent_model = field.related_model targets.append(Permission.get_target(parent_model, field.remote_field.get_accessor_name())) model = parent_model return targets
def setUpTestData(cls): # We disable synchronisation of test models. So we need to create it manually. with connection.schema_editor() as editor: editor.create_model(Parent) editor.create_model(Child1) cls.parent = Parent.objects.create(field1=1, field2=2) cls.children1 = [ Child1.objects.create(parent=cls.parent, field1=3, field2=4), Child1.objects.create(parent=cls.parent, field1=5, field2=6), ] Permission.objects.bulk_create([ Permission(permission='edit', target='permissions2.parent.field1'), Permission(permission='edit', target='permissions2.parent.children1'), Permission(permission='edit', target='permissions2.child1.field1'), Permission(permission='edit', target='permissions2.parent.field2', condition=['user.group="PME"']), Permission(permission='edit', target='permissions2.child1.field2', condition=['user.group="PME"']), ])
def get_targets(self, request, view): model = view.get_queryset().model targets = [] for lookup_field in view.parent_lookup_field.split('__'): field = getattr(model, lookup_field).field parent_model = field.related_model targets.append( Permission.get_target(parent_model, field.remote_field.get_accessor_name())) model = parent_model return targets
def has_permission(self, request, view): targets = self.get_targets(request, view) context = view._collect_permission_context() permissions = Permission.objects.filter_by_context( context).filter_by_targets(targets) if request.method in SAFE_METHODS: permission_kind = Permission.PERMISSIONS.view else: permission_kind = Permission.PERMISSIONS.edit return bool( Permission.apply_permissions(permissions, targets, permission_kind))
def _collect_permissions_targets(self): """ Collect permissions targets based on serializer's model and field name from full serializers tree. :return: """ targets = list() # Breath-first search queue = [self.root] while queue: node = queue.pop(0) if isinstance(node, serializers.ListSerializer): queue.append(node.child) continue if isinstance(node, RecursiveField): # stop too deep recursion node_fields = [] else: node_fields = node.fields.values() for field in node_fields: if isinstance(node, PermissionsBasedSerializerMixin): targets.append( Permission.get_target(node.Meta.model, field)) if isinstance(field, SeparatedReadWriteField): if isinstance(field.read_field, serializers.BaseSerializer): queue.append(field.read_field) if isinstance(field.write_field, serializers.BaseSerializer): queue.append(field.write_field) if isinstance(field, serializers.BaseSerializer): queue.append(field) return targets
def _collect_permissions_targets(self): """ Collect permissions targets based on serializer's model and field name from full serializers tree. :return: """ targets = list() # Breath-first search queue = [self.root] while queue: node = queue.pop(0) if isinstance(node, serializers.ListSerializer): queue.append(node.child) continue if isinstance(node, RecursiveField): # stop too deep recursion node_fields = [] else: node_fields = node.fields.values() for field in node_fields: if isinstance(node, PermissionsBasedSerializerMixin): targets.append(Permission.get_target(node.Meta.model, field)) if isinstance(field, SeparatedReadWriteField): if isinstance(field.read_field, serializers.BaseSerializer): queue.append(field.read_field) if isinstance(field.write_field, serializers.BaseSerializer): queue.append(field.write_field) if isinstance(field, serializers.BaseSerializer): queue.append(field) return targets