maleo-foundation 0.1.59__py3-none-any.whl → 0.1.61__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.
@@ -1,7 +1,9 @@
1
1
  from __future__ import annotations
2
2
  from pydantic import Field
3
3
  from maleo_foundation.managers.client.base import ClientServices
4
+ from maleo_foundation.client.services.signature import MaleoFoundationSignatureClientService
4
5
  from maleo_foundation.client.services.token import MaleoFoundationTokenClientService
5
6
 
6
7
  class MaleoFoundationServices(ClientServices):
8
+ signature:MaleoFoundationSignatureClientService = Field(..., description="Signature's service")
7
9
  token:MaleoFoundationTokenClientService = Field(..., description="Token's service")
@@ -0,0 +1,74 @@
1
+ from base64 import b64decode, b64encode
2
+ from Crypto.PublicKey import RSA
3
+ from Crypto.Hash import SHA256
4
+ from Crypto.Signature import pkcs1_15
5
+ from maleo_foundation.models.schemas.signature import BaseSignatureSchemas
6
+ from maleo_foundation.models.transfers.parameters.signature import BaseSignatureParametersTransfers
7
+ from maleo_foundation.models.transfers.results.signature import BaseSignatureResultsTransfers
8
+ from maleo_foundation.expanded_types.signature import BaseSignatureResultsTypes
9
+ from maleo_foundation.managers.client.base import ClientService
10
+ from maleo_foundation.utils.exceptions import BaseExceptions
11
+
12
+ class MaleoFoundationSignatureClientService(ClientService):
13
+ def sign(self, parameters:BaseSignatureParametersTransfers.Sign) -> BaseSignatureResultsTypes.Sign:
14
+ @BaseExceptions.service_exception_handler(
15
+ operation="signing single message",
16
+ logger=self._logger,
17
+ fail_result_class=BaseSignatureResultsTransfers.Fail
18
+ )
19
+ def _impl():
20
+ try:
21
+ #* Load RSA key using PyCryptodome's RSA.import_key
22
+ private_key = RSA.import_key(extern_key=parameters.key, passphrase=parameters.password)
23
+ #* Validate the key type
24
+ if not private_key.has_private():
25
+ message = "Invalid key type"
26
+ description = "A private key must be used for RSA Verify"
27
+ other = "Ensure the given key is of type private key"
28
+ return BaseSignatureResultsTransfers.Fail(message=message, description=description, other=other)
29
+ except Exception as e:
30
+ self._logger.error("Unexpected error occured while trying to import key:\n'%s'", str(e), exc_info=True)
31
+ message = "Invalid key"
32
+ description = "Unexpected error occured while trying to import key"
33
+ other = "Ensure given key is valid"
34
+ return BaseSignatureResultsTransfers.Fail(message=message, description=description, other=other)
35
+ hash = SHA256.new(parameters.message.encode()) #* Generate message hash
36
+ signature = b64encode(pkcs1_15.new(private_key).sign(hash)).decode() #* Sign the hashed message
37
+ data = BaseSignatureSchemas.Signature(signature=signature)
38
+ self._logger.info("Message successfully signed")
39
+ return BaseSignatureResultsTransfers.Sign(data=data)
40
+ return _impl()
41
+
42
+ def verify(self, parameters:BaseSignatureParametersTransfers.Verify) -> BaseSignatureResultsTypes.Verify:
43
+ @BaseExceptions.service_exception_handler(
44
+ operation="verify single signature",
45
+ logger=self._logger,
46
+ fail_result_class=BaseSignatureResultsTransfers.Fail
47
+ )
48
+ def _impl():
49
+ try:
50
+ #* Load RSA key using PyCryptodome's RSA.import_key
51
+ public_key = RSA.import_key(parameters.key)
52
+ #* Validate the key type
53
+ if public_key.has_private():
54
+ message = "Invalid key type"
55
+ description = "A public key must be used for RSA Sign"
56
+ other = "Ensure the given key is of type public key"
57
+ return BaseSignatureResultsTransfers.Fail(message=message, description=description, other=other)
58
+ except Exception as e:
59
+ self._logger.error("Unexpected error occured while trying to import key:\n'%s'", str(e), exc_info=True)
60
+ message = "Invalid key"
61
+ description = "Unexpected error occured while trying to import key"
62
+ other = "Ensure given key is valid"
63
+ return BaseSignatureResultsTransfers.Fail(message=message, description=description, other=other)
64
+ hash = SHA256.new(parameters.message.encode()) #* Generate message hash
65
+ #* Verify the hashed message and decoded signature
66
+ try:
67
+ pkcs1_15.new(public_key).verify(hash, b64decode(parameters.signature))
68
+ is_valid = True
69
+ except (TypeError, ValueError):
70
+ is_valid = False
71
+ data = BaseSignatureSchemas.IsValid(is_valid=is_valid)
72
+ self._logger.info("Signature successfully verified")
73
+ return BaseSignatureResultsTransfers.Verify(data=data)
74
+ return _impl()
@@ -0,0 +1,13 @@
1
+ from typing import Union
2
+ from maleo_foundation.models.transfers.results.signature import BaseSignatureResultsTransfers
3
+
4
+ class BaseSignatureResultsTypes:
5
+ Sign = Union[
6
+ BaseSignatureResultsTransfers.Fail,
7
+ BaseSignatureResultsTransfers.Sign
8
+ ]
9
+
10
+ Verify = Union[
11
+ BaseSignatureResultsTransfers.Fail,
12
+ BaseSignatureResultsTransfers.Verify
13
+ ]
@@ -4,16 +4,18 @@ from starlette.middleware.authentication import AuthenticationMiddleware
4
4
  from starlette.requests import HTTPConnection
