feat(flow): unify member-group-permission admin workflow and docs
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.db.session import get_db
|
||||
@@ -9,7 +11,12 @@ from app.repositories.permissions_repo import PermissionsRepository
|
||||
from app.repositories.sites_repo import SitesRepository
|
||||
from app.repositories.systems_repo import SystemsRepository
|
||||
from app.repositories.users_repo import UsersRepository
|
||||
from app.schemas.permissions import PermissionGrantRequest, PermissionRevokeRequest
|
||||
from app.schemas.permissions import (
|
||||
DirectPermissionListResponse,
|
||||
DirectPermissionRow,
|
||||
PermissionGrantRequest,
|
||||
PermissionRevokeRequest,
|
||||
)
|
||||
from app.security.api_client_auth import require_api_client
|
||||
|
||||
router = APIRouter(prefix="/admin", tags=["admin"])
|
||||
@@ -98,3 +105,42 @@ def revoke_permission(
|
||||
site_id=site_id,
|
||||
)
|
||||
return {"deleted": deleted, "result": "revoked"}
|
||||
|
||||
|
||||
@router.get("/permissions/direct", response_model=DirectPermissionListResponse)
|
||||
def list_direct_permissions(
|
||||
_: ApiClient = Depends(require_api_client),
|
||||
db: Session = Depends(get_db),
|
||||
keyword: str | None = Query(default=None),
|
||||
scope_type: str | None = Query(default=None),
|
||||
limit: int = Query(default=200, ge=1, le=500),
|
||||
offset: int = Query(default=0, ge=0),
|
||||
) -> DirectPermissionListResponse:
|
||||
perms_repo = PermissionsRepository(db)
|
||||
items, total = perms_repo.list_direct_permissions(
|
||||
keyword=keyword,
|
||||
scope_type=scope_type,
|
||||
limit=limit,
|
||||
offset=offset,
|
||||
)
|
||||
return DirectPermissionListResponse(
|
||||
items=[DirectPermissionRow(**item) for item in items],
|
||||
total=total,
|
||||
limit=limit,
|
||||
offset=offset,
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/permissions/direct/{permission_id}")
|
||||
def delete_direct_permission(
|
||||
permission_id: str,
|
||||
_: ApiClient = Depends(require_api_client),
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict[str, int | str]:
|
||||
try:
|
||||
normalized_permission_id = str(UUID(permission_id))
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="invalid_permission_id")
|
||||
perms_repo = PermissionsRepository(db)
|
||||
deleted = perms_repo.revoke_by_permission_id(normalized_permission_id)
|
||||
return {"deleted": deleted, "result": "revoked"}
|
||||
|
||||
@@ -15,6 +15,8 @@ from app.schemas.catalog import (
|
||||
CompanyItem,
|
||||
CompanyUpdateRequest,
|
||||
MemberItem,
|
||||
MemberPermissionGroupsResponse,
|
||||
MemberPermissionGroupsUpdateRequest,
|
||||
MemberUpdateRequest,
|
||||
MemberUpsertRequest,
|
||||
ModuleCreateRequest,
|
||||
@@ -22,6 +24,7 @@ from app.schemas.catalog import (
|
||||
ModuleUpdateRequest,
|
||||
PermissionGroupCreateRequest,
|
||||
PermissionGroupItem,
|
||||
PermissionGroupPermissionItem,
|
||||
PermissionGroupUpdateRequest,
|
||||
SiteCreateRequest,
|
||||
SiteItem,
|
||||
@@ -411,6 +414,45 @@ def update_member(
|
||||
)
|
||||
|
||||
|
||||
@router.get("/members/{authentik_sub}/permission-groups", response_model=MemberPermissionGroupsResponse)
|
||||
def get_member_permission_groups(
|
||||
authentik_sub: str,
|
||||
_: ApiClient = Depends(require_api_client),
|
||||
db: Session = Depends(get_db),
|
||||
) -> MemberPermissionGroupsResponse:
|
||||
users_repo = UsersRepository(db)
|
||||
groups_repo = PermissionGroupsRepository(db)
|
||||
user = users_repo.get_by_sub(authentik_sub)
|
||||
if not user:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="user_not_found")
|
||||
group_keys = groups_repo.list_group_keys_by_member_sub(authentik_sub)
|
||||
return MemberPermissionGroupsResponse(authentik_sub=authentik_sub, group_keys=group_keys)
|
||||
|
||||
|
||||
@router.put("/members/{authentik_sub}/permission-groups", response_model=MemberPermissionGroupsResponse)
|
||||
def set_member_permission_groups(
|
||||
authentik_sub: str,
|
||||
payload: MemberPermissionGroupsUpdateRequest,
|
||||
_: ApiClient = Depends(require_api_client),
|
||||
db: Session = Depends(get_db),
|
||||
) -> MemberPermissionGroupsResponse:
|
||||
users_repo = UsersRepository(db)
|
||||
groups_repo = PermissionGroupsRepository(db)
|
||||
user = users_repo.get_by_sub(authentik_sub)
|
||||
if not user:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="user_not_found")
|
||||
|
||||
unique_group_keys = list(dict.fromkeys(payload.group_keys))
|
||||
groups = groups_repo.get_by_keys(unique_group_keys)
|
||||
found_keys = {g.group_key for g in groups}
|
||||
missing = [k for k in unique_group_keys if k not in found_keys]
|
||||
if missing:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"group_not_found:{','.join(missing)}")
|
||||
|
||||
groups_repo.replace_member_groups(authentik_sub, [g.id for g in groups])
|
||||
return MemberPermissionGroupsResponse(authentik_sub=authentik_sub, group_keys=unique_group_keys)
|
||||
|
||||
|
||||
@router.get("/permission-groups")
|
||||
def list_permission_groups(
|
||||
_: ApiClient = Depends(require_api_client),
|
||||
@@ -423,6 +465,32 @@ def list_permission_groups(
|
||||
return {"items": [PermissionGroupItem(id=i.id, group_key=i.group_key, name=i.name, status=i.status).model_dump() for i in items], "total": total, "limit": limit, "offset": offset}
|
||||
|
||||
|
||||
@router.get("/permission-groups/{group_key}/permissions")
|
||||
def list_permission_group_permissions(
|
||||
group_key: str,
|
||||
_: ApiClient = Depends(require_api_client),
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict[str, list[dict]]:
|
||||
repo = PermissionGroupsRepository(db)
|
||||
group = repo.get_by_key(group_key)
|
||||
if not group:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="group_not_found")
|
||||
rows = repo.list_group_permissions(group.id)
|
||||
return {
|
||||
"items": [
|
||||
PermissionGroupPermissionItem(
|
||||
id=r.id,
|
||||
system=r.system,
|
||||
module=r.module,
|
||||
action=r.action,
|
||||
scope_type=r.scope_type,
|
||||
scope_id=r.scope_id,
|
||||
).model_dump()
|
||||
for r in rows
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@router.post("/permission-groups", response_model=PermissionGroupItem)
|
||||
def create_permission_group(
|
||||
payload: PermissionGroupCreateRequest,
|
||||
|
||||
Reference in New Issue
Block a user