Encryptors 2.70__tar.gz → 2.71__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.70 → encryptors-2.71}/PKG-INFO +1 -1
  2. {encryptors-2.70 → encryptors-2.71}/setup.py +1 -1
  3. {encryptors-2.70 → encryptors-2.71}/src/Encryptors.egg-info/PKG-INFO +1 -1
  4. {encryptors-2.70 → encryptors-2.71}/src/Encryptors.egg-info/SOURCES.txt +1 -0
  5. encryptors-2.71/src/Osdental/Enums/Secret.py +8 -0
  6. encryptors-2.71/src/Osdental/Models/TokenClaims.py +80 -0
  7. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Services/JwtAuthTokenService.py +36 -60
  8. encryptors-2.70/src/Osdental/Models/TokenClaims.py +0 -47
  9. {encryptors-2.70 → encryptors-2.71}/README.md +0 -0
  10. {encryptors-2.70 → encryptors-2.71}/setup.cfg +0 -0
  11. {encryptors-2.70 → encryptors-2.71}/src/Encryptors.egg-info/dependency_links.txt +0 -0
  12. {encryptors-2.70 → encryptors-2.71}/src/Encryptors.egg-info/entry_points.txt +0 -0
  13. {encryptors-2.70 → encryptors-2.71}/src/Encryptors.egg-info/requires.txt +0 -0
  14. {encryptors-2.70 → encryptors-2.71}/src/Encryptors.egg-info/top_level.txt +0 -0
  15. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Cache/Redis.py +0 -0
  16. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Cache/__init__.py +0 -0
  17. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Cli/__init__.py +0 -0
  18. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Constants/Constant.py +0 -0
  19. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Constants/Message.py +0 -0
  20. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Constants/__init__.py +0 -0
  21. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Context/__init__.py +0 -0
  22. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Database/BaseRepository.py +0 -0
  23. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Database/Connection.py +0 -0
  24. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Database/__init__.py +0 -0
  25. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Decorators/Grpc.py +0 -0
  26. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Decorators/Retry.py +0 -0
  27. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Decorators/SecureResolver.py +0 -0
  28. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Decorators/__init__.py +0 -0
  29. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Encryptor/Aes.py +0 -0
  30. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Encryptor/Argon2.py +0 -0
  31. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Encryptor/Bcrypt.py +0 -0
  32. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Encryptor/Jwt.py +0 -0
  33. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Encryptor/Rsa.py +0 -0
  34. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Encryptor/Sha512.py +0 -0
  35. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Encryptor/__init__.py +0 -0
  36. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Enums/AuditType.py +0 -0
  37. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Enums/CipherType.py +0 -0
  38. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Enums/FileType.py +0 -0
  39. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Enums/GrahpqlOperation.py +0 -0
  40. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Enums/GrpcStatusCode.py +0 -0
  41. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Enums/Profile.py +0 -0
  42. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Enums/ResultType.py +0 -0
  43. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Enums/StatusCode.py +0 -0
  44. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Enums/__init__.py +0 -0
  45. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Exception/ControlledException.py +0 -0
  46. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Exception/__init__.py +0 -0
  47. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Helpers/AuditHelper.py +0 -0
  48. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Helpers/AuditQueue.py +0 -0
  49. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Helpers/AuthTokenProcessor.py +0 -0
  50. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Helpers/AzureClassifier.py +0 -0
  51. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Helpers/CipherHelper.py +0 -0
  52. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Helpers/GrpcConnection.py +0 -0
  53. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Helpers/JwtTokenHelper.py +0 -0
  54. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Helpers/Resilience.py +0 -0
  55. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Helpers/__init__.py +0 -0
  56. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Http/APIClient.py +0 -0
  57. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Http/__init__.py +0 -0
  58. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Messaging/AzureServiceBus.py +0 -0
  59. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Messaging/Kafka.py +0 -0
  60. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Messaging/RabbitMQ.py +0 -0
  61. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Messaging/__init__.py +0 -0
  62. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Models/ApiResponse.py +0 -0
  63. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Models/AuditContext.py +0 -0
  64. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Models/Graphql.py +0 -0
  65. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Models/Notification.py +0 -0
  66. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Models/Response.py +0 -0
  67. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Models/Token.py +0 -0
  68. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Models/__init__.py +0 -0
  69. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Secrets/AzureKeyVaultProvider.py +0 -0
  70. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Secrets/__init__.py +0 -0
  71. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Services/ServiceBusAuditEmitter.py +0 -0
  72. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Services/WebsocketClient.py +0 -0
  73. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Services/__init__.py +0 -0
  74. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Storage/AzureBlobStorage.py +0 -0
  75. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Storage/S3Storage.py +0 -0
  76. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Storage/__init__.py +0 -0
  77. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/CaseConverter.py +0 -0
  78. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/CodeGenerator.py +0 -0
  79. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/DataNormalizer.py +0 -0
  80. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/DataUtils.py +0 -0
  81. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/DateUtils.py +0 -0
  82. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/FileMetaData.py +0 -0
  83. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/HashValidator.py +0 -0
  84. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/Mapper.py +0 -0
  85. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/PasswordGenerator.py +0 -0
  86. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/QueryGenerator.py +0 -0
  87. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/RsaUtils.py +0 -0
  88. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/TextProcessor.py +0 -0
  89. {encryptors-2.70 → encryptors-2.71}/src/Osdental/Utils/__init__.py +0 -0
  90. {encryptors-2.70 → encryptors-2.71}/src/Osdental/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Encryptors
