miso-client 0.1.0__py3-none-any.whl → 3.7.2__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.
- miso_client/__init__.py +523 -130
- miso_client/api/__init__.py +35 -0
- miso_client/api/auth_api.py +367 -0
- miso_client/api/logs_api.py +91 -0
- miso_client/api/permissions_api.py +88 -0
- miso_client/api/roles_api.py +88 -0
- miso_client/api/types/__init__.py +75 -0
- miso_client/api/types/auth_types.py +183 -0
- miso_client/api/types/logs_types.py +71 -0
- miso_client/api/types/permissions_types.py +31 -0
- miso_client/api/types/roles_types.py +31 -0
- miso_client/errors.py +30 -4
- miso_client/models/__init__.py +4 -0
- miso_client/models/config.py +275 -72
- miso_client/models/error_response.py +39 -0
- miso_client/models/filter.py +255 -0
- miso_client/models/pagination.py +44 -0
- miso_client/models/sort.py +25 -0
- miso_client/services/__init__.py +6 -5
- miso_client/services/auth.py +496 -87
- miso_client/services/cache.py +42 -41
- miso_client/services/encryption.py +18 -17
- miso_client/services/logger.py +467 -328
- miso_client/services/logger_chain.py +288 -0
- miso_client/services/permission.py +130 -67
- miso_client/services/redis.py +28 -23
- miso_client/services/role.py +145 -62
- miso_client/utils/__init__.py +3 -3
- miso_client/utils/audit_log_queue.py +222 -0
- miso_client/utils/auth_strategy.py +88 -0
- miso_client/utils/auth_utils.py +65 -0
- miso_client/utils/circuit_breaker.py +125 -0
- miso_client/utils/client_token_manager.py +244 -0
- miso_client/utils/config_loader.py +88 -17
- miso_client/utils/controller_url_resolver.py +80 -0
- miso_client/utils/data_masker.py +104 -33
- miso_client/utils/environment_token.py +126 -0
- miso_client/utils/error_utils.py +216 -0
- miso_client/utils/fastapi_endpoints.py +166 -0
- miso_client/utils/filter.py +364 -0
- miso_client/utils/filter_applier.py +143 -0
- miso_client/utils/filter_parser.py +110 -0
- miso_client/utils/flask_endpoints.py +169 -0
- miso_client/utils/http_client.py +494 -262
- miso_client/utils/http_client_logging.py +352 -0
- miso_client/utils/http_client_logging_helpers.py +197 -0
- miso_client/utils/http_client_query_helpers.py +138 -0
- miso_client/utils/http_error_handler.py +92 -0
- miso_client/utils/http_log_formatter.py +115 -0
- miso_client/utils/http_log_masker.py +203 -0
- miso_client/utils/internal_http_client.py +435 -0
- miso_client/utils/jwt_tools.py +125 -16
- miso_client/utils/logger_helpers.py +206 -0
- miso_client/utils/logging_helpers.py +70 -0
- miso_client/utils/origin_validator.py +128 -0
- miso_client/utils/pagination.py +275 -0
- miso_client/utils/request_context.py +285 -0
- miso_client/utils/sensitive_fields_loader.py +116 -0
- miso_client/utils/sort.py +116 -0
- miso_client/utils/token_utils.py +114 -0
- miso_client/utils/url_validator.py +66 -0
- miso_client/utils/user_token_refresh.py +245 -0
- miso_client-3.7.2.dist-info/METADATA +1021 -0
- miso_client-3.7.2.dist-info/RECORD +68 -0
- miso_client-0.1.0.dist-info/METADATA +0 -551
- miso_client-0.1.0.dist-info/RECORD +0 -23
- {miso_client-0.1.0.dist-info → miso_client-3.7.2.dist-info}/WHEEL +0 -0
- {miso_client-0.1.0.dist-info → miso_client-3.7.2.dist-info}/licenses/LICENSE +0 -0
- {miso_client-0.1.0.dist-info → miso_client-3.7.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Centralized API layer with typed interfaces.
|
|
3
|
+
|
|
4
|
+
Provides typed interfaces for all controller API calls, organized by domain.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from ..utils.http_client import HttpClient
|
|
8
|
+
from .auth_api import AuthApi
|
|
9
|
+
from .logs_api import LogsApi
|
|
10
|
+
from .permissions_api import PermissionsApi
|
|
11
|
+
from .roles_api import RolesApi
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ApiClient:
|
|
15
|
+
"""
|
|
16
|
+
Centralized API client for Miso Controller communication.
|
|
17
|
+
|
|
18
|
+
Wraps HttpClient and provides typed interfaces organized by domain.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, http_client: HttpClient):
|
|
22
|
+
"""
|
|
23
|
+
Initialize API client.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
http_client: HttpClient instance
|
|
27
|
+
"""
|
|
28
|
+
self.http_client = http_client
|
|
29
|
+
self.auth = AuthApi(http_client)
|
|
30
|
+
self.roles = RolesApi(http_client)
|
|
31
|
+
self.permissions = PermissionsApi(http_client)
|
|
32
|
+
self.logs = LogsApi(http_client)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
__all__ = ["ApiClient", "AuthApi", "RolesApi", "PermissionsApi", "LogsApi"]
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Auth API implementation.
|
|
3
|
+
|
|
4
|
+
Provides typed interfaces for authentication endpoints.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from ..models.config import AuthStrategy
|
|
10
|
+
from ..utils.http_client import HttpClient
|
|
11
|
+
from .types.auth_types import (
|
|
12
|
+
DeviceCodeRequest,
|
|
13
|
+
DeviceCodeResponseWrapper,
|
|
14
|
+
DeviceCodeTokenPollRequest,
|
|
15
|
+
DeviceCodeTokenPollResponse,
|
|
16
|
+
DeviceCodeTokenResponse,
|
|
17
|
+
GetPermissionsResponse,
|
|
18
|
+
GetRolesResponse,
|
|
19
|
+
GetUserResponse,
|
|
20
|
+
LoginResponse,
|
|
21
|
+
LogoutResponse,
|
|
22
|
+
RefreshPermissionsResponse,
|
|
23
|
+
RefreshRolesResponse,
|
|
24
|
+
RefreshTokenRequest,
|
|
25
|
+
RefreshTokenResponse,
|
|
26
|
+
ValidateTokenRequest,
|
|
27
|
+
ValidateTokenResponse,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AuthApi:
|
|
32
|
+
"""Auth API client for authentication endpoints."""
|
|
33
|
+
|
|
34
|
+
# Endpoint constants
|
|
35
|
+
LOGIN_ENDPOINT = "/api/v1/auth/login"
|
|
36
|
+
VALIDATE_ENDPOINT = "/api/v1/auth/validate"
|
|
37
|
+
USER_ENDPOINT = "/api/v1/auth/user"
|
|
38
|
+
LOGOUT_ENDPOINT = "/api/v1/auth/logout"
|
|
39
|
+
REFRESH_ENDPOINT = "/api/v1/auth/refresh"
|
|
40
|
+
DEVICE_CODE_ENDPOINT = "/api/v1/auth/login"
|
|
41
|
+
DEVICE_CODE_TOKEN_ENDPOINT = "/api/v1/auth/login/device/token"
|
|
42
|
+
DEVICE_CODE_REFRESH_ENDPOINT = "/api/v1/auth/login/device/refresh"
|
|
43
|
+
ROLES_ENDPOINT = "/api/v1/auth/roles"
|
|
44
|
+
ROLES_REFRESH_ENDPOINT = "/api/v1/auth/roles/refresh"
|
|
45
|
+
PERMISSIONS_ENDPOINT = "/api/v1/auth/permissions"
|
|
46
|
+
PERMISSIONS_REFRESH_ENDPOINT = "/api/v1/auth/permissions/refresh"
|
|
47
|
+
|
|
48
|
+
def __init__(self, http_client: HttpClient):
|
|
49
|
+
"""
|
|
50
|
+
Initialize Auth API client.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
http_client: HttpClient instance
|
|
54
|
+
"""
|
|
55
|
+
self.http_client = http_client
|
|
56
|
+
|
|
57
|
+
async def login(self, redirect: str, state: Optional[str] = None) -> LoginResponse:
|
|
58
|
+
"""
|
|
59
|
+
Initiate login flow (GET with query params).
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
redirect: Redirect URI for OAuth2 callback
|
|
63
|
+
state: Optional state parameter for CSRF protection
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
LoginResponse with login URL
|
|
67
|
+
|
|
68
|
+
Raises:
|
|
69
|
+
MisoClientError: If request fails
|
|
70
|
+
"""
|
|
71
|
+
params = {"redirect": redirect}
|
|
72
|
+
if state:
|
|
73
|
+
params["state"] = state
|
|
74
|
+
|
|
75
|
+
response = await self.http_client.get(self.LOGIN_ENDPOINT, params=params)
|
|
76
|
+
return LoginResponse(**response)
|
|
77
|
+
|
|
78
|
+
async def validate_token(
|
|
79
|
+
self,
|
|
80
|
+
token: str,
|
|
81
|
+
environment: Optional[str] = None,
|
|
82
|
+
application: Optional[str] = None,
|
|
83
|
+
auth_strategy: Optional[AuthStrategy] = None,
|
|
84
|
+
) -> ValidateTokenResponse:
|
|
85
|
+
"""
|
|
86
|
+
Validate authentication token (POST).
|
|
87
|
+
|
|
88
|
+
Uses authenticated_request to send the token as Bearer token for authentication,
|
|
89
|
+
while also including it in the request body for validation.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
token: JWT token to validate
|
|
93
|
+
environment: Optional environment key
|
|
94
|
+
application: Optional application key
|
|
95
|
+
auth_strategy: Optional authentication strategy
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
ValidateTokenResponse with validation result
|
|
99
|
+
|
|
100
|
+
Raises:
|
|
101
|
+
MisoClientError: If request fails
|
|
102
|
+
"""
|
|
103
|
+
request_data = ValidateTokenRequest(
|
|
104
|
+
token=token, environment=environment, application=application
|
|
105
|
+
)
|
|
106
|
+
response = await self.http_client.authenticated_request(
|
|
107
|
+
"POST",
|
|
108
|
+
self.VALIDATE_ENDPOINT,
|
|
109
|
+
token,
|
|
110
|
+
data=request_data.model_dump(exclude_none=True),
|
|
111
|
+
auth_strategy=auth_strategy,
|
|
112
|
+
)
|
|
113
|
+
return ValidateTokenResponse(**response)
|
|
114
|
+
|
|
115
|
+
async def get_user(
|
|
116
|
+
self, token: Optional[str] = None, auth_strategy: Optional[AuthStrategy] = None
|
|
117
|
+
) -> GetUserResponse:
|
|
118
|
+
"""
|
|
119
|
+
Get current user information (GET).
|
|
120
|
+
|
|
121
|
+
Token is optional - can use x-client-token header instead.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
token: Optional user token (if not provided, uses x-client-token)
|
|
125
|
+
auth_strategy: Optional authentication strategy
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
GetUserResponse with user information
|
|
129
|
+
|
|
130
|
+
Raises:
|
|
131
|
+
MisoClientError: If request fails
|
|
132
|
+
"""
|
|
133
|
+
if token:
|
|
134
|
+
response = await self.http_client.authenticated_request(
|
|
135
|
+
"GET", self.USER_ENDPOINT, token, auth_strategy=auth_strategy
|
|
136
|
+
)
|
|
137
|
+
else:
|
|
138
|
+
response = await self.http_client.get(self.USER_ENDPOINT)
|
|
139
|
+
return GetUserResponse(**response)
|
|
140
|
+
|
|
141
|
+
async def logout(self, token: Optional[str] = None) -> LogoutResponse:
|
|
142
|
+
"""
|
|
143
|
+
Logout user (POST).
|
|
144
|
+
|
|
145
|
+
If token is provided, sends it in the request body for server-side invalidation.
|
|
146
|
+
Otherwise, uses client credentials authentication.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
token: Optional user token to invalidate (sent in request body if provided)
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
LogoutResponse with logout message
|
|
153
|
+
|
|
154
|
+
Raises:
|
|
155
|
+
MisoClientError: If request fails
|
|
156
|
+
"""
|
|
157
|
+
if token:
|
|
158
|
+
# Send token in body for server-side invalidation
|
|
159
|
+
response = await self.http_client.authenticated_request(
|
|
160
|
+
"POST", self.LOGOUT_ENDPOINT, token, data={"token": token}
|
|
161
|
+
)
|
|
162
|
+
else:
|
|
163
|
+
# Use client credentials (no user token)
|
|
164
|
+
response = await self.http_client.post(self.LOGOUT_ENDPOINT)
|
|
165
|
+
return LogoutResponse(**response)
|
|
166
|
+
|
|
167
|
+
async def refresh_token(self, refresh_token: str) -> RefreshTokenResponse:
|
|
168
|
+
"""
|
|
169
|
+
Refresh user access token (POST).
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
refresh_token: Refresh token
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
RefreshTokenResponse with new tokens
|
|
176
|
+
|
|
177
|
+
Raises:
|
|
178
|
+
MisoClientError: If request fails
|
|
179
|
+
"""
|
|
180
|
+
request_data = RefreshTokenRequest(refreshToken=refresh_token)
|
|
181
|
+
response = await self.http_client.post(
|
|
182
|
+
self.REFRESH_ENDPOINT, data=request_data.model_dump()
|
|
183
|
+
)
|
|
184
|
+
return RefreshTokenResponse(**response)
|
|
185
|
+
|
|
186
|
+
async def initiate_device_code(
|
|
187
|
+
self, environment: Optional[str] = None, scope: Optional[str] = None
|
|
188
|
+
) -> DeviceCodeResponseWrapper:
|
|
189
|
+
"""
|
|
190
|
+
Initiate device code flow (POST).
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
environment: Optional environment key
|
|
194
|
+
scope: Optional OAuth2 scope string
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
DeviceCodeResponseWrapper with device code information
|
|
198
|
+
|
|
199
|
+
Raises:
|
|
200
|
+
MisoClientError: If request fails
|
|
201
|
+
"""
|
|
202
|
+
request_data = DeviceCodeRequest(environment=environment, scope=scope)
|
|
203
|
+
response = await self.http_client.post(
|
|
204
|
+
self.DEVICE_CODE_ENDPOINT, data=request_data.model_dump(exclude_none=True)
|
|
205
|
+
)
|
|
206
|
+
return DeviceCodeResponseWrapper(**response)
|
|
207
|
+
|
|
208
|
+
async def poll_device_code_token(self, device_code: str) -> DeviceCodeTokenPollResponse:
|
|
209
|
+
"""
|
|
210
|
+
Poll for device code token (POST).
|
|
211
|
+
|
|
212
|
+
Returns 202 while authorization is pending.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
device_code: Device code from initiation
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
DeviceCodeTokenPollResponse with token or pending status
|
|
219
|
+
|
|
220
|
+
Raises:
|
|
221
|
+
MisoClientError: If request fails
|
|
222
|
+
"""
|
|
223
|
+
request_data = DeviceCodeTokenPollRequest(deviceCode=device_code)
|
|
224
|
+
response = await self.http_client.post(
|
|
225
|
+
self.DEVICE_CODE_TOKEN_ENDPOINT, data=request_data.model_dump()
|
|
226
|
+
)
|
|
227
|
+
return DeviceCodeTokenPollResponse(**response)
|
|
228
|
+
|
|
229
|
+
async def refresh_device_code_token(self, refresh_token: str) -> DeviceCodeTokenResponse:
|
|
230
|
+
"""
|
|
231
|
+
Refresh device code access token (POST).
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
refresh_token: Refresh token from device code flow
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
DeviceCodeTokenResponse with new tokens
|
|
238
|
+
|
|
239
|
+
Raises:
|
|
240
|
+
MisoClientError: If request fails
|
|
241
|
+
"""
|
|
242
|
+
request_data = RefreshTokenRequest(refreshToken=refresh_token)
|
|
243
|
+
response = await self.http_client.post(
|
|
244
|
+
self.DEVICE_CODE_REFRESH_ENDPOINT, data=request_data.model_dump()
|
|
245
|
+
)
|
|
246
|
+
response_data = response.get("data", {})
|
|
247
|
+
return DeviceCodeTokenResponse(**response_data)
|
|
248
|
+
|
|
249
|
+
async def get_roles(
|
|
250
|
+
self,
|
|
251
|
+
token: Optional[str] = None,
|
|
252
|
+
environment: Optional[str] = None,
|
|
253
|
+
application: Optional[str] = None,
|
|
254
|
+
auth_strategy: Optional[AuthStrategy] = None,
|
|
255
|
+
) -> GetRolesResponse:
|
|
256
|
+
"""
|
|
257
|
+
Get user roles (GET).
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
token: Optional user token (if not provided, uses x-client-token)
|
|
261
|
+
environment: Optional environment key filter
|
|
262
|
+
application: Optional application key filter
|
|
263
|
+
auth_strategy: Optional authentication strategy
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
GetRolesResponse with user roles
|
|
267
|
+
|
|
268
|
+
Raises:
|
|
269
|
+
MisoClientError: If request fails
|
|
270
|
+
"""
|
|
271
|
+
params = {}
|
|
272
|
+
if environment:
|
|
273
|
+
params["environment"] = environment
|
|
274
|
+
if application:
|
|
275
|
+
params["application"] = application
|
|
276
|
+
|
|
277
|
+
if token:
|
|
278
|
+
response = await self.http_client.authenticated_request(
|
|
279
|
+
"GET", self.ROLES_ENDPOINT, token, params=params, auth_strategy=auth_strategy
|
|
280
|
+
)
|
|
281
|
+
else:
|
|
282
|
+
response = await self.http_client.get(self.ROLES_ENDPOINT, params=params)
|
|
283
|
+
return GetRolesResponse(**response)
|
|
284
|
+
|
|
285
|
+
async def refresh_roles(
|
|
286
|
+
self, token: Optional[str] = None, auth_strategy: Optional[AuthStrategy] = None
|
|
287
|
+
) -> RefreshRolesResponse:
|
|
288
|
+
"""
|
|
289
|
+
Refresh user roles (GET).
|
|
290
|
+
|
|
291
|
+
Args:
|
|
292
|
+
token: Optional user token (if not provided, uses x-client-token)
|
|
293
|
+
auth_strategy: Optional authentication strategy
|
|
294
|
+
|
|
295
|
+
Returns:
|
|
296
|
+
RefreshRolesResponse with refreshed roles
|
|
297
|
+
|
|
298
|
+
Raises:
|
|
299
|
+
MisoClientError: If request fails
|
|
300
|
+
"""
|
|
301
|
+
if token:
|
|
302
|
+
response = await self.http_client.authenticated_request(
|
|
303
|
+
"GET", self.ROLES_REFRESH_ENDPOINT, token, auth_strategy=auth_strategy
|
|
304
|
+
)
|
|
305
|
+
else:
|
|
306
|
+
response = await self.http_client.get(self.ROLES_REFRESH_ENDPOINT)
|
|
307
|
+
return RefreshRolesResponse(**response)
|
|
308
|
+
|
|
309
|
+
async def get_permissions(
|
|
310
|
+
self,
|
|
311
|
+
token: Optional[str] = None,
|
|
312
|
+
environment: Optional[str] = None,
|
|
313
|
+
application: Optional[str] = None,
|
|
314
|
+
auth_strategy: Optional[AuthStrategy] = None,
|
|
315
|
+
) -> GetPermissionsResponse:
|
|
316
|
+
"""
|
|
317
|
+
Get user permissions (GET).
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
token: Optional user token (if not provided, uses x-client-token)
|
|
321
|
+
environment: Optional environment key filter
|
|
322
|
+
application: Optional application key filter
|
|
323
|
+
auth_strategy: Optional authentication strategy
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
GetPermissionsResponse with user permissions
|
|
327
|
+
|
|
328
|
+
Raises:
|
|
329
|
+
MisoClientError: If request fails
|
|
330
|
+
"""
|
|
331
|
+
params = {}
|
|
332
|
+
if environment:
|
|
333
|
+
params["environment"] = environment
|
|
334
|
+
if application:
|
|
335
|
+
params["application"] = application
|
|
336
|
+
|
|
337
|
+
if token:
|
|
338
|
+
response = await self.http_client.authenticated_request(
|
|
339
|
+
"GET", self.PERMISSIONS_ENDPOINT, token, params=params, auth_strategy=auth_strategy
|
|
340
|
+
)
|
|
341
|
+
else:
|
|
342
|
+
response = await self.http_client.get(self.PERMISSIONS_ENDPOINT, params=params)
|
|
343
|
+
return GetPermissionsResponse(**response)
|
|
344
|
+
|
|
345
|
+
async def refresh_permissions(
|
|
346
|
+
self, token: Optional[str] = None, auth_strategy: Optional[AuthStrategy] = None
|
|
347
|
+
) -> RefreshPermissionsResponse:
|
|
348
|
+
"""
|
|
349
|
+
Refresh user permissions (GET).
|
|
350
|
+
|
|
351
|
+
Args:
|
|
352
|
+
token: Optional user token (if not provided, uses x-client-token)
|
|
353
|
+
auth_strategy: Optional authentication strategy
|
|
354
|
+
|
|
355
|
+
Returns:
|
|
356
|
+
RefreshPermissionsResponse with refreshed permissions
|
|
357
|
+
|
|
358
|
+
Raises:
|
|
359
|
+
MisoClientError: If request fails
|
|
360
|
+
"""
|
|
361
|
+
if token:
|
|
362
|
+
response = await self.http_client.authenticated_request(
|
|
363
|
+
"GET", self.PERMISSIONS_REFRESH_ENDPOINT, token, auth_strategy=auth_strategy
|
|
364
|
+
)
|
|
365
|
+
else:
|
|
366
|
+
response = await self.http_client.get(self.PERMISSIONS_REFRESH_ENDPOINT)
|
|
367
|
+
return RefreshPermissionsResponse(**response)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Logs API implementation.
|
|
3
|
+
|
|
4
|
+
Provides typed interfaces for logging endpoints.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from ..models.config import LogEntry
|
|
10
|
+
from ..utils.http_client import HttpClient
|
|
11
|
+
from .types.logs_types import BatchLogRequest, BatchLogResponse, LogRequest, LogResponse
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class LogsApi:
|
|
15
|
+
"""Logs API client for logging endpoints."""
|
|
16
|
+
|
|
17
|
+
# Endpoint constants
|
|
18
|
+
LOGS_ENDPOINT = "/api/v1/logs"
|
|
19
|
+
LOGS_BATCH_ENDPOINT = "/api/v1/logs/batch"
|
|
20
|
+
|
|
21
|
+
def __init__(self, http_client: HttpClient):
|
|
22
|
+
"""
|
|
23
|
+
Initialize Logs API client.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
http_client: HttpClient instance
|
|
27
|
+
"""
|
|
28
|
+
self.http_client = http_client
|
|
29
|
+
|
|
30
|
+
async def send_log(self, log_entry: LogRequest, token: Optional[str] = None) -> LogResponse:
|
|
31
|
+
"""
|
|
32
|
+
Send log entry (POST).
|
|
33
|
+
|
|
34
|
+
Supports Bearer token, x-client-token, or client credentials authentication.
|
|
35
|
+
If token is provided, uses authenticated_request. Otherwise uses client credentials (automatic).
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
log_entry: LogRequest with type and data
|
|
39
|
+
token: Optional user token (if not provided, uses x-client-token/client credentials)
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
LogResponse with success status
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
MisoClientError: If request fails
|
|
46
|
+
"""
|
|
47
|
+
if token:
|
|
48
|
+
response = await self.http_client.authenticated_request(
|
|
49
|
+
"POST",
|
|
50
|
+
self.LOGS_ENDPOINT,
|
|
51
|
+
token,
|
|
52
|
+
data=log_entry.model_dump(exclude_none=True),
|
|
53
|
+
)
|
|
54
|
+
else:
|
|
55
|
+
response = await self.http_client.post(
|
|
56
|
+
self.LOGS_ENDPOINT, data=log_entry.model_dump(exclude_none=True)
|
|
57
|
+
)
|
|
58
|
+
return LogResponse(**response)
|
|
59
|
+
|
|
60
|
+
async def send_batch_logs(
|
|
61
|
+
self, logs: list[LogEntry], token: Optional[str] = None
|
|
62
|
+
) -> BatchLogResponse:
|
|
63
|
+
"""
|
|
64
|
+
Send multiple log entries in batch (POST).
|
|
65
|
+
|
|
66
|
+
Supports Bearer token, x-client-token, or client credentials authentication.
|
|
67
|
+
If token is provided, uses authenticated_request. Otherwise uses client credentials (automatic).
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
logs: List of LogEntry objects
|
|
71
|
+
token: Optional user token (if not provided, uses x-client-token/client credentials)
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
BatchLogResponse with processing results
|
|
75
|
+
|
|
76
|
+
Raises:
|
|
77
|
+
MisoClientError: If request fails
|
|
78
|
+
"""
|
|
79
|
+
request_data = BatchLogRequest(logs=logs)
|
|
80
|
+
if token:
|
|
81
|
+
response = await self.http_client.authenticated_request(
|
|
82
|
+
"POST",
|
|
83
|
+
self.LOGS_BATCH_ENDPOINT,
|
|
84
|
+
token,
|
|
85
|
+
data=request_data.model_dump(exclude_none=True),
|
|
86
|
+
)
|
|
87
|
+
else:
|
|
88
|
+
response = await self.http_client.post(
|
|
89
|
+
self.LOGS_BATCH_ENDPOINT, data=request_data.model_dump(exclude_none=True)
|
|
90
|
+
)
|
|
91
|
+
return BatchLogResponse(**response)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Permissions API implementation.
|
|
3
|
+
|
|
4
|
+
Provides typed interfaces for permissions endpoints.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from ..models.config import AuthStrategy
|
|
10
|
+
from ..utils.http_client import HttpClient
|
|
11
|
+
from .types.permissions_types import GetPermissionsResponse, RefreshPermissionsResponse
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PermissionsApi:
|
|
15
|
+
"""Permissions API client for permission endpoints."""
|
|
16
|
+
|
|
17
|
+
# Endpoint constants
|
|
18
|
+
PERMISSIONS_ENDPOINT = "/api/v1/auth/permissions"
|
|
19
|
+
PERMISSIONS_REFRESH_ENDPOINT = "/api/v1/auth/permissions/refresh"
|
|
20
|
+
|
|
21
|
+
def __init__(self, http_client: HttpClient):
|
|
22
|
+
"""
|
|
23
|
+
Initialize Permissions API client.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
http_client: HttpClient instance
|
|
27
|
+
"""
|
|
28
|
+
self.http_client = http_client
|
|
29
|
+
|
|
30
|
+
async def get_permissions(
|
|
31
|
+
self,
|
|
32
|
+
token: Optional[str] = None,
|
|
33
|
+
environment: Optional[str] = None,
|
|
34
|
+
application: Optional[str] = None,
|
|
35
|
+
auth_strategy: Optional[AuthStrategy] = None,
|
|
36
|
+
) -> GetPermissionsResponse:
|
|
37
|
+
"""
|
|
38
|
+
Get user permissions (GET).
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
token: Optional user token (if not provided, uses x-client-token)
|
|
42
|
+
environment: Optional environment key filter
|
|
43
|
+
application: Optional application key filter
|
|
44
|
+
auth_strategy: Optional authentication strategy
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
GetPermissionsResponse with user permissions
|
|
48
|
+
|
|
49
|
+
Raises:
|
|
50
|
+
MisoClientError: If request fails
|
|
51
|
+
"""
|
|
52
|
+
params = {}
|
|
53
|
+
if environment:
|
|
54
|
+
params["environment"] = environment
|
|
55
|
+
if application:
|
|
56
|
+
params["application"] = application
|
|
57
|
+
|
|
58
|
+
if token:
|
|
59
|
+
response = await self.http_client.authenticated_request(
|
|
60
|
+
"GET", self.PERMISSIONS_ENDPOINT, token, params=params, auth_strategy=auth_strategy
|
|
61
|
+
)
|
|
62
|
+
else:
|
|
63
|
+
response = await self.http_client.get(self.PERMISSIONS_ENDPOINT, params=params)
|
|
64
|
+
return GetPermissionsResponse(**response)
|
|
65
|
+
|
|
66
|
+
async def refresh_permissions(
|
|
67
|
+
self, token: Optional[str] = None, auth_strategy: Optional[AuthStrategy] = None
|
|
68
|
+
) -> RefreshPermissionsResponse:
|
|
69
|
+
"""
|
|
70
|
+
Refresh user permissions (GET).
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
token: Optional user token (if not provided, uses x-client-token)
|
|
74
|
+
auth_strategy: Optional authentication strategy
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
RefreshPermissionsResponse with refreshed permissions
|
|
78
|
+
|
|
79
|
+
Raises:
|
|
80
|
+
MisoClientError: If request fails
|
|
81
|
+
"""
|
|
82
|
+
if token:
|
|
83
|
+
response = await self.http_client.authenticated_request(
|
|
84
|
+
"GET", self.PERMISSIONS_REFRESH_ENDPOINT, token, auth_strategy=auth_strategy
|
|
85
|
+
)
|
|
86
|
+
else:
|
|
87
|
+
response = await self.http_client.get(self.PERMISSIONS_REFRESH_ENDPOINT)
|
|
88
|
+
return RefreshPermissionsResponse(**response)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Roles API implementation.
|
|
3
|
+
|
|
4
|
+
Provides typed interfaces for roles endpoints.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from ..models.config import AuthStrategy
|
|
10
|
+
from ..utils.http_client import HttpClient
|
|
11
|
+
from .types.roles_types import GetRolesResponse, RefreshRolesResponse
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class RolesApi:
|
|
15
|
+
"""Roles API client for role endpoints."""
|
|
16
|
+
|
|
17
|
+
# Endpoint constants
|
|
18
|
+
ROLES_ENDPOINT = "/api/v1/auth/roles"
|
|
19
|
+
ROLES_REFRESH_ENDPOINT = "/api/v1/auth/roles/refresh"
|
|
20
|
+
|
|
21
|
+
def __init__(self, http_client: HttpClient):
|
|
22
|
+
"""
|
|
23
|
+
Initialize Roles API client.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
http_client: HttpClient instance
|
|
27
|
+
"""
|
|
28
|
+
self.http_client = http_client
|
|
29
|
+
|
|
30
|
+
async def get_roles(
|
|
31
|
+
self,
|
|
32
|
+
token: Optional[str] = None,
|
|
33
|
+
environment: Optional[str] = None,
|
|
34
|
+
application: Optional[str] = None,
|
|
35
|
+
auth_strategy: Optional[AuthStrategy] = None,
|
|
36
|
+
) -> GetRolesResponse:
|
|
37
|
+
"""
|
|
38
|
+
Get user roles (GET).
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
token: Optional user token (if not provided, uses x-client-token)
|
|
42
|
+
environment: Optional environment key filter
|
|
43
|
+
application: Optional application key filter
|
|
44
|
+
auth_strategy: Optional authentication strategy
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
GetRolesResponse with user roles
|
|
48
|
+
|
|
49
|
+
Raises:
|
|
50
|
+
MisoClientError: If request fails
|
|
51
|
+
"""
|
|
52
|
+
params = {}
|
|
53
|
+
if environment:
|
|
54
|
+
params["environment"] = environment
|
|
55
|
+
if application:
|
|
56
|
+
params["application"] = application
|
|
57
|
+
|
|
58
|
+
if token:
|
|
59
|
+
response = await self.http_client.authenticated_request(
|
|
60
|
+
"GET", self.ROLES_ENDPOINT, token, params=params, auth_strategy=auth_strategy
|
|
61
|
+
)
|
|
62
|
+
else:
|
|
63
|
+
response = await self.http_client.get(self.ROLES_ENDPOINT, params=params)
|
|
64
|
+
return GetRolesResponse(**response)
|
|
65
|
+
|
|
66
|
+
async def refresh_roles(
|
|
67
|
+
self, token: Optional[str] = None, auth_strategy: Optional[AuthStrategy] = None
|
|
68
|
+
) -> RefreshRolesResponse:
|
|
69
|
+
"""
|
|
70
|
+
Refresh user roles (GET).
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
token: Optional user token (if not provided, uses x-client-token)
|
|
74
|
+
auth_strategy: Optional authentication strategy
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
RefreshRolesResponse with refreshed roles
|
|
78
|
+
|
|
79
|
+
Raises:
|
|
80
|
+
MisoClientError: If request fails
|
|
81
|
+
"""
|
|
82
|
+
if token:
|
|
83
|
+
response = await self.http_client.authenticated_request(
|
|
84
|
+
"GET", self.ROLES_REFRESH_ENDPOINT, token, auth_strategy=auth_strategy
|
|
85
|
+
)
|
|
86
|
+
else:
|
|
87
|
+
response = await self.http_client.get(self.ROLES_REFRESH_ENDPOINT)
|
|
88
|
+
return RefreshRolesResponse(**response)
|