miso-client 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of miso-client might be problematic. Click here for more details.

miso_client/__init__.py CHANGED
@@ -7,34 +7,34 @@ for authentication, role-based access control, permission management, and loggin
7
7
 
8
8
  from typing import Any, Optional
9
9
 
10
+ from .errors import (
11
+ AuthenticationError,
12
+ AuthorizationError,
13
+ ConfigurationError,
14
+ ConnectionError,
15
+ MisoClientError,
16
+ )
10
17
  from .models.config import (
11
- RedisConfig,
12
- MisoClientConfig,
13
- UserInfo,
14
18
  AuthResult,
15
- LogEntry,
16
- RoleResult,
17
- PermissionResult,
19
+ ClientLoggingOptions,
18
20
  ClientTokenResponse,
21
+ LogEntry,
22
+ MisoClientConfig,
19
23
  PerformanceMetrics,
20
- ClientLoggingOptions,
24
+ PermissionResult,
25
+ RedisConfig,
26
+ RoleResult,
27
+ UserInfo,
21
28
  )
22
29
  from .services.auth import AuthService
23
- from .services.role import RoleService
30
+ from .services.cache import CacheService
31
+ from .services.encryption import EncryptionService
32
+ from .services.logger import LoggerChain, LoggerService
24
33
  from .services.permission import PermissionService
25
- from .services.logger import LoggerService, LoggerChain
26
34
  from .services.redis import RedisService
27
- from .services.encryption import EncryptionService
28
- from .services.cache import CacheService
29
- from .utils.http_client import HttpClient
35
+ from .services.role import RoleService
30
36
  from .utils.config_loader import load_config
31
- from .errors import (
32
- MisoClientError,
33
- AuthenticationError,
34
- AuthorizationError,
35
- ConnectionError,
36
- ConfigurationError,
37
- )
37
+ from .utils.http_client import HttpClient
38
38
 
39
39
  __version__ = "0.1.0"
40
40
  __author__ = "AI Fabrix Team"
@@ -44,18 +44,18 @@ __license__ = "MIT"
44
44
  class MisoClient:
45
45
  """
46
46
  Main MisoClient SDK class for authentication, authorization, and logging.
47
-
47
+
48
48
  This client provides a unified interface for:
49
49
  - Token validation and user management
50
50
  - Role-based access control
51
51
  - Permission management
52
52
  - Application logging with Redis caching
53
53
  """
54
-
54
+
55
55
  def __init__(self, config: MisoClientConfig):
56
56
  """
57
57
  Initialize MisoClient with configuration.
58
-
58
+
59
59
  Args:
60
60
  config: MisoClient configuration including controller URL, client credentials, etc.
61
61
  """
@@ -75,7 +75,7 @@ class MisoClient:
75
75
  async def initialize(self) -> None:
76
76
  """
77
77
  Initialize the client (connect to Redis if configured).
78
-
78
+
79
79
  This method should be called before using the client. It will attempt
80
80
  to connect to Redis if configured, but will gracefully fall back to
81
81
  controller-only mode if Redis is unavailable.
@@ -105,16 +105,18 @@ class MisoClient:
105
105
  def get_token(self, req: dict) -> str | None:
106
106
  """
107
107
  Extract Bearer token from request headers.
108
-
108
+
109
109
  Supports common request object patterns (dict with headers).
110
-
110
+
111
111
  Args:
112
112
  req: Request object with headers dict containing 'authorization' key
113
-
113
+
114
114
  Returns:
115
115
  Bearer token string or None if not found
