40 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			40 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import logging
 | |
| 
 | |
| from fastapi import HTTPException
 | |
| 
 | |
| from ..util import permutil
 | |
| 
 | |
| logger = logging.getLogger(__name__)
 | |
| 
 | |
| 
 | |
| async def verify(auth: str | None, perm: list[str], match=permutil.has_all):
 | |
|     """Validate session token and optional list of required permissions.
 | |
| 
 | |
|     Returns the session context.
 | |
| 
 | |
|     Raises HTTPException on failure:
 | |
|       401: unauthenticated / invalid session
 | |
|       403: required permissions missing
 | |
|     """
 | |
|     if not auth:
 | |
|         raise HTTPException(status_code=401, detail="Authentication required")
 | |
| 
 | |
|     ctx = await permutil.session_context(auth)
 | |
|     if not ctx:
 | |
|         raise HTTPException(status_code=401, detail="Session not found")
 | |
| 
 | |
|     if not match(ctx, perm):
 | |
|         # Determine which permissions are missing for clearer diagnostics
 | |
|         missing = sorted(set(perm) - set(ctx.role.permissions))
 | |
|         logger.warning(
 | |
|             "Permission denied: user=%s role=%s missing=%s required=%s granted=%s",  # noqa: E501
 | |
|             getattr(ctx.user, "uuid", "?"),
 | |
|             getattr(ctx.role, "display_name", "?"),
 | |
|             missing,
 | |
|             perm,
 | |
|             ctx.role.permissions,
 | |
|         )
 | |
|         raise HTTPException(status_code=403, detail="Permission required")
 | |
| 
 | |
|     return ctx
 | 