3
- Version: 2.70
3
+ Version: 2.71
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 REVISAR EL CACHE LOCAL DEL KEYVAULT PARA VALIDAR SI FUNCIONA
3
3
  setup(
4
4
  name="Encryptors",
5
- version="2.70",
5
+ version="2.71",
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.70
3
+ Version: 2.71
4
4
  Summary: End-to-end algorithm library
5
5
  Author: OSDental LLC
6
6
  Author-email: support@osdental.ai
@@ -35,6 +35,7 @@ src/Osdental/Enums/GrahpqlOperation.py
35
35
  src/Osdental/Enums/GrpcStatusCode.py
36
36
  src/Osdental/Enums/Profile.py
37
37
  src/Osdental/Enums/ResultType.py
38
+ src/Osdental/Enums/Secret.py
38
39
  src/Osdental/Enums/StatusCode.py
39
40
  src/Osdental/Enums/__init__.py
40
41
  src/Osdental/Exception/ControlledException.py
@@ -0,0 +1,8 @@
1
+ from enum import StrEnum
2
+
3
+ class Secret(StrEnum):
4
+
5
+ ISSUER = "LEGACY-NAME"
6
+ AUDIENCE = "LEGACY-URL"
7
+ SECRET_KEY_1 = "SECRET-KEY-1"
8
+ PUBLIC_KEY_1 = "PUBLIC-KEY-1"
@@ -0,0 +1,80 @@
1
+ from typing import Dict, Any
2
+ from dataclasses import dataclass, asdict
3
+ from typing import Optional
4
+
5
+ @dataclass(frozen=True, slots=True)
6
+ class TokenValidationOptions:
7
+ issuer: Optional[str] = None
8
+ audience: Optional[str] = None
9
+
10
+ validate_issuer: bool = True
11
+ validate_audience: bool = True
12
+
13
+ @dataclass(frozen=True, slots=True)
14
+ class BaseClaims:
15
+
16
+ def to_dict(self) -> Dict[str, Any]:
17
+ return asdict(self)
18
+
19
+ @dataclass(frozen=True, slots=True)
20
+ class AccessTokenClaims(BaseClaims):
21
+
22
+ id_legacy: int
23
+ id_enterprise: int
24
+ aes_key: str
25
+ exp: Optional[int] = 0
26
+
27
+ @classmethod
28
+ def from_dict(cls, claims: dict):
29
+
30
+ return cls(
31
+ id_legacy=claims["id_legacy"],
32
+ id_enterprise=claims["id_enterprise"],
33
+ aes_key=claims["aes_key"],
34
+ exp=claims["exp"],
35
+ )
36
+
37
+ @dataclass(frozen=True, slots=True)
38
+ class UserTokenClaims(BaseClaims):
39
+
40
+ id_legacy: str
41
+ id_enterprise: str
42
+ id_token: str
43
+ id_user: str
44
+ id_external_enterprise: str
45
+ id_profile: str
46
+ user_full_name: str
47
+ abbreviation: str
48
+ aes_key_auth: str
49
+ exp: Optional[int] = 0
50
+
51
+ @classmethod
52
+ def from_dict(cls, claims: dict):
53
+
54
+ return cls(
55
+ id_legacy=claims["id_legacy"],
56
+ id_enterprise=claims["id_enterprise"],
57
+ id_token=claims["id_token"],
58
+ id_user=claims["id_user"],
59
+ id_external_enterprise=claims["id_external_enterprise"],
60
+ id_profile=claims["id_profile"],
61
+ user_full_name=claims["user_full_name"],
62
+ abbreviation=claims["abbreviation"],
63
+ aes_key_auth=claims["aes_key_auth"],
64
+ exp=claims["exp"],
65
+ )
66
+
67
+
68
+ @dataclass(frozen=True, slots=True)
69
+ class ActionTokenClaims(BaseClaims):
70
+
71
+ sub: str
72
+ action: Optional[str] = None
73
+
74
+ @classmethod
75
+ def from_dict(cls, claims: dict):
76
+
77
+ return cls(
78
+ sub=claims["sub"],
79
+ action=claims["action"],
80
+ )
@@ -1,17 +1,13 @@
1
1
  import asyncio
2
-
3
2
  from Osdental.Models.TokenClaims import (
4
3
  BaseClaims, AccessTokenClaims, UserTokenClaims,
5
4
  ActionTokenClaims, TokenValidationOptions
6
5
  )
7
-
8
6
  from Osdental.Services import IAuthTokenService
9
-
10
7
  from Osdental.Helpers.JwtTokenHelper import JwtTokenHelper
11
-
12
8
  from Osdental.Utils.RsaUtils import normalize_rsa_keys
13
-
14
9
  from Osdental.Secrets import ISecretProvider
10
+ from Osdental.Enums.Secret import Secret
15
11
 
16
12
  class JwtAuthTokenService(IAuthTokenService):
17
13
 
@@ -27,27 +23,37 @@ class JwtAuthTokenService(IAuthTokenService):
27
23
 
28
24
  self._jwt = None
29
25
 
26
+ self._init_lock = asyncio.Lock()
27
+
30
28
 
31
- async def __get_token_signatures(self):
29
+ async def _ensure_initialized(self):
32
30
 
33
- issuer, audience, private_key, public_key = await asyncio.gather(
34
- self.secrets.get("LEGACY-NAME"),
35
- self.secrets.get("LEGACY-URL"),
36
- self.secrets.get("SECRET-KEY-1"),
37
- self.secrets.get("PUBLIC-KEY-1"),
38
- )
31
+ if self._jwt is not None:
32
+ return
33
+
34
+ async with self._init_lock:
35
+
36
+ if self._jwt is not None:
37
+ return
38
+
39
+ issuer, audience, private_key, public_key = await asyncio.gather(
40
+ self.secrets.get(Secret.ISSUER),
41
+ self.secrets.get(Secret.AUDIENCE),
42
+ self.secrets.get(Secret.SECRET_KEY_1),
43
+ self.secrets.get(Secret.PUBLIC_KEY_1),
44
+ )
39
45
 
40
- self._issuer = issuer
41
- self._audience = audience
46
+ self._issuer = issuer
47
+ self._audience = audience
42
48
 
43
- self._jwt = JwtTokenHelper(
44
- private_key_pem=normalize_rsa_keys(
45
- private_key
46
- ),
47
- public_key_pem=normalize_rsa_keys(
48
- public_key
49
+ self._jwt = JwtTokenHelper(
50
+ private_key_pem=normalize_rsa_keys(
51
+ private_key
52
+ ),
53
+ public_key_pem=normalize_rsa_keys(
54
+ public_key
55
+ )
49
56
  )
50
- )
51
57
 
52
58
 
53
59
  async def generate_token(
@@ -56,7 +62,7 @@ class JwtAuthTokenService(IAuthTokenService):
56
62
  expiration_minutes: int,
57
63
  ) -> str:
58
64
 
59
- await self.__get_token_signatures()
65
+ await self._ensure_initialized()
60
66
 
61
67
  claims = {
62
68
  **claims.to_dict(),
@@ -74,7 +80,7 @@ class JwtAuthTokenService(IAuthTokenService):
74
80
  token: str,
75
81
  ) -> AccessTokenClaims:
76
82
 
77
- await self.__get_token_signatures()
83
+ await self._ensure_initialized()
78
84
 
79
85
  claims = self._jwt.validate_token(
80
86
  token=token,
@@ -84,12 +90,7 @@ class JwtAuthTokenService(IAuthTokenService):
84
90
  )
85
91
  )
86
92
 
87
- return AccessTokenClaims(
88
- id_legacy=claims["id_legacy"],
89
- id_enterprise=claims["id_enterprise"],
90
- aes_key=claims["aes_key"],
91
- exp=claims["exp"],
92
- )
93
+ return AccessTokenClaims.from_dict(claims)
93
94
 
94
95
 
95
96
  async def validate_action_token(
@@ -97,7 +98,7 @@ class JwtAuthTokenService(IAuthTokenService):
97
98
  token: str,
98
99
  ) -> ActionTokenClaims:
99
100
 
100
- await self.__get_token_signatures()
101
+ await self._ensure_initialized()
101
102
 
102
103
  claims = self._jwt.validate_token(
103
104
  token=token,
@@ -107,10 +108,7 @@ class JwtAuthTokenService(IAuthTokenService):
107
108
  )
108
109
  )
