maleo-foundation 0.2.80__py3-none-any.whl → 0.2.82__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.
- maleo_foundation/managers/service.py +2 -2
- maleo_foundation/middlewares/base.py +53 -87
- maleo_foundation/models/transfers/general/__init__.py +25 -1
- maleo_foundation/utils/__init__.py +0 -2
- maleo_foundation/utils/dependencies/context.py +9 -0
- maleo_foundation/utils/extractor.py +53 -18
- {maleo_foundation-0.2.80.dist-info → maleo_foundation-0.2.82.dist-info}/METADATA +1 -1
- {maleo_foundation-0.2.80.dist-info → maleo_foundation-0.2.82.dist-info}/RECORD +10 -9
- {maleo_foundation-0.2.80.dist-info → maleo_foundation-0.2.82.dist-info}/WHEEL +0 -0
- {maleo_foundation-0.2.80.dist-info → maleo_foundation-0.2.82.dist-info}/top_level.txt +0 -0
@@ -416,7 +416,7 @@ class ServiceManager:
|
|
416
416
|
maleo_foundation=self._foundation
|
417
417
|
)
|
418
418
|
self._middleware.add_all()
|
419
|
-
self._loggers.application.info("Middlewares
|
419
|
+
self._loggers.application.info("Middlewares added successfully")
|
420
420
|
|
421
421
|
#* Add exception handler(s)
|
422
422
|
self._loggers.application.info("Adding exception handlers")
|
@@ -428,7 +428,7 @@ class ServiceManager:
|
|
428
428
|
exc_class_or_status_code=HTTPException,
|
429
429
|
handler=BaseExceptions.http_exception_handler
|
430
430
|
)
|
431
|
-
self._loggers.application.info("Exception handlers
|
431
|
+
self._loggers.application.info("Exception handlers added successfully")
|
432
432
|
|
433
433
|
#* Include router
|
434
434
|
self._loggers.application.info("Including routers")
|
@@ -5,7 +5,6 @@ import traceback
|
|
5
5
|
from collections import defaultdict
|
6
6
|
from datetime import datetime, timedelta, timezone
|
7
7
|
from typing import Awaitable, Callable, Optional, Sequence, Dict, List
|
8
|
-
from uuid import UUID, uuid4
|
9
8
|
|
10
9
|
from fastapi import FastAPI, Request, Response, status
|
11
10
|
from fastapi.responses import JSONResponse
|
@@ -19,7 +18,8 @@ from maleo_foundation.models.responses import BaseResponses
|
|
19
18
|
from maleo_foundation.models.transfers.general.token import MaleoFoundationTokenGeneralTransfers
|
20
19
|
from maleo_foundation.models.transfers.parameters.token import MaleoFoundationTokenParametersTransfers
|
21
20
|
from maleo_foundation.models.transfers.parameters.signature import MaleoFoundationSignatureParametersTransfers
|
22
|
-
from maleo_foundation.
|
21
|
+
from maleo_foundation.models.transfers.general import RequestContextTransfers
|
22
|
+
from maleo_foundation.utils.extractor import extract_request_context
|
23
23
|
from maleo_foundation.utils.logging import MiddlewareLogger
|
24
24
|
|
25
25
|
RequestProcessor = Callable[[Request], Awaitable[Optional[Response]]]
|
@@ -46,11 +46,12 @@ class RateLimiter:
|
|
46
46
|
|
47
47
|
def is_rate_limited(
|
48
48
|
self,
|
49
|
-
|
49
|
+
request_context:RequestContextTransfers
|
50
50
|
) -> bool:
|
51
51
|
"""Check if client IP is rate limited and record the request."""
|
52
52
|
with self._lock:
|
53
53
|
now = datetime.now()
|
54
|
+
client_ip = request_context.ip_address
|
54
55
|
self._last_seen[client_ip] = now
|
55
56
|
|
56
57
|
# Remove old requests outside the window
|
@@ -101,7 +102,6 @@ class RateLimiter:
|
|
101
102
|
f"Current tracked IPs: {len(self._requests)}"
|
102
103
|
)
|
103
104
|
|
104
|
-
|
105
105
|
class ResponseBuilder:
|
106
106
|
"""Handles response building and header management."""
|
107
107
|
|
@@ -115,42 +115,38 @@ class ResponseBuilder:
|
|
115
115
|
|
116
116
|
def add_response_headers(
|
117
117
|
self,
|
118
|
-
request:Request,
|
119
118
|
authentication:Authentication,
|
120
119
|
response:Response,
|
121
|
-
|
122
|
-
|
123
|
-
process_time:float
|
124
|
-
request_id:UUID
|
120
|
+
request_context:RequestContextTransfers,
|
121
|
+
responded_at:datetime,
|
122
|
+
process_time:float
|
125
123
|
) -> Response:
|
126
124
|
"""Add custom headers to response."""
|
127
125
|
# Basic headers
|
128
|
-
response.headers["X-Request-ID"] = str(request_id)
|
126
|
+
response.headers["X-Request-ID"] = str(request_context.request_id)
|
129
127
|
response.headers["X-Process-Time"] = str(process_time)
|
130
|
-
response.headers["X-
|
131
|
-
response.headers["X-
|
128
|
+
response.headers["X-Requested-At"] = request_context.requested_at.isoformat()
|
129
|
+
response.headers["X-Responded-At"] = responded_at.isoformat()
|
132
130
|
|
133
131
|
# Add signature header
|
134
|
-
self._add_signature_header(
|
132
|
+
self._add_signature_header(response, request_context, responded_at, process_time)
|
135
133
|
|
136
134
|
# Add new authorization header if needed
|
137
|
-
self._add_new_authorization_header(
|
135
|
+
self._add_new_authorization_header(request_context, authentication, response)
|
138
136
|
|
139
137
|
return response
|
140
138
|
|
141
139
|
def _add_signature_header(
|
142
140
|
self,
|
143
|
-
request:Request,
|
144
141
|
response:Response,
|
145
|
-
|
146
|
-
|
147
|
-
process_time:float
|
148
|
-
request_id:UUID
|
142
|
+
request_context:RequestContextTransfers,
|
143
|
+
responded_at:datetime,
|
144
|
+
process_time:float
|
149
145
|
) -> None:
|
150
146
|
"""Generate and add signature header."""
|
151
147
|
message = (
|
152
|
-
f"{
|
153
|
-
f"{
|
148
|
+
f"{request_context.method}|{request_context.url}|{request_context.requested_at.isoformat()}|"
|
149
|
+
f"{responded_at.isoformat()}|{str(process_time)}|{str(request_context.request_id)}"
|
154
150
|
)
|
155
151
|
|
156
152
|
sign_parameters = MaleoFoundationSignatureParametersTransfers.Sign(
|
@@ -165,12 +161,12 @@ class ResponseBuilder:
|
|
165
161
|
|
166
162
|
def _add_new_authorization_header(
|
167
163
|
self,
|
168
|
-
|
164
|
+
request_context:RequestContextTransfers,
|
169
165
|
authentication:Authentication,
|
170
166
|
response:Response
|
171
167
|
) -> None:
|
172
168
|
"""Add new authorization header for refresh tokens."""
|
173
|
-
if not self._should_regenerate_auth(
|
169
|
+
if not self._should_regenerate_auth(request_context, authentication, response):
|
174
170
|
return
|
175
171
|
|
176
172
|
payload = MaleoFoundationTokenGeneralTransfers.BaseEncodePayload.model_validate(
|
@@ -189,7 +185,7 @@ class ResponseBuilder:
|
|
189
185
|
|
190
186
|
def _should_regenerate_auth(
|
191
187
|
self,
|
192
|
-
|
188
|
+
request_context:RequestContextTransfers,
|
193
189
|
authentication:Authentication,
|
194
190
|
response:Response
|
195
191
|
) -> bool:
|
@@ -198,26 +194,20 @@ class ResponseBuilder:
|
|
198
194
|
authentication.user.is_authenticated
|
199
195
|
and authentication.credentials.token.type == BaseEnums.TokenType.REFRESH
|
200
196
|
and 200 <= response.status_code < 300
|
201
|
-
and "logout" not in
|
197
|
+
and "logout" not in request_context.url
|
202
198
|
)
|
203
199
|
|
204
|
-
|
205
200
|
class RequestLogger:
|
206
201
|
"""Handles request/response logging."""
|
207
202
|
|
208
|
-
def __init__(
|
209
|
-
self,
|
210
|
-
logger:MiddlewareLogger
|
211
|
-
):
|
203
|
+
def __init__(self, logger:MiddlewareLogger):
|
212
204
|
self.logger = logger
|
213
205
|
|
214
206
|
def log_request_response(
|
215
207
|
self,
|
216
|
-
request:Request,
|
217
208
|
authentication:Authentication,
|
218
209
|
response:Response,
|
219
|
-
|
220
|
-
request_id:UUID,
|
210
|
+
request_context:RequestContextTransfers,
|
221
211
|
log_level:str = "info"
|
222
212
|
) -> None:
|
223
213
|
"""Log request and response details."""
|
@@ -225,39 +215,32 @@ class RequestLogger:
|
|
225
215
|
|
226
216
|
log_func = getattr(self.logger, log_level)
|
227
217
|
log_func(
|
228
|
-
f"Request | ID: {request_id} {authentication_info} |
|
229
|
-
f"
|
230
|
-
f"Method: {
|
231
|
-
f"
|
218
|
+
f"Request | ID: {request_context.request_id} {authentication_info} | "
|
219
|
+
f"IP: {request_context.ip_address} | Host: {request_context.host} | "
|
220
|
+
f"Method: {request_context.method} | URL: {request_context.url} - "
|
221
|
+
f"Response | Status: {response.status_code}"
|
232
222
|
)
|
233
223
|
|
234
224
|
def log_exception(
|
235
225
|
self,
|
236
|
-
request:Request,
|
237
226
|
authentication:Authentication,
|
238
227
|
error:Exception,
|
239
|
-
|
240
|
-
request_id:UUID
|
228
|
+
request_context:RequestContextTransfers
|
241
229
|
) -> None:
|
242
230
|
"""Log exception details."""
|
243
231
|
authentication_info = self._get_authentication_info(authentication)
|
244
232
|
|
245
233
|
error_details = {
|
246
|
-
"
|
234
|
+
"request_context": request_context.model_dump(mode="json"),
|
247
235
|
"error": str(error),
|
248
|
-
"traceback": traceback.format_exc().split("\n")
|
249
|
-
"client_ip": client_ip,
|
250
|
-
"method": request.method,
|
251
|
-
"url": request.url.path,
|
252
|
-
"headers": dict(request.headers),
|
236
|
+
"traceback": traceback.format_exc().split("\n")
|
253
237
|
}
|
254
238
|
|
255
239
|
self.logger.error(
|
256
|
-
f"Request | ID: {request_id} {authentication_info} |
|
257
|
-
f"
|
258
|
-
f"Method: {
|
259
|
-
f"
|
260
|
-
f"Exception:\n{json.dumps(error_details, indent=4)}"
|
240
|
+
f"Request | ID: {request_context.request_id} {authentication_info} | "
|
241
|
+
f"IP: {request_context.ip_address} | Host: {request_context.host} | "
|
242
|
+
f"Method: {request_context.method} | URL: {request_context.url} - "
|
243
|
+
f"Response | Status: 500 | Exception:\n{json.dumps(error_details, indent=4)}"
|
261
244
|
)
|
262
245
|
|
263
246
|
def _get_authentication_info(self, authentication:Authentication) -> str:
|
@@ -312,43 +295,36 @@ class BaseMiddleware(BaseHTTPMiddleware):
|
|
312
295
|
|
313
296
|
async def dispatch(self, request:Request, call_next:RequestResponseEndpoint) -> Response:
|
314
297
|
"""Main middleware dispatch method."""
|
315
|
-
# Generate unique request ID
|
316
|
-
request_id = uuid4()
|
317
|
-
request.state.request_id = request_id
|
318
|
-
|
319
298
|
# Setup
|
320
299
|
self.rate_limiter.cleanup_old_data(self.request_logger.logger)
|
321
|
-
|
322
|
-
request.state.
|
300
|
+
request_context = extract_request_context(request)
|
301
|
+
request.state.request_context = request_context
|
323
302
|
start_time = time.perf_counter()
|
324
|
-
client_ip = BaseExtractors.extract_client_ip(request)
|
325
303
|
authentication = Authentication(credentials=request.auth, user=request.user)
|
326
304
|
|
327
305
|
try:
|
328
306
|
# Rate limiting check
|
329
|
-
if self.rate_limiter.is_rate_limited(
|
307
|
+
if self.rate_limiter.is_rate_limited(request_context):
|
330
308
|
return self._create_rate_limit_response(
|
331
|
-
|
309
|
+
authentication, request_context, start_time
|
332
310
|
)
|
333
311
|
|
334
312
|
# Optional preprocessing
|
335
313
|
pre_response = await self._request_processor(request)
|
336
314
|
if pre_response is not None:
|
337
315
|
return self._build_final_response(
|
338
|
-
|
339
|
-
request_timestamp, start_time, request_id
|
316
|
+
authentication, pre_response, request_context, start_time
|
340
317
|
)
|
341
318
|
|
342
319
|
# Main request processing
|
343
320
|
response = await call_next(request)
|
344
321
|
return self._build_final_response(
|
345
|
-
|
346
|
-
request_timestamp, start_time, request_id
|
322
|
+
authentication, response, request_context, start_time
|
347
323
|
)
|
348
324
|
|
349
325
|
except Exception as e:
|
350
326
|
return self._handle_exception(
|
351
|
-
request, authentication, e,
|
327
|
+
request, authentication, e, request_context, start_time
|
352
328
|
)
|
353
329
|
|
354
330
|
async def _request_processor(self, request:Request) -> Optional[Response]:
|
@@ -357,12 +333,9 @@ class BaseMiddleware(BaseHTTPMiddleware):
|
|
357
333
|
|
358
334
|
def _create_rate_limit_response(
|
359
335
|
self,
|
360
|
-
request:Request,
|
361
336
|
authentication:Authentication,
|
362
|
-
|
363
|
-
|
364
|
-
start_time:float,
|
365
|
-
request_id:UUID
|
337
|
+
request_context:RequestContextTransfers,
|
338
|
+
start_time:float
|
366
339
|
) -> Response:
|
367
340
|
"""Create rate limit exceeded response."""
|
368
341
|
response = JSONResponse(
|
@@ -371,49 +344,42 @@ class BaseMiddleware(BaseHTTPMiddleware):
|
|
371
344
|
)
|
372
345
|
|
373
346
|
return self._build_final_response(
|
374
|
-
|
375
|
-
request_timestamp, start_time, request_id, log_level="warning"
|
347
|
+
authentication, response, request_context, start_time, log_level="warning"
|
376
348
|
)
|
377
349
|
|
378
350
|
def _build_final_response(
|
379
351
|
self,
|
380
|
-
request:Request,
|
381
352
|
authentication:Authentication,
|
382
353
|
response:Response,
|
383
|
-
|
384
|
-
request_timestamp:datetime,
|
354
|
+
request_context:RequestContextTransfers,
|
385
355
|
start_time:float,
|
386
|
-
request_id:UUID,
|
387
356
|
log_level:str = "info"
|
388
357
|
) -> Response:
|
389
358
|
"""Build final response with headers and logging."""
|
390
|
-
|
359
|
+
responded_at = datetime.now(tz=timezone.utc)
|
391
360
|
process_time = time.perf_counter() - start_time
|
392
361
|
|
393
362
|
# Add headers
|
394
363
|
response = self.response_builder.add_response_headers(
|
395
|
-
|
364
|
+
authentication, response, request_context, responded_at, process_time
|
396
365
|
)
|
397
366
|
|
398
367
|
# Log request/response
|
399
368
|
self.request_logger.log_request_response(
|
400
|
-
|
369
|
+
authentication, response, request_context, log_level
|
401
370
|
)
|
402
371
|
|
403
372
|
return response
|
404
373
|
|
405
374
|
def _handle_exception(
|
406
375
|
self,
|
407
|
-
request:Request,
|
408
376
|
authentication:Authentication,
|
409
377
|
error:Exception,
|
410
|
-
|
411
|
-
|
412
|
-
start_time:float,
|
413
|
-
request_id:UUID
|
378
|
+
request_context:RequestContextTransfers,
|
379
|
+
start_time:float
|
414
380
|
) -> Response:
|
415
381
|
"""Handle exceptions and create error response."""
|
416
|
-
|
382
|
+
responded_at = datetime.now(tz=timezone.utc)
|
417
383
|
process_time = time.perf_counter() - start_time
|
418
384
|
|
419
385
|
response = JSONResponse(
|
@@ -422,11 +388,11 @@ class BaseMiddleware(BaseHTTPMiddleware):
|
|
422
388
|
)
|
423
389
|
|
424
390
|
# Log exception
|
425
|
-
self.request_logger.log_exception(
|
391
|
+
self.request_logger.log_exception(authentication, error, request_context)
|
426
392
|
|
427
393
|
# Add headers
|
428
394
|
return self.response_builder.add_response_headers(
|
429
|
-
|
395
|
+
authentication, response, request_context, responded_at, process_time
|
430
396
|
)
|
431
397
|
|
432
398
|
|
@@ -1,5 +1,10 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
+
from datetime import datetime, timezone
|
3
|
+
from pydantic import BaseModel, Field
|
4
|
+
from typing import Dict
|
5
|
+
from uuid import UUID
|
2
6
|
from maleo_foundation.models.schemas.general import BaseGeneralSchemas
|
7
|
+
from maleo_foundation.types import BaseTypes
|
3
8
|
from .token import MaleoFoundationTokenGeneralTransfers
|
4
9
|
|
5
10
|
class BaseGeneralTransfers:
|
@@ -8,4 +13,23 @@ class BaseGeneralTransfers:
|
|
8
13
|
class AccessTransfers(
|
9
14
|
BaseGeneralSchemas.AccessedBy,
|
10
15
|
BaseGeneralSchemas.AccessedAt
|
11
|
-
): pass
|
16
|
+
): pass
|
17
|
+
|
18
|
+
class RequestContextTransfers(BaseModel):
|
19
|
+
request_id:UUID = Field(..., description="Unique identifier for tracing the request")
|
20
|
+
requested_at:datetime = Field(datetime.now(tz=timezone.utc), description="Request timestamp")
|
21
|
+
method:str = Field(..., description="Request's method")
|
22
|
+
url:str = Field(..., description="Request's URL")
|
23
|
+
path_params:Dict = Field(..., description="Request's path parameters")
|
24
|
+
query_params:Dict = Field(..., description="Request's query parameters")
|
25
|
+
ip_address:str = Field("unknown", description="Client's IP address")
|
26
|
+
is_internal:BaseTypes.OptionalBoolean = Field(None, description="True if IP is internal")
|
27
|
+
user_agent:BaseTypes.OptionalString = Field(None, description="User-Agent string")
|
28
|
+
ua_browser:BaseTypes.OptionalString = Field(None, description="Browser info from sec-ch-ua")
|
29
|
+
ua_mobile:BaseTypes.OptionalString = Field(None, description="Is mobile device?")
|
30
|
+
platform:BaseTypes.OptionalString = Field(None, description="Client platform or OS")
|
31
|
+
referer:BaseTypes.OptionalString = Field(None, description="Referrer URL")
|
32
|
+
origin:BaseTypes.OptionalString = Field(None, description="Origin of the request")
|
33
|
+
host:BaseTypes.OptionalString = Field(None, description="Host header from request")
|
34
|
+
forwarded_proto:BaseTypes.OptionalString = Field(None, description="Forwarded protocol (http/https)")
|
35
|
+
language:BaseTypes.OptionalString = Field(None, description="Accepted languages from client")
|
@@ -1,7 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
from .formatter import BaseFormatter
|
3
3
|
from .exceptions import BaseExceptions
|
4
|
-
from .extractor import BaseExtractors
|
5
4
|
from .loaders import BaseLoaders
|
6
5
|
from .controller import BaseControllerUtils
|
7
6
|
from .query import BaseQueryUtils
|
@@ -9,7 +8,6 @@ from .query import BaseQueryUtils
|
|
9
8
|
class BaseUtils:
|
10
9
|
Formatter = BaseFormatter
|
11
10
|
Exceptions = BaseExceptions
|
12
|
-
Extractors = BaseExtractors
|
13
11
|
Loaders = BaseLoaders
|
14
12
|
Controller = BaseControllerUtils
|
15
13
|
Query = BaseQueryUtils
|
@@ -0,0 +1,9 @@
|
|
1
|
+
from fastapi.requests import Request
|
2
|
+
from maleo_foundation.models.transfers.general import RequestContextTransfers
|
3
|
+
|
4
|
+
class ContextDependencies:
|
5
|
+
@staticmethod
|
6
|
+
def get_request_context(
|
7
|
+
request:Request
|
8
|
+
) -> RequestContextTransfers:
|
9
|
+
return request.state.request_context
|
@@ -1,20 +1,55 @@
|
|
1
|
+
from datetime import datetime, timezone
|
2
|
+
from fastapi import Request
|
1
3
|
from starlette.requests import HTTPConnection
|
4
|
+
from uuid import uuid4
|
5
|
+
from maleo_foundation.models.transfers.general import RequestContextTransfers
|
2
6
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
x_real_ip
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
7
|
+
def extract_client_ip(conn:HTTPConnection) -> str:
|
8
|
+
"""Extract client IP with more robust handling of proxies"""
|
9
|
+
#* Check for X-Forwarded-For header (common when behind proxy/load balancer)
|
10
|
+
x_forwarded_for = conn.headers.get("X-Forwarded-For")
|
11
|
+
if x_forwarded_for:
|
12
|
+
#* The client's IP is the first one in the list
|
13
|
+
ips = [ip.strip() for ip in x_forwarded_for.split(",")]
|
14
|
+
return ips[0]
|
15
|
+
|
16
|
+
#* Check for X-Real-IP header (used by some proxies)
|
17
|
+
x_real_ip = conn.headers.get("X-Real-IP")
|
18
|
+
if x_real_ip:
|
19
|
+
return x_real_ip
|
20
|
+
|
21
|
+
#* Fall back to direct client connection
|
22
|
+
return conn.client.host if conn.client else "unknown"
|
23
|
+
|
24
|
+
def extract_request_context(request:Request) -> RequestContextTransfers:
|
25
|
+
headers = request.headers
|
26
|
+
|
27
|
+
request_id = headers.get("x-request-id")
|
28
|
+
if request_id is None:
|
29
|
+
request_id = uuid4()
|
30
|
+
|
31
|
+
ip_address = extract_client_ip(request)
|
32
|
+
|
33
|
+
ua_browser = headers.get("sec-ch-ua", "")
|
34
|
+
if ua_browser:
|
35
|
+
ua_browser = ua_browser.replace('"', "").split(",")[0].strip()
|
36
|
+
|
37
|
+
return RequestContextTransfers(
|
38
|
+
request_id=request_id,
|
39
|
+
requested_at=datetime.now(tz=timezone.utc),
|
40
|
+
method=request.method,
|
41
|
+
url=request.url.path,
|
42
|
+
path_params=dict(request.path_params),
|
43
|
+
query_params=dict(request.query_params),
|
44
|
+
ip_address=ip_address,
|
45
|
+
is_internal=ip_address.startswith("10.") or ip_address.startswith("192.168.") or ip_address.startswith("172."),
|
46
|
+
user_agent=headers.get("user-agent"),
|
47
|
+
ua_browser=ua_browser,
|
48
|
+
ua_mobile=headers.get("sec-ch-ua-mobile"),
|
49
|
+
platform=headers.get("sec-ch-ua-platform"),
|
50
|
+
referer=headers.get("referer"),
|
51
|
+
origin=headers.get("origin"),
|
52
|
+
host=headers.get("host"),
|
53
|
+
forwarded_proto=headers.get("x-forwarded-proto"),
|
54
|
+
language=headers.get("accept-language"),
|
55
|
+
)
|
@@ -34,7 +34,7 @@ maleo_foundation/expanded_types/encryption/rsa.py,sha256=Esf_H8nMz2kOLAWa3M7dlD-
|
|
34
34
|
maleo_foundation/managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
35
35
|
maleo_foundation/managers/db.py,sha256=cpY1IOiUytT9XXYtzS0E9OSYOuB7jBKo0XHe__uI1Jg,5340
|
36
36
|
maleo_foundation/managers/middleware.py,sha256=77wRCC_CWc22nSDL-UJanO3rXmSB7wLzaAIXEFjXq6M,4249
|
37
|
-
maleo_foundation/managers/service.py,sha256=
|
37
|
+
maleo_foundation/managers/service.py,sha256=9qPmOUh5PPXu03-xnZIRU4C3mNbMOnYrfJQs87oqt6k,19282
|
38
38
|
maleo_foundation/managers/cache/__init__.py,sha256=CeY0oof2bVl_v5WS-FKXNwn2gf3xrEMfUsHK9cHo59s,471
|
39
39
|
maleo_foundation/managers/cache/base.py,sha256=YyPjde4KTsp2IHV6NdFMysa0ev-1GX1rtX-0jQPuIBU,837
|
40
40
|
maleo_foundation/managers/cache/redis.py,sha256=xLa8QfXdNtghs0eBxIqc04H3XTYmxLEzrqJZAFCigvM,1150
|
@@ -47,7 +47,7 @@ maleo_foundation/managers/client/google/parameter.py,sha256=Lnj7mQgxWQpsQwbmDRK5
|
|
47
47
|
maleo_foundation/managers/client/google/secret.py,sha256=Ski1CHYeA8vjSk2Oc2Pf4CfFrzT_RcA6NEZwza7gM7Y,4464
|
48
48
|
maleo_foundation/managers/client/google/storage.py,sha256=Hq79cVreWR2AGwUzpD57NzziZjqxj__TqYIBRy-A9A0,5340
|
49
49
|
maleo_foundation/middlewares/authentication.py,sha256=UL6kL65SvqrzemlIDopoO9N1C05eWlYMHVR2tiRsVEA,4821
|
50
|
-
maleo_foundation/middlewares/base.py,sha256=
|
50
|
+
maleo_foundation/middlewares/base.py,sha256=r3XDTEhK6BB8YZ1Y8oyqExY78s4yzOqX7s7XokRlTlw,16308
|
51
51
|
maleo_foundation/middlewares/cors.py,sha256=9uvBvY2N6Vxa9RP_YtESxcWo6Doi6uS0lzAG9iLY7Uc,2288
|
52
52
|
maleo_foundation/models/__init__.py,sha256=AaKehO7c1HyKhoTGRmNHDddSeBXkW-_YNrpOGBu8Ms8,246
|
53
53
|
maleo_foundation/models/responses.py,sha256=nE5qThK-WgcYB-9J4wHzJltMA3PLmWbMI-dkxAxAdII,5631
|
@@ -62,7 +62,7 @@ maleo_foundation/models/schemas/result.py,sha256=MaWDyKGvZu0IcvKMj30lrMXojGV9Mhi
|
|
62
62
|
maleo_foundation/models/schemas/signature.py,sha256=-5ldTnJsjwqPRbHw7PFcLKITqEXJ_qKDdRHShK75NVA,620
|
63
63
|
maleo_foundation/models/schemas/token.py,sha256=RYq8v1T_WZIu8lcjwyV6Pp7ZjFkr_lW9x6QyDmXBsfw,563
|
64
64
|
maleo_foundation/models/transfers/__init__.py,sha256=oJLJ3Geeme6vBw7R2Dhvdvg4ziVvzEYAGJaP-tm_90w,299
|
65
|
-
maleo_foundation/models/transfers/general/__init__.py,sha256=
|
65
|
+
maleo_foundation/models/transfers/general/__init__.py,sha256=IOt9afCpDu7bO0rkZLiiLLP37w5rIZTxmnv6MD9od8E,1990
|
66
66
|
maleo_foundation/models/transfers/general/key.py,sha256=tLKkXbwNu7Oc1MdKa8-Y7TlBAIk54h_02AmL5Yg2PrQ,751
|
67
67
|
maleo_foundation/models/transfers/general/signature.py,sha256=J9xQy2HjpCQOnES7RJqsUnDgjFPuakQ1mxyfdTdstSE,297
|
68
68
|
maleo_foundation/models/transfers/general/token.py,sha256=O_U6dQS7oMScJzqufl6Pe21pTxMsYhOzKH8aFLxjblQ,2895
|
@@ -97,11 +97,11 @@ maleo_foundation/models/transfers/results/service/general.py,sha256=RfxzBNZQhMNw
|
|
97
97
|
maleo_foundation/models/transfers/results/service/repository.py,sha256=djITRZh2jrncxd19MyCYBux8C7u906u224U2DPgAQI8,1471
|
98
98
|
maleo_foundation/models/transfers/results/service/controllers/__init__.py,sha256=HZJWMy2dskzOCzLmp_UaL9rjbQ-sDMI7sd2bXb-4QOU,175
|
99
99
|
maleo_foundation/models/transfers/results/service/controllers/rest.py,sha256=wCuFyOTQkuBs2cqjPsWnPy0XIsCfMqGByhrSy57qp7Y,1107
|
100
|
-
maleo_foundation/utils/__init__.py,sha256=
|
100
|
+
maleo_foundation/utils/__init__.py,sha256=ZZv0NDcTdHsHl51EKfgrlCm8CQmgvyIndMcQABDudN0,391
|
101
101
|
maleo_foundation/utils/client.py,sha256=F5X9TUxWQgeOHjwsMpPoSRhZANQYZ_iFv0RJDTUVhrw,2820
|
102
102
|
maleo_foundation/utils/controller.py,sha256=D8uUfqkMpPw8M8Ykn8Uxn7dfRGwxmBxSP1h9xSkYw1I,6945
|
103
103
|
maleo_foundation/utils/exceptions.py,sha256=eM__Mxo-BC5d7JmoBd-Wh-fmryUdfjNfOuY_eONK5Fk,6361
|
104
|
-
maleo_foundation/utils/extractor.py,sha256=
|
104
|
+
maleo_foundation/utils/extractor.py,sha256=0HoJ0hLqt3-izaekjPfxqWjvUmXTsm4Muyttu0_VyuI,2109
|
105
105
|
maleo_foundation/utils/logging.py,sha256=W5Fhk_xAXVqSujaY8mv3hRH4wlQSpUn4ReuMoiKcQa4,7759
|
106
106
|
maleo_foundation/utils/merger.py,sha256=z9GROLVtGpwx84bOiakBFphKazsI-9l3F3WauTDwQLs,597
|
107
107
|
maleo_foundation/utils/query.py,sha256=nDj-9Q-5eAOvqXqKgKjtHaFAxVAY87E0BMaVXmTN7jA,7957
|
@@ -109,6 +109,7 @@ maleo_foundation/utils/repository.py,sha256=knBi3xOLlhBIEtChvqbZh4wXmgrFCB3rDwQX
|
|
109
109
|
maleo_foundation/utils/searcher.py,sha256=gsseMkr0swKj3l-xil5qqncTbYNkS96eieFE_ehaF8I,504
|
110
110
|
maleo_foundation/utils/dependencies/__init__.py,sha256=0KKGrdfj8Cc5A4SRk_ZBAxzOP795Mizdb4zIBh07KC4,122
|
111
111
|
maleo_foundation/utils/dependencies/auth.py,sha256=wS9qnmd1n2WsFhiSfyq_3Io3wwZKTENVPv4rMwxJslE,727
|
112
|
+
maleo_foundation/utils/dependencies/context.py,sha256=OXem2E00u2D3GleXhV8VI3u0cayG2CZpvVz32a0xHhs,292
|
112
113
|
maleo_foundation/utils/formatter/__init__.py,sha256=iKf5YCbEdg1qKnFHyKqqcQbqAqEeRUf8mhI3v3dQoj8,78
|
113
114
|
maleo_foundation/utils/formatter/case.py,sha256=TmvvlfzGdC_omMTB5vAa40TZBxQ3hnr-SYeo0M52Rlg,1352
|
114
115
|
maleo_foundation/utils/loaders/__init__.py,sha256=P_3ycGfeDXFjAi8bE4iLWHxBveqUIdpHgGv-klRWM3s,282
|
@@ -118,7 +119,7 @@ maleo_foundation/utils/loaders/credential/__init__.py,sha256=qopTKvcMVoTFwyRijeg
|
|
118
119
|
maleo_foundation/utils/loaders/credential/google.py,sha256=HUcuHD4tXHPt0eHInlFYxA_MDrGSOtbenpd0PX156OM,1255
|
119
120
|
maleo_foundation/utils/loaders/key/__init__.py,sha256=hVygcC2ImHc_aVrSrOmyedR8tMUZokWUKCKOSh5ctbo,106
|
120
121
|
maleo_foundation/utils/loaders/key/rsa.py,sha256=gDhyX6iTFtHiluuhFCozaZ3pOLKU2Y9TlrNMK_GVyGU,3796
|
121
|
-
maleo_foundation-0.2.
|
122
|
-
maleo_foundation-0.2.
|
123
|
-
maleo_foundation-0.2.
|
124
|
-
maleo_foundation-0.2.
|
122
|
+
maleo_foundation-0.2.82.dist-info/METADATA,sha256=G50A22g7UNj57VIUu1gtwjvyff8XrTesnYmEnlK91Pw,3598
|
123
|
+
maleo_foundation-0.2.82.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
124
|
+
maleo_foundation-0.2.82.dist-info/top_level.txt,sha256=_iBos3F_bhEOdjOnzeiEYSrCucasc810xXtLBXI8cQc,17
|
125
|
+
maleo_foundation-0.2.82.dist-info/RECORD,,
|
File without changes
|
File without changes
|