116
116
  """
117
- headers_obj = req.get("headers", {}) if isinstance(req, dict) else getattr(req, "headers", {})
117
+ headers_obj = (
118
+ req.get("headers", {}) if isinstance(req, dict) else getattr(req, "headers", {})
119
+ )
118
120
  headers: dict[str, Any] = headers_obj if isinstance(headers_obj, dict) else {}
119
121
  auth_value = headers.get("authorization") or headers.get("Authorization")
120
122
  if not isinstance(auth_value, str):
@@ -123,16 +125,16 @@ class MisoClient:
123
125
  # Support "Bearer <token>" format
124
126
  if auth_value.startswith("Bearer "):
125
127
  return auth_value[7:]
126
-
128
+
127
129
  # If no Bearer prefix, assume the whole header is the token
128
130
  return auth_value
129
131
 
130
132
  async def get_environment_token(self) -> str:
131
133
  """
132
134
  Get environment token using client credentials.
133
-
135
+
134
136
  This is called automatically by HttpClient but can be called manually.
135
-
137
+
136
138
  Returns:
137
139
  Client token string
138
140
  """
@@ -141,12 +143,12 @@ class MisoClient:
141
143
  def login(self, redirect_uri: str) -> str:
142
144
  """
143
145
  Initiate login flow by redirecting to controller.
144
-
146
+
145
147
  Returns the login URL for browser redirect or manual navigation.
146
-
148
+
147
149
  Args:
148
150
  redirect_uri: URI to redirect to after successful login
149
-
151
+
150
152
  Returns:
151
153
  Login URL string
152
154
  """
@@ -155,10 +157,10 @@ class MisoClient:
155
157
  async def validate_token(self, token: str) -> bool:
156
158
  """
157
159
  Validate token with controller.
158
-
160
+
159
161
  Args:
160
162
  token: JWT token to validate
161
-
163
+
162
164
  Returns:
163
165
  True if token is valid, False otherwise
164
166
  """
@@ -167,10 +169,10 @@ class MisoClient:
167
169
  async def get_user(self, token: str) -> UserInfo | None:
168
170
  """
169
171
  Get user information from token.
170
-
172
+
171
173
  Args:
172
174
  token: JWT token
173
-
175
+
174
176
  Returns:
175
177
  UserInfo if token is valid, None otherwise
176
178
  """
@@ -179,10 +181,10 @@ class MisoClient:
179
181
  async def get_user_info(self, token: str) -> UserInfo | None:
180
182
  """
181
183
  Get user information from GET /api/auth/user endpoint.
182
-
184
+
183
185
  Args:
184
186
  token: JWT token
185
-
187
+
186
188
  Returns:
187
189
  UserInfo if token is valid, None otherwise
188
190
  """
@@ -191,10 +193,10 @@ class MisoClient:
191
193
  async def is_authenticated(self, token: str) -> bool:
192
194
  """
193
195
  Check if user is authenticated.
194
-
196
+
195
197
  Args:
196
198
  token: JWT token
197
-
199
+
198
200
  Returns:
199
201
  True if user is authenticated, False otherwise
200
202
  """
@@ -209,10 +211,10 @@ class MisoClient:
209
211
  async def get_roles(self, token: str) -> list[str]:
210
212
  """
211
213
  Get user roles (cached in Redis if available).
212
-
214
+
213
215
  Args:
214
216
  token: JWT token
215
-
217
+
216
218
  Returns:
217
219
  List of user roles
218
220
  """
@@ -221,11 +223,11 @@ class MisoClient:
221
223
  async def has_role(self, token: str, role: str) -> bool:
222
224
  """
223
225
  Check if user has specific role.
224
-
226
+
225
227
  Args:
226
228
  token: JWT token
227
229
  role: Role to check
228
-
230
+
229
231
  Returns:
230
232
  True if user has the role, False otherwise
231
233
  """
@@ -234,11 +236,11 @@ class MisoClient:
234
236
  async def has_any_role(self, token: str, roles: list[str]) -> bool:
235
237
  """
236
238
  Check if user has any of the specified roles.
237
-
239
+
238
240
  Args:
239
241
  token: JWT token
240
242
  roles: List of roles to check
241
-
243
+
242
244
  Returns:
243
245
  True if user has any of the roles, False otherwise
244
246
  """
@@ -247,11 +249,11 @@ class MisoClient:
247
249
  async def has_all_roles(self, token: str, roles: list[str]) -> bool:
248
250
  """
