Simple access-scopes utility package.
Project description
Access scopes
Utility package for access scopes definition and checking.
Installation
pip install px-access-scopes
Usage
Defining access scopes:
access_scopes.py
from px_access_scopes import ScopeRegistry, ScopeDomain, auto, raw
# Creating root access scopes registry.
root = ScopeRegistry.create_root(ScopeDomain('TOKENS'))
# Tokens can be any Enum or even a simple object.
@root.nest('TOKENS')
class Tokens(Enum):
AUTO1 = auto
AUTO2 = auto
RAW = raw('RAW')
FIXED = 'SOME'
@Tokens.nest('NESTED')
class Nested:
AUTO = auto
SOME = 'OTHER'
Defining scopes aggregates(roles):
access_aggregates.py
from px_access_scopes import Aggregates
from .access_scopes import Tokens, Nested
class Roles(Aggregates):
Simple = Aggregate('Simple')
First = Aggregate('First')
Roles.Simple.add(Tokens.RAW)
Roles.First.add(Tokens.RAW)
Roles.First.add(Nested.SOME)
Run checkers whenever you need:
from px_access_scopes import (
ScopesCheckRunner, scopes_checker, aggregates_checker, HierarchyChecker,
domain_path_hierarchy_lookup,
)
from .access_scopes import Tokens, Nested
from .access_aggregates import Roles
# Defining a checker. The result is just a simple callable.
# ScopesCheckRunner receives special checker runners list and evaluates them,
# until it founds a match.
checker = ScopesCheckRunner((
HierarchyChecker((
scopes_checker,
aggregates_checker,
), hierarchy_lookup=domain_path_hierarchy_lookup),
))
USER1 = {'scopes': [Nested.AUTO]}
USER2 = {'scopes': [Nested.AUTO], 'aggregates': [Roles.Simple]}
USER3 = {'scopes': [Nested.AUTO], 'aggregates': [Roles.First]}
# It receives scopes list and kwargs, that internal checkers need to make decision.
checker((Nested.AUTO,), **USER1) # > True
checker((Nested.SOME,), **USER1) # > False
checker((Tokens.RAW,), **USER2) # > True
checker((Tokens.RAW,), **USER3) # > True
checker((Nested.AUTO,), **USER3) # > True
checker((Nested.SOME,), **USER3) # > True
Django
Registering scopes registries and access tokens aggregates.
On every manage.py migrate
auth Permissions and Groups will be autogenerated based on registered definitions.
settings.py
PX_ACCESS_TOKENS_REGISTRIES = [
'access_scopes.staff_root',
]
PX_ACCESS_TOKENS_AGGREGATES = [
'access_scopes.Roles',
]
access_scopes.py
from django.utils.translation import pgettext_lazy
from django.db.models.enums import TextChoices
# Has it's own, a little bit improved for django implementations:
from px_access_scopes.contrib.django import Aggregate, Aggregates, ScopeRegistry
class Roles(Aggregates):
# First parameter for any django aggregate is group identifier.
# Second is a key name, and the third one is an aggregate's verbose_name.
Admin = Aggregate(5000, 'Admin', pgettext_lazy('staff', 'Admin'))
Owner = Aggregate(4900, 'Owner', pgettext_lazy('staff', 'Owner'))
Reader = Aggregate(4800, 'Reader', pgettext_lazy('staff', 'Reader'))
staff_root = ScopeRegistry.create_root('STAFF', pgettext_lazy('staff', 'Staff'))
# TextChoices is also a Enum, but with labels so better use a django-specific registry.
@staff_root.nest('USERS', pgettext_lazy('staff', 'Users'))
class Users(TextChoices):
VIEW = 'VIEW', pgettext_lazy('staff', 'View')
CHANGE = 'CHANGE', pgettext_lazy('staff', 'Change')
CHANGE_OWN = 'CHANGE_OWN', pgettext_lazy('staff', 'Change own')
DISABLE = 'DISABLE', pgettext_lazy('staff', 'Disable')
SHARED = {Users.CHANGE_OWN}
Roles.Admin.update(
SHARED
| {Users.CHANGE, Users.VIEW, Users.DISABLE}
)
Roles.Owner.update(
SHARED
| {Users.CHANGE_OWN, Users.VIEW}
)
Roles.Reader.update(
SHARED
)
And so now you may run a checker for any user. Internally django checker will use user's .has_perm
. So this way administrators cay manage access for any user.
from px_access_scopes import (
ScopesChecker, HierarchyChecker, ScopesCheckRunner,
MultiregistryHierarchyLookup
)
from px_access_scopes.contrib.django import ScopeDomain, user_checker
# All registries, that you've registered in config
from px_access_scopes.contrib.django.globals import registries
from .access_scopes import Users
# Simple checker here.
checker: ScopesChecker = ScopesCheckRunner((
HierarchyChecker(
# Django-specific checker that calls `user.has_perm`.
(user_checker,),
hierarchy_lookup=MultiregistryHierarchyLookup(
# This might be any registries, not default ones.
registries=registries
)
),
))
def my_view(request):
can = checker(
# `.permission` - is the django's permission string.
(User.CHANGE.permission,),
# User kwarg is required for `user_checker`.
user=request.user,
)
if not can:
raise ...
...
For an easier usage scope on frontend there is an export mechanics:
from px_access_scopes.contrib.django.export import export_scopes
Function export_scopes
exports all scopes from all registered registries. It has two modes: shorter one export_scopes(as_leaves=True)
and more verbose and full export_scopes(as_leaves=False)
. It's for you to decide which one is preferable.
DRF
For django rest framework there are ready-to use permission classes.
They use the same checker mechanics as described above in django checking section.
some_views.py
from rest_framework.permissions import IsAuthenticated
from .access_scopes import Users
class UserUpdateDestroyAPIView:
permission_classes = (
IsAuthenticated
&
(
# You may pass multiple scopes here.
# Checker will be evaluated only for passed methods.
# `methods` keyword is optional as by default it will check permission
# for every possible method.
ScopePermission.from_scopes(Users.VIEW, methods=('GET',))
|
ScopePermission.from_scopes(Users.CHANGE, methods=('PUT', 'PATCH))
|
ScopePermission.from_scopes(Users.CHANGE_OWN, methods=('PUT', 'PATCH))
|
ScopePermission.from_scopes(Users.DISABLE, methods=('DELETE',))
),
)
serializer_class = UserSerializer
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[0.1.7]
Added
- Django 4.x support.
[0.1.0]
Initial version.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file px-access-scopes-0.1.7.tar.gz
.
File metadata
- Download URL: px-access-scopes-0.1.7.tar.gz
- Upload date:
- Size: 18.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d59610ec3115c85820569796598f03101c5d8740e234cdbb10c4cacc1330b12c |
|
MD5 | 9205f5b9c35b2c93b81bdff383ee44f2 |
|
BLAKE2b-256 | 71993dd7ef5b381f791dfd9b5926fbdfd38af5cb88eef97430da2fea823cb81a |