5
5
  from typing import Tuple
6
6
  from maleo_foundation.authentication import Credentials, User
7
+ from maleo_foundation.client.manager import MaleoFoundationClientManager
8
+ from maleo_foundation.managers.service import Keys
7
9
  from maleo_foundation.models.transfers.parameters.token import BaseTokenParametersTransfers
8
- from maleo_foundation.services.token import BaseTokenService
9
10
  from maleo_foundation.utils.extractor import BaseExtractors
10
11
  from maleo_foundation.utils.logging import MiddlewareLogger
11
12
 
12
13
  class Backend(AuthenticationBackend):
13
- def __init__(self, logger:MiddlewareLogger, key:str):
14
+ def __init__(self, logger:MiddlewareLogger, keys:Keys, maleo_foundation:MaleoFoundationClientManager):
14
15
  super().__init__()
15
16
  self._logger = logger
16
- self._key = key
17
+ self._keys = keys
18
+ self._maleo_foundation = maleo_foundation
17
19
 
18
20
  async def authenticate(self, conn:HTTPConnection) -> Tuple[Credentials, User]:
19
21
  client_ip = BaseExtractors.extract_client_ip(conn)
@@ -27,8 +29,8 @@ class Backend(AuthenticationBackend):
27
29
  self._logger.info(f"Request | IP: {client_ip} | URL: {conn.url.path} - Result | General: Authorization scheme is not Bearer")
28
30
  return Credentials(), User(authenticated=False)
29
31
 
30
- decode_token_parameters = BaseTokenParametersTransfers.Decode(key=self._key, token=token)
31
- decode_token_result = BaseTokenService.decode(parameters=decode_token_parameters)
32
+ decode_token_parameters = BaseTokenParametersTransfers.Decode(key=self._keys.public, token=token)
33
+ decode_token_result = self._maleo_foundation.services.token.decode(parameters=decode_token_parameters)
32
34
  if not decode_token_result.success:
33
35
  self._logger.error(f"Request | IP: {client_ip} | URL: {conn.url.path} - Result | General: Failed decoding authorization token")
34
36
  return Credentials(token=token), User(authenticated=False)
@@ -36,7 +38,7 @@ class Backend(AuthenticationBackend):
36
38
  self._logger.info(f"Request | IP: {client_ip} | URL: {conn.url.path} - Result | Username: {decode_token_result.data.u_u} | Email: {decode_token_result.data.u_e}")
37
39
  return Credentials(token=token), User(authenticated=True, username=decode_token_result.data.u_u, email=decode_token_result.data.u_e)
38
40
 
39
- def add_authentication_middleware(app:FastAPI, logger:MiddlewareLogger, key:str) -> None:
41
+ def add_authentication_middleware(app:FastAPI, logger:MiddlewareLogger, keys:Keys) -> None:
40
42
  """
41
43
  Adds Authentication middleware to the FastAPI application.
42
44
 
@@ -62,4 +64,4 @@ def add_authentication_middleware(app:FastAPI, logger:MiddlewareLogger, key:str)
62
64
  add_authentication_middleware(app=app, limit=10, window=1, cleanup_interval=60, ip_timeout=300)
63
65
  ```
64
66
  """
