cardo-python-utils 0.5.dev13__tar.gz → 0.5.dev15__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cardo_python_utils-0.5.dev13/cardo_python_utils.egg-info → cardo_python_utils-0.5.dev15}/PKG-INFO +1 -1
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15/cardo_python_utils.egg-info}/PKG-INFO +1 -1
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/pyproject.toml +1 -1
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/choices.py +4 -3
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/keycloak/api/drf.py +15 -1
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/keycloak/api/ninja.py +3 -3
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/keycloak/api/utils.py +2 -2
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/LICENSE +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/MANIFEST.in +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/README.rst +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/cardo_python_utils.egg-info/SOURCES.txt +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/cardo_python_utils.egg-info/dependency_links.txt +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/cardo_python_utils.egg-info/requires.txt +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/cardo_python_utils.egg-info/top_level.txt +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/__init__.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/data_structures.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/db.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/keycloak/__init__.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/keycloak/admin/__init__.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/keycloak/admin/auth.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/keycloak/admin/user_group.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/keycloak/admin/user_groups_changelist.html +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/keycloak/api/__init__.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/keycloak/models/__init__.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/keycloak/models/user_group.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/keycloak/service.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/django/utils.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/esma_choices.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/exceptions.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/imports.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/math.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/text.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/time.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/types_hinting.py +0 -0
- {cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/setup.cfg +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cardo-python-utils"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.dev15"
|
|
8
8
|
description = "Python library enhanced with a wide range of functions for different scenarios."
|
|
9
9
|
readme = "README.rst"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -9,6 +9,7 @@ It adds some useful methods to the Enum class, such as:
|
|
|
9
9
|
|
|
10
10
|
from abc import ABC, abstractmethod
|
|
11
11
|
from enum import EnumMeta, Enum
|
|
12
|
+
from typing import Union
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class IChoice(ABC):
|
|
@@ -41,7 +42,7 @@ class ChoiceEnumMeta(EnumMeta, IChoice, ABC):
|
|
|
41
42
|
|
|
42
43
|
return new_cls
|
|
43
44
|
|
|
44
|
-
def __contains__(cls, item: int
|
|
45
|
+
def __contains__(cls, item: Union[int, str]) -> bool:
|
|
45
46
|
if isinstance(item, int):
|
|
46
47
|
member_values = [v.value[0] for v in cls.__members__.values()]
|
|
47
48
|
elif isinstance(item, str):
|
|
@@ -75,12 +76,12 @@ class ChoiceEnum(Enum, metaclass=ChoiceEnumMeta):
|
|
|
75
76
|
return {elm.value[0]: elm.value[1] for elm in cls}
|
|
76
77
|
|
|
77
78
|
@classmethod
|
|
78
|
-
def get_by_value(cls, value: str
|
|
79
|
+
def get_by_value(cls, value: Union[str, int]):
|
|
79
80
|
value_index = 0 if isinstance(value, int) else 1
|
|
80
81
|
return next((v for v in cls.__members__.values() if v.value[value_index] == value), None)
|
|
81
82
|
|
|
82
83
|
@classmethod
|
|
83
|
-
def list_as(cls, item_type) -> list[int
|
|
84
|
+
def list_as(cls, item_type) -> list[Union[int, str]]:
|
|
84
85
|
if item_type not in [int, str]:
|
|
85
86
|
raise TypeError('Invalid item type')
|
|
86
87
|
return list(map(item_type, cls))
|
|
@@ -42,18 +42,32 @@ class HasScope(BasePermission):
|
|
|
42
42
|
allowed_scopes = ["jobs"]
|
|
43
43
|
...
|
|
44
44
|
|
|
45
|
+
It is possible to define different scopes per HTTP method
|
|
46
|
+
by setting `allowed_scopes` as a dict:
|
|
47
|
+
|
|
48
|
+
class MyApiView(APIView):
|
|
49
|
+
permission_classes = [IsAuthenticated, HasScope]
|
|
50
|
+
allowed_scopes = {
|
|
51
|
+
"get": ["jobs"],
|
|
52
|
+
"post": ["jobs_admin"],
|
|
53
|
+
}
|
|
54
|
+
...
|
|
55
|
+
|
|
45
56
|
If no particular scope is required, you can set `allowed_scopes = "*"`
|
|
46
57
|
to allow access without scope checks.
|
|
47
58
|
"""
|
|
48
59
|
|
|
49
60
|
def has_permission(self, request, view):
|
|
50
|
-
allowed_scopes = getattr(view, "allowed_scopes",
|
|
61
|
+
allowed_scopes = getattr(view, "allowed_scopes", None)
|
|
51
62
|
|
|
52
63
|
if not allowed_scopes:
|
|
53
64
|
raise Exception(
|
|
54
65
|
f"No allowed_scopes defined on the view '{view.__class__.__name__}'. "
|
|
55
66
|
"Define allowed_scopes or set it to '*' to allow any scope."
|
|
56
67
|
)
|
|
68
|
+
|
|
69
|
+
if isinstance(allowed_scopes, dict):
|
|
70
|
+
allowed_scopes = allowed_scopes.get(request.method.lower(), [])
|
|
57
71
|
|
|
58
72
|
if allowed_scopes == "*":
|
|
59
73
|
return True
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from typing import Literal, Optional
|
|
2
|
+
from typing import Literal, Optional, Union
|
|
3
3
|
|
|
4
4
|
from jwt.exceptions import InvalidTokenError
|
|
5
5
|
|
|
@@ -93,7 +93,7 @@ class AuthBearer(HttpBearer):
|
|
|
93
93
|
|
|
94
94
|
if scopes is None:
|
|
95
95
|
raise Exception(
|
|
96
|
-
f"No allowed_scopes defined on the view {view_function.__name__}."
|
|
96
|
+
f"No allowed_scopes defined on the view {view_function.__name__}. "
|
|
97
97
|
"Add the decorator @allowed_scopes([...]) or @allowed_scopes('*') to the view."
|
|
98
98
|
)
|
|
99
99
|
|
|
@@ -138,7 +138,7 @@ class AuthBearerAsync(AuthBearer):
|
|
|
138
138
|
return payload
|
|
139
139
|
|
|
140
140
|
|
|
141
|
-
def allowed_scopes(scopes: list[str]
|
|
141
|
+
def allowed_scopes(scopes: Union[list[str], Literal["*"]]):
|
|
142
142
|
"""
|
|
143
143
|
A decorator that attaches a list of required scopes to a view function
|
|
144
144
|
in the attribute `_allowed_scopes`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import TypedDict
|
|
1
|
+
from typing import TypedDict, Union
|
|
2
2
|
|
|
3
3
|
from django.conf import settings
|
|
4
4
|
from django.contrib.auth import get_user_model
|
|
@@ -13,7 +13,7 @@ class TokenPayload(TypedDict, total=False):
|
|
|
13
13
|
iat: int
|
|
14
14
|
jti: str
|
|
15
15
|
iss: str
|
|
16
|
-
aud: str
|
|
16
|
+
aud: Union[str, list[str]]
|
|
17
17
|
typ: str
|
|
18
18
|
azp: str
|
|
19
19
|
sid: str
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cardo_python_utils-0.5.dev13 → cardo_python_utils-0.5.dev15}/python_utils/data_structures.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|