249
251
  Check if user has all of the specified roles.
250
-
252
+
251
253
  Args:
252
254
  token: JWT token
253
255
  roles: List of roles to check
254
-
256
+
255
257
  Returns:
256
258
  True if user has all roles, False otherwise
257
259
  """
@@ -260,10 +262,10 @@ class MisoClient:
260
262
  async def refresh_roles(self, token: str) -> list[str]:
261
263
  """
262
264
  Force refresh roles from controller (bypass cache).
263
-
265
+
264
266
  Args:
265
267
  token: JWT token
266
-
268
+
267
269
  Returns:
268
270
  Fresh list of user roles
269
271
  """
@@ -272,10 +274,10 @@ class MisoClient:
272
274
  async def get_permissions(self, token: str) -> list[str]:
273
275
  """
274
276
  Get user permissions (cached in Redis if available).
275
-
277
+
276
278
  Args:
277
279
  token: JWT token
278
-
280
+
279
281
  Returns:
280
282
  List of user permissions
281
283
  """
@@ -284,11 +286,11 @@ class MisoClient:
284
286
  async def has_permission(self, token: str, permission: str) -> bool:
285
287
  """
286
288
  Check if user has specific permission.
287
-
289
+
288
290
  Args:
289
291
  token: JWT token
290
292
  permission: Permission to check
291
-
293
+
292
294
  Returns:
293
295
  True if user has the permission, False otherwise
294
296
  """
@@ -297,11 +299,11 @@ class MisoClient:
297
299
  async def has_any_permission(self, token: str, permissions: list[str]) -> bool:
298
300
  """
299
301
  Check if user has any of the specified permissions.
300
-
302
+
301
303
  Args:
302
304
  token: JWT token
303
305
  permissions: List of permissions to check
304
-
306
+
305
307
  Returns:
306
308
  True if user has any of the permissions, False otherwise
307
309
  """
@@ -310,11 +312,11 @@ class MisoClient:
310
312
  async def has_all_permissions(self, token: str, permissions: list[str]) -> bool:
311
313
  """
312
314
  Check if user has all of the specified permissions.
313
-
315
+
314
316
  Args:
315
317
  token: JWT token
316
318
  permissions: List of permissions to check
317
-
319
+
318
320
  Returns:
319
321
  True if user has all permissions, False otherwise
320
322
  """
@@ -323,10 +325,10 @@ class MisoClient:
323
325
  async def refresh_permissions(self, token: str) -> list[str]:
324
326
  """
325
327
  Force refresh permissions from controller (bypass cache).
326
-
328
+
327
329
  Args:
328
330
  token: JWT token
329
-
331
+
330
332
  Returns:
331
333
  Fresh list of user permissions
332
334
  """
@@ -335,7 +337,7 @@ class MisoClient:
335
337
  async def clear_permissions_cache(self, token: str) -> None:
336
338
  """
337
339
  Clear cached permissions for a user.
338
-
340
+
339
341
  Args:
340
342
  token: JWT token
341
343
  """
@@ -347,7 +349,7 @@ class MisoClient:
347
349
  def log(self) -> LoggerService:
348
350
  """
349
351
  Get logger service for application logging.
350
-
352
+
351
353
  Returns:
352
354
  LoggerService instance
353
355
  """
@@ -358,12 +360,12 @@ class MisoClient:
358
360
  def encrypt(self, plaintext: str) -> str:
359
361
  """
360
362
  Encrypt sensitive data.
361
-
363
+
362
364
  Convenience method that delegates to encryption service.
363
-
365
+
364
366
  Args:
365
367
  plaintext: Plain text string to encrypt
366
-
368
+
367
369
  Returns:
368
370
  Base64-encoded encrypted string
369
371
  """
@@ -372,12 +374,12 @@ class MisoClient:
372
374
  def decrypt(self, encrypted_text: str) -> str:
373
375
  """