65
- app.add_middleware(AuthenticationMiddleware, backend=Backend(logger=logger, key=key))
67
+ app.add_middleware(AuthenticationMiddleware, backend=Backend(logger=logger, keys=keys))
@@ -8,7 +8,10 @@ from fastapi import FastAPI, Request, Response, status
8
8
  from fastapi.responses import JSONResponse
9
9
  from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
10
10
  from typing import Awaitable, Callable, Optional, Sequence
11
+ from maleo_foundation.client.manager import MaleoFoundationClientManager
12
+ from maleo_foundation.managers.service import Keys
11
13
  from maleo_foundation.models.responses import BaseResponses
14
+ from maleo_foundation.models.transfers.parameters.signature import BaseSignatureParametersTransfers
12
15
  from maleo_foundation.utils.extractor import BaseExtractors
13
16
  from maleo_foundation.utils.logging import MiddlewareLogger
14
17
 
@@ -18,8 +21,10 @@ ResponseProcessor = Callable[[Response], Awaitable[Response]]
18
21
  class BaseMiddleware(BaseHTTPMiddleware):
19
22
  def __init__(
20
23
  self,
21
- app,
24
+ app:FastAPI,
22
25
  logger:MiddlewareLogger,
26
+ keys:Keys,
27
+ maleo_foundation:MaleoFoundationClientManager,
23
28
  allow_origins:Sequence[str] = (),
24
29
  allow_methods:Sequence[str] = ("GET",),
25
30
  allow_headers:Sequence[str] = (),
@@ -27,23 +32,23 @@ class BaseMiddleware(BaseHTTPMiddleware):
27
32
  limit:int = 10,
28
33
  window:int = 1,
29
34
  cleanup_interval:int = 60,
30
- ip_timeout:int = 300,
31
- request_processor:Optional[RequestProcessor] = None
35
+ ip_timeout:int = 300
32
36
  ):
33
37
  super().__init__(app)
34
- self.logger = logger
35
- self.allow_origins = allow_origins
36
- self.allow_methods = allow_methods
37
- self.allow_headers = allow_headers
38
- self.allow_credentials = allow_credentials
39
- self.limit = limit
40
- self.window = timedelta(seconds=window)
41
- self.cleanup_interval = timedelta(seconds=cleanup_interval)
42
- self.ip_timeout = timedelta(seconds=ip_timeout)
43
- self.requests:dict[str, list[datetime]] = defaultdict(list)
44
- self.last_seen: dict[str, datetime] = {}
45
- self.last_cleanup = datetime.now()
46
- self.request_processor = request_processor if request_processor is not None else self._request_processor
38
+ self._logger = logger
39
+ self._keys = keys
40
+ self._maleo_foundation = maleo_foundation
41
+ self._allow_origins = allow_origins
42
+ self._allow_methods = allow_methods
43
+ self._allow_headers = allow_headers
44
+ self._allow_credentials = allow_credentials
45
+ self._limit = limit
46
+ self._window = timedelta(seconds=window)
47
+ self._cleanup_interval = timedelta(seconds=cleanup_interval)
48
+ self._ip_timeout = timedelta(seconds=ip_timeout)
49
+ self._requests:dict[str, list[datetime]] = defaultdict(list)
50
+ self._last_seen: dict[str, datetime] = {}
51
+ self._last_cleanup = datetime.now()
47
52
  self._lock = threading.RLock() #* Use RLock for thread safety
48
53
 
49
54
  def _cleanup_old_data(self) -> None:
@@ -54,64 +59,72 @@ class BaseMiddleware(BaseHTTPMiddleware):
54
59
  2. IPs that haven't been seen in ip_timeout period
