Compare commits
2 Commits
e06f18ce17
...
38e5f5377a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38e5f5377a | ||
|
|
810366d00f |
95
server.py
95
server.py
@@ -5242,6 +5242,101 @@ async def get_all_roles(
|
||||
for role, count in roles_with_counts
|
||||
]
|
||||
|
||||
@api_router.get("/admin/roles/assignable", response_model=List[RoleResponse])
|
||||
async def get_assignable_roles(
|
||||
current_user: User = Depends(require_permission("users.create")),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
Get roles that the current user can assign when inviting staff
|
||||
|
||||
- Superadmin: Can assign all roles
|
||||
- Admin: Can assign admin, finance, and non-elevated custom roles
|
||||
- Returns roles filtered by user's permission level
|
||||
"""
|
||||
from sqlalchemy import func
|
||||
|
||||
# Query all roles with permission counts
|
||||
roles_query = db.query(
|
||||
Role,
|
||||
func.count(RolePermission.id).label('permission_count')
|
||||
).outerjoin(RolePermission, Role.id == RolePermission.role_id)\
|
||||
.group_by(Role.id)\
|
||||
.order_by(Role.is_system_role.desc(), Role.name)
|
||||
|
||||
all_roles = roles_query.all()
|
||||
|
||||
# Superadmin can assign any role
|
||||
if current_user.role == UserRole.superadmin:
|
||||
return [
|
||||
{
|
||||
"id": str(role.id),
|
||||
"code": role.code,
|
||||
"name": role.name,
|
||||
"description": role.description,
|
||||
"is_system_role": role.is_system_role,
|
||||
"created_at": role.created_at,
|
||||
"updated_at": role.updated_at,
|
||||
"permission_count": count
|
||||
}
|
||||
for role, count in all_roles
|
||||
]
|
||||
|
||||
# Admin users can assign: admin, finance, and non-elevated custom roles
|
||||
# Get admin role's permissions to check for elevation
|
||||
admin_role = db.query(Role).filter(Role.code == "admin").first()
|
||||
admin_permission_codes = set()
|
||||
if admin_role:
|
||||
admin_permissions = db.query(RolePermission).filter(
|
||||
RolePermission.role_id == admin_role.id
|
||||
).all()
|
||||
admin_permission_codes = {rp.permission_id for rp in admin_permissions}
|
||||
|
||||
assignable_roles = []
|
||||
for role, count in all_roles:
|
||||
# Always exclude superadmin role
|
||||
if role.code == "superadmin":
|
||||
continue
|
||||
|
||||
# Include system roles: admin and finance
|
||||
if role.is_system_role and role.code in ["admin", "finance"]:
|
||||
assignable_roles.append({
|
||||
"id": str(role.id),
|
||||
"code": role.code,
|
||||
"name": role.name,
|
||||
"description": role.description,
|
||||
"is_system_role": role.is_system_role,
|
||||
"created_at": role.created_at,
|
||||
"updated_at": role.updated_at,
|
||||
"permission_count": count
|
||||
})
|
||||
continue
|
||||
|
||||
# For custom roles, check if they're elevated
|
||||
if not role.is_system_role:
|
||||
role_permissions = db.query(RolePermission).filter(
|
||||
RolePermission.role_id == role.id
|
||||
).all()
|
||||
role_permission_ids = {rp.permission_id for rp in role_permissions}
|
||||
|
||||
# Check if custom role has permissions admin doesn't have (elevated)
|
||||
has_elevated_permissions = bool(role_permission_ids - admin_permission_codes)
|
||||
|
||||
# Only include non-elevated custom roles
|
||||
if not has_elevated_permissions:
|
||||
assignable_roles.append({
|
||||
"id": str(role.id),
|
||||
"code": role.code,
|
||||
"name": role.name,
|
||||
"description": role.description,
|
||||
"is_system_role": role.is_system_role,
|
||||
"created_at": role.created_at,
|
||||
"updated_at": role.updated_at,
|
||||
"permission_count": count
|
||||
})
|
||||
|
||||
return assignable_roles
|
||||
|
||||
@api_router.post("/admin/roles", response_model=RoleResponse)
|
||||
async def create_role(
|
||||
request: CreateRoleRequest,
|
||||
|
||||
Reference in New Issue
Block a user