109
110
 
110
- return ActionTokenClaims(
111
- sub=claims["sub"],
112
- action=claims["action"],
113
- )
111
+ return ActionTokenClaims.from_dict(claims)
114
112
 
115
113
 
116
114
  async def validate_internal_access_token(
@@ -118,7 +116,7 @@ class JwtAuthTokenService(IAuthTokenService):
118
116
  token: str,
119
117
  ) -> UserTokenClaims:
120
118
 
121
- await self.__get_token_signatures()
119
+ await self._ensure_initialized()
122
120
 
123
121
  claims = self._jwt.validate_token(
124
122
  token=token,
@@ -130,18 +128,7 @@ class JwtAuthTokenService(IAuthTokenService):
130
128
  )
131
129
  )
132
130
 
133
- return UserTokenClaims(
134
- id_legacy=claims["id_legacy"],
135
- id_enterprise=claims["id_enterprise"],
136
- id_token=claims["id_token"],
137
- id_user=claims["id_user"],
138
- id_external_enterprise=claims["id_external_enterprise"],
139
- id_profile=claims["id_profile"],
140
- user_full_name=claims["user_full_name"],
141
- abbreviation=claims["abbreviation"],
142
- aes_key_auth=claims["aes_key_auth"],
143
- exp=claims["exp"],
144
- )
131
+ return UserTokenClaims.from_dict(claims)
145
132
 