55
60
  """
56
61
  now = datetime.now()
57
- if now - self.last_cleanup > self.cleanup_interval:
62
+ if now - self._last_cleanup > self._cleanup_interval:
58
63
  with self._lock:
59
64
  #* Remove inactive IPs (not seen recently) and empty lists
60
65
  inactive_ips = []
61
- for ip in list(self.requests.keys()):
66
+ for ip in list(self._requests.keys()):
62
67
  #* Remove IPs with empty timestamp lists
63
- if not self.requests[ip]:
68
+ if not self._requests[ip]:
64
69
  inactive_ips.append(ip)
65
70
  continue
66
71
 
67
72
  #* Remove IPs that haven't been active recently
68
- last_active = self.last_seen.get(ip, datetime.min)
69
- if now - last_active > self.ip_timeout:
73
+ last_active = self._last_seen.get(ip, datetime.min)
74
+ if now - last_active > self._ip_timeout:
70
75
  inactive_ips.append(ip)
71
76
 
72
77
  #* Remove the inactive IPs
73
78
  for ip in inactive_ips:
74
- if ip in self.requests:
75
- del self.requests[ip]
76
- if ip in self.last_seen:
77
- del self.last_seen[ip]
79
+ if ip in self._requests:
80
+ del self._requests[ip]
81
+ if ip in self._last_seen:
82
+ del self._last_seen[ip]
78
83
 
79
84
  # Update last cleanup time
80
- self.last_cleanup = now
81
- self.logger.debug(f"Cleaned up request cache. Removed {len(inactive_ips)} inactive IPs. Current tracked IPs: {len(self.requests)}")
85
+ self._last_cleanup = now
86
+ self._logger.debug(f"Cleaned up request cache. Removed {len(inactive_ips)} inactive IPs. Current tracked IPs: {len(self._requests)}")
82
87
 
83
88
  def _check_rate_limit(self, client_ip:str) -> bool:
84
89
  """Check if the client has exceeded their rate limit"""
85
90
  with self._lock:
86
91
  now = datetime.now() #* Define current timestamp
87
- self.last_seen[client_ip] = now #* Update last seen timestamp for this IP
92
+ self._last_seen[client_ip] = now #* Update last seen timestamp for this IP
88
93
 
89
94
  #* Filter requests within the window
90
- self.requests[client_ip] = [timestamp for timestamp in self.requests[client_ip] if now - timestamp <= self.window]
95
+ self._requests[client_ip] = [timestamp for timestamp in self._requests[client_ip] if now - timestamp <= self._window]
91
96
 
92
97
  #* Check if the request count exceeds the limit
93
- if len(self.requests[client_ip]) >= self.limit:
98
+ if len(self._requests[client_ip]) >= self._limit:
94
99
  return True
95
100
 
96
101
  #* Add the current request timestamp
97
- self.requests[client_ip].append(now)
102
+ self._requests[client_ip].append(now)
98
103
  return False
99
104
 
100
105
  def _append_cors_headers(self, request:Request, response:Response) -> Response:
101
106
  origin = request.headers.get("Origin")
102
107
 
103
- if origin in self.allow_origins:
108
+ if origin in self._allow_origins:
104
109
  response.headers["Access-Control-Allow-Origin"] = origin
105
- response.headers["Access-Control-Allow-Methods"] = ", ".join(self.allow_methods)
106
- response.headers["Access-Control-Allow-Headers"] = ", ".join(self.allow_headers)
107
- response.headers["Access-Control-Allow-Credentials"] = "true" if self.allow_credentials else "false"
110
+ response.headers["Access-Control-Allow-Methods"] = ", ".join(self._allow_methods)
111
+ response.headers["Access-Control-Allow-Headers"] = ", ".join(self._allow_headers)
112
+ response.headers["Access-Control-Allow-Credentials"] = "true" if self._allow_credentials else "false"
108
113
 
109
114
  return response
110
115
 
111
116
  def _add_response_headers(self, request:Request, response:Response, request_timestamp:datetime, process_time:int) -> Response:
112
117
  response.headers["X-Process-Time"] = str(process_time) #* Add Process Time Header
113
118
  response.headers["X-Request-Timestamp"] = request_timestamp.isoformat() #* Add request timestamp header
114
- response.headers["X-Response-Timestamp"] = datetime.now(tz=timezone.utc).isoformat() #* Add response timestamp header
119
+ #* Define and add response timestamp header
120
+ response_timestamp = datetime.now(tz=timezone.utc)
121
+ response.headers["X-Response-Timestamp"] = response_timestamp.isoformat()
122
+ #* Generate signature header
123
+ message = f"{request.method}|{request.url.path}|{request_timestamp.isoformat()}|{response_timestamp.isoformat()}|{str(process_time)}"
124
+ sign_parameters = BaseSignatureParametersTransfers.Sign(key=self._keys.private, password=self._keys.password, message=message)
125
+ sign_result = self._maleo_foundation.services.signature.sign(parameters=sign_parameters)
126
+ if sign_result.success:
127
+ response.headers["X-Signature"] = sign_result.data.signature
115
128
  response = self._append_cors_headers(request=request, response=response) #* Re-append CORS headers
116
129
  return response
117
130
 
@@ -125,7 +138,7 @@ class BaseMiddleware(BaseHTTPMiddleware):
125
138
  client_ip:str = "unknown"
126
139
  ) -> Response:
127
140
  response = self._add_response_headers(request, response, request_timestamp, process_time)
128
- log_func = getattr(self.logger, log_level)
141
+ log_func = getattr(self._logger, log_level)
129
142
  log_func(
130
143
  f"Request | IP: {client_ip} | Method: {request.method} | URL: {request.url.path} | "
131
144
  f"Headers: {dict(request.headers)} - Response | Status: {response.status_code} | "
@@ -148,7 +161,7 @@ class BaseMiddleware(BaseHTTPMiddleware):
148
161
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
149
162
  )
150
163
 
151
- self.logger.error(
164
+ self._logger.error(
152
165
  f"Request | IP: {client_ip} | Method: {request.method} | URL: {request.url.path} | "
153
166
  f"Headers: {dict(request.headers)} - Response | Status: 500 | Exception:\n{json.dumps(error_details, indent=4)}"
154
167
  )
@@ -180,7 +193,7 @@ class BaseMiddleware(BaseHTTPMiddleware):
180
193
  )
181
194
 
182
195
  #* 2. Optional preprocessing
183
- pre_response = await self.request_processor(request)
196
+ pre_response = await self._request_processor(request)
184
197
  if pre_response is not None:
185
198
  return self._build_response(
186
199
  request=request,
@@ -1,9 +1,13 @@
1
1
  from pydantic import BaseModel, Field
2
+ from maleo_foundation.types import BaseTypes
2
3
 
3
4
  class BaseSignatureSchemas:
4
5
  class Key(BaseModel):
5
6
  key:str = Field(..., description="Key")
6
7
 
8
+ class Password(BaseModel):
9
+ password:BaseTypes.OptionalString = Field(None, min_length=32, max_length=1024, description="password")
10
+
7
11
  class Message(BaseModel):
8
12
  message:str = Field(..., description="Message")
9
13
 
@@ -0,0 +1,8 @@
1
+ from __future__ import annotations
2
+ from maleo_foundation.models.schemas.signature import BaseSignatureSchemas
3
+
4
+ class BaseSignatureGeneralTransfers:
5
+ class SignaturePackage(
6
+ BaseSignatureSchemas.Message,
7
+ BaseSignatureSchemas.Signature
8
+ ): pass
@@ -0,0 +1,14 @@
1
+ from maleo_foundation.models.schemas.signature import BaseSignatureSchemas
2
+
3
+ class BaseSignatureParametersTransfers:
4
+ class Sign(
5
+ BaseSignatureSchemas.Message,
6
+ BaseSignatureSchemas.Password,
7
+ BaseSignatureSchemas.Key
8
+ ): pass
9
+
10
+ class Verify(
11
+ BaseSignatureSchemas.Signature,
12
+ BaseSignatureSchemas.Message,
13
+ BaseSignatureSchemas.Key
14
+ ): pass
@@ -0,0 +1,12 @@
1
+ from pydantic import Field
2
+ from maleo_foundation.models.transfers.results.service.general import BaseServiceGeneralResultsTransfers
3
+ from maleo_foundation.models.schemas.signature import BaseSignatureSchemas
4
+
5
+ class BaseSignatureResultsTransfers:
6
+ class Fail(BaseServiceGeneralResultsTransfers.Fail): pass
7
+
8
+ class Sign(BaseServiceGeneralResultsTransfers.SingleData):
9
+ data:BaseSignatureSchemas.Signature = Field(..., description="Single signature data")
10
+
11
+ class Verify(BaseServiceGeneralResultsTransfers.SingleData):
12
+ data:BaseSignatureSchemas.IsValid = Field(..., description="Single verify data")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maleo_foundation
3
- Version: 0.1.59
3
+ Version: 0.1.61
4
4
  Summary: Foundation package for Maleo
5
5
  Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
6
  License: MIT
@@ -55,6 +55,7 @@ Requires-Dist: protobuf>=5.29.4
55
55
  Requires-Dist: pyasn1>=0.6.1
56
56
  Requires-Dist: pyasn1_modules>=0.4.2
57
57
  Requires-Dist: pycparser>=2.22
58
+ Requires-Dist: pycryptodome>=3.22.0
58
59
  Requires-Dist: pydantic>=2.11.3
59
60
  Requires-Dist: pydantic-settings>=2.9.1
60
61
  Requires-Dist: pydantic_core>=2.33.1
@@ -6,13 +6,15 @@ maleo_foundation/extended_types.py,sha256=pIKt-_9tby4rmune3fmWcCW_mohaNRh_1lywBm
6
6
  maleo_foundation/types.py,sha256=aKXnIgEhYGSfFqNMGLc4qIKGkINBRpkOo9R9cb2CbwI,2414
7
7
  maleo_foundation/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  maleo_foundation/client/manager.py,sha256=hF5Uiv93yHmno8ec4ukCDrpTh2apUabMeYZNVgSbxZM,1035
9
- maleo_foundation/client/services/__init__.py,sha256=ur502vxzT2FxhkZ7F0c7RjOGYAYEqmwRzz3pQsrAM8M,347
9
+ maleo_foundation/client/services/__init__.py,sha256=SUGBVhs_Zu9rNUxWIxcjGmi54W6RRlwSTqW4h8E0vW0,540
10
+ maleo_foundation/client/services/signature.py,sha256=W9ZF_FGGOMXw03jaRlZJPkakCw0grZk52P8IAkOxYLs,4373
10
11
  maleo_foundation/client/services/token.py,sha256=KJcA6aTW12JovrbBf0KoKMDgOopz-mZ_SmCRHhWLS_k,1894
11
12
  maleo_foundation/expanded_types/__init__.py,sha256=lm_r7rxlLA0sgSTGQBMR9ZbZbVDpD7Te-UYb3oRVi1g,364
12
13
  maleo_foundation/expanded_types/client.py,sha256=To0kRXp3QTmuSu5rWKaCiTsMK9qkYiyYKYbHfw-y1fY,2396
13
14
  maleo_foundation/expanded_types/general.py,sha256=bjIBREYTS73tvS-Key7P7db82a2HHlSJ1XBAvKuYmT0,826
14
15
  maleo_foundation/expanded_types/query.py,sha256=0yUG-JIVsanzB7KAkrRz_OsrhP6J0bRqD9Q3l3atQnk,2384
15
16
  maleo_foundation/expanded_types/service.py,sha256=q8jpKdbCbLWwH1UPQavKpVE14rC5rveduk2cFWzuhGw,2416
17
+ maleo_foundation/expanded_types/signature.py,sha256=zNgXRrxVCfEIGXsRANIa1Ljj-ebHjC2pWOTtw_ABJlQ,379
16
18
  maleo_foundation/expanded_types/token.py,sha256=4fRTJw6W5MYq71NksNrWNi7qYHQ4_lQwfu9WxwrMipc,355
17
19
  maleo_foundation/managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
20
  maleo_foundation/managers/db.py,sha256=Pn5EZ-c1Hy6-BihN7KokHJWmBIt3Ty96fZ0zF-srtF4,5208
@@ -26,8 +28,8 @@ maleo_foundation/managers/client/google/base.py,sha256=j3W18Pmcu9jJ5wK12bbWBI6r8
26
28
  maleo_foundation/managers/client/google/secret.py,sha256=Uh01RoOp8QOIvu8X4AGJzOJRlrfAeXHO8ZFvmKo7A-E,3114
27
29
  maleo_foundation/managers/client/google/storage.py,sha256=MPuVpLTl0QJhlBOqpxv5UtD3ANO1WCCE1sRrfHnlCZM,2355
28
30
  maleo_foundation/middlewares/__init__.py,sha256=bqE2EIFC3rWcR2AwFPR0fk2kSFfeTRzgA24GbnuT5RA,3697
29
- maleo_foundation/middlewares/authentication.py,sha256=mpJ4WJ25zw4SGvgpeJE9eSV3-AtK5IJtN2U8Dh9rmMk,3132
30
- maleo_foundation/middlewares/base.py,sha256=iGc_4JZYxE0k47Dty4aFOvpgXjQY_W_4tgqYndhq3V8,10991
31
+ maleo_foundation/middlewares/authentication.py,sha256=SC9p_7lCcGYbO9GedOKiPDF12KaGFbv1OypJsnRzLww,3329
32
+ maleo_foundation/middlewares/base.py,sha256=-tpnutxov5UxrKjWMxktpsZ0JqXYLQCkD3x2B3F3OCI,11821
31
33
  maleo_foundation/middlewares/cors.py,sha256=9uvBvY2N6Vxa9RP_YtESxcWo6Doi6uS0lzAG9iLY7Uc,2288
32
34
  maleo_foundation/models/__init__.py,sha256=AaKehO7c1HyKhoTGRmNHDddSeBXkW-_YNrpOGBu8Ms8,246
33
35
  maleo_foundation/models/responses.py,sha256=Ka9Peb1fVuQKaxyy11FVkUPtGtzyEm_9Xfe8Vla3ml0,4764
@@ -36,17 +38,20 @@ maleo_foundation/models/schemas/__init__.py,sha256=Xj8Ahsqyra-fmEaVcGPok5GOOsPQl
36
38
  maleo_foundation/models/schemas/general.py,sha256=hEQQPcddxMsJXMb36nqItIAfp3pqUyJOlaD7nXkNM2I,3609
37
39
  maleo_foundation/models/schemas/parameter.py,sha256=K47z2NzmTEhUiOfRiRLyRPXoQurbWsKBL7ObXAxIWRY,2100
38
40
  maleo_foundation/models/schemas/result.py,sha256=V3dljS2AdtWW4Pf8YsnQuiCylN1bZtEY1AtYC7okWuI,1747
39
- maleo_foundation/models/schemas/signature.py,sha256=32ECoksXCVRloTFNcb9ne3IAi5F6e6MuDniCj76ppmQ,420
41
+ maleo_foundation/models/schemas/signature.py,sha256=4DVcsBR9TnxD2R28oWk51jMtF1j5ylmorVM3jDNVlrU,609
40
42
  maleo_foundation/models/schemas/token.py,sha256=u71kPXJyCxqn_INK05MSNFhQr9MaLfQM-icYc536xik,551
41
43
  maleo_foundation/models/transfers/__init__.py,sha256=oJLJ3Geeme6vBw7R2Dhvdvg4ziVvzEYAGJaP-tm_90w,299
42
44
  maleo_foundation/models/transfers/general/__init__.py,sha256=0yW67vJvKgJmZ9htteOVatG7mb-YEpHF62dpwH2g_Bk,146
45
+ maleo_foundation/models/transfers/general/signature.py,sha256=EFcr-QC3QcDLZivkmL89ERVc5ZDGe_SYH5dMItll5Bs,264
43
46
  maleo_foundation/models/transfers/general/token.py,sha256=QZNGG5DdmQDTYIqNFMqBQDJoeahIHgzBzyXiMoTS-JA,2414
44
47
  maleo_foundation/models/transfers/parameters/__init__.py,sha256=oKW4RPIEISISRjsJzD8lsCGY1HhZRTzshPpWHcJu86k,353
45
48
  maleo_foundation/models/transfers/parameters/client.py,sha256=tn_Hwa-k-Utp5rODe7GylqZB8djIKKupgkUFscYCyLc,4059
46
49
  maleo_foundation/models/transfers/parameters/general.py,sha256=WoekZJCIoAllhXdRIJkNRdNq0QEIn0bteiHJLtzkCxU,579
47
50
  maleo_foundation/models/transfers/parameters/service.py,sha256=d7Xy_R-DtLBRozyD6r8YnTiuKlE3sb9HMDCCq9WmUbY,6757
51
+ maleo_foundation/models/transfers/parameters/signature.py,sha256=Kn6gJrQUHyn2uG6LyYnhbUEMfXJVTLgMG6n3CXZ4hu8,395
48
52
  maleo_foundation/models/transfers/parameters/token.py,sha256=WTmCKoP-KJLqZjdwr__BeVnBrnRrsxzHSQ0IBaOKvqw,535
49
53
  maleo_foundation/models/transfers/results/__init__.py,sha256=0_8uJ1IQW87RZ4nIxzWkQVi3Fxb7B8myZTngXfoxgNc,241
54
+ maleo_foundation/models/transfers/results/signature.py,sha256=md3tBOfjJlg-35ICSt8h_EZZett_x7obdlx_GQ3lB00,619
50
55
  maleo_foundation/models/transfers/results/token.py,sha256=4zDgj8FWGK6Rcz_pprwnLcpRyyXKRBPbrCl3IOrRvVg,574
51
56
  maleo_foundation/models/transfers/results/client/__init__.py,sha256=xBRuY0NUIPpQEGQ2qoBnqLZGX4W1YSrQ0VnDf5OYJBo,290
52
57
  maleo_foundation/models/transfers/results/client/service.py,sha256=TO_U53vmUEnFWiiyuu33ao3BUidt6KFxvk3GC9uo8JE,1108
@@ -57,8 +62,6 @@ maleo_foundation/models/transfers/results/service/general.py,sha256=G4x-MhQI7Km9
57
62
  maleo_foundation/models/transfers/results/service/query.py,sha256=G5A4FRkHyRRlpuGWrPV5-vqgyyBjMqu8f-Ka9BjD0lA,1828
58
63
  maleo_foundation/models/transfers/results/service/controllers/__init__.py,sha256=HZJWMy2dskzOCzLmp_UaL9rjbQ-sDMI7sd2bXb-4QOU,175
59
64
  maleo_foundation/models/transfers/results/service/controllers/rest.py,sha256=wCuFyOTQkuBs2cqjPsWnPy0XIsCfMqGByhrSy57qp7Y,1107
60
- maleo_foundation/services/__init__.py,sha256=Ho5zJSA89xdGFKIwOdzjmd8sm23cIuwrqYAxCEBBTIU,120
61
- maleo_foundation/services/token.py,sha256=QkiMBTe4aol2uDBfFP2MFa58j-yevr8HtBjenifElR0,1230
62
65
  maleo_foundation/utils/__init__.py,sha256=SRPEVoqjZoO6W8rtF_Ti8VIangg6Auwm6eHbZMdOthY,520
63
66
  maleo_foundation/utils/controller.py,sha256=ECzPzpw36zBAjKcWcDbUAhIJGbc6UpeypdUUX6ipXBg,6396
64
67
  maleo_foundation/utils/exceptions.py,sha256=LPPcU-6_3NbRIBZg2Nr2Ac5HF1qZJbHbMVnwfIfZg6g,3702
@@ -72,7 +75,7 @@ maleo_foundation/utils/loaders/__init__.py,sha256=Dnuv7BWyglSddnbsFb96s-b3KaW7UK
72
75
  maleo_foundation/utils/loaders/json.py,sha256=NsXLq3VZSgzmEf99tV1VtrmiudWdQ8Pzh_hI4Rm0cM8,397
73
76
  maleo_foundation/utils/loaders/key.py,sha256=GZ4h1ONfp6Xx8-E8AWoGP4ajAZrwPhZRtidjn_u82Qg,2562
74
77
  maleo_foundation/utils/loaders/yaml.py,sha256=jr8v3BlgmRCMTzdNgKhIYt1tnubaJXcDSSGkKVR8pbw,362
75
- maleo_foundation-0.1.59.dist-info/METADATA,sha256=QLCBip2ZVnMUnDfoTPgae6BxoaOFpQkbsLH_G46hufA,3354
76
- maleo_foundation-0.1.59.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
77
- maleo_foundation-0.1.59.dist-info/top_level.txt,sha256=_iBos3F_bhEOdjOnzeiEYSrCucasc810xXtLBXI8cQc,17
78
- maleo_foundation-0.1.59.dist-info/RECORD,,
78
+ maleo_foundation-0.1.61.dist-info/METADATA,sha256=hK2ChHmwvrqLf-cO6UwXWoGSsusrU2UCjkuAhx02nsg,3390
79
+ maleo_foundation-0.1.61.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
80
+ maleo_foundation-0.1.61.dist-info/top_level.txt,sha256=_iBos3F_bhEOdjOnzeiEYSrCucasc810xXtLBXI8cQc,17
81
+ maleo_foundation-0.1.61.dist-info/RECORD,,
@@ -1,5 +0,0 @@
1
- from __future__ import annotations
2
- from .token import BaseTokenService
3
-
4
- class BaseServices:
5
- Token = BaseTokenService
@@ -1,20 +0,0 @@
1
- import jwt
2
- from maleo_foundation.models.transfers.general.token import BaseTokenGeneralTransfers
3
- from maleo_foundation.models.schemas.token import BaseTokenSchemas
4
- from maleo_foundation.models.transfers.parameters.token import BaseTokenParametersTransfers
5
- from maleo_foundation.models.transfers.results.token import BaseTokenResultsTransfers
6
- from maleo_foundation.expanded_types.token import BaseTokenResultsTypes
7
-
8
- class BaseTokenService:
9
- @staticmethod
10
- def encode(parameters:BaseTokenParametersTransfers.Encode) -> BaseTokenResultsTypes.Encode:
11
- payload = BaseTokenGeneralTransfers.EncodePayload.model_validate(parameters.payload.model_dump()).model_dump(mode="json")
12
- token = jwt.encode(payload=payload, key=parameters.key.encode(), algorithm="RS256")
13
- data = BaseTokenSchemas.Token(token=token)
14
- return BaseTokenResultsTransfers.Encode(data=data)
15
-
16
- @staticmethod
17
- def decode(parameters:BaseTokenParametersTransfers.Decode) -> BaseTokenResultsTypes.Decode:
18
- payload = jwt.decode(jwt=parameters.token, key=parameters.key, algorithms=["RS256"])
19
- data = BaseTokenGeneralTransfers.DecodePayload.model_validate(payload)
20
- return BaseTokenResultsTransfers.Decode(data=data)