sharedkernel 2.6.3__py3-none-any.whl → 2.7.0__py3-none-any.whl
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.
- sharedkernel/config.py +2 -1
- sharedkernel/database/cache/__init__.py +0 -0
- sharedkernel/database/cache/cache_repository.py +37 -0
- sharedkernel/database/cache/redis_generic_cache.py +88 -0
- sharedkernel/ip_session_service.py +19 -18
- sharedkernel/logger/logger_service.py +3 -2
- {sharedkernel-2.6.3.dist-info → sharedkernel-2.7.0.dist-info}/METADATA +6 -2
- {sharedkernel-2.6.3.dist-info → sharedkernel-2.7.0.dist-info}/RECORD +10 -7
- {sharedkernel-2.6.3.dist-info → sharedkernel-2.7.0.dist-info}/WHEEL +0 -0
- {sharedkernel-2.6.3.dist-info → sharedkernel-2.7.0.dist-info}/top_level.txt +0 -0
sharedkernel/config.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
IP_SESSION_VERBOSE = True if os.getenv("IP_SESSION_VERBOSE", "False").lower() == "true" else False
|
|
4
|
+
LOG_VERBOSE = True if os.getenv("LOG_VERBOSE", "False").lower() == "true" else False
|
|
4
5
|
|
|
5
6
|
# Log *******************************************************************************
|
|
6
7
|
LOG_ENABLE = True if os.getenv("LOG_ENABLE", "False").lower() == "true" else False
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
from typing import Generic, Optional, TypeVar
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
|
|
6
|
+
T = TypeVar("T", bound=BaseModel)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CacheRepository(ABC, Generic[T]):
|
|
10
|
+
@abstractmethod
|
|
11
|
+
async def set(
|
|
12
|
+
self,
|
|
13
|
+
key: str,
|
|
14
|
+
value: T,
|
|
15
|
+
ttl_seconds: int | None = None,
|
|
16
|
+
) -> None:
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
async def get(self, key: str) -> Optional[T]:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
async def exists(self, key: str) -> bool:
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
async def delete(self, key: str) -> int:
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
async def delete_group(self, key_prefix: str) -> int:
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
async def clear(self) -> int:
|
|
37
|
+
pass
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from typing import Generic, Optional, Type, TypeVar
|
|
2
|
+
from pydantic import BaseModel
|
|
3
|
+
from redis.asyncio import Redis
|
|
4
|
+
|
|
5
|
+
from cache.cache_repository import CacheRepository
|
|
6
|
+
|
|
7
|
+
T = TypeVar("T", bound=BaseModel)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RedisGenericCache(CacheRepository[T], Generic[T]):
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
client: Redis,
|
|
14
|
+
namespace: str,
|
|
15
|
+
model: Type[T],
|
|
16
|
+
default_ttl_seconds: int | None = None,
|
|
17
|
+
):
|
|
18
|
+
self.client = client
|
|
19
|
+
self.namespace = namespace
|
|
20
|
+
self.model = model
|
|
21
|
+
self.default_ttl_seconds = default_ttl_seconds
|
|
22
|
+
|
|
23
|
+
def _pref(self, key: str) -> str:
|
|
24
|
+
return f"{self.namespace}:{key}"
|
|
25
|
+
|
|
26
|
+
def _unpref(self, key: str) -> str:
|
|
27
|
+
prefix = f"{self.namespace}:"
|
|
28
|
+
return key.removeprefix(prefix)
|
|
29
|
+
|
|
30
|
+
def _serialize(self, value: T) -> str:
|
|
31
|
+
return value.model_dump_json()
|
|
32
|
+
|
|
33
|
+
def _deserialize(self, raw: str | bytes) -> T:
|
|
34
|
+
return self.model.model_validate_json(raw.decode())
|
|
35
|
+
|
|
36
|
+
async def set(
|
|
37
|
+
self,
|
|
38
|
+
key: str,
|
|
39
|
+
value: T,
|
|
40
|
+
ttl_seconds: int | None = None,
|
|
41
|
+
) -> None:
|
|
42
|
+
if value is None:
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
redis_key = self._pref(key)
|
|
46
|
+
ttl = ttl_seconds if ttl_seconds else self.default_ttl_seconds
|
|
47
|
+
|
|
48
|
+
if ttl:
|
|
49
|
+
await self.client.set(redis_key, self._serialize(value), ex=ttl)
|
|
50
|
+
else:
|
|
51
|
+
await self.client.set(redis_key, self._serialize(value))
|
|
52
|
+
|
|
53
|
+
async def get(self, key: str) -> Optional[T]:
|
|
54
|
+
raw = await self.client.get(self._pref(key))
|
|
55
|
+
if raw is None:
|
|
56
|
+
return None
|
|
57
|
+
return self._deserialize(raw)
|
|
58
|
+
|
|
59
|
+
async def exists(self, key: str) -> bool:
|
|
60
|
+
return bool(await self.client.exists(self._pref(key)))
|
|
61
|
+
|
|
62
|
+
async def delete(self, key: str) -> int:
|
|
63
|
+
return await self.client.delete(self._pref(key))
|
|
64
|
+
|
|
65
|
+
async def delete_group(self, key_prefix: str) -> int:
|
|
66
|
+
pattern = self._pref(f"{key_prefix}*")
|
|
67
|
+
deleted = 0
|
|
68
|
+
|
|
69
|
+
async for key in self.client.scan_iter(match=pattern):
|
|
70
|
+
deleted += await self.client.delete(key)
|
|
71
|
+
|
|
72
|
+
return deleted
|
|
73
|
+
|
|
74
|
+
async def clear(self) -> int:
|
|
75
|
+
deleted = 0
|
|
76
|
+
|
|
77
|
+
async for key in self.client.scan_iter(match=f"{self.namespace}:*"):
|
|
78
|
+
deleted += await self.client.delete(key)
|
|
79
|
+
|
|
80
|
+
return deleted
|
|
81
|
+
|
|
82
|
+
async def get_all_ids(self) -> list[str]:
|
|
83
|
+
result: list[str] = []
|
|
84
|
+
|
|
85
|
+
async for raw in self.client.scan_iter(match=f"{self.namespace}:*"):
|
|
86
|
+
result.append(self._unpref(raw.decode()))
|
|
87
|
+
|
|
88
|
+
return result
|
|
@@ -78,88 +78,89 @@ class IPSessionAuth:
|
|
|
78
78
|
def ip_session_auth(self, request: Request):
|
|
79
79
|
|
|
80
80
|
if not config.IP_SESSION_AUTH_ENABLE:
|
|
81
|
-
if config.
|
|
81
|
+
if config.IP_SESSION_VERBOSE:
|
|
82
82
|
print("IP_SESSION_AUTH | OK | IP Session Auth is disabled")
|
|
83
83
|
return
|
|
84
84
|
|
|
85
|
-
if config.
|
|
86
|
-
print("
|
|
85
|
+
if config.IP_SESSION_VERBOSE:
|
|
86
|
+
print("="*70)
|
|
87
|
+
print("IP_SESSION_AUTH | INFO | Request Headers:\n", request.headers)
|
|
87
88
|
|
|
88
89
|
api_key = request.headers.get(config.APIKEY_HEADER_NAME)
|
|
89
90
|
|
|
90
91
|
if api_key:
|
|
91
|
-
if config.
|
|
92
|
+
if config.IP_SESSION_VERBOSE:
|
|
92
93
|
print("IP_SESSION_AUTH | OK | API Key is provided")
|
|
93
94
|
return
|
|
94
95
|
|
|
95
96
|
state = getattr(request.state, "decoded_token", None)
|
|
96
|
-
if config.
|
|
97
|
+
if config.IP_SESSION_VERBOSE:
|
|
97
98
|
print("IP_SESSION_AUTH | INFO | State: ", state)
|
|
98
99
|
|
|
99
100
|
if not state:
|
|
100
|
-
if config.
|
|
101
|
+
if config.IP_SESSION_VERBOSE:
|
|
101
102
|
print("IP_SESSION_AUTH | ERROR | No state found")
|
|
102
103
|
raise UnAuthorizedException()
|
|
103
104
|
|
|
104
105
|
nameid = state.get("nameid")
|
|
105
106
|
sessionid = state.get("sessionId")
|
|
106
|
-
if config.
|
|
107
|
+
if config.IP_SESSION_VERBOSE:
|
|
107
108
|
print("IP_SESSION_AUTH | INFO | Nameid: ", nameid)
|
|
108
109
|
print("IP_SESSION_AUTH | INFO | Sessionid: ", sessionid)
|
|
109
110
|
|
|
110
111
|
if not nameid or not sessionid:
|
|
111
|
-
if config.
|
|
112
|
+
if config.IP_SESSION_VERBOSE:
|
|
112
113
|
print("IP_SESSION_AUTH | ERROR | No nameid or sessionid found")
|
|
113
114
|
raise UnAuthorizedException()
|
|
114
115
|
|
|
115
116
|
request_ip = self._get_ip_from_request(request, config.IP_HEADER_NAME)
|
|
116
117
|
|
|
117
118
|
if not request_ip:
|
|
118
|
-
if config.
|
|
119
|
+
if config.IP_SESSION_VERBOSE:
|
|
119
120
|
print("IP_SESSION_AUTH | ERROR | No request ip found")
|
|
120
121
|
raise UnAuthorizedException()
|
|
121
122
|
|
|
122
123
|
request_ip = request_ip.strip()
|
|
123
|
-
if config.
|
|
124
|
+
if config.IP_SESSION_VERBOSE:
|
|
124
125
|
print("IP_SESSION_AUTH | INFO | Request ip: ", request_ip)
|
|
125
126
|
|
|
126
127
|
if self._is_ip_allowed(request_ip):
|
|
127
|
-
if config.
|
|
128
|
+
if config.IP_SESSION_VERBOSE:
|
|
128
129
|
print("IP_SESSION_AUTH | OK | IP is in whitelist")
|
|
129
130
|
return
|
|
130
131
|
|
|
131
132
|
redis_key = f"userId:{nameid}:session:{sessionid}"
|
|
132
133
|
user_data = self.redis.get(redis_key)
|
|
133
|
-
if config.
|
|
134
|
+
if config.IP_SESSION_VERBOSE:
|
|
134
135
|
print("IP_SESSION_AUTH | INFO | User data: ", user_data)
|
|
135
136
|
|
|
136
137
|
if not user_data:
|
|
137
|
-
if config.
|
|
138
|
+
if config.IP_SESSION_VERBOSE:
|
|
138
139
|
print("IP_SESSION_AUTH | ERROR | No user data found")
|
|
139
140
|
raise UnAuthorizedException()
|
|
140
141
|
|
|
141
142
|
try:
|
|
142
143
|
payload = json.loads(user_data.decode())
|
|
143
144
|
except (ValueError, UnicodeDecodeError, TypeError):
|
|
144
|
-
if config.
|
|
145
|
+
if config.IP_SESSION_VERBOSE:
|
|
145
146
|
print("IP_SESSION_AUTH | ERROR | Error decoding user data")
|
|
146
147
|
raise UnAuthorizedException()
|
|
147
148
|
|
|
148
149
|
stored_ip = payload.get("Ip")
|
|
149
|
-
if config.
|
|
150
|
+
if config.IP_SESSION_VERBOSE:
|
|
150
151
|
print("IP_SESSION_AUTH | INFO | Stored ip: ", stored_ip)
|
|
151
152
|
|
|
152
153
|
if not stored_ip:
|
|
153
|
-
if config.
|
|
154
|
+
if config.IP_SESSION_VERBOSE:
|
|
154
155
|
print("IP_SESSION_AUTH | ERROR | No stored ip found")
|
|
155
156
|
raise UnAuthorizedException()
|
|
156
157
|
|
|
157
158
|
if stored_ip.strip() != request_ip:
|
|
158
|
-
if config.
|
|
159
|
+
if config.IP_SESSION_VERBOSE:
|
|
159
160
|
print("IP_SESSION_AUTH | ERROR | Stored ip does not match request ip")
|
|
160
161
|
raise UnAuthorizedException()
|
|
161
162
|
|
|
162
163
|
lifetime_minutes = self._get_lifetime()
|
|
163
164
|
self.redis.expire(redis_key, lifetime_minutes * 60)
|
|
164
|
-
if config.
|
|
165
|
+
if config.IP_SESSION_VERBOSE:
|
|
165
166
|
print("IP_SESSION_AUTH | OK | IP session auth successful")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sharedkernel
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.0
|
|
4
4
|
Summary: sharekernel is a shared package between all python projects
|
|
5
5
|
Author: Smilinno
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -20,7 +20,7 @@ Requires-Dist: markdown
|
|
|
20
20
|
Requires-Dist: beautifulsoup4
|
|
21
21
|
Requires-Dist: deepdiff
|
|
22
22
|
Requires-Dist: kombu
|
|
23
|
-
Requires-Dist: redis
|
|
23
|
+
Requires-Dist: redis==8.0.0
|
|
24
24
|
Dynamic: author
|
|
25
25
|
Dynamic: description
|
|
26
26
|
Dynamic: description-content-type
|
|
@@ -31,6 +31,10 @@ Dynamic: summary
|
|
|
31
31
|
this is a shared kernel package
|
|
32
32
|
|
|
33
33
|
# Change Log
|
|
34
|
+
### Version 2.7.0
|
|
35
|
+
- Add Redis and cache repository
|
|
36
|
+
### Version 2.6.4
|
|
37
|
+
- Add Verbose to log
|
|
34
38
|
### Version 2.6.3
|
|
35
39
|
- fix bug ip-header-name
|
|
36
40
|
### Version 2.6.2
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
sharedkernel/common.py,sha256=HL5vsuJBaIeBcoXA8Hbe6jnYAv4danIszo5Y7G2gGDA,622
|
|
2
|
-
sharedkernel/config.py,sha256=
|
|
2
|
+
sharedkernel/config.py,sha256=H_PjT9jawZqKtwnlVCSuefkh_b24QJX2ckP-YNGp6aA,1996
|
|
3
3
|
sharedkernel/data_format_converter.py,sha256=GWGbfhKJBifkz-cfnqKAFjJM43WC0qdq9KSELj3xR30,3774
|
|
4
4
|
sharedkernel/date_converter.py,sha256=Cjd4ewm0pIfQzv7nlgAAB_EYrr-VvXxQGehJCNphgXc,4491
|
|
5
5
|
sharedkernel/diff_utils.py,sha256=mtwJmc05GAXUOB0ZLtqAhfBT1kGoSQ7qmP5N44P73ho,2564
|
|
6
6
|
sharedkernel/file_validation.py,sha256=X-vdUy1Se2li3f-_Ro5UJi_Muqz-QmkKu6b5eHs-eiA,2892
|
|
7
|
-
sharedkernel/ip_session_service.py,sha256=
|
|
7
|
+
sharedkernel/ip_session_service.py,sha256=qFYvXpvQfwcYa3qRckw7e0DQW0fMHnl_0zg0FAkpZXo,5812
|
|
8
8
|
sharedkernel/jwt_service.py,sha256=QNkGLn1ZzU5gBD0Cjyadtqu_zHnS3_A2y-CDZSrc4Q8,1872
|
|
9
9
|
sharedkernel/multipart_upload.py,sha256=JVlCBlznB9dWh2_spjAqzLOqQT1CHUTvrR4m7ug8qaM,1877
|
|
10
10
|
sharedkernel/regex_masking.py,sha256=zQrgteP8Cuq1EC9B7QUJqAXUxK9ISD9kWMYK2AbRfw0,3288
|
|
@@ -17,6 +17,9 @@ sharedkernel/database/mongo_generic_audit_repository.py,sha256=F8z_4l7c2wHOeF995
|
|
|
17
17
|
sharedkernel/database/mongo_generic_repository.py,sha256=KrigWbKXo99GegMjvrlH4BYGPH8kvST9smxcWjdNqEU,5887
|
|
18
18
|
sharedkernel/database/mongo_health_checker.py,sha256=IYAaV8mJgGG_uxfnSRRvbq6JybxpA58pBCpDb7XXaq8,1842
|
|
19
19
|
sharedkernel/database/pagination_response_dto.py,sha256=91Gkajx4hHmYfypP7EJTiMP1ZrzopjwRuEyMrzQ3SVE,389
|
|
20
|
+
sharedkernel/database/cache/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
+
sharedkernel/database/cache/cache_repository.py,sha256=xL5Q18wgsSzIID_Zq8r0sa2OKC_c96q7cg2zUALzPwg,750
|
|
22
|
+
sharedkernel/database/cache/redis_generic_cache.py,sha256=9_jUDfvUP37_IQ0ANDzniHv-Hj6lQDKPtJ0J76e8r7A,2526
|
|
20
23
|
sharedkernel/enum/__init__.py,sha256=BQxVEO5O1PrNB8gm5nUrh_9Us2HcdgPF-8iZuro7UEM,73
|
|
21
24
|
sharedkernel/enum/error_code.py,sha256=M_z-rAW4-zmWs1hMcc97zo4CpqzmoUidMarwo9UuNAk,551
|
|
22
25
|
sharedkernel/enum/redis_mode_enum.py,sha256=v_n9g7_rq_pdMiZrC8mMveRcjgF3eBv3K2tsaV1Pidc,136
|
|
@@ -29,7 +32,7 @@ sharedkernel/logger/log_dto.py,sha256=GN0nfZMTMJN4hXM47M_Wkkr1Fgm4kVgWfgQWNZfuUe
|
|
|
29
32
|
sharedkernel/logger/log_enums.py,sha256=b6RCy6oLx-uUQANQVoEq3yxMld0m4Gtq5pTDos78vL8,209
|
|
30
33
|
sharedkernel/logger/log_info.py,sha256=bGv8QBTNB-4EfJf-cYuuAU2c_d1PNt_7R15vc3y-fJk,141
|
|
31
34
|
sharedkernel/logger/log_middlewares.py,sha256=fjqti-K1u5dJkrbU02jTtRK__N7vEUot5N5DbAUZ-XY,1014
|
|
32
|
-
sharedkernel/logger/logger_service.py,sha256=
|
|
35
|
+
sharedkernel/logger/logger_service.py,sha256=z_1JpMWFWRAdhoErYy1UtKzhRYtd_uDGiEuP3hOz4A0,6608
|
|
33
36
|
sharedkernel/normalizer/__init__.py,sha256=cDmbquAW6o7rnvv3XkI7h5vMYp-3NmGN6zp1ryYOUcc,154
|
|
34
37
|
sharedkernel/normalizer/number_normalizer.py,sha256=zJ700T0t9P7hgxp7vox98LdPw9A4jsUjIHA_II9YmqU,286
|
|
35
38
|
sharedkernel/normalizer/phone_number_normalizer.py,sha256=8z-JGWvH45GiOkceMz9jZ4gLoW9X120I1JSzCAGWcvU,19268
|
|
@@ -40,7 +43,7 @@ sharedkernel/objects/json_string_model.py,sha256=j63tnoqiok0EmBP6T-ChYuQYKPw7mLq
|
|
|
40
43
|
sharedkernel/objects/jwt_model.py,sha256=XQHQhTbg7PT8XiUh5fd9MwRH4ldPsesI_hfbjaSqdKg,134
|
|
41
44
|
sharedkernel/objects/result.py,sha256=I_9hX5TPEO1oStzuFLjFh1rtimXorz7ml-OaW_2BMvc,680
|
|
42
45
|
sharedkernel/objects/user_info.py,sha256=51WyspRxlIWzK7Lfxgqg4D6mylXeHe9ZSenf-RhYTdA,286
|
|
43
|
-
sharedkernel-2.
|
|
44
|
-
sharedkernel-2.
|
|
45
|
-
sharedkernel-2.
|
|
46
|
-
sharedkernel-2.
|
|
46
|
+
sharedkernel-2.7.0.dist-info/METADATA,sha256=8tNBtxeSL5t9rwHqbq94K3xGS3SXVyVjhWHCPZ56fW0,4092
|
|
47
|
+
sharedkernel-2.7.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
48
|
+
sharedkernel-2.7.0.dist-info/top_level.txt,sha256=TVTOnV1MItSSlpSjqkiijuHkoVsGHS4CArpsM-lylkE,13
|
|
49
|
+
sharedkernel-2.7.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|