Encryptors 2.39__tar.gz → 2.40__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.39 → encryptors-2.40}/PKG-INFO +1 -20
- {encryptors-2.39 → encryptors-2.40}/setup.py +1 -1
- {encryptors-2.39 → encryptors-2.40}/src/Encryptors.egg-info/PKG-INFO +1 -20
- {encryptors-2.39 → encryptors-2.40}/src/Encryptors.egg-info/SOURCES.txt +1 -0
- encryptors-2.40/src/Osdental/Decorators/PublicResolver.py +3 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Decorators/SecureResolver.py +8 -3
- encryptors-2.40/src/Osdental/Graphql/Extensions/AuditExtension.py +190 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Storage/AzureBlobStorage.py +5 -1
- encryptors-2.40/src/Osdental/__init__.py +0 -0
- encryptors-2.39/README.md +0 -17
- encryptors-2.39/src/Osdental/Graphql/Extensions/AuditExtension.py +0 -120
- /encryptors-2.39/src/Osdental/Database/__init__.py → /encryptors-2.40/README.md +0 -0
- {encryptors-2.39 → encryptors-2.40}/setup.cfg +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Encryptors.egg-info/dependency_links.txt +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Encryptors.egg-info/entry_points.txt +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Encryptors.egg-info/requires.txt +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Encryptors.egg-info/top_level.txt +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Cli/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Database/BaseRepository.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Database/Connection.py +0 -0
- {encryptors-2.39/src/Osdental/Decorators → encryptors-2.40/src/Osdental/Database}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Decorators/Grpc.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Decorators/Retry.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Decorators/SqlDataNormalizer.py +0 -0
- {encryptors-2.39/src/Osdental/Encryptor → encryptors-2.40/src/Osdental/Decorators}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Encryptor/Aes.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Encryptor/Argon2.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Encryptor/Bcrypt.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Encryptor/Jwt.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Encryptor/Rsa.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Encryptor/Sha512.py +0 -0
- {encryptors-2.39/src/Osdental/Exception → encryptors-2.40/src/Osdental/Encryptor}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Exception/ControlledException.py +0 -0
- {encryptors-2.39/src/Osdental/Graphql/Extensions → encryptors-2.40/src/Osdental/Exception}/__init__.py +0 -0
- {encryptors-2.39/src/Osdental/Graphql/_Helpers → encryptors-2.40/src/Osdental/Graphql/Extensions}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Graphql/Models/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Graphql/_Exceptions/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Graphql/_Helpers/_AuditHelper.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Graphql/_Helpers/_ExtractAuthToken.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Graphql/_Helpers/_TenantPolicy.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Graphql/_Helpers/_TokenService.py +0 -0
- {encryptors-2.39/src/Osdental/Graphql → encryptors-2.40/src/Osdental/Graphql/_Helpers}/__init__.py +0 -0
- {encryptors-2.39/src/Osdental/Helpers → encryptors-2.40/src/Osdental/Graphql}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Helpers/AuditDispatcher.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Helpers/KeyVaultService.py +0 -0
- {encryptors-2.39/src/Osdental/Http → encryptors-2.40/src/Osdental/Helpers}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Http/APIClient.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Http/_Exceptions.py +0 -0
- {encryptors-2.39/src/Osdental/Models → encryptors-2.40/src/Osdental/Http}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Messaging/AzureServiceBus.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Messaging/Kafka.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Messaging/RabbitMQ.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Messaging/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Models/AuditConfig.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Models/Response.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Models/Token.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Models/_Audit.py +0 -0
- {encryptors-2.39/src/Osdental/RedisCache → encryptors-2.40/src/Osdental/Models}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/RedisCache/Redis.py +0 -0
- {encryptors-2.39/src/Osdental/Rest/Context → encryptors-2.40/src/Osdental/RedisCache}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Rest/Context/RequestContext.py +0 -0
- {encryptors-2.39/src/Osdental/Rest/Middlewares → encryptors-2.40/src/Osdental/Rest/Context}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Rest/Middlewares/RequestContextMiddleware.py +0 -0
- {encryptors-2.39/src/Osdental/Rest → encryptors-2.40/src/Osdental/Rest/Middlewares}/__init__.py +0 -0
- {encryptors-2.39/src/Osdental/Shared/Enums → encryptors-2.40/src/Osdental/Rest}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Enums/Code.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Enums/Constant.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Enums/FileType.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Enums/GrahpqlOperation.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Enums/Message.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Enums/Profile.py +0 -0
- {encryptors-2.39/src/Osdental/Shared/Utils → encryptors-2.40/src/Osdental/Shared/Enums}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Logger.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Utils/CaseConverter.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Utils/CodeGenerator.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Utils/DataNormalizer.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Utils/DataUtils.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Utils/DateUtils.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Utils/FileMetaData.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Utils/HashValidator.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Utils/Mapper.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Utils/PasswordGenerator.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Utils/QueryGenerator.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Shared/Utils/TextProcessor.py +0 -0
- {encryptors-2.39/src/Osdental/Shared → encryptors-2.40/src/Osdental/Shared/Utils}/__init__.py +0 -0
- {encryptors-2.39/src/Osdental → encryptors-2.40/src/Osdental/Shared}/__init__.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Storage/S3Storage.py +0 -0
- {encryptors-2.39 → encryptors-2.40}/src/Osdental/Storage/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Encryptors
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.40
|
|
4
4
|
Summary: End-to-end algorithm library
|
|
5
5
|
Author: OSDental LLC
|
|
6
6
|
Author-email: support@osdental.ai
|
|
@@ -59,26 +59,7 @@ Requires-Dist: gunicorn==23.0.0
|
|
|
59
59
|
Dynamic: author
|
|
60
60
|
Dynamic: author-email
|
|
61
61
|
Dynamic: classifier
|
|
62
|
-
Dynamic: description
|
|
63
62
|
Dynamic: description-content-type
|
|
64
63
|
Dynamic: requires-dist
|
|
65
64
|
Dynamic: requires-python
|
|
66
65
|
Dynamic: summary
|
|
67
|
-
|
|
68
|
-
# osdental-library
|
|
69
|
-
|
|
70
|
-
`osdental-library` is a versatile and easy-to-use library for handling common tasks related to **encryption**, **hashing**, and **JWT token management**. Ideal for projects that require a secure and efficient approach to handling sensitive data.
|
|
71
|
-
|
|
72
|
-
## Features
|
|
73
|
-
|
|
74
|
-
- Generation and validation of **hashes** using modern algorithms.
|
|
75
|
-
- Encryption and decryption of data using secure keys.
|
|
76
|
-
- Creation and verification of **JWT tokens** for authentication and authorization.
|
|
77
|
-
- Implementations that are easy to integrate into any Python project.
|
|
78
|
-
|
|
79
|
-
## Installation
|
|
80
|
-
|
|
81
|
-
You can easily install `osdental-library` using `pip`:
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
pip install osdental-library
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Encryptors
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.40
|
|
4
4
|
Summary: End-to-end algorithm library
|
|
5
5
|
Author: OSDental LLC
|
|
6
6
|
Author-email: support@osdental.ai
|
|
@@ -59,26 +59,7 @@ Requires-Dist: gunicorn==23.0.0
|
|
|
59
59
|
Dynamic: author
|
|
60
60
|
Dynamic: author-email
|
|
61
61
|
Dynamic: classifier
|
|
62
|
-
Dynamic: description
|
|
63
62
|
Dynamic: description-content-type
|
|
64
63
|
Dynamic: requires-dist
|
|
65
64
|
Dynamic: requires-python
|
|
66
65
|
Dynamic: summary
|
|
67
|
-
|
|
68
|
-
# osdental-library
|
|
69
|
-
|
|
70
|
-
`osdental-library` is a versatile and easy-to-use library for handling common tasks related to **encryption**, **hashing**, and **JWT token management**. Ideal for projects that require a secure and efficient approach to handling sensitive data.
|
|
71
|
-
|
|
72
|
-
## Features
|
|
73
|
-
|
|
74
|
-
- Generation and validation of **hashes** using modern algorithms.
|
|
75
|
-
- Encryption and decryption of data using secure keys.
|
|
76
|
-
- Creation and verification of **JWT tokens** for authentication and authorization.
|
|
77
|
-
- Implementations that are easy to integrate into any Python project.
|
|
78
|
-
|
|
79
|
-
## Installation
|
|
80
|
-
|
|
81
|
-
You can easily install `osdental-library` using `pip`:
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
pip install osdental-library
|
|
@@ -12,6 +12,7 @@ src/Osdental/Database/BaseRepository.py
|
|
|
12
12
|
src/Osdental/Database/Connection.py
|
|
13
13
|
src/Osdental/Database/__init__.py
|
|
14
14
|
src/Osdental/Decorators/Grpc.py
|
|
15
|
+
src/Osdental/Decorators/PublicResolver.py
|
|
15
16
|
src/Osdental/Decorators/Retry.py
|
|
16
17
|
src/Osdental/Decorators/SecureResolver.py
|
|
17
18
|
src/Osdental/Decorators/SqlDataNormalizer.py
|
|
@@ -8,12 +8,13 @@ from Osdental.Shared.Enums.Profile import Profile
|
|
|
8
8
|
from Osdental.Exception.ControlledException import OSDException, AccessDeniedException
|
|
9
9
|
from Osdental.Encryptor.Aes import AES
|
|
10
10
|
from Osdental.Graphql.Models import BaseGraphQLContext
|
|
11
|
+
from Osdental.Shared.Logger import logger
|
|
11
12
|
|
|
12
13
|
def secure_resolver(action = None):
|
|
13
14
|
def decorator(func: Callable):
|
|
14
15
|
|
|
15
16
|
signature = inspect.signature(func)
|
|
16
|
-
|
|
17
|
+
params = signature.parameters
|
|
17
18
|
|
|
18
19
|
@wraps(func)
|
|
19
20
|
async def wrapper(obj: Any, context: BaseGraphQLContext, **kwargs: Dict[str, Any]):
|
|
@@ -26,10 +27,13 @@ def secure_resolver(action = None):
|
|
|
26
27
|
if Profile(token.abbreviation) not in action.allowed_roles:
|
|
27
28
|
raise AccessDeniedException(error="The user's profile is not allowed to perform this action.")
|
|
28
29
|
|
|
29
|
-
if
|
|
30
|
+
if "token" in params:
|
|
31
|
+
kwargs["token"] = token
|
|
32
|
+
|
|
33
|
+
if "data" in params:
|
|
30
34
|
kwargs["data"] = payload
|
|
31
35
|
|
|
32
|
-
result: Response = await func(obj,
|
|
36
|
+
result: Response = await func(obj, **kwargs)
|
|
33
37
|
|
|
34
38
|
context.audit_plain_response = copy.deepcopy(result)
|
|
35
39
|
|
|
@@ -39,6 +43,7 @@ def secure_resolver(action = None):
|
|
|
39
43
|
return result.send()
|
|
40
44
|
|
|
41
45
|
except (Exception, OSDException) as e:
|
|
46
|
+
logger.exception(f"An error has occurred: {str(e)}")
|
|
42
47
|
result = Response(
|
|
43
48
|
status=getattr(e, "status_code", "DB_ERROR_UNEXPECTED"),
|
|
44
49
|
message=getattr(e, "message", "Could not process request."),
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from graphql.pyutils import is_awaitable
|
|
3
|
+
from ariadne.types import Extension
|
|
4
|
+
from Osdental.Shared.Logger import logger
|
|
5
|
+
from Osdental.Encryptor.Aes import AES
|
|
6
|
+
from Osdental.Graphql._Helpers._TenantPolicy import TenantPolicy
|
|
7
|
+
from Osdental.Rest.Context.RequestContext import (
|
|
8
|
+
current_context,
|
|
9
|
+
RequestContext
|
|
10
|
+
)
|
|
11
|
+
from Osdental.Graphql.Models import BaseGraphQLContext
|
|
12
|
+
from Osdental.Shared.Enums.Constant import Constant
|
|
13
|
+
|
|
14
|
+
class AuditExtension(Extension):
|
|
15
|
+
|
|
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
|
+
|
|
26
|
+
self.errors = None
|
|
27
|
+
self.request_payload = None
|
|
28
|
+
self.result = None
|
|
29
|
+
|
|
30
|
+
def _should_skip(self, body) -> bool:
|
|
31
|
+
query = body.get("query", "") or ""
|
|
32
|
+
return "__schema" in query or "__type" in query
|
|
33
|
+
|
|
34
|
+
async def resolve(self, next_, root, info, **kwargs):
|
|
35
|
+
|
|
36
|
+
context: BaseGraphQLContext = info.context
|
|
37
|
+
request = context.request
|
|
38
|
+
|
|
39
|
+
# 🔹 cache body
|
|
40
|
+
if not hasattr(context, "_cached_body"):
|
|
41
|
+
context._cached_body = await request.json()
|
|
42
|
+
|
|
43
|
+
body = context._cached_body
|
|
44
|
+
|
|
45
|
+
# 🔹 skip introspection
|
|
46
|
+
if self._should_skip(body):
|
|
47
|
+
result = next_(root, info, **kwargs)
|
|
48
|
+
if is_awaitable(result):
|
|
49
|
+
result = await result
|
|
50
|
+
return result
|
|
51
|
+
|
|
52
|
+
# 🔥 CLAVE
|
|
53
|
+
is_root = root is None
|
|
54
|
+
|
|
55
|
+
# 🔥 SOLO ROOT → TODO TU SISTEMA
|
|
56
|
+
if is_root:
|
|
57
|
+
|
|
58
|
+
# 🔹 identificar resolver público
|
|
59
|
+
resolver_fn = getattr(next_, "__wrapped__", next_)
|
|
60
|
+
is_public = getattr(resolver_fn, "_is_public", False)
|
|
61
|
+
|
|
62
|
+
# 🔹 inicializar auth UNA SOLA VEZ
|
|
63
|
+
if not hasattr(context, "_auth_initialized"):
|
|
64
|
+
context._auth_initialized = True
|
|
65
|
+
|
|
66
|
+
headers = request.headers
|
|
67
|
+
container = context.container
|
|
68
|
+
token_service = container.token_service
|
|
69
|
+
|
|
70
|
+
aes_auth = request.app.state.aes_auth
|
|
71
|
+
aes_user = request.app.state.aes_user
|
|
72
|
+
|
|
73
|
+
if not aes_auth or not aes_user:
|
|
74
|
+
aes_auth = None
|
|
75
|
+
aes_user = None
|
|
76
|
+
|
|
77
|
+
original_token = None
|
|
78
|
+
if not is_public and headers.get("authorization"):
|
|
79
|
+
try:
|
|
80
|
+
original_token = await token_service.authenticate(headers, aes_user)
|
|
81
|
+
except Exception:
|
|
82
|
+
original_token = None
|
|
83
|
+
|
|
84
|
+
context._original_token = original_token
|
|
85
|
+
context.token = original_token
|
|
86
|
+
context.aes_auth = aes_auth
|
|
87
|
+
|
|
88
|
+
# 🔐 VALIDACIÓN SOLO ROOT
|
|
89
|
+
original_token = getattr(context, "_original_token", None)
|
|
90
|
+
|
|
91
|
+
if not is_public and not original_token:
|
|
92
|
+
raise ValueError("Authorization required")
|
|
93
|
+
|
|
94
|
+
# 🔹 payload
|
|
95
|
+
variables = body.get("variables") or {}
|
|
96
|
+
|
|
97
|
+
encrypted_payload = (
|
|
98
|
+
kwargs.get("data")
|
|
99
|
+
or variables.get("data")
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
decrypted_payload = None
|
|
103
|
+
|
|
104
|
+
if encrypted_payload is not None:
|
|
105
|
+
if isinstance(encrypted_payload, dict):
|
|
106
|
+
decrypted_payload = encrypted_payload
|
|
107
|
+
|
|
108
|
+
elif isinstance(encrypted_payload, str):
|
|
109
|
+
try:
|
|
110
|
+
decrypted_payload = json.loads(encrypted_payload)
|
|
111
|
+
except Exception:
|
|
112
|
+
if context.aes_auth:
|
|
113
|
+
try:
|
|
114
|
+
decrypted_payload = AES.decrypt(context.aes_auth, encrypted_payload)
|
|
115
|
+
try:
|
|
116
|
+
decrypted_payload = json.loads(decrypted_payload)
|
|
117
|
+
except Exception:
|
|
118
|
+
pass
|
|
119
|
+
except Exception:
|
|
120
|
+
decrypted_payload = None
|
|
121
|
+
|
|
122
|
+
if decrypted_payload is not None:
|
|
123
|
+
context.decrypted_payload = decrypted_payload
|
|
124
|
+
|
|
125
|
+
if not is_public:
|
|
126
|
+
token = TenantPolicy.resolve(
|
|
127
|
+
token=context._original_token,
|
|
128
|
+
headers=request.headers,
|
|
129
|
+
decrypted_payload=decrypted_payload,
|
|
130
|
+
operation_type=info.operation.operation.value
|
|
131
|
+
)
|
|
132
|
+
context.token = token
|
|
133
|
+
|
|
134
|
+
# 🔹 auditoría request
|
|
135
|
+
if not self.request_payload:
|
|
136
|
+
token = context.token
|
|
137
|
+
|
|
138
|
+
self.request = request
|
|
139
|
+
self.request_payload = {
|
|
140
|
+
"operation_type": info.operation.operation.value,
|
|
141
|
+
"operation_name": body.get("operationName", "UnknownOperation"),
|
|
142
|
+
"query": body.get("query"),
|
|
143
|
+
"variables": decrypted_payload,
|
|
144
|
+
"user": token.user_full_name if token else "Public"
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
# 🔥 SIEMPRE ejecutar resolver (root + fields)
|
|
148
|
+
result = next_(root, info, **kwargs)
|
|
149
|
+
|
|
150
|
+
if is_awaitable(result):
|
|
151
|
+
result = await result
|
|
152
|
+
|
|
153
|
+
# 🔹 SOLO ROOT captura resultado final
|
|
154
|
+
if is_root and self.result is None:
|
|
155
|
+
self.result = result
|
|
156
|
+
|
|
157
|
+
if not getattr(context, "audit_plain_response", None):
|
|
158
|
+
context.audit_plain_response = result
|
|
159
|
+
|
|
160
|
+
return result
|
|
161
|
+
|
|
162
|
+
def has_errors(self, errors, context):
|
|
163
|
+
self.errors = errors
|
|
164
|
+
|
|
165
|
+
def request_finished(self, context):
|
|
166
|
+
|
|
167
|
+
if not self.request_payload:
|
|
168
|
+
return
|
|
169
|
+
|
|
170
|
+
query = self.request_payload.get("query", "")
|
|
171
|
+
|
|
172
|
+
if "__schema" in query or "__type" in query:
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
final_result = context.audit_plain_response or self.result
|
|
176
|
+
|
|
177
|
+
if final_result is None:
|
|
178
|
+
return
|
|
179
|
+
|
|
180
|
+
dispatcher = context.request.app.state.audit_dispatcher
|
|
181
|
+
|
|
182
|
+
try:
|
|
183
|
+
dispatcher.dispatch(
|
|
184
|
+
request=self.request,
|
|
185
|
+
request_payload=self.request_payload,
|
|
186
|
+
result=final_result,
|
|
187
|
+
audit_type=Constant.MESSAGE_LOG_INTERNAL
|
|
188
|
+
)
|
|
189
|
+
except Exception as e:
|
|
190
|
+
logger(f"[AUDIT ERROR]: {str(e)}")
|
|
File without changes
|
encryptors-2.39/README.md
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# osdental-library
|
|
2
|
-
|
|
3
|
-
`osdental-library` is a versatile and easy-to-use library for handling common tasks related to **encryption**, **hashing**, and **JWT token management**. Ideal for projects that require a secure and efficient approach to handling sensitive data.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- Generation and validation of **hashes** using modern algorithms.
|
|
8
|
-
- Encryption and decryption of data using secure keys.
|
|
9
|
-
- Creation and verification of **JWT tokens** for authentication and authorization.
|
|
10
|
-
- Implementations that are easy to integrate into any Python project.
|
|
11
|
-
|
|
12
|
-
## Installation
|
|
13
|
-
|
|
14
|
-
You can easily install `osdental-library` using `pip`:
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
pip install osdental-library
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from graphql.pyutils import is_awaitable
|
|
3
|
-
from ariadne.types import Extension
|
|
4
|
-
from Osdental.Encryptor.Aes import AES
|
|
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
|
|
11
|
-
from Osdental.Graphql._Exceptions import AESKeyNotFound
|
|
12
|
-
from Osdental.Shared.Enums.Constant import Constant
|
|
13
|
-
|
|
14
|
-
class AuditExtension(Extension):
|
|
15
|
-
|
|
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
|
-
|
|
26
|
-
self.errors = None
|
|
27
|
-
self.request_payload = None
|
|
28
|
-
self.result = None
|
|
29
|
-
|
|
30
|
-
async def resolve(self, next_, root, info, **kwargs):
|
|
31
|
-
|
|
32
|
-
if not self.request_payload:
|
|
33
|
-
context: BaseGraphQLContext = info.context
|
|
34
|
-
|
|
35
|
-
request = context.request
|
|
36
|
-
self.request = request
|
|
37
|
-
|
|
38
|
-
body = await request.json()
|
|
39
|
-
headers = request.headers
|
|
40
|
-
|
|
41
|
-
container = context.container
|
|
42
|
-
token_service = container.token_service
|
|
43
|
-
|
|
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")
|
|
52
|
-
|
|
53
|
-
original_token = await token_service.authenticate(headers, aes_user)
|
|
54
|
-
|
|
55
|
-
variables = body.get("variables") or {}
|
|
56
|
-
encrypted_payload = variables.get("data")
|
|
57
|
-
|
|
58
|
-
decrypted_payload = None
|
|
59
|
-
|
|
60
|
-
if encrypted_payload:
|
|
61
|
-
try:
|
|
62
|
-
decrypted_payload = AES.decrypt(aes_auth, encrypted_payload)
|
|
63
|
-
|
|
64
|
-
try:
|
|
65
|
-
decrypted_payload = json.loads(decrypted_payload)
|
|
66
|
-
except Exception:
|
|
67
|
-
pass
|
|
68
|
-
|
|
69
|
-
except Exception:
|
|
70
|
-
decrypted_payload = None
|
|
71
|
-
|
|
72
|
-
token = TenantPolicy.resolve(
|
|
73
|
-
token=original_token,
|
|
74
|
-
headers=request.headers,
|
|
75
|
-
decrypted_payload=decrypted_payload,
|
|
76
|
-
operation_type=info.operation.operation.value
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
self.request_payload = {
|
|
80
|
-
"operation_type": info.operation.operation.value,
|
|
81
|
-
"operation_name": body.get("operationName", "UnknownOperation"),
|
|
82
|
-
"query": body.get("query"),
|
|
83
|
-
"variables": decrypted_payload,
|
|
84
|
-
"user": token.user_full_name
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
context.decrypted_payload = decrypted_payload
|
|
88
|
-
context.token = token
|
|
89
|
-
context.aes_auth = aes_auth
|
|
90
|
-
|
|
91
|
-
result = next_(root, info, **kwargs)
|
|
92
|
-
|
|
93
|
-
if is_awaitable(result):
|
|
94
|
-
result = await result
|
|
95
|
-
|
|
96
|
-
if root is None:
|
|
97
|
-
self.result = result
|
|
98
|
-
|
|
99
|
-
return result
|
|
100
|
-
|
|
101
|
-
def has_errors(self, errors, context):
|
|
102
|
-
self.errors = errors
|
|
103
|
-
|
|
104
|
-
def request_finished(self, context):
|
|
105
|
-
if not self.request_payload: return
|
|
106
|
-
|
|
107
|
-
query = self.request_payload.get("query", "")
|
|
108
|
-
|
|
109
|
-
if "__schema" in query or "__type" in query: return
|
|
110
|
-
|
|
111
|
-
if not hasattr(context, "audit_plain_response"): return
|
|
112
|
-
|
|
113
|
-
dispatcher = context.request.app.state.audit_dispatcher
|
|
114
|
-
|
|
115
|
-
dispatcher.dispatch(
|
|
116
|
-
request=self.request,
|
|
117
|
-
request_payload=self.request_payload,
|
|
118
|
-
result=context.audit_plain_response,
|
|
119
|
-
audit_type=Constant.MESSAGE_LOG_INTERNAL
|
|
120
|
-
)
|
|
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.39/src/Osdental/Decorators → encryptors-2.40/src/Osdental/Database}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{encryptors-2.39/src/Osdental/Encryptor → encryptors-2.40/src/Osdental/Decorators}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{encryptors-2.39/src/Osdental/Exception → encryptors-2.40/src/Osdental/Encryptor}/__init__.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
|
{encryptors-2.39/src/Osdental/Graphql → encryptors-2.40/src/Osdental/Graphql/_Helpers}/__init__.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
|
{encryptors-2.39/src/Osdental/Rest/Context → encryptors-2.40/src/Osdental/RedisCache}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{encryptors-2.39 → encryptors-2.40}/src/Osdental/Rest/Middlewares/RequestContextMiddleware.py
RENAMED
|
File without changes
|
{encryptors-2.39/src/Osdental/Rest → encryptors-2.40/src/Osdental/Rest/Middlewares}/__init__.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
|
{encryptors-2.39/src/Osdental/Shared/Utils → encryptors-2.40/src/Osdental/Shared/Enums}/__init__.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
|
{encryptors-2.39/src/Osdental/Shared → encryptors-2.40/src/Osdental/Shared/Utils}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|