mdb-engine 0.1.6__py3-none-any.whl → 0.4.12__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.
Files changed (92) hide show
  1. mdb_engine/__init__.py +116 -11
  2. mdb_engine/auth/ARCHITECTURE.md +112 -0
  3. mdb_engine/auth/README.md +654 -11
  4. mdb_engine/auth/__init__.py +136 -29
  5. mdb_engine/auth/audit.py +592 -0
  6. mdb_engine/auth/base.py +252 -0
  7. mdb_engine/auth/casbin_factory.py +265 -70
  8. mdb_engine/auth/config_defaults.py +5 -5
  9. mdb_engine/auth/config_helpers.py +19 -18
  10. mdb_engine/auth/cookie_utils.py +12 -16
  11. mdb_engine/auth/csrf.py +483 -0
  12. mdb_engine/auth/decorators.py +10 -16
  13. mdb_engine/auth/dependencies.py +69 -71
  14. mdb_engine/auth/helpers.py +3 -3
  15. mdb_engine/auth/integration.py +61 -88
  16. mdb_engine/auth/jwt.py +11 -15
  17. mdb_engine/auth/middleware.py +79 -35
  18. mdb_engine/auth/oso_factory.py +21 -41
  19. mdb_engine/auth/provider.py +270 -171
  20. mdb_engine/auth/rate_limiter.py +505 -0
  21. mdb_engine/auth/restrictions.py +21 -36
  22. mdb_engine/auth/session_manager.py +24 -41
  23. mdb_engine/auth/shared_middleware.py +977 -0
  24. mdb_engine/auth/shared_users.py +775 -0
  25. mdb_engine/auth/token_lifecycle.py +10 -12
  26. mdb_engine/auth/token_store.py +17 -32
  27. mdb_engine/auth/users.py +99 -159
  28. mdb_engine/auth/utils.py +236 -42
  29. mdb_engine/cli/commands/generate.py +546 -10
  30. mdb_engine/cli/commands/validate.py +3 -7
  31. mdb_engine/cli/utils.py +7 -7
  32. mdb_engine/config.py +13 -28
  33. mdb_engine/constants.py +65 -0
  34. mdb_engine/core/README.md +117 -6
  35. mdb_engine/core/__init__.py +39 -7
  36. mdb_engine/core/app_registration.py +31 -50
  37. mdb_engine/core/app_secrets.py +289 -0
  38. mdb_engine/core/connection.py +20 -12
  39. mdb_engine/core/encryption.py +222 -0
  40. mdb_engine/core/engine.py +2862 -115
  41. mdb_engine/core/index_management.py +12 -16
  42. mdb_engine/core/manifest.py +628 -204
  43. mdb_engine/core/ray_integration.py +436 -0
  44. mdb_engine/core/seeding.py +13 -21
  45. mdb_engine/core/service_initialization.py +20 -30
  46. mdb_engine/core/types.py +40 -43
  47. mdb_engine/database/README.md +140 -17
  48. mdb_engine/database/__init__.py +17 -6
  49. mdb_engine/database/abstraction.py +37 -50
  50. mdb_engine/database/connection.py +51 -30
  51. mdb_engine/database/query_validator.py +367 -0
  52. mdb_engine/database/resource_limiter.py +204 -0
  53. mdb_engine/database/scoped_wrapper.py +747 -237
  54. mdb_engine/dependencies.py +427 -0
  55. mdb_engine/di/__init__.py +34 -0
  56. mdb_engine/di/container.py +247 -0
  57. mdb_engine/di/providers.py +206 -0
  58. mdb_engine/di/scopes.py +139 -0
  59. mdb_engine/embeddings/README.md +54 -24
  60. mdb_engine/embeddings/__init__.py +31 -24
  61. mdb_engine/embeddings/dependencies.py +38 -155
  62. mdb_engine/embeddings/service.py +78 -75
  63. mdb_engine/exceptions.py +104 -12
  64. mdb_engine/indexes/README.md +30 -13
  65. mdb_engine/indexes/__init__.py +1 -0
  66. mdb_engine/indexes/helpers.py +11 -11
  67. mdb_engine/indexes/manager.py +59 -123
  68. mdb_engine/memory/README.md +95 -4
  69. mdb_engine/memory/__init__.py +1 -2
  70. mdb_engine/memory/service.py +363 -1168
  71. mdb_engine/observability/README.md +4 -2
  72. mdb_engine/observability/__init__.py +26 -9
  73. mdb_engine/observability/health.py +17 -17
  74. mdb_engine/observability/logging.py +10 -10
  75. mdb_engine/observability/metrics.py +40 -19
  76. mdb_engine/repositories/__init__.py +34 -0
  77. mdb_engine/repositories/base.py +325 -0
  78. mdb_engine/repositories/mongo.py +233 -0
  79. mdb_engine/repositories/unit_of_work.py +166 -0
  80. mdb_engine/routing/README.md +1 -1
  81. mdb_engine/routing/__init__.py +1 -3
  82. mdb_engine/routing/websockets.py +41 -75
  83. mdb_engine/utils/__init__.py +3 -1
  84. mdb_engine/utils/mongo.py +117 -0
  85. mdb_engine-0.4.12.dist-info/METADATA +492 -0
  86. mdb_engine-0.4.12.dist-info/RECORD +97 -0
  87. {mdb_engine-0.1.6.dist-info → mdb_engine-0.4.12.dist-info}/WHEEL +1 -1
  88. mdb_engine-0.1.6.dist-info/METADATA +0 -213
  89. mdb_engine-0.1.6.dist-info/RECORD +0 -75
  90. {mdb_engine-0.1.6.dist-info → mdb_engine-0.4.12.dist-info}/entry_points.txt +0 -0
  91. {mdb_engine-0.1.6.dist-info → mdb_engine-0.4.12.dist-info}/licenses/LICENSE +0 -0
  92. {mdb_engine-0.1.6.dist-info → mdb_engine-0.4.12.dist-info}/top_level.txt +0 -0
