feat: implement admin-users management with super admin restriction
- Add /admin/admin-users routes for managing admin users (super admin only) - Remove vendor role from user creation form (vendors created via company hierarchy) - Add admin-users.html and admin-user-detail.html templates - Add admin-users.js and admin-user-detail.js for frontend logic - Move database operations to admin_platform_service (list, get, create, delete, toggle status) - Update sidebar to show Admin Users section only for super admins - Add isSuperAdmin computed property to init-alpine.js - Fix /api/v1 prefix issues in JS files (apiClient already adds prefix) - Update architecture rule JS-012 to catch more variable patterns (url, endpoint, path) - Replace inline SVGs with $icon() helper in select-platform.html Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -22,7 +22,10 @@ Routes:
|
||||
- GET /vendors/{vendor_code}/domains → Vendor domains management (auth required)
|
||||
- GET /vendor-themes → Vendor themes selection page (auth required)
|
||||
- GET /vendors/{vendor_code}/theme → Vendor theme editor (auth required)
|
||||
- GET /users → User management page (auth required)
|
||||
- GET /admin-users → Admin users management (super admin only)
|
||||
- GET /admin-users/create → Create admin user (super admin only)
|
||||
- GET /admin-users/{id} → Admin user detail (super admin only)
|
||||
- GET /users → Redirects to /admin/admin-users
|
||||
- GET /customers → Customer management page (auth required)
|
||||
- GET /inventory → Inventory management page (auth required)
|
||||
- GET /orders → Orders management page (auth required)
|
||||
@@ -396,22 +399,28 @@ async def admin_vendor_theme_page(
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# USER MANAGEMENT ROUTES
|
||||
# ADMIN USER MANAGEMENT ROUTES (Super Admin Only)
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/users", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_users_page(
|
||||
@router.get("/admin-users", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_users_list_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render users management page.
|
||||
Shows list of all platform users.
|
||||
Render admin users management page.
|
||||
Shows list of all admin users (super admins and platform admins).
|
||||
Super admin only.
|
||||
"""
|
||||
from fastapi import HTTPException
|
||||
|
||||
if not current_user.is_super_admin:
|
||||
raise HTTPException(status_code=403, detail="Super admin access required")
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"admin/users.html",
|
||||
"admin/admin-users.html",
|
||||
{
|
||||
"request": request,
|
||||
"user": current_user,
|
||||
@@ -419,15 +428,21 @@ async def admin_users_page(
|
||||
)
|
||||
|
||||
|
||||
@router.get("/users/create", response_class=HTMLResponse, include_in_schema=False)
|
||||
@router.get("/admin-users/create", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_user_create_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render user creation form.
|
||||
Render admin user creation form.
|
||||
Super admin only.
|
||||
"""
|
||||
from fastapi import HTTPException
|
||||
|
||||
if not current_user.is_super_admin:
|
||||
raise HTTPException(status_code=403, detail="Super admin access required")
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"admin/user-create.html",
|
||||
{
|
||||
@@ -437,7 +452,9 @@ async def admin_user_create_page(
|
||||
)
|
||||
|
||||
|
||||
@router.get("/users/{user_id}", response_class=HTMLResponse, include_in_schema=False)
|
||||
@router.get(
|
||||
"/admin-users/{user_id}", response_class=HTMLResponse, include_in_schema=False
|
||||
)
|
||||
async def admin_user_detail_page(
|
||||
request: Request,
|
||||
user_id: int = Path(..., description="User ID"),
|
||||
@@ -445,10 +462,16 @@ async def admin_user_detail_page(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render user detail view.
|
||||
Render admin user detail view.
|
||||
Super admin only.
|
||||
"""
|
||||
from fastapi import HTTPException
|
||||
|
||||
if not current_user.is_super_admin:
|
||||
raise HTTPException(status_code=403, detail="Super admin access required")
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"admin/user-detail.html",
|
||||
"admin/admin-user-detail.html",
|
||||
{
|
||||
"request": request,
|
||||
"user": current_user,
|
||||
@@ -458,7 +481,7 @@ async def admin_user_detail_page(
|
||||
|
||||
|
||||
@router.get(
|
||||
"/users/{user_id}/edit", response_class=HTMLResponse, include_in_schema=False
|
||||
"/admin-users/{user_id}/edit", response_class=HTMLResponse, include_in_schema=False
|
||||
)
|
||||
async def admin_user_edit_page(
|
||||
request: Request,
|
||||
@@ -467,8 +490,14 @@ async def admin_user_edit_page(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render user edit form.
|
||||
Render admin user edit form.
|
||||
Super admin only.
|
||||
"""
|
||||
from fastapi import HTTPException
|
||||
|
||||
if not current_user.is_super_admin:
|
||||
raise HTTPException(status_code=403, detail="Super admin access required")
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"admin/user-edit.html",
|
||||
{
|
||||
@@ -479,6 +508,47 @@ async def admin_user_edit_page(
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# USER MANAGEMENT ROUTES (Legacy - Redirects)
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/users", response_class=RedirectResponse, include_in_schema=False)
|
||||
async def admin_users_page_redirect():
|
||||
"""
|
||||
Redirect old /admin/users to /admin/admin-users.
|
||||
"""
|
||||
return RedirectResponse(url="/admin/admin-users", status_code=302)
|
||||
|
||||
|
||||
@router.get("/users/create", response_class=RedirectResponse, include_in_schema=False)
|
||||
async def admin_user_create_page_redirect():
|
||||
"""
|
||||
Redirect old /admin/users/create to /admin/admin-users/create.
|
||||
"""
|
||||
return RedirectResponse(url="/admin/admin-users/create", status_code=302)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/users/{user_id}", response_class=RedirectResponse, include_in_schema=False
|
||||
)
|
||||
async def admin_user_detail_page_redirect(user_id: int = Path(..., description="User ID")):
|
||||
"""
|
||||
Redirect old /admin/users/{id} to /admin/admin-users/{id}.
|
||||
"""
|
||||
return RedirectResponse(url=f"/admin/admin-users/{user_id}", status_code=302)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/users/{user_id}/edit", response_class=RedirectResponse, include_in_schema=False
|
||||
)
|
||||
async def admin_user_edit_page_redirect(user_id: int = Path(..., description="User ID")):
|
||||
"""
|
||||
Redirect old /admin/users/{id}/edit to /admin/admin-users/{id}/edit.
|
||||
"""
|
||||
return RedirectResponse(url=f"/admin/admin-users/{user_id}/edit", status_code=302)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# CUSTOMER MANAGEMENT ROUTES
|
||||
# ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user