feat(admin): add delete APIs and UI actions for all admin resources

This commit is contained in:
Chris
2026-03-31 20:58:20 +08:00
parent 556fc8d5cb
commit 2b29a1a274

View File

@@ -1,12 +1,14 @@
import secrets import secrets
from fastapi import APIRouter, Depends, HTTPException, Query, status from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy import select from sqlalchemy import delete, select
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.core.keygen import generate_key from app.core.keygen import generate_key
from app.core.config import get_settings from app.core.config import get_settings
from app.db.session import get_db from app.db.session import get_db
from app.models.api_client import ApiClient from app.models.api_client import ApiClient
from app.models.permission_group_member import PermissionGroupMember
from app.models.permission_group_permission import PermissionGroupPermission
from app.repositories.companies_repo import CompaniesRepository from app.repositories.companies_repo import CompaniesRepository
from app.repositories.modules_repo import ModulesRepository from app.repositories.modules_repo import ModulesRepository
from app.repositories.permission_groups_repo import PermissionGroupsRepository from app.repositories.permission_groups_repo import PermissionGroupsRepository
@@ -195,6 +197,21 @@ def update_system(
return SystemItem(id=row.id, system_key=row.system_key, name=row.name, status=row.status) return SystemItem(id=row.id, system_key=row.system_key, name=row.name, status=row.status)
@router.delete("/systems/{system_key}")
def delete_system(
system_key: str,
db: Session = Depends(get_db),
) -> dict[str, int | str]:
repo = SystemsRepository(db)
row = repo.get_by_key(system_key)
if not row:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="system_not_found")
db.execute(delete(PermissionGroupPermission).where(PermissionGroupPermission.system == system_key))
db.delete(row)
db.commit()
return {"deleted": 1, "result": "deleted"}
@router.get("/modules") @router.get("/modules")
def list_modules( def list_modules(
db: Session = Depends(get_db), db: Session = Depends(get_db),
@@ -253,6 +270,21 @@ def update_module(
return ModuleItem(id=row.id, system_key=row.system_key, module_key=row.module_key, name=row.name, status=row.status) return ModuleItem(id=row.id, system_key=row.system_key, module_key=row.module_key, name=row.name, status=row.status)
@router.delete("/modules/{module_key}")
def delete_module(
module_key: str,
db: Session = Depends(get_db),
) -> dict[str, int | str]:
modules_repo = ModulesRepository(db)
row = modules_repo.get_by_key(module_key)
if not row:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="module_not_found")
db.execute(delete(PermissionGroupPermission).where(PermissionGroupPermission.module == module_key))
db.delete(row)
db.commit()
return {"deleted": 1, "result": "deleted"}
@router.get("/systems/{system_key}/groups") @router.get("/systems/{system_key}/groups")
def list_system_groups( def list_system_groups(
system_key: str, system_key: str,
@@ -374,6 +406,30 @@ def update_company(
return CompanyItem(id=row.id, company_key=row.company_key, name=row.name, status=row.status) return CompanyItem(id=row.id, company_key=row.company_key, name=row.name, status=row.status)
@router.delete("/companies/{company_key}")
def delete_company(
company_key: str,
db: Session = Depends(get_db),
) -> dict[str, int | str]:
companies_repo = CompaniesRepository(db)
sites_repo = SitesRepository(db)
company = companies_repo.get_by_key(company_key)
if not company:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="company_not_found")
company_sites, _ = sites_repo.list(company_id=company.id, limit=10000, offset=0)
company_site_keys = [s.site_key for s in company_sites]
if company_site_keys:
db.execute(
delete(PermissionGroupPermission).where(
PermissionGroupPermission.scope_type == "site",
PermissionGroupPermission.scope_id.in_(company_site_keys),
)
)
db.delete(company)
db.commit()
return {"deleted": 1, "result": "deleted"}
@router.get("/companies/{company_key}/sites") @router.get("/companies/{company_key}/sites")
def list_company_sites( def list_company_sites(
company_key: str, company_key: str,
@@ -478,6 +534,26 @@ def update_site(
return SiteItem(id=row.id, site_key=row.site_key, company_key=company_key, name=row.name, status=row.status) return SiteItem(id=row.id, site_key=row.site_key, company_key=company_key, name=row.name, status=row.status)
@router.delete("/sites/{site_key}")
def delete_site(
site_key: str,
db: Session = Depends(get_db),
) -> dict[str, int | str]:
sites_repo = SitesRepository(db)
row = sites_repo.get_by_key(site_key)
if not row:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="site_not_found")
db.execute(
delete(PermissionGroupPermission).where(
PermissionGroupPermission.scope_type == "site",
PermissionGroupPermission.scope_id == site_key,
)
)
db.delete(row)
db.commit()
return {"deleted": 1, "result": "deleted"}
@router.get("/members") @router.get("/members")
def list_members( def list_members(
db: Session = Depends(get_db), db: Session = Depends(get_db),
@@ -595,6 +671,21 @@ def update_member(
) )
@router.delete("/members/{authentik_sub}")
def delete_member(
authentik_sub: str,
db: Session = Depends(get_db),
) -> dict[str, int | str]:
users_repo = UsersRepository(db)
row = users_repo.get_by_sub(authentik_sub)
if not row:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="user_not_found")
db.execute(delete(PermissionGroupMember).where(PermissionGroupMember.authentik_sub == authentik_sub))
db.delete(row)
db.commit()
return {"deleted": 1, "result": "deleted"}
@router.post("/members/{authentik_sub}/password/reset", response_model=MemberPasswordResetResponse) @router.post("/members/{authentik_sub}/password/reset", response_model=MemberPasswordResetResponse)
def reset_member_password( def reset_member_password(
authentik_sub: str, authentik_sub: str,
@@ -759,6 +850,19 @@ def rotate_api_client_key(
return ApiClientRotateKeyResponse(client_key=row.client_key, api_key=api_key) return ApiClientRotateKeyResponse(client_key=row.client_key, api_key=api_key)
@router.delete("/api-clients/{client_key}")
def delete_api_client(
client_key: str,
db: Session = Depends(get_db),
) -> dict[str, int | str]:
row = db.scalar(select(ApiClient).where(ApiClient.client_key == client_key))
if not row:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="api_client_not_found")
db.delete(row)
db.commit()
return {"deleted": 1, "result": "deleted"}
@router.get("/permission-groups") @router.get("/permission-groups")
def list_permission_groups( def list_permission_groups(
db: Session = Depends(get_db), db: Session = Depends(get_db),
@@ -898,6 +1002,20 @@ def update_permission_group(
return PermissionGroupItem(id=row.id, group_key=row.group_key, name=row.name, status=row.status) return PermissionGroupItem(id=row.id, group_key=row.group_key, name=row.name, status=row.status)
@router.delete("/permission-groups/{group_key}")
def delete_permission_group(
group_key: str,
db: Session = Depends(get_db),
) -> dict[str, int | str]:
repo = PermissionGroupsRepository(db)
row = repo.get_by_key(group_key)
if not row:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="group_not_found")
db.delete(row)
db.commit()
return {"deleted": 1, "result": "deleted"}
@router.post("/permission-groups/{group_key}/members/{authentik_sub}") @router.post("/permission-groups/{group_key}/members/{authentik_sub}")
def add_group_member( def add_group_member(
group_key: str, group_key: str,