374
376
  Decrypt sensitive data.
375
-
377
+
376
378
  Convenience method that delegates to encryption service.
377
-
379
+
378
380
  Args:
379
381
  encrypted_text: Base64-encoded encrypted string
380
-
382
+
381
383
  Returns:
382
384
  Decrypted plain text string
383
385
  """
@@ -388,12 +390,12 @@ class MisoClient:
388
390
  async def cache_get(self, key: str) -> Optional[Any]:
389
391
  """
390
392
  Get cached value.
391
-
393
+
392
394
  Convenience method that delegates to cache service.
393
-
395
+
394
396
  Args:
395
397
  key: Cache key
396
-
398
+
397
399
  Returns:
398
400
  Cached value if found, None otherwise
399
401
  """
@@ -402,14 +404,14 @@ class MisoClient:
402
404
  async def cache_set(self, key: str, value: Any, ttl: int) -> bool:
403
405
  """
404
406
  Set cached value with TTL.
405
-
407
+
406
408
  Convenience method that delegates to cache service.
407
-
409
+
408
410
  Args:
409
411
  key: Cache key
410
412
  value: Value to cache
411
413
  ttl: Time to live in seconds
412
-
414
+
413
415
  Returns:
414
416
  True if successful, False otherwise
415
417
  """
@@ -418,12 +420,12 @@ class MisoClient:
418
420
  async def cache_delete(self, key: str) -> bool:
419
421
  """
420
422
  Delete cached value.
421
-
423
+
422
424
  Convenience method that delegates to cache service.
423
-
425
+
424
426
  Args:
425
427
  key: Cache key
426
-
428
+
427
429
  Returns:
428
430
  True if deleted, False otherwise
429
431
  """
@@ -432,7 +434,7 @@ class MisoClient:
432
434
  async def cache_clear(self) -> None:
433
435
  """
434
436
  Clear all cached values.
435
-
437
+
436
438
  Convenience method that delegates to cache service.
437
439
  """
438
440
  await self.cache.clear()
@@ -442,7 +444,7 @@ class MisoClient:
442
444
  def get_config(self) -> MisoClientConfig:
443
445
  """
444
446
  Get current configuration.
445
-
447
+
446
448
  Returns:
447
449
  Copy of current configuration
448
450
  """
@@ -451,7 +453,7 @@ class MisoClient:
451
453
  def is_redis_connected(self) -> bool:
452
454
  """
453
455
  Check if Redis is connected.
454
-
456
+
455
457
  Returns:
456
458
  True if Redis is connected, False otherwise
457
459
  """
miso_client/errors.py CHANGED
@@ -7,11 +7,13 @@ This module defines custom exceptions for the MisoClient SDK.
7
7
 
8
8
  class MisoClientError(Exception):
9
9
  """Base exception for MisoClient SDK errors."""
10
-
11
- def __init__(self, message: str, status_code: int | None = None, error_body: dict | None = None):
10
+
11
+ def __init__(
12
+ self, message: str, status_code: int | None = None, error_body: dict | None = None
13
+ ):
12
14
  """
13
15
  Initialize MisoClient error.
14
-
16
+
15
17
  Args:
16
18
  message: Error message
17
19
  status_code: HTTP status code if applicable
@@ -25,20 +27,23 @@ class MisoClientError(Exception):
25
27
 
26
28
  class AuthenticationError(MisoClientError):
27
29
  """Raised when authentication fails."""
30
+
28
31
  pass
29
32
 
30
33
 
31
34
  class AuthorizationError(MisoClientError):
32
35
  """Raised when authorization check fails."""
36
+
33
37
  pass
34
38
 
35
39
 
36
40
  class ConnectionError(MisoClientError):
37
41
  """Raised when connection to controller or Redis fails."""
42
+
38
43
  pass
39
44
 
40
45
 
41
46
  class ConfigurationError(MisoClientError):
42
47
  """Raised when configuration is invalid."""
43
- pass
44
48
 
49
+ pass