Encryptors 2.41__tar.gz → 2.43__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.
Files changed (90) hide show
  1. {encryptors-2.41 → encryptors-2.43}/PKG-INFO +1 -1
  2. {encryptors-2.41 → encryptors-2.43}/setup.py +1 -1
  3. {encryptors-2.41 → encryptors-2.43}/src/Encryptors.egg-info/PKG-INFO +1 -1
  4. encryptors-2.43/src/Osdental/Decorators/SecureResolver.py +61 -0
  5. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Graphql/Extensions/AuditExtension.py +17 -12
  6. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Helpers/AuditDispatcher.py +6 -5
  7. encryptors-2.43/src/Osdental/Helpers/ResponseDecryptor.py +33 -0
  8. encryptors-2.41/src/Osdental/Decorators/SecureResolver.py +0 -56
  9. encryptors-2.41/src/Osdental/Helpers/ResponseDecryptor.py +0 -15
  10. {encryptors-2.41 → encryptors-2.43}/README.md +0 -0
  11. {encryptors-2.41 → encryptors-2.43}/setup.cfg +0 -0
  12. {encryptors-2.41 → encryptors-2.43}/src/Encryptors.egg-info/SOURCES.txt +0 -0
  13. {encryptors-2.41 → encryptors-2.43}/src/Encryptors.egg-info/dependency_links.txt +0 -0
  14. {encryptors-2.41 → encryptors-2.43}/src/Encryptors.egg-info/entry_points.txt +0 -0
  15. {encryptors-2.41 → encryptors-2.43}/src/Encryptors.egg-info/requires.txt +0 -0
  16. {encryptors-2.41 → encryptors-2.43}/src/Encryptors.egg-info/top_level.txt +0 -0
  17. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Cli/__init__.py +0 -0
  18. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Database/BaseRepository.py +0 -0
  19. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Database/Connection.py +0 -0
  20. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Database/__init__.py +0 -0
  21. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Decorators/Grpc.py +0 -0
  22. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Decorators/PublicResolver.py +0 -0
  23. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Decorators/Retry.py +0 -0
  24. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Decorators/SqlDataNormalizer.py +0 -0
  25. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Decorators/__init__.py +0 -0
  26. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Encryptor/Aes.py +0 -0
  27. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Encryptor/Argon2.py +0 -0
  28. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Encryptor/Bcrypt.py +0 -0
  29. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Encryptor/Jwt.py +0 -0
  30. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Encryptor/Rsa.py +0 -0
  31. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Encryptor/Sha512.py +0 -0
  32. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Encryptor/__init__.py +0 -0
  33. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Exception/ControlledException.py +0 -0
  34. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Exception/__init__.py +0 -0
  35. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Graphql/Extensions/__init__.py +0 -0
  36. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Graphql/Models/__init__.py +0 -0
  37. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Graphql/_Exceptions/__init__.py +0 -0
  38. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Graphql/_Helpers/_AuditHelper.py +0 -0
  39. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Graphql/_Helpers/_ExtractAuthToken.py +0 -0
  40. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Graphql/_Helpers/_TenantPolicy.py +0 -0
  41. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Graphql/_Helpers/_TokenService.py +0 -0
  42. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Graphql/_Helpers/__init__.py +0 -0
  43. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Graphql/__init__.py +0 -0
  44. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Helpers/KeyVaultService.py +0 -0
  45. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Helpers/__init__.py +0 -0
  46. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Http/APIClient.py +0 -0
  47. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Http/_Exceptions.py +0 -0
  48. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Http/__init__.py +0 -0
  49. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Messaging/AzureServiceBus.py +0 -0
  50. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Messaging/Kafka.py +0 -0
  51. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Messaging/RabbitMQ.py +0 -0
  52. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Messaging/__init__.py +0 -0
  53. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Models/AuditConfig.py +0 -0
  54. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Models/Response.py +0 -0
  55. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Models/Token.py +0 -0
  56. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Models/_Audit.py +0 -0
  57. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Models/__init__.py +0 -0
  58. {encryptors-2.41 → encryptors-2.43}/src/Osdental/RedisCache/Redis.py +0 -0
  59. {encryptors-2.41 → encryptors-2.43}/src/Osdental/RedisCache/__init__.py +0 -0
  60. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Rest/Context/RequestContext.py +0 -0
  61. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Rest/Context/__init__.py +0 -0
  62. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Rest/Middlewares/RequestContextMiddleware.py +0 -0
  63. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Rest/Middlewares/__init__.py +0 -0
  64. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Rest/__init__.py +0 -0
  65. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Enums/Code.py +0 -0
  66. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Enums/Constant.py +0 -0
  67. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Enums/FileType.py +0 -0
  68. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Enums/GrahpqlOperation.py +0 -0
  69. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Enums/Message.py +0 -0
  70. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Enums/Profile.py +0 -0
  71. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Enums/__init__.py +0 -0
  72. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Logger.py +0 -0
  73. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/CaseConverter.py +0 -0
  74. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/CodeGenerator.py +0 -0
  75. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/DataNormalizer.py +0 -0
  76. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/DataUtils.py +0 -0
  77. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/DateUtils.py +0 -0
  78. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/FileMetaData.py +0 -0
  79. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/HashValidator.py +0 -0
  80. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/Mapper.py +0 -0
  81. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/PasswordGenerator.py +0 -0
  82. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/QueryGenerator.py +0 -0
  83. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/RsaUtils.py +0 -0
  84. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/TextProcessor.py +0 -0
  85. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/Utils/__init__.py +0 -0
  86. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Shared/__init__.py +0 -0
  87. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Storage/AzureBlobStorage.py +0 -0
  88. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Storage/S3Storage.py +0 -0
  89. {encryptors-2.41 → encryptors-2.43}/src/Osdental/Storage/__init__.py +0 -0
  90. {encryptors-2.41 → encryptors-2.43}/src/Osdental/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Encryptors
3
- Version: 2.41
3
+ Version: 2.43
4
4
  Summary: End-to-end algorithm library
5
5
  Author: OSDental LLC
6
6
  Author-email: support@osdental.ai
@@ -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.41",
5
+ version="2.43",
6
6
  author="OSDental LLC",
7
7
  author_email="support@osdental.ai",
8
8
  description="End-to-end algorithm library",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Encryptors
3
- Version: 2.41
3
+ Version: 2.43
4
4
  Summary: End-to-end algorithm library
5
5
  Author: OSDental LLC
6
6
  Author-email: support@osdental.ai
@@ -0,0 +1,61 @@
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
6
+ from Osdental.Shared.Logger import logger
7
+
8
+ def resolver(public: bool = False, action=None):
9
+
10
+ def decorator(func: Callable):
11
+
12
+ @wraps(func)
13
+ async def wrapper(obj, info, **kwargs):
14
+ try:
15
+ context = info.context
16
+ token = getattr(context, "token", None)
17
+
18
+ # 🔐 AUTH
19
+ if not public:
20
+ if not token:
21
+ raise AccessDeniedException(
22
+ error="Authorization required"
23
+ )
24
+
25
+ # 🎯 AUTHORIZATION (roles)
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=None
46
+ ).send()
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
+ ).send()
56
+
57
+ wrapper._is_public = public
58
+
59
+ return wrapper
60
+
61
+ return decorator
@@ -8,6 +8,7 @@ from Osdental.Rest.Context.RequestContext import (
8
8
  current_context,
9
9
  RequestContext
10
10
  )
11
+ from Osdental.Models.Response import Response
11
12
  from Osdental.Graphql.Models import BaseGraphQLContext
12
13
  from Osdental.Shared.Enums.Constant import Constant
13
14
 
@@ -37,8 +38,7 @@ class AuditExtension(Extension):
37
38
  request = context.request
38
39
 
39
40
  # cache body
40
- if not hasattr(context, "_cached_body"):
41
- context._cached_body = await request.json()
41
+ context._cached_body = getattr(context, "_cached_body", None) or await request.json()
42
42
 
43
43
  body = context._cached_body
44
44
 
