Source code for shuup.admin.utils.permissions

# -*- coding: utf-8 -*-
# This file is part of Shuup.
#
# Copyright (c) 2012-2021, Shuup Commerce Inc. All rights reserved.
#
# This source code is licensed under the OSL-3.0 license found in the
# LICENSE file in the root directory of this source tree.
import six
import warnings
from django.contrib.auth.models import Permission

from shuup import configuration
from shuup.core import cache

USER_PERMISSIONS_CACHE_NAMESPACE = "user_permissions"


[docs]def get_default_model_permissions(model): """ Return a set of all default permissions for a given model. :param model: Model class :type model: django.db.Model :return: Set of default model permissions as strings :rtype: set[str] """ warnings.warn( "Warning! `get_default_model_permissions` is deprecated in Shuup 2.0. " "Use human readable permission strings instead.", DeprecationWarning, ) permissions = set() for default in model._meta.default_permissions: permissions.add("%s.%s_%s" % (model._meta.app_label, default, model._meta.model_name)) return permissions
[docs]def get_missing_permissions(user, permissions): """ Return a set of missing permissions for a given iterable of permission strings. 1. Check missing permissions using `User.has_perm`-method allows us to use Django model permissions. 2. Check missing permissions using Shuup admin custom permissions which are stored to configuration items per user group. :param user: User instance to check for permissions. :type user: django.contrib.auth.models.User :param permissions: Iterable of permission strings. :type permissions: Iterable[str] :return: Set of missing permission strings. :rtype: set[str] """ if getattr(user, "is_superuser", False): return set() group_permissions = None if user: cache_key = "{}:{}".format(USER_PERMISSIONS_CACHE_NAMESPACE, user.pk) group_permissions = cache.get(cache_key) if group_permissions is None: group_permissions = get_permissions_from_groups(user.groups.values_list("pk", flat=True)) cache.set(cache_key, group_permissions) if group_permissions: missing_permissions = set(p for p in set(permissions) if p not in group_permissions) else: missing_permissions = set(permissions) return missing_permissions
[docs]def has_permission(user, permission): """ Returns whether user has permission for a given permission string. :param user: User instance to check for permission. :type user: django.contrib.auth.models.User :param permission: Permission string. :type permission: str :return: Whether user has permission. :rtype: bool """ return not bool(get_missing_permissions(user, [permission]))
def _get_permission_key_for_group(group_id): return "%s_admin_permissions" % group_id
[docs]def get_permissions_for_user(user): return get_permissions_from_groups(user.groups.values_list("pk", flat=True))
[docs]def get_permissions_from_group(group): group_id = group if isinstance(group, six.integer_types) else group.pk return set(configuration.get(None, _get_permission_key_for_group(group_id), default=[]))
[docs]def set_permissions_for_group(group, permissions): group_id = group if isinstance(group, six.integer_types) else group.pk configuration.set(None, _get_permission_key_for_group(group_id), permissions) cache.bump_version(USER_PERMISSIONS_CACHE_NAMESPACE)
[docs]def get_permissions_from_groups(groups): permissions = set() for group in groups: group_id = group if isinstance(group, six.integer_types) else group.pk permissions |= get_permissions_from_group(group_id) return permissions
[docs]def get_permissions_from_urls(urls): """ Return a set of permissions for a given iterable of urls. :param urls: Iterable of url objects to check for permissions. :type urls: Iterable[django.urls.RegexURLPattern] :return: Set of permissions for urls as strings. :rtype: set[str] """ permissions = set() for url in urls: if hasattr(url, "permissions") and url.permissions: permissions.update(url.permissions) return permissions
[docs]def get_permission_object_from_string(permission_string): """ Given a permission string of the form `app_label.permission_string`, get actual permission object. :param permission_string: Permission string. :type permission_strings: str :return: Permission object. :rtype: django.contrib.auth.models.Permission """ warnings.warn( "Warning! `get_permission_object_from_string` is deprecated in Shuup 2.0. " "Django permission shouldn't be needed.", DeprecationWarning, ) app_label, codename = permission_string.split(".") return Permission.objects.get(content_type__app_label=app_label, codename=codename)
[docs]def get_permissions_for_module_url(admin_module, url_name): """ Returns a set of permissions for a given admin module that match with `url_name`. If the url_name doesn't match with any admin url, a blank set is returned :param admin_module: The admin module to return permissions. :type admin_module: shuup.admin.AdminModule :param url_name: the url name. :type url_name: string :return: Set of permissions for the given module and url. :rtype: set[str] """ for url in admin_module.get_urls(): if url.name == url_name: return get_permissions_from_urls([url]) return set()