Encryptors 2.31__tar.gz → 2.32__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 (113) hide show
  1. {encryptors-2.31 → encryptors-2.32}/PKG-INFO +1 -1
  2. {encryptors-2.31 → encryptors-2.32}/setup.py +1 -1
  3. {encryptors-2.31 → encryptors-2.32}/src/Encryptors.egg-info/PKG-INFO +1 -1
  4. {encryptors-2.31 → encryptors-2.32}/src/Encryptors.egg-info/SOURCES.txt +11 -26
  5. encryptors-2.32/src/Osdental/Database/Connection.py +66 -0
  6. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Encryptor/Bcrypt.py +1 -1
  7. encryptors-2.32/src/Osdental/Exception/ControlledException.py +142 -0
  8. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Graphql/Extensions/AuditExtension.py +7 -3
  9. encryptors-2.32/src/Osdental/Graphql/_Exceptions/__init__.py +8 -0
  10. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Graphql/_Helpers/_AuditHelper.py +9 -13
  11. encryptors-2.32/src/Osdental/Graphql/_Helpers/_ExtractAuthToken.py +11 -0
  12. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Graphql/_Helpers/_TenantPolicy.py +10 -2
  13. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Graphql/_Helpers/_TokenService.py +4 -6
  14. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Helpers/AuditDispatcher.py +45 -17
  15. encryptors-2.32/src/Osdental/Http/APIClient.py +137 -0
  16. encryptors-2.32/src/Osdental/Http/_Exceptions.py +12 -0
  17. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Messaging/AzureServiceBus.py +12 -3
  18. encryptors-2.32/src/Osdental/Messaging/Kafka.py +11 -0
  19. encryptors-2.32/src/Osdental/Messaging/RabbitMQ.py +11 -0
  20. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Messaging/__init__.py +2 -2
  21. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Models/Response.py +3 -3
  22. encryptors-2.32/src/Osdental/Models/_Audit.py +13 -0
  23. encryptors-2.32/src/Osdental/Rest/Context/RequestContext.py +19 -0
  24. encryptors-2.32/src/Osdental/Rest/Middlewares/RequestContextMiddleware.py +22 -0
  25. encryptors-2.32/src/Osdental/Shared/Enums/Constant.py +10 -0
  26. encryptors-2.31/src/Osdental/BlobStorage/Storage.py +0 -50
  27. encryptors-2.31/src/Osdental/Database/Connection.py +0 -218
  28. encryptors-2.31/src/Osdental/Database/UnitOfWork.py +0 -44
  29. encryptors-2.31/src/Osdental/Database/UowFactory.py +0 -8
  30. encryptors-2.31/src/Osdental/Decorators/AuditLog.py +0 -87
  31. encryptors-2.31/src/Osdental/Decorators/DecryptedData.py +0 -139
  32. encryptors-2.31/src/Osdental/Exception/ControlledException.py +0 -189
  33. encryptors-2.31/src/Osdental/ExternalHttp/Client.py +0 -117
  34. encryptors-2.31/src/Osdental/Grpc/Base/GrpcClientBase.py +0 -61
  35. encryptors-2.31/src/Osdental/Grpc/Client/PortalClient.py +0 -44
  36. encryptors-2.31/src/Osdental/Grpc/Generated/Common_pb2.py +0 -40
  37. encryptors-2.31/src/Osdental/Grpc/Generated/Common_pb2_grpc.py +0 -24
  38. encryptors-2.31/src/Osdental/Grpc/Generated/Portal_pb2.py +0 -37
  39. encryptors-2.31/src/Osdental/Grpc/Generated/Portal_pb2_grpc.py +0 -140
  40. encryptors-2.31/src/Osdental/InternalHttp/Request.py +0 -105
  41. encryptors-2.31/src/Osdental/InternalHttp/Response.py +0 -39
  42. encryptors-2.31/src/Osdental/Messaging/Kafka.py +0 -12
  43. encryptors-2.31/src/Osdental/Messaging/RabbitMQ.py +0 -12
  44. encryptors-2.31/src/Osdental/Models/CDataIntegration.py +0 -41
  45. encryptors-2.31/src/Osdental/ServicesBus/ServicesBus.py +0 -26
  46. encryptors-2.31/src/Osdental/ServicesBus/TaskQueue.py +0 -52
  47. encryptors-2.31/src/Osdental/Shared/Config/__init__.py +0 -15
  48. encryptors-2.31/src/Osdental/Shared/Enums/Constant.py +0 -16
  49. encryptors-2.31/src/Osdental/Shared/Enums/__init__.py +0 -0
  50. encryptors-2.31/src/Osdental/Shared/Utils/__init__.py +0 -0
  51. encryptors-2.31/src/Osdental/Shared/__init__.py +0 -0
  52. encryptors-2.31/src/Osdental/__init__.py +0 -0
  53. {encryptors-2.31 → encryptors-2.32}/README.md +0 -0
  54. {encryptors-2.31 → encryptors-2.32}/setup.cfg +0 -0
  55. {encryptors-2.31 → encryptors-2.32}/src/Encryptors.egg-info/dependency_links.txt +0 -0
  56. {encryptors-2.31 → encryptors-2.32}/src/Encryptors.egg-info/entry_points.txt +0 -0
  57. {encryptors-2.31 → encryptors-2.32}/src/Encryptors.egg-info/requires.txt +0 -0
  58. {encryptors-2.31 → encryptors-2.32}/src/Encryptors.egg-info/top_level.txt +0 -0
  59. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Cli/__init__.py +0 -0
  60. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Database/BaseRepository.py +0 -0
  61. {encryptors-2.31/src/Osdental/BlobStorage → encryptors-2.32/src/Osdental/Database}/__init__.py +0 -0
  62. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Decorators/Grpc.py +0 -0
  63. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Decorators/Retry.py +0 -0
  64. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Decorators/SecureResolver.py +0 -0
  65. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Decorators/SqlDataNormalizer.py +0 -0
  66. {encryptors-2.31/src/Osdental/Database → encryptors-2.32/src/Osdental/Decorators}/__init__.py +0 -0
  67. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Encryptor/Aes.py +0 -0
  68. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Encryptor/Argon2.py +0 -0
  69. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Encryptor/Jwt.py +0 -0
  70. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Encryptor/Rsa.py +0 -0
  71. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Encryptor/Sha512.py +0 -0
  72. {encryptors-2.31/src/Osdental/Decorators → encryptors-2.32/src/Osdental/Encryptor}/__init__.py +0 -0
  73. {encryptors-2.31/src/Osdental/Encryptor → encryptors-2.32/src/Osdental/Exception}/__init__.py +0 -0
  74. {encryptors-2.31/src/Osdental/Exception → encryptors-2.32/src/Osdental/Graphql/Extensions}/__init__.py +0 -0
  75. {encryptors-2.31/src/Osdental/ExternalHttp → encryptors-2.32/src/Osdental/Graphql/_Helpers}/__init__.py +0 -0
  76. {encryptors-2.31/src/Osdental/Graphql/Extensions → encryptors-2.32/src/Osdental/Graphql}/__init__.py +0 -0
  77. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Helpers/KeyVaultService.py +0 -0
  78. {encryptors-2.31/src/Osdental/Graphql/_Helpers → encryptors-2.32/src/Osdental/Helpers}/__init__.py +0 -0
  79. {encryptors-2.31/src/Osdental/Graphql → encryptors-2.32/src/Osdental/Http}/__init__.py +0 -0
  80. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Models/AuditConfig.py +0 -0
  81. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Models/Catalog.py +0 -0
  82. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Models/Legacy.py +0 -0
  83. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Models/Token.py +0 -0
  84. {encryptors-2.31/src/Osdental/Grpc/Base → encryptors-2.32/src/Osdental/Models}/__init__.py +0 -0
  85. {encryptors-2.31 → encryptors-2.32}/src/Osdental/RedisCache/Redis.py +0 -0
  86. {encryptors-2.31/src/Osdental/Grpc/Client → encryptors-2.32/src/Osdental/RedisCache}/__init__.py +0 -0
  87. {encryptors-2.31/src/Osdental/Grpc/Generated → encryptors-2.32/src/Osdental/Rest/Context}/__init__.py +0 -0
  88. {encryptors-2.31/src/Osdental/Grpc → encryptors-2.32/src/Osdental/Rest/Middlewares}/__init__.py +0 -0
  89. {encryptors-2.31/src/Osdental/Helpers → encryptors-2.32/src/Osdental/Rest}/__init__.py +0 -0
  90. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Enums/Code.py +0 -0
  91. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Enums/FileType.py +0 -0
  92. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Enums/GrahpqlOperation.py +0 -0
  93. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Enums/Message.py +0 -0
  94. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Enums/Profile.py +0 -0
  95. {encryptors-2.31/src/Osdental/InternalHttp → encryptors-2.32/src/Osdental/Shared/Enums}/__init__.py +0 -0
  96. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Logger.py +0 -0
  97. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Utils/CaseConverter.py +0 -0
  98. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Utils/CodeGenerator.py +0 -0
  99. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Utils/DataNormalizer.py +0 -0
  100. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Utils/DataUtils.py +0 -0
  101. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Utils/DateUtils.py +0 -0
  102. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Utils/FileMetaData.py +0 -0
  103. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Utils/HashValidator.py +0 -0
  104. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Utils/Mapper.py +0 -0
  105. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Utils/PasswordGenerator.py +0 -0
  106. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Utils/QueryGenerator.py +0 -0
  107. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Shared/Utils/TextProcessor.py +0 -0
  108. {encryptors-2.31/src/Osdental/Models → encryptors-2.32/src/Osdental/Shared/Utils}/__init__.py +0 -0
  109. {encryptors-2.31/src/Osdental/RedisCache → encryptors-2.32/src/Osdental/Shared}/__init__.py +0 -0
  110. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Storage/AzureBlobStorage.py +0 -0
  111. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Storage/S3Storage.py +0 -0
  112. {encryptors-2.31 → encryptors-2.32}/src/Osdental/Storage/__init__.py +0 -0
  113. {encryptors-2.31/src/Osdental/ServicesBus → encryptors-2.32/src/Osdental}/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Encryptors