@@ -119,7 +119,7 @@ class AuditExtension(Extension):
119
119
  decrypted_payload = None
120
120
 
121
121
  if decrypted_payload is not None:
122
- context.decrypted_payload = decrypted_payload
122
+ kwargs["data"] = decrypted_payload
123
123
 
124
124
  if not is_public:
125
125
  token = TenantPolicy.resolve(
@@ -153,9 +153,6 @@ class AuditExtension(Extension):
153
153
  if is_root and self.result is None:
154
154
  self.result = result
155
155
 
156
- if not getattr(context, "audit_plain_response", None):
157
- context.audit_plain_response = result
158
-
159
156
  return result
160
157
 
161
158
  def has_errors(self, errors, context):
@@ -168,13 +165,18 @@ class AuditExtension(Extension):
168
165
 
169
166
  query = self.request_payload.get("query", "")
170
167
 
171
- if "__schema" in query or "__type" in query:
168
+ if self._should_skip({"query": query}):
169
+ return
170
+
171
+ if self.result is None:
172
172
  return
173
173
 
174
- final_result = context.audit_plain_response or self.result
174
+ decrypted_key = None
175
175
 
176
- if final_result is None:
177
- return
176
+ if isinstance(self.result, Response):
177
+ decrypted_key = self.result.key or context.aes_auth
178
+ else:
179
+ decrypted_key = context.aes_auth
178
180
 
179
181
  dispatcher = context.request.app.state.audit_dispatcher
180
182
 
@@ -182,8 +184,11 @@ class AuditExtension(Extension):
182
184
  dispatcher.dispatch(
183
185
  request=self.request,
184
186
  request_payload=self.request_payload,
185
- result=final_result,
187
+ result=self.result,
188
+ metadata={
189
+ "decrypted_key": decrypted_key
190
+ },
186
191
  audit_type=Constant.MESSAGE_LOG_INTERNAL
187
192
  )
188
193
  except Exception as e:
189
- logger(f"[AUDIT ERROR]: {str(e)}")
194
+ 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
- key = result.key
106
+ decrypted_key = metadata["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 key is not None:
131
- data = decryptor_data(encryption_type, key, data)
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",
@@ -0,0 +1,33 @@
1
+ from typing import Dict, Any
2
+ from Osdental.Encryptor.Aes import AES
3
+ from Osdental.Encryptor.Rsa import RSAEncryptor
4
+ from Osdental.Shared.Logger import logger
5
+
6
+ VALID_TYPES = {"RSA", "AES"}
7
+
8
+ def encryptor_data(encryption_type: str, key: str, data: Dict[str, Any] | str) -> Any:
9
+ match encryption_type:
10
+
11
+ case "AES":
12
+ return AES.encrypt(key, data)
13
+
14
+ case "RSA":
15
+ return RSAEncryptor.encrypt(data, key)
16
+
17
+ case _:
18
+ logger.warning(f"Encryption type '{encryption_type}' not supported.")
19
+ return data
20
+
21
+ def decryptor_data(encryption_type: str, key: str, data: Dict[str, Any] | str) -> Any:
22
+
23
+ match encryption_type:
24
+
25
+ case "AES":
26
+ return AES.decrypt(key, data)
27
+
28
+ case "RSA":
29
+ return RSAEncryptor.decrypt(data, key)
30
+
31
+ case _:
32
+ logger.warning(f"Encryption type '{encryption_type}' not supported.")
33
+ return data
@@ -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
@@ -1,15 +0,0 @@
1
- from typing import Dict, Any
2
- from Osdental.Encryptor.Aes import AES
3
- from Osdental.Encryptor.Rsa import RSAEncryptor
4
-
5
- VALID_TYPES = {"RSA", "AES"}
6
-
7
- def decryptor_data(encryption_type: str, key: str, data: Dict[str, Any] | str) -> Any:
8
-
9
- match encryption_type:
10
-
11
- case "AES":
12
- return AES.decrypt(key, data)
13
-
14
- case "RSA":
15
- return RSAEncryptor.decrypt(data, key)
File without changes
File without changes