@@ -8,13 +8,16 @@ This module is part of MDB_ENGINE - MongoDB Engine.
8
8
 
9
9
  import logging
10
10
  from datetime import datetime, timedelta
11
- from typing import Any, Dict, List, Optional
11
+ from typing import Any
12
12
 
13
13
  from bson.objectid import ObjectId
14
14
 
15
15
  try:
16
- from pymongo.errors import (ConnectionFailure, OperationFailure,
17
- ServerSelectionTimeoutError)
16
+ from pymongo.errors import (
17
+ ConnectionFailure,
18
+ OperationFailure,
19
+ ServerSelectionTimeoutError,
20
+ )
18
21
  except ImportError:
19
22
  ConnectionFailure = Exception
20
23
  OperationFailure = Exception
@@ -93,10 +96,10 @@ class SessionManager:
93
96
  user_id: str,
94
97
  device_id: str,
95
98
  refresh_jti: str,
96
- device_info: Optional[Dict[str, Any]] = None,
97
- ip_address: Optional[str] = None,
98
- session_fingerprint: Optional[str] = None,
99
- ) -> Optional[Dict[str, Any]]:
99
+ device_info: dict[str, Any] | None = None,
100
+ ip_address: str | None = None,
101
+ session_fingerprint: str | None = None,
102
+ ) -> dict[str, Any] | None:
100
103
  """
101
104
  Create a new user session.
102
105
 
@@ -120,9 +123,7 @@ class SessionManager:
120
123
  # Remove oldest inactive session
121
124
  await self.cleanup_inactive_sessions(user_id)
122
125
  # Check again
123
- active_sessions = await self.get_user_sessions(
124
- user_id, active_only=True
125
- )
126
+ active_sessions = await self.get_user_sessions(user_id, active_only=True)
126
127
  if len(active_sessions) >= self.max_sessions:
127
128
  # Force remove oldest session
128
129
  if active_sessions:
@@ -168,13 +169,11 @@ class SessionManager:
168
169
  ValueError,
169
170
  TypeError,
170
171
  ) as e:
171
- logger.error(
172
- f"Error creating session for user {user_id}: {e}", exc_info=True
173
- )
172
+ logger.error(f"Error creating session for user {user_id}: {e}", exc_info=True)
174
173
  return None
175
174
 
176
175
  async def update_session_activity(
177
- self, refresh_jti: str, ip_address: Optional[str] = None
176
+ self, refresh_jti: str, ip_address: str | None = None
178
177
  ) -> bool:
179
178
  """
180
179
  Update session last_seen timestamp (activity tracking).
@@ -205,14 +204,10 @@ class SessionManager:
205
204
  ValueError,
206
205
  TypeError,
