feat(rbac): add roles and permissions
This commit is contained in:
parent
86a32a942c
commit
694b7bd09a
37 changed files with 2682 additions and 218 deletions
93
backend/hermes/app/repositories/rbac_repository.py
Normal file
93
backend/hermes/app/repositories/rbac_repository.py
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session, selectinload
|
||||
|
||||
from app.models.rbac import Permission, Role
|
||||
from app.schemas.rbac import RoleCreate, RolePermissionUpdate, RoleUpdate
|
||||
|
||||
|
||||
class RbacRepository:
|
||||
@staticmethod
|
||||
def get_roles(db: Session) -> list[Role]:
|
||||
return list(
|
||||
db.scalars(
|
||||
select(Role)
|
||||
.options(selectinload(Role.permissions))
|
||||
.order_by(Role.name)
|
||||
)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_role_by_id(db: Session, role_id: int) -> Role | None:
|
||||
return db.scalar(
|
||||
select(Role)
|
||||
.where(Role.id == role_id)
|
||||
.options(selectinload(Role.permissions))
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_role_by_name(db: Session, name: str) -> Role | None:
|
||||
return db.scalar(
|
||||
select(Role)
|
||||
.where(Role.name == name)
|
||||
.options(selectinload(Role.permissions))
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_permissions(db: Session) -> list[Permission]:
|
||||
return list(db.scalars(select(Permission).order_by(Permission.module, Permission.name)))
|
||||
|
||||
@staticmethod
|
||||
def get_permissions_by_ids(db: Session, permission_ids: list[int]) -> list[Permission]:
|
||||
if not permission_ids:
|
||||
return []
|
||||
|
||||
return list(db.scalars(select(Permission).where(Permission.id.in_(permission_ids))))
|
||||
|
||||
@staticmethod
|
||||
def create_role(db: Session, role: RoleCreate) -> Role:
|
||||
db_role = Role(
|
||||
name=role.name,
|
||||
display_name=role.display_name,
|
||||
description=role.description,
|
||||
is_system=False,
|
||||
)
|
||||
db_role.permissions = RbacRepository.get_permissions_by_ids(db, role.permission_ids)
|
||||
|
||||
db.add(db_role)
|
||||
db.commit()
|
||||
db.refresh(db_role)
|
||||
|
||||
return RbacRepository.get_role_by_id(db, db_role.id) or db_role
|
||||
|
||||
@staticmethod
|
||||
def update_role(db: Session, db_role: Role, role: RoleUpdate) -> Role:
|
||||
db_role.name = role.name
|
||||
db_role.display_name = role.display_name
|
||||
db_role.description = role.description
|
||||
db_role.permissions = RbacRepository.get_permissions_by_ids(db, role.permission_ids)
|
||||
|
||||
db.commit()
|
||||
db.refresh(db_role)
|
||||
|
||||
return RbacRepository.get_role_by_id(db, db_role.id) or db_role
|
||||
|
||||
@staticmethod
|
||||
def update_role_permissions(
|
||||
db: Session,
|
||||
db_role: Role,
|
||||
permission_update: RolePermissionUpdate,
|
||||
) -> Role:
|
||||
db_role.permissions = RbacRepository.get_permissions_by_ids(
|
||||
db,
|
||||
permission_update.permission_ids,
|
||||
)
|
||||
|
||||
db.commit()
|
||||
db.refresh(db_role)
|
||||
|
||||
return RbacRepository.get_role_by_id(db, db_role.id) or db_role
|
||||
|
||||
@staticmethod
|
||||
def delete_role(db: Session, db_role: Role) -> None:
|
||||
db.delete(db_role)
|
||||
db.commit()
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy.orm import Session, joinedload, selectinload
|
||||
|
||||
from app.core.security import hash_password
|
||||
from app.models.rbac import Role
|
||||
from app.models.user import User
|
||||
from app.schemas.user import UserCreate, UserPasswordUpdate, UserUpdate
|
||||
|
||||
|
|
@ -9,15 +10,31 @@ from app.schemas.user import UserCreate, UserPasswordUpdate, UserUpdate
|
|||
class UserRepository:
|
||||
@staticmethod
|
||||
def get_all(db: Session) -> list[User]:
|
||||
return list(db.scalars(select(User).order_by(User.created_at.desc())))
|
||||
return list(
|
||||
db.scalars(
|
||||
select(User)
|
||||
.options(
|
||||
joinedload(User.primary_role).selectinload(Role.permissions),
|
||||
)
|
||||
.order_by(User.created_at.desc())
|
||||
)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_by_id(db: Session, user_id: int) -> User | None:
|
||||
return db.get(User, user_id)
|
||||
return db.scalar(
|
||||
select(User)
|
||||
.where(User.id == user_id)
|
||||
.options(joinedload(User.primary_role).selectinload(Role.permissions))
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_by_username(db: Session, username: str) -> User | None:
|
||||
return db.scalar(select(User).where(User.username == username))
|
||||
return db.scalar(
|
||||
select(User)
|
||||
.where(User.username == username)
|
||||
.options(joinedload(User.primary_role).selectinload(Role.permissions))
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def find_conflict(
|
||||
|
|
@ -52,6 +69,7 @@ class UserRepository:
|
|||
username=user.username,
|
||||
email=str(user.email),
|
||||
role=user.role,
|
||||
role_id=user.role_id,
|
||||
is_active=user.is_active,
|
||||
password_hash=hash_password(user.password),
|
||||
)
|
||||
|
|
@ -60,7 +78,7 @@ class UserRepository:
|
|||
db.commit()
|
||||
db.refresh(db_user)
|
||||
|
||||
return db_user
|
||||
return UserRepository.get_by_id(db, db_user.id) or db_user
|
||||
|
||||
@staticmethod
|
||||
def update(db: Session, db_user: User, user: UserUpdate) -> User:
|
||||
|
|
@ -69,6 +87,8 @@ class UserRepository:
|
|||
db_user.username = user.username
|
||||
db_user.email = str(user.email)
|
||||
db_user.role = user.role
|
||||
if user.role_id is not None:
|
||||
db_user.role_id = user.role_id
|
||||
db_user.is_active = user.is_active
|
||||
|
||||
if user.password:
|
||||
|
|
@ -77,7 +97,7 @@ class UserRepository:
|
|||
db.commit()
|
||||
db.refresh(db_user)
|
||||
|
||||
return db_user
|
||||
return UserRepository.get_by_id(db, db_user.id) or db_user
|
||||
|
||||
@staticmethod
|
||||
def update_password(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue