feat(rbac): add roles and permissions
This commit is contained in:
parent
86a32a942c
commit
694b7bd09a
37 changed files with 2682 additions and 218 deletions
94
backend/hermes/app/core/rbac.py
Normal file
94
backend/hermes/app/core/rbac.py
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
from collections.abc import Iterable
|
||||
|
||||
from fastapi import Depends, HTTPException, status
|
||||
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.security import verify_access_token
|
||||
from app.db.database import get_db
|
||||
from app.models.user import User
|
||||
from app.repositories.user_repository import UserRepository
|
||||
|
||||
bearer_scheme = HTTPBearer(auto_error=False)
|
||||
|
||||
|
||||
def get_current_user(
|
||||
credentials: HTTPAuthorizationCredentials | None = Depends(bearer_scheme),
|
||||
db: Session = Depends(get_db),
|
||||
) -> User:
|
||||
if credentials is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Nicht authentifiziert",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
username = verify_access_token(credentials.credentials)
|
||||
user = UserRepository.get_by_username(db, username)
|
||||
|
||||
if user is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Nicht authentifiziert",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
return user
|
||||
|
||||
|
||||
def get_current_active_user(current_user: User = Depends(get_current_user)) -> User:
|
||||
if not current_user.is_active:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Nicht authentifiziert",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
return current_user
|
||||
|
||||
|
||||
def get_user_permission_names(user: User) -> set[str]:
|
||||
if user.primary_role is None:
|
||||
return set()
|
||||
|
||||
return {permission.name for permission in user.primary_role.permissions}
|
||||
|
||||
|
||||
def require_permission(permission: str):
|
||||
def dependency(current_user: User = Depends(get_current_active_user)) -> User:
|
||||
if permission not in get_user_permission_names(current_user):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Keine Berechtigung",
|
||||
)
|
||||
return current_user
|
||||
|
||||
return dependency
|
||||
|
||||
|
||||
def require_any_permission(permissions: Iterable[str]):
|
||||
permission_set = set(permissions)
|
||||
|
||||
def dependency(current_user: User = Depends(get_current_active_user)) -> User:
|
||||
if get_user_permission_names(current_user).isdisjoint(permission_set):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Keine Berechtigung",
|
||||
)
|
||||
return current_user
|
||||
|
||||
return dependency
|
||||
|
||||
|
||||
def require_all_permissions(permissions: Iterable[str]):
|
||||
permission_set = set(permissions)
|
||||
|
||||
def dependency(current_user: User = Depends(get_current_active_user)) -> User:
|
||||
if not permission_set.issubset(get_user_permission_names(current_user)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Keine Berechtigung",
|
||||
)
|
||||
return current_user
|
||||
|
||||
return dependency
|
||||
Loading…
Add table
Add a link
Reference in a new issue