207
206
  ) as e:
208
- logger.error(
209
- f"Error updating session activity for {refresh_jti}: {e}", exc_info=True
210
- )
207
+ logger.error(f"Error updating session activity for {refresh_jti}: {e}", exc_info=True)
211
208
  return False
212
209
 
213
- async def get_session_by_refresh_token(
214
- self, refresh_jti: str
215
- ) -> Optional[Dict[str, Any]]:
210
+ async def get_session_by_refresh_token(self, refresh_jti: str) -> dict[str, Any] | None:
216
211
  """
217
212
  Get session by refresh token JWT ID.
218
213
 
@@ -223,9 +218,7 @@ class SessionManager:
223
218
  Session document or None if not found
224
219
  """
225
220
  try:
226
- session = await self.collection.find_one(
227
- {"refresh_jti": refresh_jti, "active": True}
228
- )
221
+ session = await self.collection.find_one({"refresh_jti": refresh_jti, "active": True})
229
222
  return session
230
223
  except (
231
224
  OperationFailure,
@@ -241,7 +234,7 @@ class SessionManager:
241
234
  return None
242
235
 
243
236
  async def validate_session_fingerprint(
244
- self, refresh_jti: str, current_fingerprint: str, strict: Optional[bool] = None
237
+ self, refresh_jti: str, current_fingerprint: str, strict: bool | None = None
245
238
  ) -> bool:
246
239
  """
247
240
  Validate session fingerprint matches stored fingerprint.
@@ -267,9 +260,7 @@ class SessionManager:
267
260
  stored_fingerprint = session.get("session_fingerprint")
268
261
 
269
262
  if not stored_fingerprint:
270
- strict_mode = (
271
- strict if strict is not None else self.fingerprinting_strict
272
- )
263
+ strict_mode = strict if strict is not None else self.fingerprinting_strict
273
264
  return not strict_mode
274
265
 
275
266
  return stored_fingerprint == current_fingerprint
@@ -297,7 +288,7 @@ class SessionManager:
297
288
 
298
289
  async def get_user_sessions(
299
290
  self, user_id: str, active_only: bool = True
300
- ) -> List[Dict[str, Any]]:
291
+ ) -> list[dict[str, Any]]:
301
292
  """
302
293
  Get all sessions for a user.
303
294
 
@@ -313,9 +304,7 @@ class SessionManager:
313
304
  if active_only:
314
305
  query["active"] = True
315
306
 
316
- sessions = (
317
- await self.collection.find(query).sort("last_seen", -1).to_list(None)
318
- )
307
+ sessions = await self.collection.find(query).sort("last_seen", -1).to_list(None)
319
308
  return sessions
320
309
  except (
321
310
  OperationFailure,
@@ -324,9 +313,7 @@ class SessionManager:
324
313
  ValueError,
325
314
  TypeError,
326
315
  ) as e:
327
- logger.error(
328
- f"Error getting sessions for user {user_id}: {e}", exc_info=True
329
- )
316
+ logger.error(f"Error getting sessions for user {user_id}: {e}", exc_info=True)
330
317
  return []
331
318
 
332
319
  async def revoke_session(self, session_id: Any) -> bool:
@@ -367,9 +354,7 @@ class SessionManager:
367
354
  logger.error(f"Error revoking session {session_id}: {e}", exc_info=True)
368
355
  return False
369
356
 
370
- async def revoke_user_sessions(
371
- self, user_id: str, exclude_device_id: Optional[str] = None
372
- ) -> int:
357
+ async def revoke_user_sessions(self, user_id: str, exclude_device_id: str | None = None) -> int:
373
358
  """
374
359
  Revoke all sessions for a user.
375
360
 
@@ -400,12 +385,10 @@ class SessionManager:
400
385
  ValueError,
401
386
  TypeError,
402
387
  ) as e:
403
- logger.error(
404
- f"Error revoking sessions for user {user_id}: {e}", exc_info=True
405
- )
388
+ logger.error(f"Error revoking sessions for user {user_id}: {e}", exc_info=True)
406
389
  return 0
407
390
 
408
- async def cleanup_inactive_sessions(self, user_id: Optional[str] = None) -> int:
391
+ async def cleanup_inactive_sessions(self, user_id: str | None = None) -> int:
409
392
  """
410
393
  Clean up inactive sessions (beyond inactivity timeout).
411
394