Encryptors 2.42__tar.gz → 2.44__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.42 → encryptors-2.44}/PKG-INFO +1 -1
- {encryptors-2.42 → encryptors-2.44}/setup.py +1 -1
- {encryptors-2.42 → encryptors-2.44}/src/Encryptors.egg-info/PKG-INFO +1 -1
- encryptors-2.44/src/Osdental/Decorators/SecureResolver.py +59 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Graphql/Extensions/AuditExtension.py +39 -49
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Graphql/_Helpers/_AuditHelper.py +1 -1
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Helpers/AuditDispatcher.py +6 -5
- encryptors-2.42/src/Osdental/Decorators/SecureResolver.py +0 -56
- {encryptors-2.42 → encryptors-2.44}/README.md +0 -0
- {encryptors-2.42 → encryptors-2.44}/setup.cfg +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Encryptors.egg-info/SOURCES.txt +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Encryptors.egg-info/dependency_links.txt +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Encryptors.egg-info/entry_points.txt +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Encryptors.egg-info/requires.txt +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Encryptors.egg-info/top_level.txt +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Cli/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Database/BaseRepository.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Database/Connection.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Database/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Decorators/Grpc.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Decorators/PublicResolver.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Decorators/Retry.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Decorators/SqlDataNormalizer.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Decorators/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Encryptor/Aes.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Encryptor/Argon2.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Encryptor/Bcrypt.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Encryptor/Jwt.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Encryptor/Rsa.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Encryptor/Sha512.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Encryptor/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Exception/ControlledException.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Exception/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Graphql/Extensions/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Graphql/Models/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Graphql/_Exceptions/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Graphql/_Helpers/_ExtractAuthToken.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Graphql/_Helpers/_TenantPolicy.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Graphql/_Helpers/_TokenService.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Graphql/_Helpers/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Graphql/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Helpers/KeyVaultService.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Helpers/ResponseDecryptor.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Helpers/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Http/APIClient.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Http/_Exceptions.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Http/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Messaging/AzureServiceBus.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Messaging/Kafka.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Messaging/RabbitMQ.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Messaging/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Models/AuditConfig.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Models/Response.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Models/Token.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Models/_Audit.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Models/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/RedisCache/Redis.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/RedisCache/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Rest/Context/RequestContext.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Rest/Context/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Rest/Middlewares/RequestContextMiddleware.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Rest/Middlewares/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Rest/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Enums/Code.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Enums/Constant.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Enums/FileType.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Enums/GrahpqlOperation.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Enums/Message.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Enums/Profile.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Enums/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Logger.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/CaseConverter.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/CodeGenerator.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/DataNormalizer.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/DataUtils.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/DateUtils.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/FileMetaData.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/HashValidator.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/Mapper.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/PasswordGenerator.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/QueryGenerator.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/RsaUtils.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/TextProcessor.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/Utils/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Shared/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Storage/AzureBlobStorage.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Storage/S3Storage.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/Storage/__init__.py +0 -0
- {encryptors-2.42 → encryptors-2.44}/src/Osdental/__init__.py +0 -0
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
# ANDERSON ESTO YA SE SUBIO Y ESTA ESTABLE, AUN TE QUEDA PENDIENTE LA AUDITORIA CON RSA Y AES DE ACCESSTOKEN
|
|
3
3
|
setup(
|
|
4
4
|
name="Encryptors",
|
|
5
|
-
version="2.
|
|
5
|
+
version="2.44",
|
|
6
6
|
author="OSDental LLC",
|
|
7
7
|
author_email="support@osdental.ai",
|
|
8
8
|
description="End-to-end algorithm library",
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
from typing import Callable
|
|
3
|
+
from Osdental.Models.Response import Response
|
|
4
|
+
from Osdental.Shared.Enums.Profile import Profile
|
|
5
|
+
from Osdental.Exception.ControlledException import OSDException, AccessDeniedException, UnauthorizedException
|
|
6
|
+
from Osdental.Shared.Logger import logger
|
|
7
|
+
|
|
8
|
+
def resolver(public: bool = False, action=None):
|
|
9
|
+
|
|
10
|
+
def decorator(func: Callable):
|
|
11
|
+
|
|
12
|
+
func._is_public = public
|
|
13
|
+
|
|
14
|
+
@wraps(func)
|
|
15
|
+
async def wrapper(obj, info, **kwargs):
|
|
16
|
+
try:
|
|
17
|
+
context = info.context
|
|
18
|
+
token = getattr(context, "token", None)
|
|
19
|
+
|
|
20
|
+
if not public:
|
|
21
|
+
if not token:
|
|
22
|
+
raise UnauthorizedException(
|
|
23
|
+
error="Authorization required"
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if action:
|
|
27
|
+
if Profile(token.abbreviation) not in action.allowed_roles:
|
|
28
|
+
raise AccessDeniedException(
|
|
29
|
+
error="User not allowed to perform this action"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
result = await func(obj, info, **kwargs)
|
|
33
|
+
|
|
34
|
+
if not isinstance(result, Response):
|
|
35
|
+
raise TypeError("Resolver must return a Response instance")
|
|
36
|
+
|
|
37
|
+
return result
|
|
38
|
+
|
|
39
|
+
except OSDException as e:
|
|
40
|
+
logger.warning(f"Business error: {str(e)}")
|
|
41
|
+
|
|
42
|
+
return Response(
|
|
43
|
+
status=e.status_code,
|
|
44
|
+
message=e.message,
|
|
45
|
+
error=e.error
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
except Exception as e:
|
|
49
|
+
logger.exception(f"Unexpected error: {str(e)}")
|
|
50
|
+
|
|
51
|
+
return Response(
|
|
52
|
+
status="DB_ERROR_UNEXPECTED",
|
|
53
|
+
message="Could not process request.",
|
|
54
|
+
error=str(e)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
return wrapper
|
|
58
|
+
|
|
59
|
+
return decorator
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import inspect
|
|
1
2
|
import json
|
|
2
|
-
import copy
|
|
3
3
|
from graphql.pyutils import is_awaitable
|
|
4
4
|
from ariadne.types import Extension
|
|
5
5
|
from Osdental.Shared.Logger import logger
|
|
@@ -9,8 +9,8 @@ from Osdental.Rest.Context.RequestContext import (
|
|
|
9
9
|
current_context,
|
|
10
10
|
RequestContext
|
|
11
11
|
)
|
|
12
|
+
from Osdental.Models.Response import Response
|
|
12
13
|
from Osdental.Graphql.Models import BaseGraphQLContext
|
|
13
|
-
from Osdental.Helpers.ResponseDecryptor import encryptor_data, VALID_TYPES
|
|
14
14
|
from Osdental.Shared.Enums.Constant import Constant
|
|
15
15
|
|
|
16
16
|
class AuditExtension(Extension):
|
|
@@ -39,9 +39,7 @@ class AuditExtension(Extension):
|
|
|
39
39
|
request = context.request
|
|
40
40
|
|
|
41
41
|
# cache body
|
|
42
|
-
|
|
43
|
-
context._cached_body = await request.json()
|
|
44
|
-
|
|
42
|
+
context._cached_body = getattr(context, "_cached_body", None) or await request.json()
|
|
45
43
|
body = context._cached_body
|
|
46
44
|
|
|
47
45
|
# skip introspection
|
|
@@ -57,7 +55,7 @@ class AuditExtension(Extension):
|
|
|
57
55
|
if is_root:
|
|
58
56
|
|
|
59
57
|
# identificar resolver público
|
|
60
|
-
resolver_fn =
|
|
58
|
+
resolver_fn = inspect.unwrap(next_)
|
|
61
59
|
is_public = getattr(resolver_fn, "_is_public", False)
|
|
62
60
|
|
|
63
61
|
# inicializar auth UNA SOLA VEZ
|
|
@@ -68,27 +66,20 @@ class AuditExtension(Extension):
|
|
|
68
66
|
container = context.container
|
|
69
67
|
token_service = container.token_service
|
|
70
68
|
|
|
71
|
-
aes_auth = request.app.state.aes_auth
|
|
72
|
-
aes_user = request.app.state.aes_user
|
|
73
|
-
|
|
74
|
-
if not aes_auth or not aes_user:
|
|
75
|
-
aes_auth = None
|
|
76
|
-
aes_user = None
|
|
77
|
-
|
|
78
69
|
original_token = None
|
|
70
|
+
context.aes_auth = None
|
|
79
71
|
if not is_public and headers.get("authorization"):
|
|
72
|
+
aes_auth = request.app.state.aes_auth
|
|
73
|
+
aes_user = request.app.state.aes_user
|
|
74
|
+
|
|
80
75
|
try:
|
|
81
76
|
original_token = await token_service.authenticate(headers, aes_user)
|
|
82
77
|
except Exception:
|
|
83
78
|
original_token = None
|
|
84
79
|
|
|
85
|
-
|
|
86
|
-
context.token = original_token
|
|
87
|
-
context.aes_auth = aes_auth
|
|
80
|
+
context.aes_auth = aes_auth
|
|
88
81
|
|
|
89
82
|
# VALIDACIÓN SOLO ROOT
|
|
90
|
-
original_token = getattr(context, "_original_token", None)
|
|
91
|
-
|
|
92
83
|
if not is_public and not original_token:
|
|
93
84
|
raise ValueError("Authorization required")
|
|
94
85
|
|
|
@@ -102,30 +93,30 @@ class AuditExtension(Extension):
|
|
|
102
93
|
|
|
103
94
|
decrypted_payload = None
|
|
104
95
|
|
|
105
|
-
if encrypted_payload is not None:
|
|
106
|
-
if isinstance(encrypted_payload, dict):
|
|
107
|
-
decrypted_payload = encrypted_payload
|
|
96
|
+
if not is_public and encrypted_payload is not None:
|
|
108
97
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
decrypted_payload = json.loads(encrypted_payload)
|
|
112
|
-
except Exception:
|
|
113
|
-
if context.aes_auth:
|
|
114
|
-
try:
|
|
115
|
-
decrypted_payload = AES.decrypt(context.aes_auth, encrypted_payload)
|
|
116
|
-
try:
|
|
117
|
-
decrypted_payload = json.loads(decrypted_payload)
|
|
118
|
-
except Exception:
|
|
119
|
-
pass
|
|
120
|
-
except Exception:
|
|
121
|
-
decrypted_payload = None
|
|
98
|
+
if not isinstance(encrypted_payload, str):
|
|
99
|
+
raise ValueError("Encrypted payload must be a string")
|
|
122
100
|
|
|
101
|
+
if not context.aes_auth:
|
|
102
|
+
raise ValueError("Missing AES configuration")
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
decrypted = AES.decrypt(context.aes_auth, encrypted_payload)
|
|
106
|
+
except Exception:
|
|
107
|
+
raise ValueError("Invalid encrypted payload")
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
decrypted_payload = json.loads(decrypted)
|
|
111
|
+
except Exception:
|
|
112
|
+
raise ValueError("Decrypted payload is not valid JSON")
|
|
113
|
+
|
|
123
114
|
if decrypted_payload is not None:
|
|
124
|
-
|
|
115
|
+
kwargs["data"] = decrypted_payload
|
|
125
116
|
|
|
126
117
|
if not is_public:
|
|
127
118
|
token = TenantPolicy.resolve(
|
|
128
|
-
token=
|
|
119
|
+
token=original_token,
|
|
129
120
|
headers=request.headers,
|
|
130
121
|
decrypted_payload=decrypted_payload,
|
|
131
122
|
operation_type=info.operation.operation.value
|
|
@@ -155,13 +146,6 @@ class AuditExtension(Extension):
|
|
|
155
146
|
if is_root and self.result is None:
|
|
156
147
|
self.result = result
|
|
157
148
|
|
|
158
|
-
if not getattr(context, "audit_plain_response", None):
|
|
159
|
-
if result.encryption_type in VALID_TYPES and result.key:
|
|
160
|
-
result_copy = copy.deepcopy(result)
|
|
161
|
-
result = encryptor_data(result.encryption_type, result.key, result.data)
|
|
162
|
-
|
|
163
|
-
context.audit_plain_response = result_copy
|
|
164
|
-
|
|
165
149
|
return result
|
|
166
150
|
|
|
167
151
|
def has_errors(self, errors, context):
|
|
@@ -174,13 +158,16 @@ class AuditExtension(Extension):
|
|
|
174
158
|
|
|
175
159
|
query = self.request_payload.get("query", "")
|
|
176
160
|
|
|
177
|
-
if "
|
|
161
|
+
if self._should_skip({"query": query}):
|
|
162
|
+
return
|
|
163
|
+
|
|
164
|
+
if self.result is None:
|
|
178
165
|
return
|
|
179
166
|
|
|
180
|
-
|
|
167
|
+
decrypted_key = context.aes_auth
|
|
181
168
|
|
|
182
|
-
if
|
|
183
|
-
|
|
169
|
+
if isinstance(self.result, Response):
|
|
170
|
+
decrypted_key = self.result.key or decrypted_key
|
|
184
171
|
|
|
185
172
|
dispatcher = context.request.app.state.audit_dispatcher
|
|
186
173
|
|
|
@@ -188,8 +175,11 @@ class AuditExtension(Extension):
|
|
|
188
175
|
dispatcher.dispatch(
|
|
189
176
|
request=self.request,
|
|
190
177
|
request_payload=self.request_payload,
|
|
191
|
-
result=
|
|
178
|
+
result=self.result,
|
|
179
|
+
metadata={
|
|
180
|
+
"decrypted_key": decrypted_key
|
|
181
|
+
},
|
|
192
182
|
audit_type=Constant.MESSAGE_LOG_INTERNAL
|
|
193
183
|
)
|
|
194
184
|
except Exception as e:
|
|
195
|
-
logger(f"[AUDIT ERROR]: {str(e)}")
|
|
185
|
+
logger.warning(f"[AUDIT ERROR]: {str(e)}")
|
|
@@ -40,6 +40,7 @@ class AuditDispatcher:
|
|
|
40
40
|
request: Request,
|
|
41
41
|
request_payload: Dict[str, Any],
|
|
42
42
|
result: Response,
|
|
43
|
+
metadata: Dict[str, Any],
|
|
43
44
|
audit_type: str = None
|
|
44
45
|
):
|
|
45
46
|
try:
|
|
@@ -47,6 +48,7 @@ class AuditDispatcher:
|
|
|
47
48
|
"request": request,
|
|
48
49
|
"request_payload": request_payload,
|
|
49
50
|
"result": result,
|
|
51
|
+
"metadata": metadata,
|
|
50
52
|
"audit_type": audit_type
|
|
51
53
|
}
|
|
52
54
|
|
|
@@ -77,6 +79,7 @@ class AuditDispatcher:
|
|
|
77
79
|
request_payload = payload["request_payload"]
|
|
78
80
|
result: Response = payload["result"]
|
|
79
81
|
audit_type = payload["audit_type"]
|
|
82
|
+
metadata = payload["metadata"]
|
|
80
83
|
|
|
81
84
|
operation_name = request_payload.get("operation_name")
|
|
82
85
|
if operation_name == 'UnknownOperation':
|
|
@@ -100,9 +103,8 @@ class AuditDispatcher:
|
|
|
100
103
|
|
|
101
104
|
# Obtencion de campos adicionales cuando es otro tipo de encriptacion o clave
|
|
102
105
|
encryption_type = result.encryption_type
|
|
103
|
-
|
|
106
|
+
decrypted_key = metadata.get("decrypted_key")
|
|
104
107
|
|
|
105
|
-
|
|
106
108
|
if audit_type == Constant.MESSAGE_LOG_INTERNAL:
|
|
107
109
|
|
|
108
110
|
ERROR_PREFIXES = ("DB_ERROR", "DB_WARNING")
|
|
@@ -116,7 +118,6 @@ class AuditDispatcher:
|
|
|
116
118
|
except ValueError:
|
|
117
119
|
is_error = True
|
|
118
120
|
|
|
119
|
-
|
|
120
121
|
if is_error:
|
|
121
122
|
payload = AuditHelper.build_final_payload(
|
|
122
123
|
_type="ERROR",
|
|
@@ -127,8 +128,8 @@ class AuditDispatcher:
|
|
|
127
128
|
audit_message = request_audit_payload | payload
|
|
128
129
|
|
|
129
130
|
else:
|
|
130
|
-
if encryption_type in VALID_TYPES and
|
|
131
|
-
data = decryptor_data(encryption_type,
|
|
131
|
+
if encryption_type in VALID_TYPES and decrypted_key:
|
|
132
|
+
data = decryptor_data(encryption_type, decrypted_key, data)
|
|
132
133
|
|
|
133
134
|
payload = AuditHelper.build_final_payload(
|
|
134
135
|
_type="RESPONSE",
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import inspect
|
|
2
|
-
import copy
|
|
3
|
-
from functools import wraps
|
|
4
|
-
from typing import Callable, Dict, Any
|
|
5
|
-
from Osdental.Models.Token import AuthToken
|
|
6
|
-
from Osdental.Models.Response import Response
|
|
7
|
-
from Osdental.Shared.Enums.Profile import Profile
|
|
8
|
-
from Osdental.Exception.ControlledException import OSDException, AccessDeniedException
|
|
9
|
-
from Osdental.Encryptor.Aes import AES
|
|
10
|
-
from Osdental.Graphql.Models import BaseGraphQLContext
|
|
11
|
-
from Osdental.Shared.Logger import logger
|
|
12
|
-
|
|
13
|
-
def secure_resolver(action = None):
|
|
14
|
-
def decorator(func: Callable):
|
|
15
|
-
|
|
16
|
-
signature = inspect.signature(func)
|
|
17
|
-
params = signature.parameters
|
|
18
|
-
|
|
19
|
-
@wraps(func)
|
|
20
|
-
async def wrapper(obj: Any, context: BaseGraphQLContext, **kwargs: Dict[str, Any]):
|
|
21
|
-
try:
|
|
22
|
-
token: AuthToken = context.token
|
|
23
|
-
payload = getattr(context, "decrypted_payload", None)
|
|
24
|
-
aes_auth = getattr(context, "aes_auth", None)
|
|
25
|
-
|
|
26
|
-
if action:
|
|
27
|
-
if Profile(token.abbreviation) not in action.allowed_roles:
|
|
28
|
-
raise AccessDeniedException(error="The user's profile is not allowed to perform this action.")
|
|
29
|
-
|
|
30
|
-
if "token" in params:
|
|
31
|
-
kwargs["token"] = token
|
|
32
|
-
|
|
33
|
-
if "data" in params:
|
|
34
|
-
kwargs["data"] = payload
|
|
35
|
-
|
|
36
|
-
result: Response = await func(obj, **kwargs)
|
|
37
|
-
|
|
38
|
-
context.audit_plain_response = copy.deepcopy(result)
|
|
39
|
-
|
|
40
|
-
if result.data is not None and result.encryption_type == "AES" and result.key is None:
|
|
41
|
-
result.data = AES.encrypt(aes_auth, result.data)
|
|
42
|
-
|
|
43
|
-
return result.send()
|
|
44
|
-
|
|
45
|
-
except (Exception, OSDException) as e:
|
|
46
|
-
logger.exception(f"An error has occurred: {str(e)}")
|
|
47
|
-
result = Response(
|
|
48
|
-
status=getattr(e, "status_code", "DB_ERROR_UNEXPECTED"),
|
|
49
|
-
message=getattr(e, "message", "Could not process request."),
|
|
50
|
-
error=f"{type(e).__name__}: {str(e)}"
|
|
51
|
-
)
|
|
52
|
-
context.audit_plain_response = result
|
|
53
|
-
return result.send()
|
|
54
|
-
|
|
55
|
-
return wrapper
|
|
56
|
-
return decorator
|
|
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
|
{encryptors-2.42 → encryptors-2.44}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|