Encryptors 2.77__tar.gz → 2.79__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.
- {encryptors-2.77 → encryptors-2.79}/PKG-INFO +1 -1
- {encryptors-2.77 → encryptors-2.79}/setup.py +1 -1
- {encryptors-2.77 → encryptors-2.79}/src/Encryptors.egg-info/PKG-INFO +1 -1
- {encryptors-2.77 → encryptors-2.79}/src/Encryptors.egg-info/SOURCES.txt +1 -0
- encryptors-2.79/src/Osdental/Decorators/PublicResolver.py +139 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Decorators/SecureResolver.py +31 -38
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Helpers/AuditQueue.py +5 -2
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Helpers/AuthTokenProcessor.py +2 -2
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Models/Graphql.py +1 -0
- {encryptors-2.77 → encryptors-2.79}/README.md +0 -0
- {encryptors-2.77 → encryptors-2.79}/setup.cfg +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Encryptors.egg-info/dependency_links.txt +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Encryptors.egg-info/entry_points.txt +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Encryptors.egg-info/requires.txt +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Encryptors.egg-info/top_level.txt +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Cache/Redis.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Cache/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Cli/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Constants/Constant.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Constants/Message.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Constants/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Context/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Database/BaseRepository.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Database/Connection.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Database/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Decorators/Grpc.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Decorators/Retry.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Decorators/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Encryptor/Aes.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Encryptor/Argon2.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Encryptor/Bcrypt.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Encryptor/Jwt.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Encryptor/Rsa.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Encryptor/Sha512.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Encryptor/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Enums/AuditType.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Enums/CipherType.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Enums/FileType.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Enums/GrahpqlOperation.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Enums/GrpcStatusCode.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Enums/Profile.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Enums/ResultType.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Enums/Secret.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Enums/StatusCode.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Enums/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Exception/ControlledException.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Exception/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Helpers/AuditHelper.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Helpers/AzureClassifier.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Helpers/CipherHelper.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Helpers/JwtTokenHelper.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Helpers/Resilience.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Helpers/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Http/APIClient.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Http/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Messaging/AzureServiceBus.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Messaging/Kafka.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Messaging/RabbitMQ.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Messaging/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Models/ApiResponse.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Models/AuditContext.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Models/Notification.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Models/Response.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Models/Token.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Models/TokenClaims.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Models/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Secrets/AzureKeyVaultProvider.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Secrets/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Services/GrpcConnection.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Services/JwtAuthTokenService.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Services/ServiceBusAuditEmitter.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Services/WebsocketClient.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Services/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Storage/AzureBlobStorage.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Storage/S3Storage.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Storage/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/CaseConverter.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/CodeGenerator.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/DataNormalizer.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/DataUtils.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/DateUtils.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/FileMetaData.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/HashValidator.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/Mapper.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/PasswordGenerator.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/QueryGenerator.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/RsaUtils.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/TextProcessor.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/Utils/__init__.py +0 -0
- {encryptors-2.77 → encryptors-2.79}/src/Osdental/__init__.py +0 -0
|
@@ -18,6 +18,7 @@ src/Osdental/Database/BaseRepository.py
|
|
|
18
18
|
src/Osdental/Database/Connection.py
|
|
19
19
|
src/Osdental/Database/__init__.py
|
|
20
20
|
src/Osdental/Decorators/Grpc.py
|
|
21
|
+
src/Osdental/Decorators/PublicResolver.py
|
|
21
22
|
src/Osdental/Decorators/Retry.py
|
|
22
23
|
src/Osdental/Decorators/SecureResolver.py
|
|
23
24
|
src/Osdental/Decorators/__init__.py
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import asyncio
|
|
3
|
+
from functools import wraps
|
|
4
|
+
from typing import Callable
|
|
5
|
+
from graphql import GraphQLResolveInfo
|
|
6
|
+
from Osdental.Models.Response import Response
|
|
7
|
+
from Osdental.Models.Graphql import BaseGraphQLContext
|
|
8
|
+
from Osdental.Models.TokenClaims import AccessTokenClaims
|
|
9
|
+
from Osdental.Exception.ControlledException import (
|
|
10
|
+
OSDException
|
|
11
|
+
)
|
|
12
|
+
from Osdental.Services import IAuthTokenService
|
|
13
|
+
from Osdental.Helpers.AuthTokenProcessor import (
|
|
14
|
+
decrypt_and_parse_payload, get_current_user,
|
|
15
|
+
get_current_aes_key
|
|
16
|
+
)
|
|
17
|
+
from Osdental.Enums.StatusCode import StatusCode
|
|
18
|
+
from Osdental.Models.AuditContext import AuditContext
|
|
19
|
+
from Osdental.Helpers.AuditHelper import (
|
|
20
|
+
_build_success_payload, _build_error_payload, _build_unexpected_payload
|
|
21
|
+
)
|
|
22
|
+
from Osdental.Context import _ctx
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def public_resolver():
|
|
28
|
+
|
|
29
|
+
def decorator(func: Callable):
|
|
30
|
+
|
|
31
|
+
@wraps(func)
|
|
32
|
+
async def wrapper(obj, info: GraphQLResolveInfo, **kwargs):
|
|
33
|
+
try:
|
|
34
|
+
context: BaseGraphQLContext = info.context
|
|
35
|
+
container = context.container
|
|
36
|
+
request = context.request
|
|
37
|
+
headers = request.headers
|
|
38
|
+
settings = container.settings
|
|
39
|
+
|
|
40
|
+
access_token = headers.get("Accesstoken")
|
|
41
|
+
claims: AccessTokenClaims | None = None
|
|
42
|
+
audit_ctx: AuditContext | None = None
|
|
43
|
+
operation_type = info.operation.operation.value
|
|
44
|
+
|
|
45
|
+
# ── 1. AUTENTICACIÓN ──────────────────────────────
|
|
46
|
+
token_service: IAuthTokenService = container.auth_token_service
|
|
47
|
+
|
|
48
|
+
claims = await token_service.validate_external_access_token(
|
|
49
|
+
access_token
|
|
50
|
+
)
|
|
51
|
+
context.access_token = access_token
|
|
52
|
+
context.access_token_claims = claims
|
|
53
|
+
|
|
54
|
+
# ── 2. DECRYPT DEL PAYLOAD ────────────────────────
|
|
55
|
+
body = await request.json()
|
|
56
|
+
encrypted_payload = (
|
|
57
|
+
kwargs.get("data")
|
|
58
|
+
or body.get("variables", {}).get("data")
|
|
59
|
+
)
|
|
60
|
+
decrypted_payload = None
|
|
61
|
+
|
|
62
|
+
if encrypted_payload is not None:
|
|
63
|
+
decrypted_payload = decrypt_and_parse_payload(
|
|
64
|
+
aes_key_auth=claims.aes_key,
|
|
65
|
+
encrypted_payload=encrypted_payload
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
kwargs["data"] = decrypted_payload
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# ── 5. CONTEXTO DE AUDITORÍA ──────────────
|
|
72
|
+
# Lo construimos antes del resolver para que siempre exista
|
|
73
|
+
user = get_current_user(context)
|
|
74
|
+
key = get_current_aes_key(context)
|
|
75
|
+
audit_ctx = AuditContext.from_request(
|
|
76
|
+
request=request,
|
|
77
|
+
settings=settings,
|
|
78
|
+
body=body,
|
|
79
|
+
operation_type=operation_type,
|
|
80
|
+
id_user=user,
|
|
81
|
+
decrypted_key=key,
|
|
82
|
+
decrypted_payload=decrypted_payload,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
_ctx.set(audit_ctx)
|
|
86
|
+
|
|
87
|
+
# ── 6. EJECUTAR RESOLVER ──────────────────
|
|
88
|
+
result = await func(obj, info, **kwargs)
|
|
89
|
+
|
|
90
|
+
if not isinstance(result, Response):
|
|
91
|
+
raise TypeError("Resolver must return a Response instance")
|
|
92
|
+
|
|
93
|
+
# ── 7. AUDITAR ÉXITO ──────────────────────
|
|
94
|
+
_ = asyncio.create_task(
|
|
95
|
+
container.audit_emitter.emit(
|
|
96
|
+
{
|
|
97
|
+
"payload": _build_success_payload(audit_ctx, result),
|
|
98
|
+
"is_auditable": settings.is_auditable,
|
|
99
|
+
}
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
return result
|
|
104
|
+
|
|
105
|
+
except OSDException as e:
|
|
106
|
+
logger.warning(f"Business error: {str(e)}")
|
|
107
|
+
if audit_ctx:
|
|
108
|
+
_ = asyncio.create_task(
|
|
109
|
+
container.audit_emitter.emit(
|
|
110
|
+
{
|
|
111
|
+
"payload": _build_error_payload(audit_ctx, e),
|
|
112
|
+
"is_auditable": settings.is_auditable,
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
return Response(
|
|
117
|
+
status=e.status_code,
|
|
118
|
+
message=e.message,
|
|
119
|
+
error=e.error
|
|
120
|
+
)
|
|
121
|
+
except Exception as e:
|
|
122
|
+
logger.exception(f"Unexpected error: {str(e)}")
|
|
123
|
+
if audit_ctx:
|
|
124
|
+
_ = asyncio.create_task(
|
|
125
|
+
container.audit_emitter.emit(
|
|
126
|
+
{
|
|
127
|
+
"payload": _build_unexpected_payload(audit_ctx, e),
|
|
128
|
+
"is_auditable": settings.is_auditable,
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
return Response(
|
|
133
|
+
status=StatusCode.INTERNAL_SERVER_ERROR,
|
|
134
|
+
message="Could not process request.",
|
|
135
|
+
error=str(e)
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
return wrapper
|
|
139
|
+
return decorator
|
|
@@ -6,7 +6,7 @@ from graphql import GraphQLResolveInfo
|
|
|
6
6
|
from Osdental.Models.Response import Response
|
|
7
7
|
from Osdental.Models.Graphql import BaseGraphQLContext
|
|
8
8
|
from Osdental.Models.TokenClaims import (
|
|
9
|
-
UserTokenClaims
|
|
9
|
+
UserTokenClaims
|
|
10
10
|
)
|
|
11
11
|
from Osdental.Models.Token import AuthToken
|
|
12
12
|
from Osdental.Enums.Profile import Profile
|
|
@@ -28,10 +28,9 @@ from Osdental.Context import _ctx
|
|
|
28
28
|
logger = logging.getLogger(__name__)
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def resolver(
|
|
31
|
+
def resolver(action=None):
|
|
32
32
|
|
|
33
33
|
def decorator(func: Callable):
|
|
34
|
-
func._is_public = public
|
|
35
34
|
|
|
36
35
|
@wraps(func)
|
|
37
36
|
async def wrapper(obj, info: GraphQLResolveInfo, **kwargs):
|
|
@@ -42,29 +41,19 @@ def resolver(public: bool = False, action=None):
|
|
|
42
41
|
headers = request.headers
|
|
43
42
|
settings = container.settings
|
|
44
43
|
|
|
45
|
-
access_token = headers.get("Accesstoken")
|
|
46
44
|
token: type[AuthToken] | None = None
|
|
47
|
-
|
|
48
|
-
claims: UserTokenClaims | AccessTokenClaims | None = None
|
|
45
|
+
claims: UserTokenClaims | None = None
|
|
49
46
|
audit_ctx: AuditContext | None = None
|
|
50
47
|
operation_type = info.operation.operation.value
|
|
51
48
|
|
|
52
49
|
# ── 1. AUTENTICACIÓN ──────────────────────────────
|
|
53
50
|
token_service: IAuthTokenService = container.auth_token_service
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
elif public and access_token:
|
|
62
|
-
claims = await token_service.validate_external_access_token(
|
|
63
|
-
access_token
|
|
64
|
-
)
|
|
65
|
-
aes_key = claims.aes_key
|
|
66
|
-
context.access_token = access_token
|
|
67
|
-
context.access_token_claims = claims
|
|
51
|
+
user_token = extract_bearer_token(headers)
|
|
52
|
+
context.user_token = user_token
|
|
53
|
+
|
|
54
|
+
claims = await token_service.validate_internal_access_token(
|
|
55
|
+
user_token
|
|
56
|
+
)
|
|
68
57
|
|
|
69
58
|
# ── 2. DECRYPT DEL PAYLOAD ────────────────────────
|
|
70
59
|
body = await request.json()
|
|
@@ -76,26 +65,24 @@ def resolver(public: bool = False, action=None):
|
|
|
76
65
|
|
|
77
66
|
if encrypted_payload is not None:
|
|
78
67
|
decrypted_payload = decrypt_and_parse_payload(
|
|
79
|
-
aes_key_auth=
|
|
68
|
+
aes_key_auth=claims.aes_key_auth,
|
|
80
69
|
encrypted_payload=encrypted_payload
|
|
81
70
|
)
|
|
82
71
|
|
|
83
72
|
kwargs["data"] = decrypted_payload
|
|
84
73
|
|
|
85
74
|
# ── 3. TENANT POLICY ──────────────────────────────
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
context.token = token
|
|
75
|
+
token = build_auth_token(
|
|
76
|
+
claims=claims,
|
|
77
|
+
headers=request.headers,
|
|
78
|
+
decrypted_payload=decrypted_payload,
|
|
79
|
+
operation_type=operation_type,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
context.token = token
|
|
96
83
|
|
|
97
84
|
# ── 4. CONTROL DE ACCESO POR ROL ─────────────────
|
|
98
|
-
if
|
|
85
|
+
if action:
|
|
99
86
|
if Profile(token.abbreviation) not in action.allowed_roles:
|
|
100
87
|
raise AccessDeniedException(
|
|
101
88
|
status_code=StatusCode.BUSINESS_RULE_WARNING,
|
|
@@ -127,8 +114,10 @@ def resolver(public: bool = False, action=None):
|
|
|
127
114
|
# ── 7. AUDITAR ÉXITO ──────────────────────
|
|
128
115
|
_ = asyncio.create_task(
|
|
129
116
|
container.audit_emitter.emit(
|
|
130
|
-
|
|
131
|
-
|
|
117
|
+
{
|
|
118
|
+
"payload": _build_success_payload(audit_ctx, result),
|
|
119
|
+
"is_auditable": settings.is_auditable,
|
|
120
|
+
}
|
|
132
121
|
)
|
|
133
122
|
)
|
|
134
123
|
|
|
@@ -139,8 +128,10 @@ def resolver(public: bool = False, action=None):
|
|
|
139
128
|
if audit_ctx:
|
|
140
129
|
_ = asyncio.create_task(
|
|
141
130
|
container.audit_emitter.emit(
|
|
142
|
-
|
|
143
|
-
|
|
131
|
+
{
|
|
132
|
+
"payload": _build_error_payload(audit_ctx, e),
|
|
133
|
+
"is_auditable": settings.is_auditable,
|
|
134
|
+
}
|
|
144
135
|
)
|
|
145
136
|
)
|
|
146
137
|
return Response(
|
|
@@ -153,8 +144,10 @@ def resolver(public: bool = False, action=None):
|
|
|
153
144
|
if audit_ctx:
|
|
154
145
|
_ = asyncio.create_task(
|
|
155
146
|
container.audit_emitter.emit(
|
|
156
|
-
|
|
157
|
-
|
|
147
|
+
{
|
|
148
|
+
"payload": _build_unexpected_payload(audit_ctx, e),
|
|
149
|
+
"is_auditable": settings.is_auditable,
|
|
150
|
+
}
|
|
158
151
|
)
|
|
159
152
|
)
|
|
160
153
|
return Response(
|
|
@@ -27,10 +27,13 @@ class AuditQueue:
|
|
|
27
27
|
|
|
28
28
|
async def _consume(self):
|
|
29
29
|
while True:
|
|
30
|
-
|
|
30
|
+
item = await self._queue.get()
|
|
31
31
|
|
|
32
32
|
try:
|
|
33
|
-
await self._worker(
|
|
33
|
+
await self._worker(
|
|
34
|
+
item["payload"],
|
|
35
|
+
item["is_auditable"],
|
|
36
|
+
)
|
|
34
37
|
|
|
35
38
|
except Exception:
|
|
36
39
|
logger.exception("Error processing audit")
|
|
@@ -10,11 +10,11 @@ from Osdental.Enums.Profile import Profile
|
|
|
10
10
|
from Osdental.Models.TokenClaims import UserTokenClaims
|
|
11
11
|
from Osdental.Models.Graphql import BaseGraphQLContext
|
|
12
12
|
|
|
13
|
-
def extract_bearer_token(headers: Headers) -> str:
|
|
13
|
+
def extract_bearer_token(headers: Headers) -> str | None:
|
|
14
14
|
|
|
15
15
|
authorization = headers.get("authorization")
|
|
16
16
|
if not authorization or not authorization.startswith("Bearer "):
|
|
17
|
-
|
|
17
|
+
return None
|
|
18
18
|
|
|
19
19
|
return authorization.removeprefix("Bearer ").strip()
|
|
20
20
|
|
|
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
|
|
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
|
|
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
|
|
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
|