maleo-foundation 0.2.96__py3-none-any.whl → 0.2.97__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/authentication.py +9 -9
- maleo_foundation/authorization.py +2 -2
- maleo_foundation/client/manager.py +11 -2
- maleo_foundation/client/services/encryption/aes.py +2 -2
- maleo_foundation/client/services/encryption/rsa.py +2 -2
- maleo_foundation/client/services/key.py +6 -3
- maleo_foundation/client/services/signature.py +2 -2
- maleo_foundation/client/services/token.py +2 -2
- maleo_foundation/constants.py +7 -7
- maleo_foundation/managers/cache/base.py +5 -1
- maleo_foundation/managers/cache/redis.py +12 -12
- maleo_foundation/managers/client/base.py +8 -8
- maleo_foundation/managers/client/google/base.py +6 -6
- maleo_foundation/managers/client/google/parameter.py +12 -5
- maleo_foundation/managers/client/google/secret.py +22 -7
- maleo_foundation/managers/client/google/storage.py +17 -17
- maleo_foundation/managers/client/maleo.py +9 -9
- maleo_foundation/managers/db.py +12 -12
- maleo_foundation/managers/middleware.py +22 -22
- maleo_foundation/managers/service.py +52 -52
- maleo_foundation/middlewares/authentication.py +11 -8
- maleo_foundation/middlewares/base.py +68 -64
- maleo_foundation/middlewares/cors.py +6 -6
- maleo_foundation/models/responses.py +37 -37
- maleo_foundation/models/schemas/encryption.py +5 -5
- maleo_foundation/models/schemas/general.py +33 -33
- maleo_foundation/models/schemas/hash.py +4 -4
- maleo_foundation/models/schemas/key.py +4 -4
- maleo_foundation/models/schemas/parameter.py +15 -15
- maleo_foundation/models/schemas/result.py +47 -47
- maleo_foundation/models/schemas/signature.py +5 -5
- maleo_foundation/models/schemas/token.py +4 -4
- maleo_foundation/models/transfers/general/__init__.py +63 -18
- maleo_foundation/models/transfers/general/key.py +4 -4
- maleo_foundation/models/transfers/general/token.py +71 -20
- maleo_foundation/models/transfers/parameters/token.py +1 -1
- maleo_foundation/models/transfers/results/client/controllers/http.py +4 -4
- maleo_foundation/models/transfers/results/encryption/aes.py +2 -2
- maleo_foundation/models/transfers/results/encryption/rsa.py +2 -2
- maleo_foundation/models/transfers/results/hash.py +2 -2
- maleo_foundation/models/transfers/results/key.py +3 -3
- maleo_foundation/models/transfers/results/signature.py +2 -2
- maleo_foundation/models/transfers/results/token.py +2 -2
- maleo_foundation/utils/cleaner.py +22 -0
- maleo_foundation/utils/client.py +6 -6
- maleo_foundation/utils/controller.py +8 -8
- maleo_foundation/utils/dependencies/auth.py +2 -2
- maleo_foundation/utils/dependencies/context.py +1 -1
- maleo_foundation/utils/exceptions.py +10 -10
- maleo_foundation/utils/extractor.py +2 -2
- maleo_foundation/utils/formatter/case.py +4 -4
- maleo_foundation/utils/loaders/credential/google.py +3 -1
- maleo_foundation/utils/loaders/json.py +2 -2
- maleo_foundation/utils/loaders/yaml.py +2 -2
- maleo_foundation/utils/logging.py +30 -24
- maleo_foundation/utils/merger.py +5 -2
- maleo_foundation/utils/query.py +48 -44
- maleo_foundation/utils/repository.py +8 -8
- maleo_foundation/utils/searcher.py +4 -1
- {maleo_foundation-0.2.96.dist-info → maleo_foundation-0.2.97.dist-info}/METADATA +1 -1
- {maleo_foundation-0.2.96.dist-info → maleo_foundation-0.2.97.dist-info}/RECORD +63 -62
- {maleo_foundation-0.2.96.dist-info → maleo_foundation-0.2.97.dist-info}/WHEEL +0 -0
- {maleo_foundation-0.2.96.dist-info → maleo_foundation-0.2.97.dist-info}/top_level.txt +0 -0
@@ -44,96 +44,96 @@ from maleo_foundation.utils.logging import (
|
|
44
44
|
from maleo_foundation.utils.merger import deep_merge
|
45
45
|
|
46
46
|
class Settings(BaseSettings):
|
47
|
-
ENVIRONMENT:BaseEnums.EnvironmentType = Field(..., description="Environment")
|
48
|
-
SERVICE_KEY:str = Field(..., description="Service's key")
|
49
|
-
GOOGLE_CREDENTIALS_PATH:str = Field("credentials/maleo-google-service-account.json", description="Internal credential's file path")
|
50
|
-
STATIC_CONFIGURATIONS_PATH:str = Field("configs/static.yaml", description="Maleo's static configurations path")
|
51
|
-
RUNTIME_CONFIGURATIONS_PATH:str = Field("configs/runtime.yaml", description="Service's runtime configurations path")
|
47
|
+
ENVIRONMENT: BaseEnums.EnvironmentType = Field(..., description="Environment")
|
48
|
+
SERVICE_KEY: str = Field(..., description="Service's key")
|
49
|
+
GOOGLE_CREDENTIALS_PATH: str = Field("credentials/maleo-google-service-account.json", description="Internal credential's file path")
|
50
|
+
STATIC_CONFIGURATIONS_PATH: str = Field("configs/static.yaml", description="Maleo's static configurations path")
|
51
|
+
RUNTIME_CONFIGURATIONS_PATH: str = Field("configs/runtime.yaml", description="Service's runtime configurations path")
|
52
52
|
|
53
53
|
class MaleoCredentials(BaseModel):
|
54
|
-
id:int = Field(..., description="ID")
|
55
|
-
uuid:UUID = Field(..., description="UUID")
|
56
|
-
username:str = Field(..., description="Username")
|
57
|
-
email:str = Field(..., description="Email")
|
58
|
-
password:str = Field(..., description="Password")
|
54
|
+
id: int = Field(..., description="ID")
|
55
|
+
uuid: UUID = Field(..., description="UUID")
|
56
|
+
username: str = Field(..., description="Username")
|
57
|
+
email: str = Field(..., description="Email")
|
58
|
+
password: str = Field(..., description="Password")
|
59
59
|
|
60
60
|
class MiddlewareRuntimeConfigurations(BaseModel):
|
61
|
-
base:BaseMiddlewareConfigurations = Field(..., description="Base middleware's configurations")
|
61
|
+
base: BaseMiddlewareConfigurations = Field(..., description="Base middleware's configurations")
|
62
62
|
|
63
63
|
class Config:
|
64
64
|
arbitrary_types_allowed=True
|
65
65
|
|
66
66
|
class ServiceConfigurations(BaseModel):
|
67
|
-
key:str = Field(..., description="Service's key")
|
68
|
-
name:str = Field(..., description="Service's name")
|
69
|
-
host:str = Field(..., description="Service's host")
|
70
|
-
port:int = Field(..., description="Service's port")
|
67
|
+
key: str = Field(..., description="Service's key")
|
68
|
+
name: str = Field(..., description="Service's name")
|
69
|
+
host: str = Field(..., description="Service's host")
|
70
|
+
port: int = Field(..., description="Service's port")
|
71
71
|
|
72
72
|
class RuntimeConfigurations(BaseModel):
|
73
|
-
service:ServiceConfigurations = Field(..., description="Service's configurations")
|
74
|
-
middleware:MiddlewareRuntimeConfigurations = Field(..., description="Middleware's runtime configurations")
|
75
|
-
database:str = Field(..., description="Database's name")
|
73
|
+
service: ServiceConfigurations = Field(..., description="Service's configurations")
|
74
|
+
middleware: MiddlewareRuntimeConfigurations = Field(..., description="Middleware's runtime configurations")
|
75
|
+
database: str = Field(..., description="Database's name")
|
76
76
|
|
77
77
|
class Config:
|
78
78
|
arbitrary_types_allowed=True
|
79
79
|
|
80
80
|
class MiddlewareStaticConfigurations(BaseModel):
|
81
|
-
general:GeneralMiddlewareConfigurations = Field(..., description="Middleware's general configurations")
|
82
|
-
cors:CORSMiddlewareConfigurations = Field(..., description="CORS middleware's configurations")
|
81
|
+
general: GeneralMiddlewareConfigurations = Field(..., description="Middleware's general configurations")
|
82
|
+
cors: CORSMiddlewareConfigurations = Field(..., description="CORS middleware's configurations")
|
83
83
|
|
84
84
|
class Config:
|
85
85
|
arbitrary_types_allowed=True
|
86
86
|
|
87
87
|
class MaleoClientConfiguration(BaseModel):
|
88
|
-
key:str = Field(..., description="Client's key")
|
89
|
-
name:str = Field(..., description="Client's name")
|
90
|
-
url:str = Field(..., description="Client's URL")
|
88
|
+
key: str = Field(..., description="Client's key")
|
89
|
+
name: str = Field(..., description="Client's name")
|
90
|
+
url: str = Field(..., description="Client's URL")
|
91
91
|
|
92
92
|
class MaleoClientConfigurations(BaseModel):
|
93
|
-
telemetry:MaleoClientConfiguration = Field(..., description="MaleoTelemetry client's configuration")
|
94
|
-
metadata:MaleoClientConfiguration = Field(..., description="MaleoMetadata client's configuration")
|
95
|
-
identity:MaleoClientConfiguration = Field(..., description="MaleoIdentity client's configuration")
|
96
|
-
access:MaleoClientConfiguration = Field(..., description="MaleoAccess client's configuration")
|
97
|
-
workshop:MaleoClientConfiguration = Field(..., description="MaleoWorkshop client's configuration")
|
98
|
-
medix:MaleoClientConfiguration = Field(..., description="MaleoMedix client's configuration")
|
99
|
-
fhir:MaleoClientConfiguration = Field(..., description="MaleoFHIR client's configuration")
|
100
|
-
dicom:MaleoClientConfiguration = Field(..., description="MaleoDICOM client's configuration")
|
101
|
-
scribe:MaleoClientConfiguration = Field(..., description="MaleoScribe client's configuration")
|
102
|
-
cds:MaleoClientConfiguration = Field(..., description="MaleoCDS client's configuration")
|
103
|
-
imaging:MaleoClientConfiguration = Field(..., description="MaleoImaging client's configuration")
|
104
|
-
mcu:MaleoClientConfiguration = Field(..., description="MaleoMCU client's configuration")
|
93
|
+
telemetry: MaleoClientConfiguration = Field(..., description="MaleoTelemetry client's configuration")
|
94
|
+
metadata: MaleoClientConfiguration = Field(..., description="MaleoMetadata client's configuration")
|
95
|
+
identity: MaleoClientConfiguration = Field(..., description="MaleoIdentity client's configuration")
|
96
|
+
access: MaleoClientConfiguration = Field(..., description="MaleoAccess client's configuration")
|
97
|
+
workshop: MaleoClientConfiguration = Field(..., description="MaleoWorkshop client's configuration")
|
98
|
+
medix: MaleoClientConfiguration = Field(..., description="MaleoMedix client's configuration")
|
99
|
+
fhir: MaleoClientConfiguration = Field(..., description="MaleoFHIR client's configuration")
|
100
|
+
dicom: MaleoClientConfiguration = Field(..., description="MaleoDICOM client's configuration")
|
101
|
+
scribe: MaleoClientConfiguration = Field(..., description="MaleoScribe client's configuration")
|
102
|
+
cds: MaleoClientConfiguration = Field(..., description="MaleoCDS client's configuration")
|
103
|
+
imaging: MaleoClientConfiguration = Field(..., description="MaleoImaging client's configuration")
|
104
|
+
mcu: MaleoClientConfiguration = Field(..., description="MaleoMCU client's configuration")
|
105
105
|
|
106
106
|
class Config:
|
107
107
|
arbitrary_types_allowed=True
|
108
108
|
|
109
109
|
class ClientConfigurations(BaseModel):
|
110
|
-
maleo:MaleoClientConfigurations = Field(..., description="Maleo client's configurations")
|
110
|
+
maleo: MaleoClientConfigurations = Field(..., description="Maleo client's configurations")
|
111
111
|
|
112
112
|
class Config:
|
113
113
|
arbitrary_types_allowed=True
|
114
114
|
|
115
115
|
class StaticConfigurations(BaseModel):
|
116
|
-
middleware:MiddlewareStaticConfigurations = Field(..., description="Middleware's static configurations")
|
117
|
-
client:ClientConfigurations = Field(..., description="Client's configurations")
|
116
|
+
middleware: MiddlewareStaticConfigurations = Field(..., description="Middleware's static configurations")
|
117
|
+
client: ClientConfigurations = Field(..., description="Client's configurations")
|
118
118
|
|
119
119
|
class Config:
|
120
120
|
arbitrary_types_allowed=True
|
121
121
|
|
122
122
|
class Configurations(BaseModel):
|
123
|
-
service:ServiceConfigurations = Field(..., description="Service's configurations")
|
124
|
-
middleware:MiddlewareConfigurations = Field(..., description="Middleware's configurations")
|
125
|
-
cache:CacheConfigurations = Field(..., description="Cache's configurations")
|
126
|
-
database:DatabaseConfigurations = Field(..., description="Database's configurations")
|
127
|
-
client:ClientConfigurations = Field(..., description="Client's configurations")
|
123
|
+
service: ServiceConfigurations = Field(..., description="Service's configurations")
|
124
|
+
middleware: MiddlewareConfigurations = Field(..., description="Middleware's configurations")
|
125
|
+
cache: CacheConfigurations = Field(..., description="Cache's configurations")
|
126
|
+
database: DatabaseConfigurations = Field(..., description="Database's configurations")
|
127
|
+
client: ClientConfigurations = Field(..., description="Client's configurations")
|
128
128
|
|
129
129
|
class Config:
|
130
130
|
arbitrary_types_allowed=True
|
131
131
|
|
132
132
|
class Loggers(BaseModel):
|
133
|
-
application:ServiceLogger = Field(..., description="Application logger")
|
134
|
-
repository:ServiceLogger = Field(..., description="Repository logger")
|
135
|
-
database:ServiceLogger = Field(..., description="Database logger")
|
136
|
-
middleware:MiddlewareLoggers = Field(..., description="Middleware logger")
|
133
|
+
application: ServiceLogger = Field(..., description="Application logger")
|
134
|
+
repository: ServiceLogger = Field(..., description="Repository logger")
|
135
|
+
database: ServiceLogger = Field(..., description="Database logger")
|
136
|
+
middleware: MiddlewareLoggers = Field(..., description="Middleware logger")
|
137
137
|
|
138
138
|
class Config:
|
139
139
|
arbitrary_types_allowed=True
|
@@ -141,9 +141,9 @@ class Loggers(BaseModel):
|
|
141
141
|
class ServiceManager:
|
142
142
|
def __init__(
|
143
143
|
self,
|
144
|
-
db_metadata:MetaData,
|
145
|
-
log_config:SimpleConfig,
|
146
|
-
settings:Optional[Settings] = None
|
144
|
+
db_metadata: MetaData,
|
145
|
+
log_config: SimpleConfig,
|
146
|
+
settings: Optional[Settings] = None
|
147
147
|
):
|
148
148
|
self._db_metadata = db_metadata #* Declare DB Metadata
|
149
149
|
self._log_config = log_config #* Declare log config
|
@@ -394,8 +394,8 @@ class ServiceManager:
|
|
394
394
|
|
395
395
|
def create_app(
|
396
396
|
self,
|
397
|
-
router:APIRouter,
|
398
|
-
lifespan:Optional[Lifespan[AppType]]=None
|
397
|
+
router: APIRouter,
|
398
|
+
lifespan: Optional[Lifespan[AppType]]=None
|
399
399
|
) -> FastAPI:
|
400
400
|
self._loggers.application.info("Creating FastAPI application")
|
401
401
|
root_path = "" if self._settings.ENVIRONMENT == "local" else f"/{self._configs.service.key.removeprefix("maleo-")}"
|
@@ -15,16 +15,19 @@ from maleo_foundation.utils.logging import MiddlewareLogger
|
|
15
15
|
class Backend(AuthenticationBackend):
|
16
16
|
def __init__(
|
17
17
|
self,
|
18
|
-
keys:BaseGeneralSchemas.RSAKeys,
|
19
|
-
logger:MiddlewareLogger,
|
20
|
-
maleo_foundation:MaleoFoundationClientManager
|
18
|
+
keys: BaseGeneralSchemas.RSAKeys,
|
19
|
+
logger: MiddlewareLogger,
|
20
|
+
maleo_foundation: MaleoFoundationClientManager
|
21
21
|
):
|
22
22
|
super().__init__()
|
23
23
|
self._keys = keys
|
24
24
|
self._logger = logger
|
25
25
|
self._maleo_foundation = maleo_foundation
|
26
26
|
|
27
|
-
async def authenticate(
|
27
|
+
async def authenticate(
|
28
|
+
self,
|
29
|
+
conn: HTTPConnection
|
30
|
+
) -> Tuple[Credentials, User]:
|
28
31
|
if "Authorization" in conn.headers:
|
29
32
|
auth = conn.headers["Authorization"]
|
30
33
|
parts = auth.split()
|
@@ -95,10 +98,10 @@ class Backend(AuthenticationBackend):
|
|
95
98
|
return Credentials(), User(authenticated=False)
|
96
99
|
|
97
100
|
def add_authentication_middleware(
|
98
|
-
app:FastAPI,
|
99
|
-
keys:BaseGeneralSchemas.RSAKeys,
|
100
|
-
logger:MiddlewareLogger,
|
101
|
-
maleo_foundation:MaleoFoundationClientManager
|
101
|
+
app: FastAPI,
|
102
|
+
keys: BaseGeneralSchemas.RSAKeys,
|
103
|
+
logger: MiddlewareLogger,
|
104
|
+
maleo_foundation: MaleoFoundationClientManager
|
102
105
|
) -> None:
|
103
106
|
"""
|
104
107
|
Adds Authentication middleware to the FastAPI application.
|
@@ -30,10 +30,10 @@ class RateLimiter:
|
|
30
30
|
|
31
31
|
def __init__(
|
32
32
|
self,
|
33
|
-
limit:int,
|
34
|
-
window:timedelta,
|
35
|
-
ip_timeout:timedelta,
|
36
|
-
cleanup_interval:timedelta
|
33
|
+
limit: int,
|
34
|
+
window: timedelta,
|
35
|
+
ip_timeout: timedelta,
|
36
|
+
cleanup_interval: timedelta
|
37
37
|
):
|
38
38
|
self.limit = limit
|
39
39
|
self.window = window
|
@@ -46,7 +46,7 @@ class RateLimiter:
|
|
46
46
|
|
47
47
|
def is_rate_limited(
|
48
48
|
self,
|
49
|
-
request_context:RequestContextTransfers
|
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:
|
@@ -70,7 +70,7 @@ class RateLimiter:
|
|
70
70
|
|
71
71
|
def cleanup_old_data(
|
72
72
|
self,
|
73
|
-
logger:MiddlewareLogger
|
73
|
+
logger: MiddlewareLogger
|
74
74
|
) -> None:
|
75
75
|
"""Clean up old request data to prevent memory growth."""
|
76
76
|
now = datetime.now()
|
@@ -107,19 +107,19 @@ class ResponseBuilder:
|
|
107
107
|
|
108
108
|
def __init__(
|
109
109
|
self,
|
110
|
-
keys:BaseGeneralSchemas.RSAKeys,
|
111
|
-
maleo_foundation:MaleoFoundationClientManager
|
110
|
+
keys: BaseGeneralSchemas.RSAKeys,
|
111
|
+
maleo_foundation: MaleoFoundationClientManager
|
112
112
|
):
|
113
113
|
self.keys = keys
|
114
114
|
self.maleo_foundation = maleo_foundation
|
115
115
|
|
116
116
|
def add_response_headers(
|
117
117
|
self,
|
118
|
-
authentication:Authentication,
|
119
|
-
response:Response,
|
120
|
-
request_context:RequestContextTransfers,
|
121
|
-
responded_at:datetime,
|
122
|
-
process_time:float
|
118
|
+
authentication: Authentication,
|
119
|
+
response: Response,
|
120
|
+
request_context: RequestContextTransfers,
|
121
|
+
responded_at: datetime,
|
122
|
+
process_time: float
|
123
123
|
) -> Response:
|
124
124
|
"""Add custom headers to response."""
|
125
125
|
# Basic headers
|
@@ -138,10 +138,10 @@ class ResponseBuilder:
|
|
138
138
|
|
139
139
|
def _add_signature_header(
|
140
140
|
self,
|
141
|
-
response:Response,
|
142
|
-
request_context:RequestContextTransfers,
|
143
|
-
responded_at:datetime,
|
144
|
-
process_time:float
|
141
|
+
response: Response,
|
142
|
+
request_context: RequestContextTransfers,
|
143
|
+
responded_at: datetime,
|
144
|
+
process_time: float
|
145
145
|
) -> None:
|
146
146
|
"""Generate and add signature header."""
|
147
147
|
message = (
|
@@ -185,9 +185,9 @@ class ResponseBuilder:
|
|
185
185
|
|
186
186
|
def _should_regenerate_auth(
|
187
187
|
self,
|
188
|
-
request_context:RequestContextTransfers,
|
189
|
-
authentication:Authentication,
|
190
|
-
response:Response
|
188
|
+
request_context: RequestContextTransfers,
|
189
|
+
authentication: Authentication,
|
190
|
+
response: Response
|
191
191
|
) -> bool:
|
192
192
|
"""Check if authorization should be regenerated."""
|
193
193
|
return (
|
@@ -205,10 +205,10 @@ class RequestLogger:
|
|
205
205
|
|
206
206
|
def log_request_response(
|
207
207
|
self,
|
208
|
-
authentication:Authentication,
|
209
|
-
response:Response,
|
210
|
-
request_context:RequestContextTransfers,
|
211
|
-
log_level:str = "info"
|
208
|
+
authentication: Authentication,
|
209
|
+
response: Response,
|
210
|
+
request_context: RequestContextTransfers,
|
211
|
+
log_level: str = "info"
|
212
212
|
) -> None:
|
213
213
|
"""Log request and response details."""
|
214
214
|
authentication_info = self._get_authentication_info(authentication)
|
@@ -223,9 +223,9 @@ class RequestLogger:
|
|
223
223
|
|
224
224
|
def log_exception(
|
225
225
|
self,
|
226
|
-
authentication:Authentication,
|
227
|
-
error:Exception,
|
228
|
-
request_context:RequestContextTransfers
|
226
|
+
authentication: Authentication,
|
227
|
+
error: Exception,
|
228
|
+
request_context: RequestContextTransfers
|
229
229
|
) -> None:
|
230
230
|
"""Log exception details."""
|
231
231
|
authentication_info = self._get_authentication_info(authentication)
|
@@ -260,18 +260,18 @@ class BaseMiddleware(BaseHTTPMiddleware):
|
|
260
260
|
|
261
261
|
def __init__(
|
262
262
|
self,
|
263
|
-
app:FastAPI,
|
264
|
-
keys:BaseGeneralSchemas.RSAKeys,
|
265
|
-
logger:MiddlewareLogger,
|
266
|
-
maleo_foundation:MaleoFoundationClientManager,
|
267
|
-
allow_origins:Sequence[str] = (),
|
268
|
-
allow_methods:Sequence[str] = ("GET",),
|
269
|
-
allow_headers:Sequence[str] = (),
|
270
|
-
allow_credentials:bool = False,
|
271
|
-
limit:int = 10,
|
272
|
-
window:int = 1,
|
273
|
-
cleanup_interval:int = 60,
|
274
|
-
ip_timeout:int = 300
|
263
|
+
app: FastAPI,
|
264
|
+
keys: BaseGeneralSchemas.RSAKeys,
|
265
|
+
logger: MiddlewareLogger,
|
266
|
+
maleo_foundation: MaleoFoundationClientManager,
|
267
|
+
allow_origins: Sequence[str] = (),
|
268
|
+
allow_methods: Sequence[str] = ("GET",),
|
269
|
+
allow_headers: Sequence[str] = (),
|
270
|
+
allow_credentials: bool = False,
|
271
|
+
limit: int = 10,
|
272
|
+
window: int = 1,
|
273
|
+
cleanup_interval: int = 60,
|
274
|
+
ip_timeout: int = 300
|
275
275
|
):
|
276
276
|
super().__init__(app)
|
277
277
|
|
@@ -293,7 +293,11 @@ class BaseMiddleware(BaseHTTPMiddleware):
|
|
293
293
|
'allow_credentials': allow_credentials,
|
294
294
|
}
|
295
295
|
|
296
|
-
async def dispatch(
|
296
|
+
async def dispatch(
|
297
|
+
self,
|
298
|
+
request: Request,
|
299
|
+
call_next: RequestResponseEndpoint
|
300
|
+
) -> Response:
|
297
301
|
"""Main middleware dispatch method."""
|
298
302
|
# Setup
|
299
303
|
self.rate_limiter.cleanup_old_data(self.request_logger.logger)
|
@@ -333,9 +337,9 @@ class BaseMiddleware(BaseHTTPMiddleware):
|
|
333
337
|
|
334
338
|
def _create_rate_limit_response(
|
335
339
|
self,
|
336
|
-
authentication:Authentication,
|
337
|
-
request_context:RequestContextTransfers,
|
338
|
-
start_time:float
|
340
|
+
authentication: Authentication,
|
341
|
+
request_context: RequestContextTransfers,
|
342
|
+
start_time: float
|
339
343
|
) -> Response:
|
340
344
|
"""Create rate limit exceeded response."""
|
341
345
|
response = JSONResponse(
|
@@ -349,11 +353,11 @@ class BaseMiddleware(BaseHTTPMiddleware):
|
|
349
353
|
|
350
354
|
def _build_final_response(
|
351
355
|
self,
|
352
|
-
authentication:Authentication,
|
353
|
-
response:Response,
|
354
|
-
request_context:RequestContextTransfers,
|
355
|
-
start_time:float,
|
356
|
-
log_level:str = "info"
|
356
|
+
authentication: Authentication,
|
357
|
+
response: Response,
|
358
|
+
request_context: RequestContextTransfers,
|
359
|
+
start_time: float,
|
360
|
+
log_level: str = "info"
|
357
361
|
) -> Response:
|
358
362
|
"""Build final response with headers and logging."""
|
359
363
|
responded_at = datetime.now(tz=timezone.utc)
|
@@ -373,10 +377,10 @@ class BaseMiddleware(BaseHTTPMiddleware):
|
|
373
377
|
|
374
378
|
def _handle_exception(
|
375
379
|
self,
|
376
|
-
authentication:Authentication,
|
377
|
-
error:Exception,
|
378
|
-
request_context:RequestContextTransfers,
|
379
|
-
start_time:float
|
380
|
+
authentication: Authentication,
|
381
|
+
error: Exception,
|
382
|
+
request_context: RequestContextTransfers,
|
383
|
+
start_time: float
|
380
384
|
) -> Response:
|
381
385
|
"""Handle exceptions and create error response."""
|
382
386
|
responded_at = datetime.now(tz=timezone.utc)
|
@@ -397,18 +401,18 @@ class BaseMiddleware(BaseHTTPMiddleware):
|
|
397
401
|
|
398
402
|
|
399
403
|
def add_base_middleware(
|
400
|
-
app:FastAPI,
|
401
|
-
keys:BaseGeneralSchemas.RSAKeys,
|
402
|
-
logger:MiddlewareLogger,
|
403
|
-
maleo_foundation:MaleoFoundationClientManager,
|
404
|
-
allow_origins:Sequence[str] = (),
|
405
|
-
allow_methods:Sequence[str] = ("GET",),
|
406
|
-
allow_headers:Sequence[str] = (),
|
407
|
-
allow_credentials:bool = False,
|
408
|
-
limit:int = 10,
|
409
|
-
window:int = 1,
|
410
|
-
cleanup_interval:int = 60,
|
411
|
-
ip_timeout:int = 300
|
404
|
+
app: FastAPI,
|
405
|
+
keys: BaseGeneralSchemas.RSAKeys,
|
406
|
+
logger: MiddlewareLogger,
|
407
|
+
maleo_foundation: MaleoFoundationClientManager,
|
408
|
+
allow_origins: Sequence[str] = (),
|
409
|
+
allow_methods: Sequence[str] = ("GET",),
|
410
|
+
allow_headers: Sequence[str] = (),
|
411
|
+
allow_credentials: bool = False,
|
412
|
+
limit: int = 10,
|
413
|
+
window: int = 1,
|
414
|
+
cleanup_interval: int = 60,
|
415
|
+
ip_timeout: int = 300
|
412
416
|
) -> None:
|
413
417
|
"""
|
414
418
|
Add Base middleware to the FastAPI application.
|
@@ -3,12 +3,12 @@ from fastapi.middleware.cors import CORSMiddleware
|
|
3
3
|
from typing import Sequence
|
4
4
|
|
5
5
|
def add_cors_middleware(
|
6
|
-
app:FastAPI,
|
7
|
-
allow_origins:Sequence[str] = (),
|
8
|
-
allow_methods:Sequence[str] = ("GET",),
|
9
|
-
allow_headers:Sequence[str] = (),
|
10
|
-
allow_credentials:bool = False,
|
11
|
-
expose_headers:Sequence[str] = ()
|
6
|
+
app: FastAPI,
|
7
|
+
allow_origins: Sequence[str] = (),
|
8
|
+
allow_methods: Sequence[str] = ("GET",),
|
9
|
+
allow_headers: Sequence[str] = (),
|
10
|
+
allow_credentials: bool = False,
|
11
|
+
expose_headers: Sequence[str] = ()
|
12
12
|
) -> None:
|
13
13
|
"""
|
14
14
|
Adds CORS (Cross-Origin Resource Sharing) middleware to the FastAPI application.
|
@@ -7,62 +7,62 @@ from maleo_foundation.types import BaseTypes
|
|
7
7
|
|
8
8
|
class BaseResponses:
|
9
9
|
class Fail(BaseResultSchemas.Fail):
|
10
|
-
other:BaseTypes.OptionalAny = Field("Please try again later or contact administrator.", description="Response's other information")
|
10
|
+
other: BaseTypes.OptionalAny = Field("Please try again later or contact administrator.", description="Response's other information")
|
11
11
|
|
12
12
|
class BadRequest(Fail):
|
13
|
-
code:str = "MAL-BDR-001"
|
14
|
-
message:str = "Bad Request"
|
15
|
-
description:str = "Bad/Unexpected parameters given in the request"
|
13
|
+
code: str = "MAL-BDR-001"
|
14
|
+
message: str = "Bad Request"
|
15
|
+
description: str = "Bad/Unexpected parameters given in the request"
|
16
16
|
|
17
17
|
class InvalidExpand(BadRequest):
|
18
|
-
code:str = "MAL-INE-001"
|
19
|
-
message:str = "Invalid expand"
|
20
|
-
description:str = "Invalid expand field(s) configuration are given. Check 'other' for more information."
|
18
|
+
code: str = "MAL-INE-001"
|
19
|
+
message: str = "Invalid expand"
|
20
|
+
description: str = "Invalid expand field(s) configuration are given. Check 'other' for more information."
|
21
21
|
|
22
22
|
class InvalidParameter(BadRequest):
|
23
|
-
code:str = "MAL-IPR-001"
|
24
|
-
message:str = "Invalid parameters"
|
25
|
-
description:str = "Invalid parameters and/or parameters combinations is given. Check 'other' for more information."
|
23
|
+
code: str = "MAL-IPR-001"
|
24
|
+
message: str = "Invalid parameters"
|
25
|
+
description: str = "Invalid parameters and/or parameters combinations is given. Check 'other' for more information."
|
26
26
|
|
27
27
|
class InvalidSystemRole(BadRequest):
|
28
|
-
code:str = "MAL-ISR-001"
|
29
|
-
message:str = "Invalid system role"
|
30
|
-
description:str = "Invalid system role is detected in authorization token. Check 'other' for more information."
|
28
|
+
code: str = "MAL-ISR-001"
|
29
|
+
message: str = "Invalid system role"
|
30
|
+
description: str = "Invalid system role is detected in authorization token. Check 'other' for more information."
|
31
31
|
|
32
32
|
class Unauthorized(Fail):
|
33
|
-
code:str = "MAL-ATH-001"
|
34
|
-
message:str = "Unauthorized Request"
|
35
|
-
description:str = "You are unauthorized to request this resource"
|
33
|
+
code: str = "MAL-ATH-001"
|
34
|
+
message: str = "Unauthorized Request"
|
35
|
+
description: str = "You are unauthorized to request this resource"
|
36
36
|
|
37
37
|
class Forbidden(Fail):
|
38
|
-
code:str = "MAL-ATH-002"
|
39
|
-
message:str = "Forbidden Request"
|
40
|
-
description:str = "You are forbidden from requesting this resource"
|
38
|
+
code: str = "MAL-ATH-002"
|
39
|
+
message: str = "Forbidden Request"
|
40
|
+
description: str = "You are forbidden from requesting this resource"
|
41
41
|
|
42
42
|
class MethodNotAllowed(Fail):
|
43
|
-
code:str = "MAL-MTA-002"
|
44
|
-
message:str = "Method Not Allowed"
|
45
|
-
description:str = "Method not allowed for requesting this resource"
|
43
|
+
code: str = "MAL-MTA-002"
|
44
|
+
message: str = "Method Not Allowed"
|
45
|
+
description: str = "Method not allowed for requesting this resource"
|
46
46
|
|
47
47
|
class ValidationError(Fail):
|
48
|
-
code:str = "MAL-VLD-001"
|
49
|
-
message:str = "Validation Error"
|
50
|
-
description:str = "Request validation failed due to missing or invalid fields. Check other for more info."
|
48
|
+
code: str = "MAL-VLD-001"
|
49
|
+
message: str = "Validation Error"
|
50
|
+
description: str = "Request validation failed due to missing or invalid fields. Check other for more info."
|
51
51
|
|
52
52
|
class RateLimitExceeded(Fail):
|
53
|
-
code:str = "MAL-RTL-001"
|
54
|
-
message:str = "Rate Limit Exceeded"
|
55
|
-
description:str = "This resource is requested too many times. Please try again later."
|
53
|
+
code: str = "MAL-RTL-001"
|
54
|
+
message: str = "Rate Limit Exceeded"
|
55
|
+
description: str = "This resource is requested too many times. Please try again later."
|
56
56
|
|
57
57
|
class ServerError(Fail):
|
58
|
-
code:str = "MAL-EXC-001"
|
59
|
-
message:str = "Unexpected Server Error"
|
60
|
-
description:str = "An unexpected error occurred while processing your request."
|
58
|
+
code: str = "MAL-EXC-001"
|
59
|
+
message: str = "Unexpected Server Error"
|
60
|
+
description: str = "An unexpected error occurred while processing your request."
|
61
61
|
|
62
62
|
class NotImplemented(Fail):
|
63
|
-
code:str = "MAL-NIM-001"
|
64
|
-
message:str = "Not Implemented"
|
65
|
-
description:str = "This request is not yet implemented by the system."
|
63
|
+
code: str = "MAL-NIM-001"
|
64
|
+
message: str = "Not Implemented"
|
65
|
+
description: str = "This request is not yet implemented by the system."
|
66
66
|
|
67
67
|
class NotFound(BaseResultSchemas.NotFound): pass
|
68
68
|
|
@@ -73,9 +73,9 @@ class BaseResponses:
|
|
73
73
|
class UnpaginatedMultipleData(BaseResultSchemas.UnpaginatedMultipleData): pass
|
74
74
|
|
75
75
|
class PaginatedMultipleData(BaseResultSchemas.PaginatedMultipleData):
|
76
|
-
page:int = Field(1, ge=1, description="Page number, must be >= 1.", exclude=True)
|
77
|
-
limit:int = Field(10, ge=1, le=100, description="Page size, must be 1 <= limit <= 100.", exclude=True)
|
78
|
-
total_data:int = Field(..., ge=0, description="Total data count", exclude=True)
|
76
|
+
page: int = Field(1, ge=1, description="Page number, must be >= 1.", exclude=True)
|
77
|
+
limit: int = Field(10, ge=1, le=100, description="Page size, must be 1 <= limit <= 100.", exclude=True)
|
78
|
+
total_data: int = Field(..., ge=0, description="Total data count", exclude=True)
|
79
79
|
|
80
80
|
@model_validator(mode="before")
|
81
81
|
@classmethod
|
@@ -3,16 +3,16 @@ from maleo_foundation.types import BaseTypes
|
|
3
3
|
|
4
4
|
class MaleoFoundationEncryptionSchemas:
|
5
5
|
class Key(BaseModel):
|
6
|
-
key:str = Field(..., description="Key")
|
6
|
+
key: str = Field(..., description="Key")
|
7
7
|
|
8
8
|
class Password(BaseModel):
|
9
|
-
password:BaseTypes.OptionalString = Field(None, min_length=32, max_length=1024, description="password")
|
9
|
+
password: BaseTypes.OptionalString = Field(None, min_length=32, max_length=1024, description="password")
|
10
10
|
|
11
11
|
class InitializationVector(BaseModel):
|
12
|
-
initialization_vector:str = Field(..., description="Initialization vector")
|
12
|
+
initialization_vector: str = Field(..., description="Initialization vector")
|
13
13
|
|
14
14
|
class Plaintext(BaseModel):
|
15
|
-
plaintext:str = Field(..., description="Plaintext")
|
15
|
+
plaintext: str = Field(..., description="Plaintext")
|
16
16
|
|
17
17
|
class Ciphertext(BaseModel):
|
18
|
-
ciphertext:str = Field(..., description="Ciphertext")
|
18
|
+
ciphertext: str = Field(..., description="Ciphertext")
|