Encryptors 2.34__tar.gz → 2.36__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.34 → encryptors-2.36}/PKG-INFO +1 -1
- {encryptors-2.34 → encryptors-2.36}/setup.py +1 -1
- {encryptors-2.34 → encryptors-2.36}/src/Encryptors.egg-info/PKG-INFO +1 -1
- {encryptors-2.34 → encryptors-2.36}/src/Encryptors.egg-info/SOURCES.txt +1 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Decorators/SecureResolver.py +11 -13
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Encryptor/Aes.py +10 -10
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Exception/ControlledException.py +9 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Graphql/Extensions/AuditExtension.py +29 -11
- encryptors-2.36/src/Osdental/Graphql/Models/__init__.py +14 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Graphql/_Exceptions/__init__.py +1 -1
- encryptors-2.36/src/Osdental/Graphql/_Helpers/_ExtractAuthToken.py +11 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Graphql/_Helpers/_TenantPolicy.py +10 -7
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Graphql/_Helpers/_TokenService.py +6 -9
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Helpers/AuditDispatcher.py +1 -1
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Http/APIClient.py +4 -2
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Models/Token.py +0 -2
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Enums/Code.py +1 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Enums/Message.py +1 -0
- encryptors-2.34/src/Osdental/Graphql/_Helpers/_ExtractAuthToken.py +0 -11
- {encryptors-2.34 → encryptors-2.36}/README.md +0 -0
- {encryptors-2.34 → encryptors-2.36}/setup.cfg +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Encryptors.egg-info/dependency_links.txt +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Encryptors.egg-info/entry_points.txt +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Encryptors.egg-info/requires.txt +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Encryptors.egg-info/top_level.txt +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Cli/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Database/BaseRepository.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Database/Connection.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Database/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Decorators/Grpc.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Decorators/Retry.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Decorators/SqlDataNormalizer.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Decorators/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Encryptor/Argon2.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Encryptor/Bcrypt.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Encryptor/Jwt.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Encryptor/Rsa.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Encryptor/Sha512.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Encryptor/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Exception/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Graphql/Extensions/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Graphql/_Helpers/_AuditHelper.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Graphql/_Helpers/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Graphql/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Helpers/KeyVaultService.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Helpers/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Http/_Exceptions.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Http/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Messaging/AzureServiceBus.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Messaging/Kafka.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Messaging/RabbitMQ.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Messaging/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Models/AuditConfig.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Models/Catalog.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Models/Legacy.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Models/Response.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Models/_Audit.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Models/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/RedisCache/Redis.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/RedisCache/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Rest/Context/RequestContext.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Rest/Context/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Rest/Middlewares/RequestContextMiddleware.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Rest/Middlewares/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Rest/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Enums/Constant.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Enums/FileType.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Enums/GrahpqlOperation.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Enums/Profile.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Enums/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Logger.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Utils/CaseConverter.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Utils/CodeGenerator.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Utils/DataNormalizer.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Utils/DataUtils.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Utils/DateUtils.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Utils/FileMetaData.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Utils/HashValidator.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Utils/Mapper.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Utils/PasswordGenerator.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Utils/QueryGenerator.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Utils/TextProcessor.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/Utils/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Shared/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Storage/AzureBlobStorage.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Storage/S3Storage.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/Storage/__init__.py +0 -0
- {encryptors-2.34 → encryptors-2.36}/src/Osdental/__init__.py +0 -0
|
@@ -28,6 +28,7 @@ src/Osdental/Exception/__init__.py
|
|
|
28
28
|
src/Osdental/Graphql/__init__.py
|
|
29
29
|
src/Osdental/Graphql/Extensions/AuditExtension.py
|
|
30
30
|
src/Osdental/Graphql/Extensions/__init__.py
|
|
31
|
+
src/Osdental/Graphql/Models/__init__.py
|
|
31
32
|
src/Osdental/Graphql/_Exceptions/__init__.py
|
|
32
33
|
src/Osdental/Graphql/_Helpers/_AuditHelper.py
|
|
33
34
|
src/Osdental/Graphql/_Helpers/_ExtractAuthToken.py
|
|
@@ -2,15 +2,13 @@ import inspect
|
|
|
2
2
|
import copy
|
|
3
3
|
from functools import wraps
|
|
4
4
|
from typing import Callable, Dict, Any
|
|
5
|
-
from graphql import GraphQLResolveInfo
|
|
6
5
|
from Osdental.Models.Token import AuthToken
|
|
7
6
|
from Osdental.Models.Response import Response
|
|
8
7
|
from Osdental.Shared.Enums.Profile import Profile
|
|
9
|
-
from Osdental.Exception.ControlledException import OSDException
|
|
8
|
+
from Osdental.Exception.ControlledException import OSDException, AccessDeniedException
|
|
10
9
|
from Osdental.Encryptor.Aes import AES
|
|
10
|
+
from Osdental.Graphql.Models import BaseGraphQLContext
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
aes = AES()
|
|
14
12
|
def secure_resolver(action = None):
|
|
15
13
|
def decorator(func: Callable):
|
|
16
14
|
|
|
@@ -18,25 +16,25 @@ def secure_resolver(action = None):
|
|
|
18
16
|
accepts_data = "data" in signature.parameters
|
|
19
17
|
|
|
20
18
|
@wraps(func)
|
|
21
|
-
async def wrapper(obj: Any,
|
|
19
|
+
async def wrapper(obj: Any, context: BaseGraphQLContext, **kwargs: Dict[str, Any]):
|
|
22
20
|
try:
|
|
23
|
-
token: AuthToken =
|
|
24
|
-
payload = getattr(
|
|
25
|
-
|
|
21
|
+
token: AuthToken = context.token
|
|
22
|
+
payload = getattr(context, "decrypted_payload", None)
|
|
23
|
+
aes_auth = getattr(context, "aes_auth", None)
|
|
26
24
|
|
|
27
25
|
if action:
|
|
28
26
|
if Profile(token.abbreviation) not in action.allowed_roles:
|
|
29
|
-
raise
|
|
27
|
+
raise AccessDeniedException(error="The user's profile is not allowed to perform this action.")
|
|
30
28
|
|
|
31
29
|
if accepts_data and payload:
|
|
32
30
|
kwargs["data"] = payload
|
|
33
31
|
|
|
34
|
-
result: Response = await func(obj,
|
|
32
|
+
result: Response = await func(obj, context, **kwargs)
|
|
35
33
|
|
|
36
|
-
|
|
34
|
+
context.audit_plain_response = copy.deepcopy(result)
|
|
37
35
|
|
|
38
36
|
if result.data is not None:
|
|
39
|
-
result.data =
|
|
37
|
+
result.data = AES.encrypt(aes_auth, result.data)
|
|
40
38
|
|
|
41
39
|
return result.send()
|
|
42
40
|
|
|
@@ -46,7 +44,7 @@ def secure_resolver(action = None):
|
|
|
46
44
|
message=getattr(e, "message", "Could not process request."),
|
|
47
45
|
error=f"{type(e).__name__}: {str(e)}"
|
|
48
46
|
)
|
|
49
|
-
|
|
47
|
+
context.audit_plain_response = result
|
|
50
48
|
return result.send()
|
|
51
49
|
|
|
52
50
|
return wrapper
|
|
@@ -10,9 +10,8 @@ from Osdental.Shared.Enums.Constant import Constant
|
|
|
10
10
|
|
|
11
11
|
class AES:
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
self.TAG_LENGTH = 16
|
|
13
|
+
IV_LENGTH = 32
|
|
14
|
+
TAG_LENGTH = 16
|
|
16
15
|
|
|
17
16
|
@staticmethod
|
|
18
17
|
def generate_key() -> str:
|
|
@@ -20,7 +19,8 @@ class AES:
|
|
|
20
19
|
key = os.urandom(32)
|
|
21
20
|
return base64.b64encode(key).decode(Constant.DEFAULT_ENCODING)
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
@classmethod
|
|
23
|
+
def encrypt(cls, aes_key:str, data:Dict[str,str] | str | List[Dict[str,str]]) -> str:
|
|
24
24
|
"""
|
|
25
25
|
Encrypts data using AES-GCM.
|
|
26
26
|
Supports dictionary, string, or list inputs.
|
|
@@ -34,7 +34,7 @@ class AES:
|
|
|
34
34
|
|
|
35
35
|
try:
|
|
36
36
|
key = base64.b64decode(aes_key)
|
|
37
|
-
iv = os.urandom(
|
|
37
|
+
iv = os.urandom(cls.IV_LENGTH)
|
|
38
38
|
if isinstance(data, (dict, list)):
|
|
39
39
|
json_data = json.dumps(data)
|
|
40
40
|
else:
|
|
@@ -52,8 +52,8 @@ class AES:
|
|
|
52
52
|
logger.error(f'Unexpected AES encryption error: {str(e)}')
|
|
53
53
|
raise AESEncryptException(error=str(e))
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
def decrypt(
|
|
55
|
+
@classmethod
|
|
56
|
+
def decrypt(cls, aes_key:str, encrypted_data:str, silent:bool = False):
|
|
57
57
|
"""
|
|
58
58
|
Decrypts data using AES-GCM.
|
|
59
59
|
Expects encrypted data to represent either a JSON object (dict) or a plain string.
|
|
@@ -65,9 +65,9 @@ class AES:
|
|
|
65
65
|
try:
|
|
66
66
|
key = base64.b64decode(aes_key)
|
|
67
67
|
encrypted_data = base64.b64decode(encrypted_data)
|
|
68
|
-
iv = encrypted_data[:
|
|
69
|
-
tag = encrypted_data[-
|
|
70
|
-
ciphertext = encrypted_data[
|
|
68
|
+
iv = encrypted_data[:cls.IV_LENGTH]
|
|
69
|
+
tag = encrypted_data[-cls.TAG_LENGTH:]
|
|
70
|
+
ciphertext = encrypted_data[cls.IV_LENGTH:-cls.TAG_LENGTH]
|
|
71
71
|
cipher = Cipher(algorithms.AES(key), modes.GCM(iv, tag))
|
|
72
72
|
decryptor = cipher.decryptor()
|
|
73
73
|
plaintext = decryptor.update(ciphertext) + decryptor.finalize()
|
|
@@ -24,6 +24,15 @@ class UnauthorizedException(OSDException):
|
|
|
24
24
|
):
|
|
25
25
|
super().__init__(message=message, error=error, status_code=status_code)
|
|
26
26
|
|
|
27
|
+
class AccessDeniedException(OSDException):
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
message: str = Message.ACCESS_DENIED_MSG,
|
|
31
|
+
error: str = None,
|
|
32
|
+
status_code: str = Code.INVALID_REQUEST_PARAMS_CODE
|
|
33
|
+
):
|
|
34
|
+
super().__init__(message=message, error=error, status_code=status_code)
|
|
35
|
+
|
|
27
36
|
class RequestDataException(OSDException):
|
|
28
37
|
def __init__(
|
|
29
38
|
self,
|
|
@@ -3,36 +3,54 @@ from graphql.pyutils import is_awaitable
|
|
|
3
3
|
from ariadne.types import Extension
|
|
4
4
|
from Osdental.Encryptor.Aes import AES
|
|
5
5
|
from Osdental.Graphql._Helpers._TenantPolicy import TenantPolicy
|
|
6
|
+
from Osdental.Rest.Context.RequestContext import (
|
|
7
|
+
current_context,
|
|
8
|
+
RequestContext
|
|
9
|
+
)
|
|
10
|
+
from Osdental.Graphql.Models import BaseGraphQLContext
|
|
6
11
|
from Osdental.Graphql._Exceptions import AESKeyNotFound
|
|
7
12
|
from Osdental.Shared.Enums.Constant import Constant
|
|
8
13
|
|
|
9
14
|
class AuditExtension(Extension):
|
|
10
15
|
|
|
11
16
|
def request_started(self, context):
|
|
17
|
+
request = context.request
|
|
18
|
+
self._ctx_token = current_context.set(
|
|
19
|
+
RequestContext(
|
|
20
|
+
request=request,
|
|
21
|
+
request_id=request.headers.get("x-request-id"),
|
|
22
|
+
user=None
|
|
23
|
+
)
|
|
24
|
+
)
|
|
25
|
+
|
|
12
26
|
self.errors = None
|
|
13
27
|
self.request_payload = None
|
|
14
28
|
self.result = None
|
|
15
|
-
self.aes = AES()
|
|
16
29
|
|
|
17
30
|
async def resolve(self, next_, root, info, **kwargs):
|
|
18
31
|
|
|
19
32
|
if not self.request_payload:
|
|
20
|
-
context = info.context
|
|
33
|
+
context: BaseGraphQLContext = info.context
|
|
21
34
|
|
|
22
|
-
request =
|
|
35
|
+
request = context.request
|
|
23
36
|
self.request = request
|
|
24
37
|
|
|
25
|
-
body = request.
|
|
38
|
+
body = await request.json()
|
|
39
|
+
headers = request.headers
|
|
26
40
|
|
|
27
41
|
container = context.container
|
|
28
|
-
|
|
29
42
|
token_service = container.token_service
|
|
30
43
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
44
|
+
aes_auth = request.app.state.aes_auth
|
|
45
|
+
aes_user = request.app.state.aes_user
|
|
46
|
+
|
|
47
|
+
if not aes_auth:
|
|
48
|
+
raise AESKeyNotFound("AES user key is missing.", "aes_auth")
|
|
49
|
+
|
|
50
|
+
if not aes_user:
|
|
51
|
+
raise AESKeyNotFound("AES authorization key is missing.", "aes_user")
|
|
34
52
|
|
|
35
|
-
original_token = await token_service.authenticate(
|
|
53
|
+
original_token = await token_service.authenticate(headers, aes_user)
|
|
36
54
|
|
|
37
55
|
variables = body.get("variables") or {}
|
|
38
56
|
encrypted_payload = variables.get("data")
|
|
@@ -41,7 +59,7 @@ class AuditExtension(Extension):
|
|
|
41
59
|
|
|
42
60
|
if encrypted_payload:
|
|
43
61
|
try:
|
|
44
|
-
decrypted_payload =
|
|
62
|
+
decrypted_payload = AES.decrypt(aes_auth, encrypted_payload)
|
|
45
63
|
|
|
46
64
|
try:
|
|
47
65
|
decrypted_payload = json.loads(decrypted_payload)
|
|
@@ -68,7 +86,7 @@ class AuditExtension(Extension):
|
|
|
68
86
|
|
|
69
87
|
context.decrypted_payload = decrypted_payload
|
|
70
88
|
context.token = token
|
|
71
|
-
context.
|
|
89
|
+
context.aes_auth = aes_auth
|
|
72
90
|
|
|
73
91
|
result = next_(root, info, **kwargs)
|
|
74
92
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Optional, Any
|
|
3
|
+
from fastapi import Request
|
|
4
|
+
from Osdental.Models.Token import AuthToken
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class BaseGraphQLContext:
|
|
8
|
+
request: Request
|
|
9
|
+
container: Any
|
|
10
|
+
# valores agregados durante ejecución (AuditExtention)
|
|
11
|
+
token: Optional[AuthToken] = None
|
|
12
|
+
decrypted_payload: Optional[dict] = None
|
|
13
|
+
aes_auth: Optional[str] = None
|
|
14
|
+
audit_plain_response: Optional[Any] = None
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from starlette.datastructures import Headers
|
|
2
|
+
|
|
3
|
+
class ExtractAuthToken:
|
|
4
|
+
|
|
5
|
+
@staticmethod
|
|
6
|
+
def get_auth_token(headers: Headers) -> str:
|
|
7
|
+
authorization = headers.get("authorization")
|
|
8
|
+
if not authorization or not authorization.startswith("Bearer "):
|
|
9
|
+
raise ValueError("Missing Bearer token")
|
|
10
|
+
|
|
11
|
+
return authorization.split(" ")[1]
|
|
@@ -14,13 +14,16 @@ class TenantPolicy:
|
|
|
14
14
|
decrypted_payload: Dict[str, Any],
|
|
15
15
|
operation_type: str
|
|
16
16
|
) -> AuthToken:
|
|
17
|
-
aes = AES()
|
|
18
|
-
# Solo aplicamos cambios si es QUERY
|
|
19
|
-
if operation_type != OperationType.QUERY.value:
|
|
20
|
-
return token # devolver token tal cual
|
|
21
17
|
|
|
18
|
+
# Set original idExternalEnterprise
|
|
19
|
+
token.base_id_external_enterprise = token.id_external_enterprise
|
|
22
20
|
# SUPER ADMIN / OSDEL ADMIN -> UUID 0
|
|
23
|
-
|
|
21
|
+
should_use_zero_uuid = (
|
|
22
|
+
token.abbreviation.startswith(("SPAU", "OSDA"))
|
|
23
|
+
and operation_type == OperationType.QUERY
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if should_use_zero_uuid:
|
|
24
27
|
token.id_external_enterprise = str(UUID(int=0))
|
|
25
28
|
return token
|
|
26
29
|
|
|
@@ -28,13 +31,13 @@ class TenantPolicy:
|
|
|
28
31
|
if token.abbreviation.startswith("OSDMK"):
|
|
29
32
|
dynamic_client_id = headers.get("dynamicClientId")
|
|
30
33
|
if dynamic_client_id:
|
|
31
|
-
decrypted_mk_id =
|
|
34
|
+
decrypted_mk_id = AES.decrypt(token.aes_key_auth, dynamic_client_id)
|
|
32
35
|
token.id_external_enterprise = decrypted_mk_id
|
|
33
36
|
token.mk_id_external_enterprise = decrypted_mk_id
|
|
34
37
|
return token
|
|
35
38
|
|
|
36
39
|
# If it comes by request, it is taken as priority
|
|
37
|
-
external_enterprise_req = decrypted_payload.get(
|
|
40
|
+
external_enterprise_req = decrypted_payload.get("idExternalEnterprise")
|
|
38
41
|
if external_enterprise_req and token:
|
|
39
42
|
token.id_external_enterprise = external_enterprise_req
|
|
40
43
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from
|
|
1
|
+
from starlette.datastructures import Headers
|
|
2
2
|
from Osdental.Encryptor.Aes import AES
|
|
3
3
|
from Osdental.Encryptor.Jwt import JWT
|
|
4
4
|
from Osdental.Models.Token import AuthToken
|
|
@@ -9,23 +9,20 @@ class TokenService:
|
|
|
9
9
|
def __init__(self, jwt_user_key: str, auth_validator):
|
|
10
10
|
self.jwt_user_key = jwt_user_key
|
|
11
11
|
self.auth_validator = auth_validator
|
|
12
|
-
self.aes = AES()
|
|
13
12
|
|
|
14
|
-
async def authenticate(self,
|
|
15
|
-
encrypted_token = ExtractAuthToken.get_auth_token(
|
|
13
|
+
async def authenticate(self, headers: Headers, aes_user: str) -> AuthToken:
|
|
14
|
+
encrypted_token = ExtractAuthToken.get_auth_token(headers)
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
user_token = self.aes.decrypt(aes_user, encrypted_token)
|
|
16
|
+
user_token = AES.decrypt(aes_user, encrypted_token)
|
|
20
17
|
payload = JWT.extract_payload(user_token, self.jwt_user_key)
|
|
21
18
|
token = AuthToken(**payload)
|
|
22
19
|
|
|
23
20
|
# Validate via RPC
|
|
24
|
-
|
|
21
|
+
paylod = {
|
|
25
22
|
'idToken': token.id_token,
|
|
26
23
|
'idUser': token.id_user
|
|
27
24
|
}
|
|
28
|
-
is_valid = await self.auth_validator.validate_auth_token(
|
|
25
|
+
is_valid = await self.auth_validator.validate_auth_token(paylod)
|
|
29
26
|
if not is_valid:
|
|
30
27
|
raise ValueError("You are not authorized to access this portal.")
|
|
31
28
|
|
|
@@ -87,7 +87,7 @@ class AuditDispatcher:
|
|
|
87
87
|
request=request,
|
|
88
88
|
audit_config=self._audit_config,
|
|
89
89
|
operation_name=operation_name,
|
|
90
|
-
full_name=request_payload.get("user"),
|
|
90
|
+
full_name=request_payload.get("user", "Joe Doe"),
|
|
91
91
|
payload=request_payload.get("variables")
|
|
92
92
|
)
|
|
93
93
|
request_audit_payload = await AuditHelper.build_request_payload(audit=audit)
|
|
@@ -37,9 +37,11 @@ class APIClient:
|
|
|
37
37
|
**kwargs
|
|
38
38
|
)
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
ctx = current_context.get()
|
|
41
|
+
|
|
42
|
+
if ctx and ctx.request:
|
|
43
|
+
request = ctx.request
|
|
41
44
|
|
|
42
|
-
if request:
|
|
43
45
|
dispatcher = request.app.state.audit_dispatcher
|
|
44
46
|
dispatcher.dispatch(
|
|
45
47
|
request=request,
|
|
@@ -18,8 +18,6 @@ class AuthToken(BaseModel):
|
|
|
18
18
|
access_token: Optional[str] = Field(default=None, alias="accessToken")
|
|
19
19
|
base_id_external_enterprise: Optional[str] = Field(default=None, alias="baseIdExternalEnterprise")
|
|
20
20
|
mk_id_external_enterprise: Optional[str] = Field(default=None, alias="mkIdExternalEnterprise")
|
|
21
|
-
jwt_user_key: Optional[str] = Field(default=None, alias="jwtUserKey")
|
|
22
|
-
legacy: Optional[Legacy] = Field(default=None, alias="legacy")
|
|
23
21
|
|
|
24
22
|
class ConfigDict:
|
|
25
23
|
populate_by_name = True
|
|
@@ -8,6 +8,7 @@ class Code(StrEnum):
|
|
|
8
8
|
APP_ERROR_CODE = 'DB_ERROR_CONTROLLED'
|
|
9
9
|
UNEXPECTED_ERROR_CODE = 'DB_ERROR_UNEXPECTED'
|
|
10
10
|
INVALID_REQUEST_PARAMS_CODE = 'DB_WARNING_INVALID_REQUEST_PARAMS'
|
|
11
|
+
ACCESS_DENIED_CODE = "DB_WARNING_ACCESS_DENIED_CODE"
|
|
11
12
|
DATABASE_ERROR_CODE = 'DB_WARNING_DATABASE_ERROR'
|
|
12
13
|
DATABASE_CONNECTION_ERROR_CODE = 'DB_ERROR_DATABASE_CONNECTION'
|
|
13
14
|
RSA_ERROR_CODE = 'DB_ERROR_RSA'
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from enum import StrEnum
|
|
2
2
|
|
|
3
3
|
class Message(StrEnum):
|
|
4
|
+
ACCESS_DENIED_MSG = "You do not have the necessary privileges for this operation."
|
|
4
5
|
UNEXPECTED_ERROR_MSG = 'Something went wrong while processing your request. Please try again later.'
|
|
5
6
|
PORTAL_ACCESS_RESTRICTED_MSG = 'You are not authorized to access this portal.'
|
|
6
7
|
PROCESS_SUCCESS_MSG = 'Process executed successfully.'
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
from fastapi import Request
|
|
2
|
-
|
|
3
|
-
class ExtractAuthToken:
|
|
4
|
-
|
|
5
|
-
@staticmethod
|
|
6
|
-
def get_auth_token(request: Request) -> str:
|
|
7
|
-
authorization = request.headers.get("authorization")
|
|
8
|
-
if not authorization or not authorization.startswith("Bearer "):
|
|
9
|
-
raise ValueError("Missing Bearer token")
|
|
10
|
-
|
|
11
|
-
return authorization.split(" ")[1]
|
|
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
|
{encryptors-2.34 → encryptors-2.36}/src/Osdental/Rest/Middlewares/RequestContextMiddleware.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|