cardo-python-utils 0.5.dev14__tar.gz → 0.5.dev16__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.dev14/cardo_python_utils.egg-info → cardo_python_utils-0.5.dev16}/PKG-INFO +1 -1
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16/cardo_python_utils.egg-info}/PKG-INFO +1 -1
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/pyproject.toml +1 -1
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/keycloak/api/drf.py +22 -2
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/keycloak/api/utils.py +6 -3
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/LICENSE +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/MANIFEST.in +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/README.rst +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/cardo_python_utils.egg-info/SOURCES.txt +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/cardo_python_utils.egg-info/dependency_links.txt +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/cardo_python_utils.egg-info/requires.txt +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/cardo_python_utils.egg-info/top_level.txt +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/__init__.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/choices.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/data_structures.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/db.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/keycloak/__init__.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/keycloak/admin/__init__.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/keycloak/admin/auth.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/keycloak/admin/user_group.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/keycloak/admin/user_groups_changelist.html +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/keycloak/api/__init__.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/keycloak/api/ninja.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/keycloak/models/__init__.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/keycloak/models/user_group.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/keycloak/service.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/django/utils.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/esma_choices.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/exceptions.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/imports.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/math.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/text.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/time.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/python_utils/types_hinting.py +0 -0
- {cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/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.dev16"
|
|
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"
|
|
@@ -13,7 +13,7 @@ class AuthenticationBackend(authentication.TokenAuthentication):
|
|
|
13
13
|
|
|
14
14
|
def authenticate_credentials(self, token: str):
|
|
15
15
|
try:
|
|
16
|
-
payload = decode_jwt(token)
|
|
16
|
+
payload = decode_jwt(token, audience=self._get_audience())
|
|
17
17
|
except InvalidTokenError as e:
|
|
18
18
|
raise AuthenticationFailed(f"Invalid token: {str(e)}") from e
|
|
19
19
|
|
|
@@ -26,6 +26,12 @@ class AuthenticationBackend(authentication.TokenAuthentication):
|
|
|
26
26
|
|
|
27
27
|
user = create_or_update_user(username, payload)
|
|
28
28
|
return user, payload
|
|
29
|
+
|
|
30
|
+
def _get_audience(self):
|
|
31
|
+
"""
|
|
32
|
+
Allows subclasses to override the audience used for JWT decoding.
|
|
33
|
+
"""
|
|
34
|
+
return getattr(settings, "JWT_AUDIENCE", None)
|
|
29
35
|
|
|
30
36
|
|
|
31
37
|
class HasScope(BasePermission):
|
|
@@ -42,18 +48,32 @@ class HasScope(BasePermission):
|
|
|
42
48
|
allowed_scopes = ["jobs"]
|
|
43
49
|
...
|
|
44
50
|
|
|
51
|
+
It is possible to define different scopes per HTTP method
|
|
52
|
+
by setting `allowed_scopes` as a dict:
|
|
53
|
+
|
|
54
|
+
class MyApiView(APIView):
|
|
55
|
+
permission_classes = [IsAuthenticated, HasScope]
|
|
56
|
+
allowed_scopes = {
|
|
57
|
+
"get": ["jobs"],
|
|
58
|
+
"post": ["jobs_admin"],
|
|
59
|
+
}
|
|
60
|
+
...
|
|
61
|
+
|
|
45
62
|
If no particular scope is required, you can set `allowed_scopes = "*"`
|
|
46
63
|
to allow access without scope checks.
|
|
47
64
|
"""
|
|
48
65
|
|
|
49
66
|
def has_permission(self, request, view):
|
|
50
|
-
allowed_scopes = getattr(view, "allowed_scopes",
|
|
67
|
+
allowed_scopes = getattr(view, "allowed_scopes", None)
|
|
51
68
|
|
|
52
69
|
if not allowed_scopes:
|
|
53
70
|
raise Exception(
|
|
54
71
|
f"No allowed_scopes defined on the view '{view.__class__.__name__}'. "
|
|
55
72
|
"Define allowed_scopes or set it to '*' to allow any scope."
|
|
56
73
|
)
|
|
74
|
+
|
|
75
|
+
if isinstance(allowed_scopes, dict):
|
|
76
|
+
allowed_scopes = allowed_scopes.get(request.method.lower(), [])
|
|
57
77
|
|
|
58
78
|
if allowed_scopes == "*":
|
|
59
79
|
return True
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import TypedDict, Union
|
|
1
|
+
from typing import Optional, TypedDict, Union
|
|
2
2
|
|
|
3
3
|
from django.conf import settings
|
|
4
4
|
from django.contrib.auth import get_user_model
|
|
@@ -27,7 +27,7 @@ class TokenPayload(TypedDict, total=False):
|
|
|
27
27
|
groups: list[str] # Full path of the user group, e.g. "/group1/subgroup1"
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
def decode_jwt(token: str) -> TokenPayload:
|
|
30
|
+
def decode_jwt(token: str, audience: Optional[str] = None) -> TokenPayload:
|
|
31
31
|
"""
|
|
32
32
|
Decode a JWT token using the public certificate of the Auth Server.
|
|
33
33
|
|
|
@@ -36,11 +36,14 @@ def decode_jwt(token: str) -> TokenPayload:
|
|
|
36
36
|
"""
|
|
37
37
|
signing_key = jwks_client.get_signing_key_from_jwt(token)
|
|
38
38
|
|
|
39
|
+
if audience is None:
|
|
40
|
+
audience = getattr(settings, "JWT_AUDIENCE", None)
|
|
41
|
+
|
|
39
42
|
return decode(
|
|
40
43
|
token,
|
|
41
44
|
signing_key.key,
|
|
42
45
|
algorithms=["RS256"],
|
|
43
|
-
audience=
|
|
46
|
+
audience=audience,
|
|
44
47
|
)
|
|
45
48
|
|
|
46
49
|
|
|
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
|
{cardo_python_utils-0.5.dev14 → cardo_python_utils-0.5.dev16}/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
|
|
File without changes
|