146
133
 
147
134
  async def validate_token_for_refresh(
@@ -152,19 +139,8 @@ class JwtAuthTokenService(IAuthTokenService):
152
139
  Valida firma pero ignora exp.
153
140
  Usar exclusivamente para emitir un nuevo token cuando el anterior venció.
154
141
  """
155
- await self.__get_token_signatures()
142
+ await self._ensure_initialized()
156
143
 
157
144
  claims = self._jwt.get_claims_ignore_expiration(token)
158
145
 
159
- return UserTokenClaims(
160
- id_legacy=claims["id_legacy"],
161
- id_enterprise=claims["id_enterprise"],
162
- id_token=claims["id_token"],
163
- id_user=claims["id_user"],
164
- id_external_enterprise=claims["id_external_enterprise"],
165
- id_profile=claims["id_profile"],
166
- user_full_name=claims["user_full_name"],
167
- abbreviation=claims["abbreviation"],
168
- aes_key_auth=claims["aes_key_auth"],
169
- exp=claims["exp"],
170
- )
146
+ return UserTokenClaims.from_dict(claims)
@@ -1,47 +0,0 @@
1
- from typing import Dict, Any
2
- from dataclasses import dataclass, asdict
3
- from typing import Optional
4
-
5
- @dataclass(frozen=True, slots=True)
6
- class TokenValidationOptions:
7
- issuer: Optional[str] = None
8
- audience: Optional[str] = None
9
-
10
- validate_issuer: bool = True
11
- validate_audience: bool = True
12
-
13
- @dataclass(frozen=True, slots=True)
14
- class BaseClaims:
15
-
16
- def to_dict(self) -> Dict[str, Any]:
17
- return asdict(self)
18
-
19
- @dataclass(frozen=True, slots=True)
20
- class AccessTokenClaims(BaseClaims):
21
-
22
- id_legacy: int
23
- id_enterprise: int
24
- aes_key: str
25
- exp: Optional[int] = 0
26
-
27
-
28
- @dataclass(frozen=True, slots=True)
29
- class UserTokenClaims(BaseClaims):
30
-
31
- id_legacy: str
32
- id_enterprise: str
33
- id_token: str
34
- id_user: str
35
- id_external_enterprise: str
36
- id_profile: str
37
- user_full_name: str
38
- abbreviation: str
39
- aes_key_auth: str
40
- exp: Optional[int] = 0
41
-
42
-
43
- @dataclass(frozen=True, slots=True)
44
- class ActionTokenClaims(BaseClaims):
45
-
46
- sub: str
47
- action: Optional[str] = None
File without changes
File without changes