Пример #1
0
 def save(self, *args, **kwargs):
     content_type = get_ctype_from_polymorphic(self.content_object)
     if content_type != self.permission.content_type:
         raise ValidationError("Cannot persist permission not designed for "
             "this class (permission's type is %r and object's type is %r)"
             % (self.permission.content_type, content_type))
     return super(BaseObjectPermission, self).save(*args, **kwargs)
Пример #2
0
def get_perms_for_model(cls):
    """
    Returns queryset of all Permission objects for the given class. It is
    possible to pass Model as class or instance.
    """
    if isinstance(cls, basestring):
        app_label, model_name = cls.split('.')
        model = models.get_model(app_label, model_name)
    else:
        model = cls
    ctype = get_ctype_from_polymorphic(model)
    return Permission.objects.filter(content_type=ctype)
Пример #3
0
def get_groups_with_perms(obj, attach_perms=False):
    """
    Returns queryset of all ``Group`` objects with *any* object permissions for
    the given ``obj``.

    :param obj: persisted Django's ``Model`` instance

    :param attach_perms: Default: ``False``. If set to ``True`` result would be
      dictionary of ``Group`` instances with permissions' codenames list as
      values. This would fetch groups eagerly!

    Example::

        >>> from django.contrib.flatpages.models import FlatPage
        >>> from guardian.shortcuts import assign_perm, get_groups_with_perms
        >>> from guardian.models import Group
        >>>
        >>> page = FlatPage.objects.create(title='Some page', path='/some/page/')
        >>> admins = Group.objects.create(name='Admins')
        >>> assign_perm('change_flatpage', admins, page)
        >>>
        >>> get_groups_with_perms(page)
        [<Group: admins>]
        >>>
        >>> get_groups_with_perms(page, attach_perms=True)
        {<Group: admins>: [u'change_flatpage']}

    """
    ctype = get_ctype_from_polymorphic(obj)
    if not attach_perms:
        # It's much easier without attached perms so we do it first if that is
        # the case
        group_model = get_group_obj_perms_model(obj)
        group_rel_name = group_model.group.field.related_query_name()
        if group_model.objects.is_generic():
            group_filters = {
                '%s__content_type' % group_rel_name: ctype,
                '%s__object_pk' % group_rel_name: obj.pk,
            }
        else:
            group_filters = {'%s__content_object' % group_rel_name: obj}
        groups = Group.objects.filter(**group_filters).distinct()
        return groups
    else:
        # TODO: Do not hit db for each group!
        groups = {}
        for group in get_groups_with_perms(obj):
            if not group in groups:
                groups[group] = sorted(get_perms(group, obj))
        return groups
Пример #4
0
    def remove_perm(self, perm, group, obj):
        """
        Removes permission ``perm`` for an instance ``obj`` and given ``group``.
        """
        if getattr(obj, 'pk', None) is None:
            raise ObjectNotPersisted("Object %s needs to be persisted first"
                % obj)
        filters = {
            'permission__codename': perm,
            'permission__content_type': get_ctype_from_polymorphic(obj),
            'group': group,
        }
        if self.is_generic():
            filters['object_pk'] = obj.pk
        else:
            filters['content_object__pk'] = obj.pk

        self.filter(**filters).delete()
Пример #5
0
    def has_object_permission(self, request, view, obj):
        ctype = get_ctype_from_polymorphic(obj)

        model_cls = ctype.model_class()
        user = request.user

        perms = self.get_required_object_permissions(request.method, model_cls)

        if not user.has_perms(perms, obj):
            if request.method in SAFE_METHODS:
                raise Http404

            read_perms = self.get_required_object_permissions('GET', model_cls)
            if not user.has_perms(read_perms, obj):
                raise Http404

            return False

        return True
Пример #6
0
    def assign_perm(self, perm, group, obj):
        """
        Assigns permission with given ``perm`` for an instance ``obj`` and
        ``group``.
        """
        if getattr(obj, 'pk', None) is None:
            raise ObjectNotPersisted("Object %s needs to be persisted first"
                % obj)
        ctype = get_ctype_from_polymorphic(obj)
        permission = Permission.objects.get(content_type=ctype, codename=perm)

        kwargs = {'permission': permission, 'group': group}
        if self.is_generic():
            kwargs['content_type'] = ctype
            kwargs['object_pk'] = obj.pk
        else:
            kwargs['content_object'] = obj
        obj_perm, created = self.get_or_create(**kwargs)
        return obj_perm
Пример #7
0
    def has_object_permission(self, request, view, obj):
        ctype = get_ctype_from_polymorphic(obj)

        model_cls = ctype.model_class()
        user = request.user

        perms = self.get_required_object_permissions(request.method, model_cls)

        if not user.has_perms(perms, obj):
            if request.method in SAFE_METHODS:
                raise Http404

            read_perms = self.get_required_object_permissions('GET', model_cls)
            if not user.has_perms(read_perms, obj):
                raise Http404

            return False

        return True
Пример #8
0
    def remove_perm(self, perm, user, obj):
        """
        Removes permission ``perm`` for an instance ``obj`` and given ``user``.

        Please note that we do NOT fetch object permission from database - we
        use ``Queryset.delete`` method for removing it. Main implication of this
        is that ``post_delete`` signals would NOT be fired.
        """
        if getattr(obj, 'pk', None) is None:
            raise ObjectNotPersisted("Object %s needs to be persisted first"
                % obj)
        filters = {
            'permission__codename': perm,
            'permission__content_type': get_ctype_from_polymorphic(obj),
            'user': user,
        }
        if self.is_generic():
            filters['object_pk'] = obj.pk
        else:
            filters['content_object__pk'] = obj.pk
        self.filter(**filters).delete()
Пример #9
0
    def get_perms(self, obj):
        """
        Returns list of ``codename``'s of all permissions for given ``obj``.

        :param obj: Django model instance for which permission should be checked

        """
        if self.user and not self.user.is_active:
            return []
        User = get_user_model()
        ctype = get_ctype_from_polymorphic(obj)
        key = self.get_local_cache_key(obj)
        if not key in self._obj_perms_cache:

            group_model = get_group_obj_perms_model(obj)
            group_rel_name = group_model.permission.field.related_query_name()
            if self.user:
                fieldname = '%s__group__%s' % (
                    group_rel_name,
                    User.groups.field.related_query_name(),
                )
                group_filters = {fieldname: self.user}
            else:
                group_filters = {'%s__group' % group_rel_name: self.group}
            if group_model.objects.is_generic():
                group_filters.update({
                    '%s__content_type' % group_rel_name: ctype,
                    '%s__object_pk' % group_rel_name: obj.pk,
                })
            else:
                group_filters['%s__content_object' % group_rel_name] = obj

            if self.user and self.user.is_superuser:
                perms = list(chain(*Permission.objects
                    .filter(content_type=ctype)
                    .values_list("codename")))
            elif self.user:
                model = get_user_obj_perms_model(obj)
                related_name = model.permission.field.related_query_name()
                user_filters = {'%s__user' % related_name: self.user}
                if model.objects.is_generic():
                    user_filters.update({
                        '%s__content_type' % related_name: ctype,
                        '%s__object_pk' % related_name: obj.pk,
                    })
                else:
                    user_filters['%s__content_object' % related_name] = obj
                perms_qs = Permission.objects.filter(content_type=ctype)
                # Query user and group permissions separately and then combine
                # the results to avoid a slow query
                user_perms_qs = perms_qs.filter(**user_filters)
                user_perms = user_perms_qs.values_list("codename", flat=True)
                group_perms_qs = perms_qs.filter(**group_filters)
                group_perms = group_perms_qs.values_list("codename", flat=True)
                perms = list(set(chain(user_perms, group_perms)))
            else:
                perms = list(set(chain(*Permission.objects
                    .filter(content_type=ctype)
                    .filter(**group_filters)
                    .values_list("codename"))))
            self._obj_perms_cache[key] = perms
        return self._obj_perms_cache[key]
Пример #10
0
 def get_local_cache_key(self, obj):
     """
     Returns cache key for ``_obj_perms_cache`` dict.
     """
     ctype = get_ctype_from_polymorphic(obj)
     return (ctype.id, obj.pk)
Пример #11
0
def get_users_with_perms(obj, attach_perms=False, with_superusers=False,
        with_group_users=True):
    """
    Returns queryset of all ``User`` objects with *any* object permissions for
    the given ``obj``.

    :param obj: persisted Django's ``Model`` instance

    :param attach_perms: Default: ``False``. If set to ``True`` result would be
      dictionary of ``User`` instances with permissions' codenames list as
      values. This would fetch users eagerly!

    :param with_superusers: Default: ``False``. If set to ``True`` result would
      contain all superusers.

    :param with_group_users: Default: ``True``. If set to ``False`` result would
      **not** contain those users who have only group permissions for given
      ``obj``.

    Example::

        >>> from django.contrib.flatpages.models import FlatPage
        >>> from django.contrib.auth.models import User
        >>> from guardian.shortcuts import assign_perm, get_users_with_perms
        >>>
        >>> page = FlatPage.objects.create(title='Some page', path='/some/page/')
        >>> joe = User.objects.create_user('joe', '*****@*****.**', 'joesecret')
        >>> assign_perm('change_flatpage', joe, page)
        >>>
        >>> get_users_with_perms(page)
        [<User: joe>]
        >>>
        >>> get_users_with_perms(page, attach_perms=True)
        {<User: joe>: [u'change_flatpage']}

    """
    ctype = get_ctype_from_polymorphic(obj)
    if not attach_perms:
        # It's much easier without attached perms so we do it first if that is
        # the case
        user_model = get_user_obj_perms_model(obj)
        related_name = user_model.user.field.related_query_name()
        if user_model.objects.is_generic():
            user_filters = {
                '%s__content_type' % related_name: ctype,
                '%s__object_pk' % related_name: obj.pk,
            }
        else:
            user_filters = {'%s__content_object' % related_name: obj}
        qset = Q(**user_filters)
        if with_group_users:
            group_model = get_group_obj_perms_model(obj)
            group_rel_name = group_model.group.field.related_query_name()
            if group_model.objects.is_generic():
                group_filters = {
                    'groups__%s__content_type' % group_rel_name: ctype,
                    'groups__%s__object_pk' % group_rel_name: obj.pk,
                }
            else:
                group_filters = {
                    'groups__%s__content_object' % group_rel_name: obj,
                }
            qset = qset | Q(**group_filters)
        if with_superusers:
            qset = qset | Q(is_superuser=True)
        return get_user_model().objects.filter(qset).distinct()
    else:
        # TODO: Do not hit db for each user!
        users = {}
        for user in get_users_with_perms(obj,
                with_group_users=with_group_users):
            users[user] = sorted(get_perms(user, obj))
        return users