3
- Version: 2.31
3
+ Version: 2.32
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
 
3
3
  setup(
4
4
  name="Encryptors",
5
- version="2.31",
5
+ version="2.32",
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.31
3
+ Version: 2.32
4
4
  Summary: End-to-end algorithm library
5
5
  Author: OSDental LLC
6
6
  Author-email: support@osdental.ai
@@ -7,16 +7,10 @@ src/Encryptors.egg-info/entry_points.txt
7
7
  src/Encryptors.egg-info/requires.txt
8
8
  src/Encryptors.egg-info/top_level.txt
9
9
  src/Osdental/__init__.py
10
- src/Osdental/BlobStorage/Storage.py
11
- src/Osdental/BlobStorage/__init__.py
12
10
  src/Osdental/Cli/__init__.py
13
11
  src/Osdental/Database/BaseRepository.py
14
12
  src/Osdental/Database/Connection.py
15
- src/Osdental/Database/UnitOfWork.py
16
- src/Osdental/Database/UowFactory.py
17
13
  src/Osdental/Database/__init__.py
18
- src/Osdental/Decorators/AuditLog.py
19
- src/Osdental/Decorators/DecryptedData.py
20
14
  src/Osdental/Decorators/Grpc.py
21
15
  src/Osdental/Decorators/Retry.py
22
16
  src/Osdental/Decorators/SecureResolver.py
@@ -31,50 +25,41 @@ src/Osdental/Encryptor/Sha512.py
31
25
  src/Osdental/Encryptor/__init__.py
32
26
  src/Osdental/Exception/ControlledException.py
33
27
  src/Osdental/Exception/__init__.py
34
- src/Osdental/ExternalHttp/Client.py
35
- src/Osdental/ExternalHttp/__init__.py
36
28
  src/Osdental/Graphql/__init__.py
37
29
  src/Osdental/Graphql/Extensions/AuditExtension.py
38
30
  src/Osdental/Graphql/Extensions/__init__.py
31
+ src/Osdental/Graphql/_Exceptions/__init__.py
39
32
  src/Osdental/Graphql/_Helpers/_AuditHelper.py
33
+ src/Osdental/Graphql/_Helpers/_ExtractAuthToken.py
40
34
  src/Osdental/Graphql/_Helpers/_TenantPolicy.py
41
35
  src/Osdental/Graphql/_Helpers/_TokenService.py
42
36
  src/Osdental/Graphql/_Helpers/__init__.py
43
- src/Osdental/Grpc/__init__.py
44
- src/Osdental/Grpc/Base/GrpcClientBase.py
45
- src/Osdental/Grpc/Base/__init__.py
46
- src/Osdental/Grpc/Client/PortalClient.py
47
- src/Osdental/Grpc/Client/__init__.py
48
- src/Osdental/Grpc/Generated/Common_pb2.py
49
- src/Osdental/Grpc/Generated/Common_pb2_grpc.py
50
- src/Osdental/Grpc/Generated/Portal_pb2.py
51
- src/Osdental/Grpc/Generated/Portal_pb2_grpc.py
52
- src/Osdental/Grpc/Generated/__init__.py
53
37
  src/Osdental/Helpers/AuditDispatcher.py
54
38
  src/Osdental/Helpers/KeyVaultService.py
55
39
  src/Osdental/Helpers/__init__.py
56
- src/Osdental/InternalHttp/Request.py
57
- src/Osdental/InternalHttp/Response.py
58
- src/Osdental/InternalHttp/__init__.py
40
+ src/Osdental/Http/APIClient.py
41
+ src/Osdental/Http/_Exceptions.py
42
+ src/Osdental/Http/__init__.py
59
43
  src/Osdental/Messaging/AzureServiceBus.py
60
44
  src/Osdental/Messaging/Kafka.py
61
45
  src/Osdental/Messaging/RabbitMQ.py
62
46
  src/Osdental/Messaging/__init__.py
63
47
  src/Osdental/Models/AuditConfig.py
64
- src/Osdental/Models/CDataIntegration.py
65
48
  src/Osdental/Models/Catalog.py
66
49
  src/Osdental/Models/Legacy.py
67
50
  src/Osdental/Models/Response.py
68
51
  src/Osdental/Models/Token.py
52
+ src/Osdental/Models/_Audit.py
69
53
  src/Osdental/Models/__init__.py
70
54
  src/Osdental/RedisCache/Redis.py
71
55
  src/Osdental/RedisCache/__init__.py
72
- src/Osdental/ServicesBus/ServicesBus.py
73
- src/Osdental/ServicesBus/TaskQueue.py
74
- src/Osdental/ServicesBus/__init__.py
56
+ src/Osdental/Rest/__init__.py
57
+ src/Osdental/Rest/Context/RequestContext.py
58
+ src/Osdental/Rest/Context/__init__.py
59
+ src/Osdental/Rest/Middlewares/RequestContextMiddleware.py
60
+ src/Osdental/Rest/Middlewares/__init__.py
75
61
  src/Osdental/Shared/Logger.py
76
62
  src/Osdental/Shared/__init__.py
77
- src/Osdental/Shared/Config/__init__.py
78
63
  src/Osdental/Shared/Enums/Code.py
79
64
  src/Osdental/Shared/Enums/Constant.py
80
65
  src/Osdental/Shared/Enums/FileType.py
@@ -0,0 +1,66 @@
1
+ import struct
2
+ import urllib
3
+ from typing import Dict
4
+ from azure.identity import DefaultAzureCredential
5
+ from sqlalchemy import event
6
+ from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
7
+ from sqlalchemy.orm import sessionmaker
8
+
9
+ SQL_COPT_SS_ACCESS_TOKEN = 1256
10
+ class Connection:
11
+
12
+ _instances: Dict[str, 'Connection'] = {}
13
+
14
+ def __new__(cls, db_url: str):
15
+ if db_url not in cls._instances:
16
+ cls._instances[db_url] = super(Connection, cls).__new__(cls)
17
+ return cls._instances[db_url]
18
+
19
+ def __init__(self, db_url: str):
20
+ if not hasattr(self, 'initialized'):
21
+ self.credential = DefaultAzureCredential()
22
+ raw_odbc_string = db_url
23
+ params = urllib.parse.quote_plus(raw_odbc_string)
24
+ sqlalchemy_url = f"mssql+aioodbc:///?odbc_connect={params}"
25
+ self.engine = create_async_engine(
26
+ sqlalchemy_url,
27
+ pool_size=20,
28
+ max_overflow=40,
29
+ pool_timeout=30,
30
+ pool_recycle=1800,
31
+ pool_pre_ping=True
32
+ )
33
+ self._attach_token_listener()
34
+ self.session_factory = sessionmaker(
35
+ bind=self.engine,
36
+ class_=AsyncSession,
37
+ expire_on_commit=False
38
+ )
39
+ self.initialized = True
40
+
41
+ def _attach_token_listener(self):
42
+
43
+ @event.listens_for(self.engine.sync_engine, "do_connect")
44
+ def provide_token(dialect, conn_rec, cargs, cparams):
45
+
46
+ token = self.credential.get_token(
47
+ "https://database.windows.net/.default"
48
+ ).token
49
+
50
+ token_bytes = token.encode("utf-16-le")
51
+
52
+ token_struct = struct.pack(
53
+ f"<I{len(token_bytes)}s",
54
+ len(token_bytes),
55
+ token_bytes
56
+ )
57
+
58
+ cparams["attrs_before"] = {
59
+ SQL_COPT_SS_ACCESS_TOKEN: token_struct
60
+ }
61
+
62
+
63
+ async def close_engine(self) -> None:
64
+ """Dispose of the engine and remove instance."""
65
+ if self.engine:
66
+ await self.engine.dispose()
@@ -1,6 +1,6 @@
1
1
  import bcrypt
2
2
  from Osdental.Exception.ControlledException import OSDException
3
- from Osdental.Shared.Constant import Constant
3
+ from Osdental.Shared.Enums.Constant import Constant
4
4
 
5
5
  class BcryptPasswordManager:
6
6
  def __init__(self, rounds: int = 12):
@@ -0,0 +1,142 @@
1
+ from typing import Any
2
+ from Osdental.Shared.Enums.Code import Code
3
+ from Osdental.Shared.Enums.Message import Message
4
+
5
+ class OSDException(Exception):
6
+ """ Base class for all custom exceptions. """
7
+ def __init__(
8
+ self,
9
+ message: str = Message.UNEXPECTED_ERROR_MSG,
10
+ error: str = None,
11
+ status_code: Any = Code.APP_ERROR_CODE
12
+ ):
13
+ super().__init__(error)
14
+ self.message = message
15
+ self.error = error
16
+ self.status_code = status_code
17
+
18
+ class UnauthorizedException(OSDException):
19
+ def __init__(
20
+ self,
21
+ message: str = Message.PORTAL_ACCESS_RESTRICTED_MSG,
22
+ error: str = None,
23
+ status_code: str = Code.UNAUTHORIZATED_CODE
24
+ ):
25
+ super().__init__(message=message, error=error, status_code=status_code)
26
+
27
+ class RequestDataException(OSDException):
28
+ def __init__(
29
+ self,
30
+ message: str = Message.INVALID_REQUEST_PARAMS_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
+
36
+ class DatabaseConnectionException(OSDException):
37
+ def __init__(
38
+ self,
39
+ message: str = Message.INVALID_FORMAT_MSG,
40
+ error: str = None,
41
+ status_code: str = Code.DATABASE_CONNECTION_ERROR_CODE
42
+ ):
43
+ super().__init__(message=message, error=error, status_code=status_code)
44
+
45
+ class DatabaseException(OSDException):
46
+ def __init__(
47
+ self,
48
+ message: str = Message.UNEXPECTED_ERROR_MSG,
49
+ error: str = None,
50
+ status_code: str = Code.DATABASE_ERROR_CODE
51
+ ):
52
+ super().__init__(message=message, error=error, status_code=status_code)
53
+
54
+ class RSAEncryptException(OSDException):
55
+ def __init__(
56
+ self,
57
+ message: str = Message.UNEXPECTED_ERROR_MSG,
58
+ error: str = None,
59
+ status_code: str = Code.RSA_ERROR_CODE
60
+ ):
61
+ super().__init__(message=message, error=error, status_code=status_code)
62
+
63
+ class AESEncryptException(OSDException):
64
+ def __init__(
65
+ self,
66
+ message: str = Message.UNEXPECTED_ERROR_MSG,
67
+ error: str = None,
68
+ status_code: str = Code.AES_ERROR_CODE
69
+ ):
70
+ super().__init__(message=message, error=error, status_code=status_code)
71
+
72
+ class JWTokenException(OSDException):
73
+ def __init__(
74
+ self,
75
+ message: str = Message.UNEXPECTED_ERROR_MSG,
76
+ error: str = None,
77
+ status_code: str = Code.JWT_ERROR_CODE
78
+ ):
79
+ super().__init__(message=message, error=error, status_code=status_code)
80
+
81
+ class AzureException(OSDException):
82
+ def __init__(
83
+ self,
84
+ message: str = Message.UNEXPECTED_ERROR_MSG,
85
+ error: str = None,
86
+ status_code: str = Code.AZURE_ERROR_CODE
87
+ ):
88
+ super().__init__(message=message, error=error, status_code=status_code)
89
+
90
+ class RedisException(OSDException):
91
+ def __init__(
92
+ self,
93
+ message: str = Message.UNEXPECTED_ERROR_MSG,
94
+ error: str = None,
95
+ status_code: str = Code.REDIS_ERROR_CODE
96
+ ):
97
+ super().__init__(message=message, error=error, status_code=status_code)
98
+
99
+ class ValidationDataException(OSDException):
100
+ def __init__(
101
+ self,
102
+ message: str = Message.UNEXPECTED_ERROR_MSG,
103
+ error: str = None,
104
+ status_code: str = Code.REQUEST_VALIDATION_ERROR_CODE
105
+ ):
106
+ super().__init__(message=message, error=error, status_code=status_code)
107
+
108
+ class UnexpectedException(OSDException):
109
+ def __init__(
110
+ self,
111
+ message: str = Message.UNEXPECTED_ERROR_MSG,
112
+ error: str = None,
113
+ status_code: str = Code.UNEXPECTED_ERROR_CODE
114
+ ):
115
+ super().__init__(message=message, error=error, status_code=status_code)
116
+
117
+ class MissingFieldException(OSDException):
118
+ def __init__(
119
+ self,
120
+ message: str = Message.MISSING_FIELD_ERROR_MSG,
121
+ error: str = None,
122
+ status_code: str = Code.MISSING_FIELD_ERROR_CODE
123
+ ):
124
+ super().__init__(message=message, error=error, status_code=status_code)
125
+
126
+ class ProfilePermissionDeniedException(OSDException):
127
+ def __init__(
128
+ self,
129
+ message: str = Message.PROFILE_PERMISSION_DENIED_MSG,
130
+ error: str = None,
131
+ status_code: str = Code.PROFILE_PERMISSION_DENIED_CODE
132
+ ):
133
+ super().__init__(message=message, error=error, status_code=status_code)
134
+
135
+ class InvalidFormatException(OSDException):
136
+ def __init__(
137
+ self,
138
+ message: str = Message.INVALID_FORMAT_MSG,
139
+ error: str = None,
140
+ status_code: str = Code.INVALID_FORMAT_CODE
141
+ ):
142
+ super().__init__(message=message, error=error, status_code=status_code)
@@ -3,7 +3,7 @@ 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.Models.Token import AuthToken
6
+ from Osdental.Graphql._Exceptions import AESKeyNotFound
7
7
 
8
8
  class AuditExtension(Extension):
9
9
 
@@ -29,7 +29,7 @@ class AuditExtension(Extension):
29
29
 
30
30
  aes_key = request.app.state.aes_auth
31
31
  if not aes_key:
32
- raise ValueError("Could not find authorization key Aes.")
32
+ raise AESKeyNotFound("Could not find authorization key Aes.")
33
33
 
34
34
  original_token = await token_service.authenticate(request)
35
35
 
@@ -50,7 +50,7 @@ class AuditExtension(Extension):
50
50
  except Exception:
51
51
  decrypted_payload = None
52
52
 
53
- token: AuthToken = TenantPolicy.resolve(
53
+ token = TenantPolicy.resolve(
54
54
  token=original_token,
55
55
  headers=request.headers,
56
56
  decrypted_payload=decrypted_payload,
@@ -83,6 +83,10 @@ class AuditExtension(Extension):
83
83
  self.errors = errors
84
84
 
85
85
  def request_finished(self, context):
86
+ query = self.request_payload.get("query", "")
87
+ if "__schema" in query or "__type" in query: return
88
+
89
+ if not hasattr(context, "audit_plain_response"): return
86
90
 
87
91
  dispatcher = context.request.app.state.audit_dispatcher
88
92
 
@@ -0,0 +1,8 @@
1
+ from Osdental.Exception.ControlledException import OSDException
2
+
3
+ class AESKeyNotFound(OSDException):
4
+ def __init__(
5
+ self,
6
+ error: str = None,
7
+ ):
8
+ super().__init__(error=error)
@@ -1,19 +1,15 @@
1
1
  import json
2
2
  from typing import Dict, Literal, Any, Optional
3
- from fastapi import Request
4
- from Osdental.Models.AuditConfig import AuditConfig
3
+ from Osdental.Models._Audit import Audit
5
4
 
6
5
  class AuditHelper:
7
6
 
8
7
  @staticmethod
9
- async def build_request_payload(
10
- request: Request,
11
- audit_config: AuditConfig,
12
- payload: Any = {},
13
- operation_name: str = "Unknown",
14
- full_name: str = "Joe Doe"
15
- ) -> Dict:
16
-
8
+ async def build_request_payload(audit: Audit) -> Dict:
9
+ request = audit.request
10
+ audit_config = audit.audit_config
11
+ payload = audit.payload
12
+
17
13
  default_value = "*"
18
14
 
19
15
  user_ip = request.headers.get("X-Forwarded-For")
@@ -39,14 +35,14 @@ class AuditHelper:
39
35
  "microServiceUrl": str(request.url),
40
36
  "microServiceName": audit_config.microservice_name,
41
37
  "microServiceVersion": audit_config.microservice_version,
42
- "serviceName": operation_name,
38
+ "serviceName": audit.operation_name,
43
39
  "machineNameUser": request.headers.get("Machinenameuser", default_value),
44
40
  "ipUser": user_ip or default_value,
45
- "userName": full_name,
41
+ "userName": audit.full_name,
46
42
  "localitation": default_value,
47
43
  "httpMethod": request.method,
48
44
  "messageIn": json.dumps(payload) if payload else default_value,
49
- "auditLog": "MESSAGE_LOG_INTERNAL"
45
+ "auditLog": audit.audit_type
50
46
  }
51
47
 
52
48
  @staticmethod
@@ -0,0 +1,11 @@
1
+ from fastapi import Request
2
+
3
+ class ExtractAuthToken:
4
+
5
+ @staticmethod
6
+ async 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]
@@ -1,11 +1,19 @@
1
- from Osdental.Encryptor.Aes import AES
1
+ from typing import Dict, Any
2
2
  from uuid import UUID
3
3
  from graphql import OperationType
4
+ from starlette.datastructures import Headers
5
+ from Osdental.Encryptor.Aes import AES
6
+ from Osdental.Models.Token import AuthToken
4
7
 
5
8
  class TenantPolicy:
6
9
 
7
10
  @staticmethod
8
- def resolve(token, headers, decrypted_payload, operation_type: str):
11
+ def resolve(
12
+ token: AuthToken,
13
+ headers: Headers,
14
+ decrypted_payload: Dict[str, Any],
15
+ operation_type: str
16
+ ) -> AuthToken:
9
17
  aes = AES()
10
18
  # Solo aplicamos cambios si es QUERY
11
19
  if operation_type != OperationType.QUERY.value:
@@ -1,6 +1,8 @@
1
+ from fastapi import Request
1
2
  from Osdental.Encryptor.Aes import AES
2
3
  from Osdental.Encryptor.Jwt import JWT
3
4
  from Osdental.Models.Token import AuthToken
5
+ from Osdental.Graphql._Helpers._ExtractAuthToken import ExtractAuthToken
4
6
 
5
7
  class TokenService:
6
8
 
@@ -9,12 +11,8 @@ class TokenService:
9
11
  self.auth_validator = auth_validator
10
12
  self.aes = AES()
11
13
 
12
- async def authenticate(self, request):
13
- authorization = request.headers.get("authorization")
14
- if not authorization or not authorization.startswith("Bearer "):
15
- raise ValueError("Missing Bearer token")
16
-
17
- encrypted_token = authorization.split(" ")[1]
14
+ async def authenticate(self, request: Request) -> AuthToken:
15
+ encrypted_token = ExtractAuthToken.get_auth_token(request)
18
16
 
19
17
  aes_user = request.app.state.aes_user
20
18
 
@@ -1,8 +1,13 @@
1
1
  import asyncio
2
- import logging
2
+ from typing import Dict, Any
3
+ from fastapi import Request
3
4
  from Osdental.Models.AuditConfig import AuditConfig
4
5
  from Osdental.Messaging import IMessageQueue
5
6
  from Osdental.Graphql._Helpers._AuditHelper import AuditHelper
7
+ from Osdental.Models._Audit import Audit
8
+ from Osdental.Models.Response import Response
9
+ from Osdental.Shared.Enums.Constant import Constant
10
+ from Osdental.Shared.Logger import logger
6
11
 
7
12
  class AuditDispatcher:
8
13
 
@@ -29,19 +34,25 @@ class AuditDispatcher:
29
34
  await self._worker_task
30
35
 
31
36
  # Ultra rápido, no bloquea
32
- def dispatch(self, request, request_payload, result, errors = None):
37
+ def dispatch(
38
+ self,
39
+ request: Request,
40
+ request_payload: Dict[str, Any],
41
+ result: Response,
42
+ audit_type: str = None
43
+ ):
33
44
  try:
34
45
  payload = {
35
46
  "request": request,
36
47
  "request_payload": request_payload,
37
48
  "result": result,
38
- "errors": errors
49
+ "audit_type": audit_type
39
50
  }
40
51
 
41
52
  self._queue.put_nowait(payload)
42
53
 
43
54
  except asyncio.QueueFull:
44
- logging.error("Audit queue full. Dropping message.")
55
+ logger.error("Audit queue full. Dropping message.")
45
56
 
46
57
  # Worker real
47
58
  async def _worker(self):
@@ -55,39 +66,56 @@ class AuditDispatcher:
55
66
  try:
56
67
  await self._process(payload)
57
68
  except Exception:
58
- logging.exception("Audit processing failed")
69
+ logger.exception("Audit processing failed")
59
70
  finally:
60
71
  self._queue.task_done()
61
72
 
62
73
  # Logica
63
- async def _process(self, payload):
74
+ async def _process(self, payload: Dict[str, Any]):
64
75
  request = payload["request"]
65
76
  request_payload = payload["request_payload"]
66
77
  result = payload["result"]
78
+ audit_type = payload["audit_type"]
67
79
 
68
80
  operation_name = request_payload.get("operation_name")
69
81
  if operation_name == 'UnknownOperation':
70
- logging.info("Skipping audit: no data in GraphQL response")
82
+ logger.info("Skipping audit: no data in GraphQL response")
71
83
  return
72
84
 
73
- request_audit_payload = await AuditHelper.build_request_payload(
85
+ audit = Audit(
86
+ audit_type=audit_type,
74
87
  request=request,
75
88
  audit_config=self._audit_config,
76
89
  operation_name=operation_name,
77
90
  full_name=request_payload.get("user"),
78
91
  payload=request_payload.get("variables")
79
92
  )
93
+ request_audit_payload = await AuditHelper.build_request_payload(audit=audit)
80
94
 
81
- status = result.get("status")
82
- message = result.get("message")
83
- data = result.get("data")
95
+ status_code = result.status
96
+ message = result.message
97
+ data = result.data
98
+ error = result.error if result.error else message
84
99
 
85
- ERROR_PREFIXES = ("DB_ERROR", "DB_WARNING")
86
- if status.upper().startswith(ERROR_PREFIXES):
100
+ if audit_type == Constant.MESSAGE_LOG_INTERNAL:
101
+
102
+ ERROR_PREFIXES = ("DB_ERROR", "DB_WARNING")
103
+
104
+ is_error = status_code.upper().startswith(ERROR_PREFIXES)
105
+
106
+ else:
107
+
108
+ try:
109
+ is_error = not (200 <= status_code < 300)
110
+ except ValueError:
111
+ is_error = True
112
+
113
+
114
+ if is_error:
87
115
  payload = AuditHelper.build_final_payload(
88
116
  _type="ERROR",
89
- status_code=status,
90
- error=message
117
+ status_code=status_code,
118
+ error=error
91
119
  )
92
120
 
93
121
  audit_message = request_audit_payload | payload
@@ -95,10 +123,10 @@ class AuditDispatcher:
95
123
  else:
96
124
  payload = AuditHelper.build_final_payload(
97
125
  _type="RESPONSE",
98
- status_code="200",
126
+ status_code=status_code,
99
127
  result=data
100
128
  )
101
129
 
102
130
  audit_message = request_audit_payload | payload
103
131
 
104
- await self._messaging.enqueue(audit_message)
132
+ await self._messaging.send_message(audit_message)