abs-auth-rbac-core 0.1.18__py3-none-any.whl → 0.1.19__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 abs-auth-rbac-core might be problematic. Click here for more details.

@@ -23,3 +23,12 @@ class GovCasbinRule(BaseCasbinRule):
23
23
  self.v3 = v3
24
24
  self.v4 = v4
25
25
  self.v5 = v5
26
+
27
+
28
+ def __str__(self):
29
+ arr = [self.ptype]
30
+ for v in (self.v0, self.v1, self.v2, self.v3):
31
+ if v is None:
32
+ break
33
+ arr.append(v)
34
+ return ", ".join(arr)
@@ -155,12 +155,11 @@ class RBACService:
155
155
  """
156
156
  with self.db() as session:
157
157
  try:
158
- if hasattr(permissions,'model_dump'):
159
- add_permissions = [Permission(**permission.model_dump()) for permission in permissions]
158
+ if hasattr(permissions[0], "model_dump"):
159
+ permission_objs = [Permission(**permission.model_dump()) for permission in permissions]
160
160
  else:
161
- add_permissions = [Permission(**permission) for permission in permissions]
162
-
163
- session.bulk_save_objects(add_permissions)
161
+ permission_objs = [Permission(**permission) for permission in permissions]
162
+ session.bulk_save_objects(permission_objs)
164
163
  session.commit()
165
164
  return add_permissions
166
165
  except Exception as e:
@@ -43,6 +43,7 @@ class PermissionAction(str, Enum):
43
43
  EDIT = "EDIT"
44
44
  DELETE = "DELETE"
45
45
  MANAGE = "MANAGE"
46
+ DOWNLOAD = "DOWNLOAD"
46
47
  CONFIGURE_IMPORTANCE = "CONFIGURE_IMPORTANCE"
47
48
  VIEW_FIELD_RESULTS = "VIEW_FIELD_RESULTS"
48
49
  UPDATE_STATUS = "UPDATE_STATUS"
@@ -163,12 +164,23 @@ class PermissionModule(str, Enum):
163
164
  AI_EMS="AI_EMS"
164
165
  ENTITY_MANAGER="ENTITY_MANAGER"
165
166
  ASL = "ASL"
167
+ EDS = "EDS"
166
168
 
167
169
 
168
170
 
169
171
  class PermissionResource(str, Enum):
172
+ DASHBOARD = "DASHBOARDS"
170
173
  WORKFORCE_AGENT = "WORKFORCE_AGENT"
171
174
  EPAR = "EPAR"
175
+ EPARS = "EPARS"
176
+ OCFO = "OCFO"
177
+ EDS_ASSISTANT = "EDS_ASSISTANT"
178
+ REPORTS = "REPORTS"
179
+ WORKFLOW = "WORKFLOW"
180
+ FEEDBACK = "FEEDBACK"
181
+ OCFO_TUTORIALS = "OCFO_TUTORIALS"
182
+ EPAR_TUTORIALS = "EPAR_TUTORIALS"
183
+ RECENT_REVIEW_EPARS = "RECENT_REVIEW_EPARS"
172
184
  EPAR_PROTRACK_INTEGRATION = "EPAR_PROTRACK_INTEGRATION"
173
185
  EPAR_DASHBOARD = "EPAR_DASHBOARD"
174
186
  NOTIFICATIONS = "NOTIFICATIONS"
@@ -247,6 +259,104 @@ class PermissionData(NamedTuple):
247
259
 
248
260
 
249
261
  class PermissionConstants:
262
+ EDS_DASHBOARD_VIEW = PermissionData(
263
+ name="View EDS Dashboard",
264
+ description="View EDS Dashboard",
265
+ module=PermissionModule.EDS,
266
+ resource=PermissionResource.DASHBOARD,
267
+ action=PermissionAction.VIEW,
268
+ )
269
+ EDS_EPARS_VIEW = PermissionData(
270
+ name="View EPARs",
271
+ description="View EPARs",
272
+ module=PermissionModule.EDS,
273
+ resource=PermissionResource.EPARS,
274
+ action=PermissionAction.VIEW,
275
+ )
276
+ EDS_OCFO_VIEW = PermissionData(
277
+ name="View OCFO",
278
+ description="View OCFO",
279
+ module=PermissionModule.EDS,
280
+ resource=PermissionResource.OCFO,
281
+ action=PermissionAction.VIEW,
282
+ )
283
+ EDS_EDS_ASSISTANT_VIEW = PermissionData(
284
+ name="View EDS Assistant",
285
+ description="View EDS Assistant",
286
+ module=PermissionModule.EDS,
287
+ resource=PermissionResource.EDS_ASSISTANT,
288
+ action=PermissionAction.VIEW,
289
+ )
290
+ EDS_REPORTS_VIEW = PermissionData(
291
+ name="View Reports",
292
+ description="View Reports",
293
+ module=PermissionModule.EDS,
294
+ resource=PermissionResource.REPORTS,
295
+ action=PermissionAction.VIEW,
296
+ )
297
+ EDS_EAPR_CREATE = PermissionData(
298
+ name="Create EPAR",
299
+ description="Create EPAR",
300
+ module=PermissionModule.EDS,
301
+ resource=PermissionResource.EPAR,
302
+ action=PermissionAction.CREATE,
303
+ )
304
+ EDS_EPAR_EDIT = PermissionData(
305
+ name="Edit EPAR",
306
+ description="Edit EPAR",
307
+ module=PermissionModule.EDS,
308
+ resource=PermissionResource.EPAR,
309
+ action=PermissionAction.EDIT,
310
+ )
311
+ EDS_EPAR_DOWNLOAD = PermissionData(
312
+ name="Download EPAR",
313
+ description="Download EPAR",
314
+ module=PermissionModule.EDS,
315
+ resource=PermissionResource.EPAR,
316
+ action=PermissionAction.DOWNLOAD,
317
+ )
318
+ EDS_EPAR_VIEW = PermissionData(
319
+ name="View EPAR",
320
+ description="View EPAR",
321
+ module=PermissionModule.EDS,
322
+ resource=PermissionResource.EPAR,
323
+ action=PermissionAction.VIEW,
324
+ )
325
+ EDS_WORKFLOW_VIEW = PermissionData(
326
+ name="View Workflow",
327
+ description="View Workflow",
328
+ module=PermissionModule.EDS,
329
+ resource=PermissionResource.WORKFLOW,
330
+ action=PermissionAction.VIEW,
331
+ )
332
+ EDS_FEEDBACK_VIEW = PermissionData(
333
+ name="View Feedback",
334
+ description="View Feedback",
335
+ module=PermissionModule.EDS,
336
+ resource=PermissionResource.FEEDBACK,
337
+ action=PermissionAction.VIEW,
338
+ )
339
+ EDS_OCFO_TUTORIALS_VIEW = PermissionData(
340
+ name="View OCFO Tutorials",
341
+ description="View OCFO Tutorials",
342
+ module=PermissionModule.EDS,
343
+ resource=PermissionResource.OCFO_TUTORIALS,
344
+ action=PermissionAction.VIEW,
345
+ )
346
+ EDS_EPAR_TUTORIALS_VIEW = PermissionData(
347
+ name="View EPAR Tutorials",
348
+ description="View EPAR Tutorials",
349
+ module=PermissionModule.EDS,
350
+ resource=PermissionResource.EPAR_TUTORIALS,
351
+ action=PermissionAction.VIEW,
352
+ )
353
+ EDS_RECENT_REVIEW_EPARS_VIEW = PermissionData(
354
+ name="View Recent Review EPARs",
355
+ description="View Recent Review EPARs",
356
+ module=PermissionModule.EDS,
357
+ resource=PermissionResource.RECENT_REVIEW_EPARS,
358
+ action=PermissionAction.VIEW,
359
+ )
250
360
  VIEW_BILLING = PermissionData(
251
361
  name="View Billing",
252
362
  description="View Billing accounts",
@@ -0,0 +1,761 @@
1
+ Metadata-Version: 2.3
2
+ Name: abs-auth-rbac-core
3
+ Version: 0.1.19
4
+ Summary: RBAC and Auth core utilities including JWT token management.
5
+ License: MIT
6
+ Author: AutoBridgeSystems
7
+ Author-email: info@autobridgesystems.com
8
+ Requires-Python: >=3.13,<4.0
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Requires-Dist: abs-exception-core (>=0.1.0,<0.2.0)
13
+ Requires-Dist: casbin (>=1.41.0,<2.0.0)
14
+ Requires-Dist: casbin-redis-watcher (>=1.3.0,<2.0.0)
15
+ Requires-Dist: casbin-sqlalchemy-adapter (>=1.4.0,<2.0.0)
16
+ Requires-Dist: fastapi[standard] (>=0.115.12,<0.116.0)
17
+ Requires-Dist: passlib (>=1.7.4,<2.0.0)
18
+ Requires-Dist: psycopg2-binary (>=2.9.10,<3.0.0)
19
+ Requires-Dist: pyjwt (>=2.10.1,<3.0.0)
20
+ Requires-Dist: sqlalchemy (>=2.0.40,<3.0.0)
21
+ Description-Content-Type: text/markdown
22
+
23
+ # ABS Auth RBAC Core
24
+
25
+ A comprehensive authentication and Role-Based Access Control (RBAC) package for FastAPI applications. This package provides robust JWT-based authentication and flexible role-based permission management using Casbin with Redis support for real-time policy updates.
26
+
27
+ ## Features
28
+
29
+ - **JWT-based Authentication**: Secure token-based authentication with customizable expiration
30
+ - **Password Hashing**: Secure password storage using bcrypt
31
+ - **Role-Based Access Control (RBAC)**: Flexible permission management using Casbin
32
+ - **Real-time Policy Updates**: Redis integration for live policy synchronization
33
+ - **User-Role Management**: Dynamic role assignment and revocation
34
+ - **Permission Enforcement**: Decorator-based permission checking
35
+ - **Middleware Integration**: Seamless FastAPI middleware integration
36
+ - **Comprehensive Error Handling**: Built-in exception handling for security scenarios
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ pip install abs-auth-rbac-core
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ ### 1. Basic Setup
47
+
48
+ ```python
49
+ from abs_auth_rbac_core.auth.jwt_functions import JWTFunctions
50
+ from abs_auth_rbac_core.rbac import RBACService
51
+ import os
52
+
53
+ # Initialize JWT functions
54
+ jwt_functions = JWTFunctions(
55
+ secret_key=os.getenv("JWT_SECRET_KEY"),
56
+ algorithm=os.getenv("JWT_ALGORITHM", "HS256"),
57
+ expire_minutes=int(os.getenv("JWT_EXPIRE_MINUTES", "60"))
58
+ )
59
+
60
+ # Initialize RBAC service with database session
61
+ rbac_service = RBACService(
62
+ session=your_db_session,
63
+ redis_config=RedisWatcherSchema(
64
+ host=os.getenv("REDIS_HOST"),
65
+ port=int(os.getenv("REDIS_PORT", "6379")),
66
+ channel=os.getenv("REDIS_CHANNEL", "casbin_policy_updates"),
67
+ password=os.getenv("REDIS_PASSWORD"),
68
+ ssl=os.getenv("REDIS_SSL", "false").lower() == "true"
69
+ )
70
+ )
71
+ ```
72
+
73
+ ### 2. Authentication Setup
74
+
75
+ The auth middleware can be implemented in two ways:
76
+
77
+ #### Option 1: Using the Package Middleware (Recommended)
78
+
79
+ The package middleware automatically handles JWT token validation and sets the user in the request state:
80
+
81
+ ```python
82
+ from abs_auth_rbac_core.auth.middleware import auth_middleware
83
+
84
+ # Create authentication middleware
85
+ auth_middleware = auth_middleware(
86
+ db_session=your_db_session,
87
+ jwt_secret_key=os.getenv("JWT_SECRET_KEY"),
88
+ jwt_algorithm=os.getenv("JWT_ALGORITHM", "HS256")
89
+ )
90
+
91
+ # Apply to specific routers (recommended approach)
92
+ app.include_router(
93
+ protected_router,
94
+ dependencies=[Depends(auth_middleware)]
95
+ )
96
+
97
+ # Public routes (no middleware)
98
+ app.include_router(public_router)
99
+ ```
100
+
101
+ **How it works:**
102
+ 1. The middleware validates the JWT token from the Authorization header
103
+ 2. Extracts the user UUID from the token payload
104
+ 3. Fetches the user from the database using the UUID
105
+ 4. **Sets the user object in `request.state.user`**
106
+ 5. Returns the user object for use in route handlers
107
+
108
+ **Accessing the user in routes:**
109
+ ```python
110
+ @router.get("/profile")
111
+ async def get_profile(request: Request):
112
+ # User is automatically available in request.state.user
113
+ user = request.state.user
114
+ return {"user_id": user.uuid, "email": user.email}
115
+ ```
116
+
117
+ #### Option 2: Custom Authentication Function
118
+
119
+ ```python
120
+ from abs_auth_rbac_core.auth import JWTFunctions
121
+ from fastapi import Security, HTTPAuthorizationCredentials
122
+ from fastapi.security import HTTPBearer
123
+ from abs_exception_core.exceptions import UnauthorizedError
124
+
125
+ # Create security scheme
126
+ security = HTTPBearer(auto_error=False)
127
+ jwt_functions = JWTFunctions(
128
+ secret_key=os.getenv("JWT_SECRET_KEY"),
129
+ algorithm=os.getenv("JWT_ALGORITHM", "HS256"),
130
+ expire_minutes=int(os.getenv("JWT_EXPIRE_MINUTES", "60"))
131
+ )
132
+
133
+ async def get_current_user(
134
+ credentials: HTTPAuthorizationCredentials = Security(security),
135
+ ) -> Dict:
136
+ try:
137
+ if not credentials:
138
+ raise UnauthorizedError(detail="No authorization token provided")
139
+
140
+ token = credentials.credentials
141
+ # Remove 'Bearer ' prefix if present
142
+ if token.lower().startswith("bearer "):
143
+ token = token[7:]
144
+
145
+ decoded_token = jwt_functions.decode_jwt(token)
146
+ if not decoded_token:
147
+ raise UnauthorizedError(detail="Invalid or expired token")
148
+
149
+ return decoded_token
150
+ except Exception as e:
151
+ raise UnauthorizedError(detail=str(e))
152
+
153
+ # Use in individual routes
154
+ @app.get("/protected")
155
+ async def protected_route(current_user: dict = Depends(get_current_user)):
156
+ return {"message": f"Hello {current_user.get('name')}"}
157
+ ```
158
+
159
+ ### 3. RBAC Operations
160
+
161
+ ```python
162
+ # Create a role with permissions
163
+ role = rbac_service.create_role(
164
+ name="admin",
165
+ description="Administrator role with full access",
166
+ permission_ids=["permission_uuid1", "permission_uuid2"]
167
+ )
168
+
169
+ # Assign roles to user
170
+ rbac_service.bulk_assign_roles_to_user(
171
+ user_uuid="user_uuid",
172
+ role_uuids=["role_uuid1", "role_uuid2"]
173
+ )
174
+
175
+ # Check user permissions
176
+ has_permission = rbac_service.check_permission(
177
+ user_uuid="user_uuid",
178
+ resource="USER_MANAGEMENT",
179
+ action="VIEW",
180
+ module="USER_MANAGEMENT"
181
+ )
182
+
183
+ # Get user permissions
184
+ user_permissions = rbac_service.get_user_permissions(user_uuid="user_uuid")
185
+ user_roles = rbac_service.get_user_roles(user_uuid="user_uuid")
186
+ ```
187
+
188
+ ## Core Components
189
+
190
+ ### Authentication (`auth/`)
191
+ - `jwt_functions.py`: JWT token management and password hashing
192
+ - `middleware.py`: Authentication middleware for FastAPI
193
+ - `auth_functions.py`: Core authentication functions
194
+
195
+ ### RBAC (`rbac/`)
196
+ - `service.py`: Main RBAC service with role and permission management
197
+ - `decorator.py`: Decorators for permission checking
198
+
199
+ ### Models (`models/`)
200
+ - `user.py`: User model
201
+ - `roles.py`: Role model
202
+ - `permissions.py`: Permission model
203
+ - `user_role.py`: User-Role association model
204
+ - `role_permission.py`: Role-Permission association model
205
+ - `rbac_model.py`: Base RBAC model
206
+ - `base_model.py`: Base model with common fields
207
+
208
+ ### Utilities (`util/`)
209
+ - `permission_constants.py`: Predefined permission constants and enums
210
+
211
+ ## Complete Implementation Example
212
+
213
+ ### 1. Dependency Injection Setup
214
+
215
+ ```python
216
+ from dependency_injector import containers, providers
217
+ from abs_auth_rbac_core.auth.middleware import auth_middleware
218
+ from abs_auth_rbac_core.rbac import RBACService
219
+ from abs_auth_rbac_core.util.permission_constants import (
220
+ PermissionAction,
221
+ PermissionModule,
222
+ PermissionResource
223
+ )
224
+
225
+ class Container(containers.DeclarativeContainer):
226
+ # Configure wiring for dependency injection
227
+ wiring_config = containers.WiringConfiguration(
228
+ modules=[
229
+ "src.api.auth_route",
230
+ "src.api.endpoints.rbac.permission_route",
231
+ "src.api.endpoints.rbac.role_route",
232
+ "src.api.endpoints.rbac.users_route",
233
+ # Add other modules that need dependency injection
234
+ ]
235
+ )
236
+
237
+ # Database session provider
238
+ db_session = providers.Factory(your_db_session_factory)
239
+
240
+ # RBAC service provider
241
+ rbac_service = providers.Singleton(
242
+ RBACService,
243
+ session=db_session,
244
+ redis_config=RedisWatcherSchema(
245
+ host=os.getenv("REDIS_HOST"),
246
+ port=int(os.getenv("REDIS_PORT", "6379")),
247
+ channel=os.getenv("REDIS_CHANNEL", "casbin_policy_updates"),
248
+ password=os.getenv("REDIS_PASSWORD"),
249
+ ssl=os.getenv("REDIS_SSL", "false").lower() == "true"
250
+ )
251
+ )
252
+
253
+ # Auth middleware provider
254
+ get_auth_middleware = providers.Factory(
255
+ auth_middleware,
256
+ db_session=db_session,
257
+ jwt_secret_key=os.getenv("JWT_SECRET_KEY"),
258
+ jwt_algorithm=os.getenv("JWT_ALGORITHM", "HS256")
259
+ )
260
+
261
+ # Initialize container
262
+ container = Container()
263
+ app.container = container
264
+ ```
265
+
266
+ ### 2. Complete Application Setup
267
+
268
+ ```python
269
+ from fastapi import FastAPI, Depends
270
+ from dependency_injector.wiring import Provide, inject
271
+ from src.core.container import Container
272
+
273
+ @singleton
274
+ class CreateApp:
275
+ def __init__(self):
276
+ self.container = Container()
277
+ self.db = self.container.db()
278
+ # Get the auth middleware factory
279
+ self.auth_middleware = self.container.get_auth_middleware()
280
+
281
+ self.app = FastAPI(
282
+ title="Your Service",
283
+ description="Service Description",
284
+ version="0.0.1"
285
+ )
286
+
287
+ # Apply CORS middleware
288
+ self.app.add_middleware(
289
+ CORSMiddleware,
290
+ allow_origins=[str(origin) for origin in configs.BACKEND_CORS_ORIGINS],
291
+ allow_credentials=True,
292
+ allow_methods=["*"],
293
+ allow_headers=["*"],
294
+ )
295
+
296
+ # Public routes (no authentication required)
297
+ self.app.include_router(auth_router, tags=["Auth"])
298
+ self.app.include_router(public_router_v1)
299
+
300
+ # Protected routes (authentication required)
301
+ self.app.include_router(
302
+ router_v1,
303
+ dependencies=[Depends(self.auth_middleware)]
304
+ )
305
+
306
+ # Register exception handlers
307
+ register_exception_handlers(self.app)
308
+
309
+ # Initialize application
310
+ application = CreateApp()
311
+ app = application.app
312
+ ```
313
+
314
+ ### 3. Route Implementation with Permissions
315
+
316
+ ```python
317
+ from fastapi import APIRouter, Depends, Request
318
+ from dependency_injector.wiring import Provide, inject
319
+ from abs_auth_rbac_core.rbac import rbac_require_permission
320
+ from abs_auth_rbac_core.util.permission_constants import (
321
+ PermissionAction,
322
+ PermissionModule,
323
+ PermissionResource
324
+ )
325
+
326
+ # Protected router (requires authentication)
327
+ router = APIRouter(prefix="/users")
328
+
329
+ # Public router (no authentication required)
330
+ public_router = APIRouter(prefix="/users")
331
+
332
+ # Public route example (no authentication or permissions required)
333
+ @public_router.post("/all", response_model=FindUserResult)
334
+ @inject
335
+ async def get_user_list(
336
+ request: Request,
337
+ find_query: FindUser = Body(...),
338
+ rbac_service: RBACService = Depends(Provide[Container.rbac_service]),
339
+ service: UserService = Depends(Provide[Container.user_service]),
340
+ ):
341
+ """Get the list of users with filtering, sorting and pagination"""
342
+ find_query.searchable_fields = find_query.searchable_fields or ["name"]
343
+ users = service.get_list(schema=find_query)
344
+ return users
345
+
346
+ # Protected route with permission check
347
+ @router.get("/{user_id}", response_model=UserProfile)
348
+ @inject
349
+ @rbac_require_permission(
350
+ f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.USER_MANAGEMENT.value}:{PermissionAction.VIEW.value}"
351
+ )
352
+ async def get_user(
353
+ user_id: int,
354
+ request: Request,
355
+ service: UserService = Depends(Provide[Container.user_service]),
356
+ rbac_service: RBACService = Depends(Provide[Container.rbac_service]),
357
+ ):
358
+ """Get user profile with permissions and roles"""
359
+ return service.get_user_profile("id", user_id, rbac_service)
360
+ ```
361
+
362
+ **How the RBAC decorator works:**
363
+ 1. The `@rbac_require_permission` decorator automatically extracts the user from `request.state.user`
364
+ 2. Gets the user's UUID: `current_user_uuid = request.state.user.uuid`
365
+ 3. Checks if the user has the required permissions using the RBAC service
366
+ 4. If permission is denied, raises `PermissionDeniedError`
367
+ 5. If permission is granted, the route handler executes normally
368
+
369
+ **Important:** The `request: Request` parameter is required in routes that use the `@rbac_require_permission` decorator because it needs access to `request.state.user`.
370
+
371
+ ### Authentication Flow Overview
372
+
373
+ ```
374
+ 1. Client sends request with Authorization header
375
+ Authorization: Bearer <jwt_token>
376
+
377
+ 2. Auth middleware intercepts the request
378
+ ├── Validates JWT token
379
+ ├── Extracts user UUID from token
380
+ ├── Fetches user from database
381
+ └── Sets user in request.state.user
382
+
383
+ 3. RBAC decorator checks permissions
384
+ ├── Gets user UUID from request.state.user
385
+ ├── Checks permissions against Casbin policies
386
+ └── Allows/denies access based on permissions
387
+
388
+ 4. Route handler executes (if permissions granted)
389
+ └── Can access user via request.state.user
390
+ ```
391
+
392
+ ### Accessing Current User
393
+
394
+ #### In Routes with RBAC Decorator
395
+ ```python
396
+ @router.get("/my-profile")
397
+ @inject
398
+ @rbac_require_permission(
399
+ f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.USER_MANAGEMENT.value}:{PermissionAction.VIEW.value}"
400
+ )
401
+ async def get_my_profile(
402
+ request: Request,
403
+ rbac_service: RBACService = Depends(Provide[Container.rbac_service]),
404
+ ):
405
+ # Access current user from request state
406
+ current_user = request.state.user
407
+ return service.get_user_profile("uuid", current_user.uuid, rbac_service)
408
+ ```
409
+
410
+ #### In Routes with Custom Auth Function
411
+ ```python
412
+ @router.get("/profile")
413
+ async def get_profile(current_user: dict = Depends(get_current_user)):
414
+ # current_user is the decoded JWT payload
415
+ return {"user_id": current_user["uuid"], "email": current_user["email"]}
416
+ ```
417
+
418
+ #### In Service Methods
419
+ ```python
420
+ def some_service_method(self, user_uuid: str, rbac_service: RBACService):
421
+ # Get user permissions
422
+ permissions = rbac_service.get_user_permissions(user_uuid=user_uuid)
423
+ # Get user roles
424
+ roles = rbac_service.get_user_roles(user_uuid=user_uuid)
425
+ return {"permissions": permissions, "roles": roles}
426
+ ```
427
+
428
+ @router.post("/create")
429
+ @inject
430
+ @rbac_require_permission(
431
+ f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.USER_MANAGEMENT.value}:{PermissionAction.CREATE.value}"
432
+ )
433
+ async def create_user(
434
+ user: CreateUserWithRoles,
435
+ request: Request,
436
+ rbac_service: RBACService = Depends(Provide[Container.rbac_service]),
437
+ ):
438
+ """Create a new user with roles"""
439
+ new_user = service.add_user(user)
440
+
441
+ # Assign roles if provided
442
+ if user.role_uuids and len(user.role_uuids) > 0 and new_user.uuid:
443
+ rbac_service.bulk_assign_roles_to_user(
444
+ user_uuid=new_user.uuid,
445
+ role_uuids=user.role_uuids,
446
+ )
447
+ return new_user
448
+
449
+ @router.patch("/{user_id}")
450
+ @inject
451
+ @rbac_require_permission(
452
+ f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.USER_MANAGEMENT.value}:{PermissionAction.EDIT.value}"
453
+ )
454
+ async def update_user(
455
+ user_id: int,
456
+ user: UpdateUserWithRoles,
457
+ request: Request,
458
+ rbac_service: RBACService = Depends(Provide[Container.rbac_service]),
459
+ ):
460
+ """Update user with new attributes and roles"""
461
+ return service.patch_user(user_id, user, rbac_service)
462
+
463
+ @router.delete("/{user_id}")
464
+ @inject
465
+ @rbac_require_permission(
466
+ f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.USER_MANAGEMENT.value}:{PermissionAction.DELETE.value}"
467
+ )
468
+ async def delete_user(
469
+ user_id: int,
470
+ request: Request,
471
+ rbac_service: RBACService = Depends(Provide[Container.rbac_service]),
472
+ ):
473
+ """Delete user"""
474
+ return service.remove_user(user_id, rbac_service)
475
+ ```
476
+
477
+ ### 3. Role and Permission Management
478
+
479
+ ```python
480
+ @router.get("/roles")
481
+ @inject
482
+ @rbac_require_permission(
483
+ f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.ROLE_MANAGEMENT.value}:{PermissionAction.VIEW.value}"
484
+ )
485
+ async def get_roles(
486
+ request: Request,
487
+ rbac_service: RBACService = Depends(Provide[Container.rbac_service]),
488
+ ):
489
+ """Get all roles"""
490
+ return rbac_service.list_roles()
491
+
492
+ @router.post("/roles")
493
+ @inject
494
+ @rbac_require_permission(
495
+ f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.ROLE_MANAGEMENT.value}:{PermissionAction.CREATE.value}"
496
+ )
497
+ async def create_role(
498
+ role: CreateRoleSchema,
499
+ request: Request,
500
+ rbac_service: RBACService = Depends(Provide[Container.rbac_service]),
501
+ ):
502
+ """Create a new role with permissions"""
503
+ return rbac_service.create_role(
504
+ name=role.name,
505
+ description=role.description,
506
+ permission_ids=role.permission_ids
507
+ )
508
+
509
+ @router.get("/user-permissions/{user_uuid}")
510
+ @inject
511
+ @rbac_require_permission([
512
+ f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.USER_MANAGEMENT.value}:{PermissionAction.VIEW.value}",
513
+ f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.ROLE_MANAGEMENT.value}:{PermissionAction.VIEW.value}"
514
+ ])
515
+ async def get_user_permissions(
516
+ user_uuid: str,
517
+ request: Request,
518
+ rbac_service: RBACService = Depends(Provide[Container.rbac_service]),
519
+ ):
520
+ """Get all permissions for a user"""
521
+ return rbac_service.get_user_permissions(user_uuid)
522
+ ```
523
+
524
+ ### 4. User Profile with Permissions
525
+
526
+ ```python
527
+ def get_user_profile(self, attr: str, value: any, rbac_service: RBACService) -> UserProfile:
528
+ """Get user profile with permissions and roles"""
529
+ user = self.user_repository.read_by_attr(attr, value, eager=True)
530
+
531
+ # Get user permissions and roles
532
+ permissions = rbac_service.get_user_permissions(user_uuid=user.uuid)
533
+ user_permissions = rbac_service.get_user_only_permissions(user_uuid=user.uuid)
534
+ roles = rbac_service.get_user_roles(user_uuid=user.uuid)
535
+
536
+ # Convert roles to response models
537
+ role_models = [UserRoleResponse.model_validate(role) for role in roles]
538
+
539
+ return UserProfile(
540
+ id=user.id,
541
+ uuid=user.uuid,
542
+ email=user.email,
543
+ name=user.name,
544
+ is_active=user.is_active,
545
+ last_login_at=user.last_login_at,
546
+ permissions=permissions,
547
+ user_permissions=user_permissions,
548
+ roles=role_models,
549
+ )
550
+ ```
551
+
552
+ ## Permission System
553
+
554
+ ### Permission Format
555
+ Permissions follow the format: `module:resource:action`
556
+
557
+ - **Module**: The system module (e.g., `USER_MANAGEMENT`, `EMAIL_PROCESS`)
558
+ - **Resource**: The specific resource within the module (e.g., `USER_MANAGEMENT`, `ROLE_MANAGEMENT`)
559
+ - **Action**: The action being performed (e.g., `VIEW`, `CREATE`, `EDIT`, `DELETE`)
560
+
561
+ ### Using Permission Constants
562
+
563
+ ```python
564
+ from abs_auth_rbac_core.util.permission_constants import (
565
+ PermissionAction,
566
+ PermissionModule,
567
+ PermissionResource,
568
+ PermissionConstants
569
+ )
570
+
571
+ # Using enums
572
+ permission_string = f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.USER_MANAGEMENT.value}:{PermissionAction.VIEW.value}"
573
+
574
+ # Using predefined constants
575
+ user_view_permission = PermissionConstants.RBAC_USER_MANAGEMENT_VIEW
576
+ permission_string = f"{user_view_permission.module}:{user_view_permission.resource}:{user_view_permission.action}"
577
+ ```
578
+
579
+ ### Multiple Permissions
580
+
581
+ ```python
582
+ @rbac_require_permission([
583
+ f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.USER_MANAGEMENT.value}:{PermissionAction.VIEW.value}",
584
+ f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.ROLE_MANAGEMENT.value}:{PermissionAction.VIEW.value}"
585
+ ])
586
+ async def get_user_with_roles():
587
+ # User needs both permissions to access this endpoint
588
+ pass
589
+ ```
590
+
591
+ ## Configuration
592
+
593
+ ### Environment Variables
594
+
595
+ ```bash
596
+ # JWT Configuration
597
+ JWT_SECRET_KEY=your-secret-key
598
+ JWT_ALGORITHM=HS256
599
+ JWT_ACCESS_TOKEN_EXPIRE_MINUTES=60
600
+ JWT_REFRESH_TOKEN_EXPIRE_MINUTES=1440
601
+
602
+ # Redis Configuration (for real-time policy updates)
603
+ REDIS_HOST=localhost
604
+ REDIS_PORT=6379
605
+ REDIS_PASSWORD=your-redis-password
606
+ REDIS_CHANNEL=casbin_policy_updates
607
+ REDIS_SSL=false
608
+
609
+ # Database Configuration
610
+ DATABASE_URI=postgresql://user:password@localhost/dbname
611
+ ```
612
+
613
+ ### Casbin Policy Configuration
614
+
615
+ The package uses a default policy configuration that supports:
616
+ - Role-based access control
617
+ - Resource-based permissions
618
+ - Module-based organization
619
+ - Super admin bypass
620
+
621
+ Policy format: `[role] [resource] [action] [module]`
622
+
623
+ ## Error Handling
624
+
625
+ The package includes comprehensive error handling:
626
+
627
+ ```python
628
+ from abs_exception_core.exceptions import (
629
+ UnauthorizedError,
630
+ PermissionDeniedError,
631
+ ValidationError,
632
+ DuplicatedError,
633
+ NotFoundError
634
+ )
635
+
636
+ # Handle authentication errors
637
+ try:
638
+ user = await auth_middleware(request)
639
+ except UnauthorizedError as e:
640
+ return {"error": "Authentication failed", "detail": str(e)}
641
+
642
+ # Handle permission errors
643
+ try:
644
+ # Protected operation
645
+ pass
646
+ except PermissionDeniedError as e:
647
+ return {"error": "Permission denied", "detail": str(e)}
648
+ ```
649
+
650
+ ## Best Practices
651
+
652
+ ### 1. Security
653
+ - Always use environment variables for sensitive data
654
+ - Implement proper password policies
655
+ - Regularly rotate JWT secret keys
656
+ - Use HTTPS in production
657
+ - Implement rate limiting for authentication endpoints
658
+
659
+ ### 2. Permission Design
660
+ - Use descriptive permission names
661
+ - Group related permissions by module
662
+ - Implement least privilege principle
663
+ - Document permission requirements
664
+
665
+ ### 3. Performance
666
+ - Use Redis for real-time policy updates
667
+ - Implement caching for frequently accessed permissions
668
+ - Optimize database queries with eager loading
669
+ - Monitor policy enforcement performance
670
+
671
+ ### 4. Maintenance
672
+ - Regularly audit user permissions
673
+ - Implement permission cleanup for inactive users
674
+ - Monitor and log security events
675
+ - Keep dependencies updated
676
+
677
+ ### 5. Testing
678
+ - Test all permission combinations
679
+ - Mock external dependencies
680
+ - Test error scenarios
681
+ - Implement integration tests
682
+
683
+ ## Monitoring and Logging
684
+
685
+ ```python
686
+ import logging
687
+ from abs_utils.logger import setup_logger
688
+
689
+ logger = setup_logger(__name__)
690
+
691
+ # Log authentication events
692
+ logger.info(f"User {user_uuid} authenticated successfully")
693
+
694
+ # Log permission checks
695
+ logger.info(f"Permission check: {user_uuid} -> {resource}:{action}:{module}")
696
+
697
+ # Log role assignments
698
+ logger.info(f"Roles assigned to user {user_uuid}: {role_uuids}")
699
+ ```
700
+
701
+ ## Migration and Deployment
702
+
703
+ ### Database Migrations
704
+ Ensure your database has the required tables:
705
+ - `users`
706
+ - `roles`
707
+ - `permissions`
708
+ - `user_roles`
709
+ - `role_permissions`
710
+ - `gov_casbin_rules`
711
+
712
+ ### Redis Setup
713
+ For real-time policy updates, configure Redis:
714
+ ```bash
715
+ # Install Redis
716
+ sudo apt-get install redis-server
717
+
718
+ # Configure Redis
719
+ redis-cli config set requirepass your-password
720
+ redis-cli config set notify-keyspace-events KEA
721
+ ```
722
+
723
+ ### Health Checks
724
+ ```python
725
+ @app.get("/health")
726
+ async def health_check():
727
+ return {
728
+ "status": "healthy",
729
+ "rbac_watcher": rbac_service.is_watcher_active(),
730
+ "policy_count": rbac_service.get_policy_count()
731
+ }
732
+ ```
733
+
734
+ ## Troubleshooting
735
+
736
+ ### Common Issues
737
+
738
+ 1. **Authentication Fails**
739
+ - Check JWT secret key configuration
740
+ - Verify token expiration settings
741
+ - Ensure user exists in database
742
+
743
+ 2. **Permission Denied**
744
+ - Verify user has required roles
745
+ - Check role-permission assignments
746
+ - Validate permission format
747
+
748
+ 3. **Redis Connection Issues**
749
+ - Check Redis server status
750
+ - Verify connection parameters
751
+ - Ensure Redis supports pub/sub
752
+
753
+ 4. **Policy Not Updating**
754
+ - Check Redis watcher configuration
755
+ - Verify policy format
756
+ - Monitor Redis logs
757
+
758
+ ## License
759
+
760
+ This project is licensed under the MIT License - see the LICENSE file for details.
761
+
@@ -5,7 +5,7 @@ abs_auth_rbac_core/auth/jwt_functions.py,sha256=9vhjWrxXdE8fVQ4FGrPj9y6PoSEsaeFo
5
5
  abs_auth_rbac_core/auth/middleware.py,sha256=Hn5EoDE2zEWXHXTgrSFgE85s0ivzFNTxYIqtgLBdtGE,1849
6
6
  abs_auth_rbac_core/models/__init__.py,sha256=9ImboxQ04XxRjd5o1RDBn465BOj3F2pahuVXF15NuqE,292
7
7
  abs_auth_rbac_core/models/base_model.py,sha256=AaWObslm8sTetv4H1Ia_gPpi_75uF5z1o7Et9WAvstU,612
8
- abs_auth_rbac_core/models/gov_casbin_rule.py,sha256=uWkzOgtG0_8CXR4YLBz_JINA8apcB1D4aWiCgSkuTCs,789
8
+ abs_auth_rbac_core/models/gov_casbin_rule.py,sha256=lzt837KLX1HiXsBH8Y43G-pPAKmm_ykhn-m13_VOUyI,999
9
9
  abs_auth_rbac_core/models/permissions.py,sha256=op_6t3OKDGzQvroVhYgoM7g_umr7MD-ZABjk5HdTpB8,859
10
10
  abs_auth_rbac_core/models/rbac_model.py,sha256=GbgMA-lJoU__xYP7wCw2FB9P1ftMzRAU2sWyGnmqnt4,323
11
11
  abs_auth_rbac_core/models/role_permission.py,sha256=KQ7MGwFvHhXgWL73TGH_elfG0rTLj5Ct11EWi6ypNb8,414
@@ -17,11 +17,11 @@ abs_auth_rbac_core/models/user_role.py,sha256=20pqmtJPzlUrI9ulHGouk8XlFgrGG7I6ik
17
17
  abs_auth_rbac_core/rbac/__init__.py,sha256=oYjtpmfrkEbwWCBAWuRoU1fM4fCpBxkF_lwQrelK1As,79
18
18
  abs_auth_rbac_core/rbac/decorator.py,sha256=pEFAW0Nn2iE4KBctPhNOmO_VLeJFDX2V9v2LsCu6kHY,1824
19
19
  abs_auth_rbac_core/rbac/policy.conf,sha256=wghhhKxgZH0rPhh1QFrIpq9nevJT3s7OxxvXiU3zzuI,305
20
- abs_auth_rbac_core/rbac/service.py,sha256=YKur4trtTc0N-u3oqrfAJf9yLOTzSU-Pn2qh5drciqs,37250
20
+ abs_auth_rbac_core/rbac/service.py,sha256=abG09-jnjhhql_47kE7IDRbZTvP5-RiChCDyauugHQo,37253
21
21
  abs_auth_rbac_core/schema/__init__.py,sha256=v9xibJ8Wr9k0u6PEYNK0LCGUJD71SB5vxu9BZG0S7tM,46
22
22
  abs_auth_rbac_core/schema/permission.py,sha256=XvxPU68FY0PFgkF4GR2bSrzNvFB8c8OgY_d0JOJvMc8,203
23
23
  abs_auth_rbac_core/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- abs_auth_rbac_core/util/permission_constants.py,sha256=ICnn7mDoNt4_adUcbMjWtBeY2MgJu4F9qS5jRgR3nNU,92039
25
- abs_auth_rbac_core-0.1.18.dist-info/METADATA,sha256=F1uG5WazxHEz9jAwRqYAPfT1ccnpbLsYrOPT1DLXet4,6689
26
- abs_auth_rbac_core-0.1.18.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
27
- abs_auth_rbac_core-0.1.18.dist-info/RECORD,,
24
+ abs_auth_rbac_core/util/permission_constants.py,sha256=cUEi6S9iNK4jwxevlb4ZNiBUcFSu4wlkN-p-O3-l7xs,95712
25
+ abs_auth_rbac_core-0.1.19.dist-info/METADATA,sha256=WFk4zpwzAmPo988AG_7eBTmruz9xSbSLKsAFkSuoAYg,23270
26
+ abs_auth_rbac_core-0.1.19.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
27
+ abs_auth_rbac_core-0.1.19.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.2
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,234 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: abs-auth-rbac-core
3
- Version: 0.1.18
4
- Summary: RBAC and Auth core utilities including JWT token management.
5
- License: MIT
6
- Author: AutoBridgeSystems
7
- Author-email: info@autobridgesystems.com
8
- Requires-Python: >=3.13,<4.0
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.13
12
- Requires-Dist: abs-exception-core (>=0.1.0,<0.2.0)
13
- Requires-Dist: casbin (>=1.41.0,<2.0.0)
14
- Requires-Dist: casbin-redis-watcher (>=1.3.0,<2.0.0)
15
- Requires-Dist: casbin-sqlalchemy-adapter (>=1.4.0,<2.0.0)
16
- Requires-Dist: fastapi[standard] (>=0.115.12,<0.116.0)
17
- Requires-Dist: passlib (>=1.7.4,<2.0.0)
18
- Requires-Dist: psycopg2-binary (>=2.9.10,<3.0.0)
19
- Requires-Dist: pyjwt (>=2.10.1,<3.0.0)
20
- Requires-Dist: sqlalchemy (>=2.0.40,<3.0.0)
21
- Description-Content-Type: text/markdown
22
-
23
- # ABS Auth RBAC Core
24
-
25
- A comprehensive authentication and Role-Based Access Control (RBAC) package for FastAPI applications. This package provides robust JWT-based authentication and flexible role-based permission management using Casbin.
26
-
27
- ## Features
28
-
29
- - JWT-based authentication with customizable token expiration
30
- - Password hashing using bcrypt
31
- - Role-Based Access Control (RBAC) with Casbin integration
32
- - Flexible permission management
33
- - User-role and role-permission associations
34
- - Middleware for authentication and authorization
35
-
36
- ## Installation
37
-
38
- ```bash
39
- pip install abs-auth-rbac-core
40
- ```
41
-
42
- ## Quick Start
43
-
44
- ### 1. Authentication Setup
45
-
46
- ```python
47
- from abs_auth_rbac_core.auth.jwt_functions import JWTFunctions
48
- import os
49
-
50
- # Initialize JWT functions with environment variables
51
- jwt_functions = JWTFunctions(
52
- secret_key=os.getenv("JWT_SECRET_KEY"),
53
- algorithm=os.getenv("JWT_ALGORITHM", "HS256"),
54
- expire_minutes=int(os.getenv("JWT_EXPIRE_MINUTES", "60"))
55
- )
56
-
57
- # Create access token
58
- token = jwt_functions.create_access_token(data={"sub": "user_id"})
59
-
60
- # Verify password
61
- is_valid = jwt_functions.verify_password(plain_password, hashed_password)
62
-
63
- # Get password hash
64
- hashed_password = jwt_functions.get_password_hash(plain_password)
65
- ```
66
-
67
- ### 2. RBAC Setup
68
-
69
- ```python
70
- from abs_auth_rbac_core.rbac.service import RBACService
71
-
72
- # Initialize RBAC service
73
- rbac_service = RBACService(
74
- session=your_db_session
75
- )
76
-
77
- # Create a role with permissions
78
- role = rbac_service.create_role(
79
- name="admin",
80
- description="Administrator role",
81
- permission_ids=["permission_uuid1", "permission_uuid2"]
82
- )
83
-
84
- # Assign roles to user
85
- rbac_service.bulk_assign_roles_to_user(
86
- user_uuid="user_uuid",
87
- role_uuids=["role_uuid1", "role_uuid2"]
88
- )
89
-
90
- # Check permission
91
- has_permission = rbac_service.check_permission(
92
- user_uuid="user_uuid",
93
- resource="resource_name",
94
- action="action_name",
95
- module="module_name"
96
- )
97
- ```
98
-
99
- ## Core Components
100
-
101
- ### Authentication (`auth/`)
102
- - `jwt_functions.py`: JWT token management and password hashing
103
- - `middleware.py`: Authentication middleware for FastAPI
104
- - `auth_functions.py`: Core authentication functions
105
-
106
- ### RBAC (`rbac/`)
107
- - `service.py`: Main RBAC service with role and permission management
108
- - `decorator.py`: Decorators for permission checking
109
-
110
- ### Models (`models/`)
111
- - `user.py`: User model
112
- - `roles.py`: Role model
113
- - `permissions.py`: Permission model
114
- - `user_role.py`: User-Role association model
115
- - `role_permission.py`: Role-Permission association model
116
- - `rbac_model.py`: Base RBAC model
117
- - `base_model.py`: Base model with common fields
118
-
119
- ## Usage Examples
120
-
121
- ### 1. Setting Up Authentication Middleware
122
-
123
- ```python
124
- from fastapi import FastAPI, Depends
125
- from dependency_injector import containers, providers
126
- from abs_auth_rbac_core.auth.middleware import auth_middleware
127
- from abs_auth_rbac_core.rbac import RBACService
128
-
129
- # Create a container for dependency injection
130
- class Container(containers.DeclarativeContainer):
131
- # Database session provider
132
- db_session = providers.Factory(your_db_session_factory)
133
-
134
- # RBAC service provider
135
- rbac_service = providers.Factory(
136
- RBACService,
137
- session=db_session
138
- )
139
-
140
- # Auth middleware provider
141
- get_auth_middleware = providers.Factory(
142
- auth_middleware,
143
- db_session=db_session,
144
- jwt_secret_key=os.getenv("JWT_SECRET_KEY"),
145
- jwt_algorithm=os.getenv("JWT_ALGORITHM", "HS256")
146
- )
147
-
148
- # Initialize FastAPI app
149
- app = FastAPI()
150
- container = Container()
151
- app.container = container
152
- ```
153
-
154
- ### 2. Applying Middleware to Routers
155
-
156
- ```python
157
- from fastapi import FastAPI, Depends
158
- from src.core.container import Container
159
-
160
- class CreateApp:
161
- def __init__(self):
162
- self.container = Container()
163
- self.auth_middleware = self.container.get_auth_middleware()
164
-
165
- self.app = FastAPI(
166
- title="Your Service",
167
- description="Service Description",
168
- version="0.0.1"
169
- )
170
-
171
- # Apply middleware to specific routers
172
- self.app.include_router(
173
- users_router,
174
- dependencies=[Depends(self.auth_middleware)],
175
- tags=["Users"]
176
- )
177
-
178
- # Public routes (no middleware)
179
- self.app.include_router(
180
- public_router,
181
- tags=["Public"]
182
- )
183
- ```
184
-
185
- ### 3. Permission Management
186
-
187
- ```python
188
- from abs_auth_rbac_core.util.permission_constants import (
189
- PermissionAction,
190
- PermissionModule,
191
- PermissionResource
192
- )
193
-
194
- # permissions
195
- permission = PermissionData(
196
- name="User Management",
197
- description="Manage user accounts",
198
- module=PermissionModule.USER_MANAGEMENT,
199
- resource=PermissionResource.USER_MANAGEMENT,
200
- action=PermissionAction.MANAGE
201
- )
202
-
203
- # Check permissions in route
204
- @app.get("/users")
205
- @rbac_require_permission(
206
- f"{PermissionModule.USER_MANAGEMENT.value}:{PermissionResource.USER_MANAGEMENT.value}:{PermissionAction.VIEW.value}"
207
- )
208
- async def list_users():
209
- return {"users": [...]}
210
- ```
211
-
212
- ## Error Handling
213
-
214
- The package includes comprehensive error handling for common scenarios:
215
- - `UnauthorizedError`: For invalid or expired tokens
216
- - `ValidationError`: For invalid token formats
217
- - `DuplicatedError`: For duplicate role names
218
- - `NotFoundError`: For non-existent resources
219
- - `PermissionDeniedError`: For insufficient permissions
220
-
221
- ## Best Practices
222
-
223
- 1. Always use environment variables for sensitive data (secret keys, etc.)
224
- 2. Implement proper error handling for authentication and authorization failures
225
- 3. Use the middleware for global authentication
226
- 4. Implement proper logging for security-related events
227
- 5. Regularly rotate secret keys and tokens
228
- 6. Use strong password policies
229
- 7. Implement rate limiting for authentication endpoints
230
-
231
- ## License
232
-
233
- This project is licensed under the MIT License - see the LICENSE file for details.
234
-