156 lines
6.5 KiB
Python
156 lines
6.5 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy import select, func
|
|
from typing import List
|
|
import ulid
|
|
|
|
from app.core.database.db_session import get_db
|
|
from app.core.permissions.RoleChecker import get_current_user, RoleChecker
|
|
from app.models.UserModel import User
|
|
from app.models.RoleModel import Role
|
|
from app.models.PermissionModel import Permission, RolePermission
|
|
from app.schemas.RolePermission import RoleResponse, RoleCreate, PermissionResponse, RolePermissionUpdate
|
|
|
|
router = APIRouter(prefix="/api/v1/role-permissions", tags=["Roles & Permissions Control"])
|
|
|
|
@router.get("/roles/all", response_model=List[RoleResponse])
|
|
def get_all_roles(
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(RoleChecker(["Super Admin", "Admin"]))
|
|
):
|
|
stmt = select(Role).where(Role.deleted_at.is_(None))
|
|
roles = db.execute(stmt).scalars().all()
|
|
return roles
|
|
|
|
@router.post("/roles/create", response_model=RoleResponse, status_code=status.HTTP_201_CREATED)
|
|
def create_role(
|
|
data: RoleCreate,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(RoleChecker(["Super Admin", "Admin"]))
|
|
):
|
|
existing = db.execute(select(Role).where(Role.role_name == data.role_name)).scalar_one_or_none()
|
|
if existing:
|
|
raise HTTPException(status_code=400, detail="Role name already exists")
|
|
|
|
role_id = str(ulid.ULID())
|
|
new_role = Role(
|
|
role_id=role_id,
|
|
role_name=data.role_name,
|
|
role_prefix=data.role_prefix,
|
|
description=data.description,
|
|
is_system=False,
|
|
is_active=True
|
|
)
|
|
db.add(new_role)
|
|
db.commit()
|
|
db.refresh(new_role)
|
|
return new_role
|
|
|
|
@router.delete("/roles/delete/{role_id}", status_code=status.HTTP_200_OK)
|
|
def delete_role(
|
|
role_id: str,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(RoleChecker(["Super Admin", "Admin"]))
|
|
):
|
|
role = db.execute(select(Role).where(Role.role_id == role_id)).scalar_one_or_none()
|
|
if not role:
|
|
raise HTTPException(status_code=404, detail="Role not found")
|
|
if role.is_system:
|
|
raise HTTPException(status_code=400, detail="System roles cannot be deleted")
|
|
|
|
user_assigned = db.execute(select(User).where(User.role_id == role_id, User.deleted_at.is_(None))).scalars().all()
|
|
if len(user_assigned) > 0:
|
|
raise HTTPException(status_code=400, detail="Cannot delete role because it is currently assigned to users")
|
|
|
|
role.deleted_at = db.execute(select(func.now())).scalar()
|
|
db.commit()
|
|
return {"detail": "Role deleted successfully"}
|
|
|
|
@router.get("/permissions/all", response_model=List[PermissionResponse])
|
|
def get_all_permissions(
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(RoleChecker(["Super Admin", "Admin"]))
|
|
):
|
|
stmt = select(Permission).where(Permission.is_active.is_(True))
|
|
permissions = db.execute(stmt).scalars().all()
|
|
if not permissions:
|
|
# Auto-seed standard platform permissions if permissions table is empty
|
|
seed_data = [
|
|
("users:read", "User Management", "View user lists and profile details"),
|
|
("users:write", "User Management", "Create and modify staff user accounts"),
|
|
("users:delete", "User Management", "Delete or deactivate staff user accounts"),
|
|
("roles:manage", "User Management", "Create, edit and assign roles & access control policies"),
|
|
("catalog:read", "Catalog Management", "View categories, brands, devices, and sales products"),
|
|
("catalog:write", "Catalog Management", "Create and edit product catalog items"),
|
|
("catalog:delete", "Catalog Management", "Delete catalog items, brands, and categories"),
|
|
("inventory:manage", "Inventory & Purchases", "Manage stock movements, warehouses, and purchase orders"),
|
|
("marketing:manage", "Marketing & Storefront", "Manage homepage sections, banners, and layout controls"),
|
|
("settings:manage", "System Infrastructure", "Configure global system settings and security policies"),
|
|
]
|
|
for code, group, desc in seed_data:
|
|
p_id = str(ulid.ULID())
|
|
parts = code.split(":")
|
|
module = parts[0]
|
|
action = parts[1]
|
|
resource = "general"
|
|
permission_code = f"{module}.{resource}.{action}"
|
|
p_obj = Permission(
|
|
permission_id=p_id,
|
|
module=module,
|
|
resource=resource,
|
|
action=action,
|
|
permission_code=permission_code,
|
|
description=desc,
|
|
is_active=True
|
|
)
|
|
db.add(p_obj)
|
|
db.commit()
|
|
permissions = db.execute(stmt).scalars().all()
|
|
return permissions
|
|
|
|
@router.get("/roles/{role_id}/permissions", response_model=List[str])
|
|
def get_role_permissions(
|
|
role_id: str,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(RoleChecker(["Super Admin", "Admin"]))
|
|
):
|
|
role = db.execute(select(Role).where(Role.role_id == role_id)).scalar_one_or_none()
|
|
if not role:
|
|
raise HTTPException(status_code=404, detail="Role not found")
|
|
|
|
stmt = select(RolePermission.permission_id).where(RolePermission.role_id == role_id)
|
|
perm_ids = db.execute(stmt).scalars().all()
|
|
return perm_ids
|
|
|
|
@router.post("/roles/{role_id}/permissions", status_code=status.HTTP_200_OK)
|
|
def update_role_permissions(
|
|
role_id: str,
|
|
data: RolePermissionUpdate,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(RoleChecker(["Super Admin", "Admin"]))
|
|
):
|
|
role = db.execute(select(Role).where(Role.role_id == role_id)).scalar_one_or_none()
|
|
if not role:
|
|
raise HTTPException(status_code=404, detail="Role not found")
|
|
|
|
if role.role_name.lower() == "super admin":
|
|
raise HTTPException(status_code=400, detail="Permissions for Super Admin role cannot be modified")
|
|
|
|
if data.permission_ids:
|
|
valid_perms = db.execute(select(Permission.permission_id).where(Permission.permission_id.in_(data.permission_ids))).scalars().all()
|
|
if len(valid_perms) != len(data.permission_ids):
|
|
raise HTTPException(status_code=400, detail="One or more permission IDs are invalid")
|
|
|
|
db.query(RolePermission).filter(RolePermission.role_id == role_id).delete()
|
|
|
|
for perm_id in data.permission_ids:
|
|
link_id = str(ulid.ULID())
|
|
link = RolePermission(
|
|
id=link_id,
|
|
role_id=role_id,
|
|
permission_id=perm_id
|
|
)
|
|
db.add(link)
|
|
|
|
db.commit()
|
|
return {"detail": "Role permissions updated successfully"}
|