Giter Club home page Giter Club logo

Comments (3)

ericmuijs avatar ericmuijs commented on June 25, 2024

Example for improvement in guardian shortcuts for direct model:

if not any_perm and len(codenames): objects = queryset.filter(pk__in=Subquery(groups_obj_perms_queryset.values(fields[0]))) return objects

from django-guardian.

iamMHZ avatar iamMHZ commented on June 25, 2024

@ericmuijs
Yeah, there are some performance pitfalls specially in the shortcuts, You can send a PR imporving that (Supprots are very wellcome for the project #603)

from django-guardian.

vecchp avatar vecchp commented on June 25, 2024

Ended up writing a direct model only shortcut for another project. This may be useful for some people and maybe a PR can come out of it. Though I wasn't able to update the core library. Should result in a single query

from functools import reduce
from operator import and_, or_
from typing import List, TypeVar, Union, cast

from django.contrib.auth.models import AbstractBaseUser, AnonymousUser
from django.db.models import Exists, Model, OuterRef, Q, QuerySet
from guardian.utils import get_group_obj_perms_model, get_user_obj_perms_model

T = TypeVar("T", bound=Model)


def get_objects_for_user(
    user: Union[AbstractBaseUser, AnonymousUser],
    perms: List[str],
    klass: QuerySet[T],
    any_perm: bool = False,
) -> QuerySet[T]:
    """
    Fetches a queryset of objects for which the user has specified permissions.
    Acts as a replacement for Django Guardian's `get_objects_for_user`, aiming
    for flexible and efficient permission checks using Django's ORM.

    Args:
        user: User for whom to retrieve objects.
        perms: Permission strings to check.
        klass: Initial queryset of model objects.
        any_perm: If True, returns objects for any permissions. Else, all.

    Returns:
        A queryset of objects with the specified permissions for the user.

    Note:
        - Dynamically builds queries for user/group permissions.
        - Requires `klass` as a correct model type queryset and `perms` to be
          model-appropriate permission codenames.
        - Custom `UserObjectPermission` and `GroupObjectPermission` models
          associate permissions with model instances, enabling granular access
          control.
    """
    if not user.is_authenticated or not perms:
        return klass.none()

    user_permissions_field = get_user_obj_perms_model(
        klass.model
    ).permission.field.related_query_name()
    group_permissions_field = get_group_obj_perms_model(
        klass.model
    ).permission.field.related_query_name()

    qs = klass
    permission_filters = []

    for perm in perms:
        perm_codename = perm.split(".")[-1]
        user_perm_query = Q(
            **{
                f"{user_permissions_field}__permission__codename": perm_codename,
                f"{user_permissions_field}__user": user,
            }
        )
        group_perm_query = Q(
            **{
                f"{group_permissions_field}__permission__codename": perm_codename,
                f"{group_permissions_field}__group__user": user,
            }
        )
        permission_filters.append(
            Exists(klass.filter(user_perm_query | group_perm_query, pk=OuterRef("pk")))
        )

    if any_perm:
        combined_condition = reduce(or_, permission_filters)
    else:
        combined_condition = reduce(and_, permission_filters)

    return cast(
        QuerySet[T],
        qs.annotate(has_permission=combined_condition).filter(has_permission=True),
    )

from django-guardian.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.