feat: add Admin UI for platform module management (Phase 5)
Added a complete Admin UI for managing platform modules:
API endpoints (app/api/v1/admin/modules.py):
- GET /modules - List all available modules
- GET /modules/platforms/{id} - Get platform modules
- PUT /modules/platforms/{id} - Update enabled modules
- POST /modules/platforms/{id}/enable - Enable a module
- POST /modules/platforms/{id}/disable - Disable a module
- POST /modules/platforms/{id}/enable-all - Enable all
- POST /modules/platforms/{id}/disable-optional - Core only
Admin UI:
- New page route: /admin/platforms/{code}/modules
- Template: platform-modules.html
- JavaScript: platform-modules.js
- Link added to platform-detail.html Super Admin section
Features:
- Toggle modules on/off with dependency resolution
- Enable all / Core only bulk actions
- Visual dependency indicators
- Separate sections for core vs optional modules
- Feature list preview per module
Also includes require_menu_access updates to page routes from Phase 2.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -48,11 +48,12 @@ from fastapi.templating import Jinja2Templates
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.deps import (
|
||||
get_current_admin_from_cookie_or_header,
|
||||
get_current_admin_optional,
|
||||
get_db,
|
||||
require_menu_access,
|
||||
)
|
||||
from app.core.config import settings
|
||||
from models.database.admin_menu_config import FrontendType
|
||||
from models.database.user import User
|
||||
|
||||
router = APIRouter()
|
||||
@@ -132,7 +133,7 @@ async def admin_select_platform_page(
|
||||
@router.get("/dashboard", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_dashboard_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("dashboard", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -156,7 +157,7 @@ async def admin_dashboard_page(
|
||||
@router.get("/companies", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_companies_list_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("companies", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -175,7 +176,7 @@ async def admin_companies_list_page(
|
||||
@router.get("/companies/create", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_company_create_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("companies", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -196,7 +197,7 @@ async def admin_company_create_page(
|
||||
async def admin_company_detail_page(
|
||||
request: Request,
|
||||
company_id: int = Path(..., description="Company ID"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("companies", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -218,7 +219,7 @@ async def admin_company_detail_page(
|
||||
async def admin_company_edit_page(
|
||||
request: Request,
|
||||
company_id: int = Path(..., description="Company ID"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("companies", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -242,7 +243,7 @@ async def admin_company_edit_page(
|
||||
@router.get("/vendors", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_vendors_list_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("vendors", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -261,7 +262,7 @@ async def admin_vendors_list_page(
|
||||
@router.get("/vendors/create", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_vendor_create_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("vendors", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -282,7 +283,7 @@ async def admin_vendor_create_page(
|
||||
async def admin_vendor_detail_page(
|
||||
request: Request,
|
||||
vendor_code: str = Path(..., description="Vendor code"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("vendors", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -305,7 +306,7 @@ async def admin_vendor_detail_page(
|
||||
async def admin_vendor_edit_page(
|
||||
request: Request,
|
||||
vendor_code: str = Path(..., description="Vendor code"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("vendors", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -334,7 +335,7 @@ async def admin_vendor_edit_page(
|
||||
async def admin_vendor_domains_page(
|
||||
request: Request,
|
||||
vendor_code: str = Path(..., description="Vendor code"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("vendors", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -359,7 +360,7 @@ async def admin_vendor_domains_page(
|
||||
@router.get("/vendor-themes", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_vendor_themes_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("vendor-themes", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -381,7 +382,7 @@ async def admin_vendor_themes_page(
|
||||
async def admin_vendor_theme_page(
|
||||
request: Request,
|
||||
vendor_code: str = Path(..., description="Vendor code"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("vendor-themes", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -406,18 +407,14 @@ async def admin_vendor_theme_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),
|
||||
current_user: User = Depends(require_menu_access("admin-users", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render admin users management page.
|
||||
Shows list of all admin users (super admins and platform admins).
|
||||
Super admin only.
|
||||
Super admin only (menu is in super_admin_only section).
|
||||
"""
|
||||
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/admin-users.html",
|
||||
@@ -431,17 +428,13 @@ async def admin_users_list_page(
|
||||
@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),
|
||||
current_user: User = Depends(require_menu_access("admin-users", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render admin user creation form.
|
||||
Super admin only.
|
||||
Super admin only (menu is in super_admin_only section).
|
||||
"""
|
||||
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",
|
||||
@@ -458,17 +451,13 @@ async def admin_user_create_page(
|
||||
async def admin_user_detail_page(
|
||||
request: Request,
|
||||
user_id: int = Path(..., description="User ID"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("admin-users", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render admin user detail view.
|
||||
Super admin only.
|
||||
Super admin only (menu is in super_admin_only section).
|
||||
"""
|
||||
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/admin-user-detail.html",
|
||||
@@ -486,17 +475,13 @@ async def admin_user_detail_page(
|
||||
async def admin_user_edit_page(
|
||||
request: Request,
|
||||
user_id: int = Path(..., description="User ID"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("admin-users", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render admin user edit form.
|
||||
Super admin only.
|
||||
Super admin only (menu is in super_admin_only section).
|
||||
"""
|
||||
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/admin-user-edit.html",
|
||||
@@ -557,7 +542,7 @@ async def admin_user_edit_page_redirect(user_id: int = Path(..., description="Us
|
||||
@router.get("/customers", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_customers_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("customers", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -581,7 +566,7 @@ async def admin_customers_page(
|
||||
@router.get("/notifications", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_notifications_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("notifications", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -605,7 +590,7 @@ async def admin_notifications_page(
|
||||
@router.get("/email-templates", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_email_templates_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("email-templates", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -629,7 +614,7 @@ async def admin_email_templates_page(
|
||||
@router.get("/messages", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_messages_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("messages", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -653,7 +638,7 @@ async def admin_messages_page(
|
||||
async def admin_conversation_detail_page(
|
||||
request: Request,
|
||||
conversation_id: int = Path(..., description="Conversation ID"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("messages", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -678,7 +663,7 @@ async def admin_conversation_detail_page(
|
||||
@router.get("/inventory", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_inventory_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("inventory", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -702,7 +687,7 @@ async def admin_inventory_page(
|
||||
@router.get("/orders", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_orders_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("orders", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -726,7 +711,7 @@ async def admin_orders_page(
|
||||
@router.get("/imports", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_imports_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("imports", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -745,7 +730,7 @@ async def admin_imports_page(
|
||||
@router.get("/background-tasks", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_background_tasks_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("background-tasks", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -765,7 +750,7 @@ async def admin_background_tasks_page(
|
||||
@router.get("/marketplace", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_marketplace_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("marketplace-letzshop", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -791,7 +776,7 @@ async def admin_marketplace_page(
|
||||
)
|
||||
async def admin_marketplace_letzshop_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("marketplace-letzshop", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -814,7 +799,7 @@ async def admin_marketplace_letzshop_page(
|
||||
async def admin_letzshop_order_detail_page(
|
||||
request: Request,
|
||||
order_id: int = Path(..., description="Letzshop order ID"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("marketplace-letzshop", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -840,7 +825,7 @@ async def admin_letzshop_order_detail_page(
|
||||
async def admin_letzshop_product_detail_page(
|
||||
request: Request,
|
||||
product_id: int = Path(..., description="Marketplace Product ID"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("marketplace-letzshop", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -870,7 +855,7 @@ async def admin_letzshop_product_detail_page(
|
||||
)
|
||||
async def admin_letzshop_vendor_directory_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("marketplace-letzshop", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -900,7 +885,7 @@ async def admin_letzshop_vendor_directory_page(
|
||||
)
|
||||
async def admin_marketplace_products_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("marketplace-letzshop", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -924,7 +909,7 @@ async def admin_marketplace_products_page(
|
||||
async def admin_marketplace_product_detail_page(
|
||||
request: Request,
|
||||
product_id: int = Path(..., description="Marketplace Product ID"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("marketplace-letzshop", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -945,7 +930,7 @@ async def admin_marketplace_product_detail_page(
|
||||
@router.get("/vendor-products", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_vendor_products_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("vendor-products", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -964,7 +949,7 @@ async def admin_vendor_products_page(
|
||||
@router.get("/vendor-products/create", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_vendor_product_create_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("vendor-products", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -988,7 +973,7 @@ async def admin_vendor_product_create_page(
|
||||
async def admin_vendor_product_detail_page(
|
||||
request: Request,
|
||||
product_id: int = Path(..., description="Vendor Product ID"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("vendor-products", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1013,7 +998,7 @@ async def admin_vendor_product_detail_page(
|
||||
async def admin_vendor_product_edit_page(
|
||||
request: Request,
|
||||
product_id: int = Path(..., description="Vendor Product ID"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("vendor-products", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1038,7 +1023,7 @@ async def admin_vendor_product_edit_page(
|
||||
@router.get("/subscription-tiers", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_subscription_tiers_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("subscription-tiers", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1057,7 +1042,7 @@ async def admin_subscription_tiers_page(
|
||||
@router.get("/subscriptions", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_subscriptions_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("subscriptions", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1076,7 +1061,7 @@ async def admin_subscriptions_page(
|
||||
@router.get("/billing-history", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_billing_history_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("billing-history", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1100,7 +1085,7 @@ async def admin_billing_history_page(
|
||||
@router.get("/settings", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_settings_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("settings", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1116,10 +1101,33 @@ async def admin_settings_page(
|
||||
)
|
||||
|
||||
|
||||
@router.get("/my-menu", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_my_menu_config(
|
||||
request: Request,
|
||||
current_user: User = Depends(require_menu_access("my-menu", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render personal menu configuration page for super admins.
|
||||
Allows super admins to customize their own sidebar menu.
|
||||
"""
|
||||
# Only super admins can configure their own menu
|
||||
if not current_user.is_super_admin:
|
||||
return RedirectResponse(url="/admin/settings", status_code=302)
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"admin/my-menu-config.html",
|
||||
{
|
||||
"request": request,
|
||||
"user": current_user,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.get("/logs", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_logs_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("logs", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1143,7 +1151,7 @@ async def admin_logs_page(
|
||||
@router.get("/platforms", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_platforms_list(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1165,7 +1173,7 @@ async def admin_platforms_list(
|
||||
async def admin_platform_detail(
|
||||
request: Request,
|
||||
platform_code: str = Path(..., description="Platform code (oms, loyalty, etc.)"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1190,7 +1198,7 @@ async def admin_platform_detail(
|
||||
async def admin_platform_edit(
|
||||
request: Request,
|
||||
platform_code: str = Path(..., description="Platform code"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1207,6 +1215,66 @@ async def admin_platform_edit(
|
||||
)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/platforms/{platform_code}/menu-config",
|
||||
response_class=HTMLResponse,
|
||||
include_in_schema=False,
|
||||
)
|
||||
async def admin_platform_menu_config(
|
||||
request: Request,
|
||||
platform_code: str = Path(..., description="Platform code"),
|
||||
current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render platform menu configuration page.
|
||||
Super admin only - allows configuring which menu items are visible
|
||||
for the platform's admin and vendor frontends.
|
||||
"""
|
||||
# Only super admins can access menu configuration
|
||||
if not current_user.is_super_admin:
|
||||
return RedirectResponse(url=f"/admin/platforms/{platform_code}", status_code=302)
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"admin/platform-menu-config.html",
|
||||
{
|
||||
"request": request,
|
||||
"user": current_user,
|
||||
"platform_code": platform_code,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/platforms/{platform_code}/modules",
|
||||
response_class=HTMLResponse,
|
||||
include_in_schema=False,
|
||||
)
|
||||
async def admin_platform_modules(
|
||||
request: Request,
|
||||
platform_code: str = Path(..., description="Platform code"),
|
||||
current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render platform module configuration page.
|
||||
Super admin only - allows enabling/disabling feature modules
|
||||
for the platform.
|
||||
"""
|
||||
# Only super admins can access module configuration
|
||||
if not current_user.is_super_admin:
|
||||
return RedirectResponse(url=f"/admin/platforms/{platform_code}", status_code=302)
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"admin/platform-modules.html",
|
||||
{
|
||||
"request": request,
|
||||
"user": current_user,
|
||||
"platform_code": platform_code,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# CONTENT MANAGEMENT SYSTEM (CMS) ROUTES
|
||||
# ============================================================================
|
||||
@@ -1215,7 +1283,7 @@ async def admin_platform_edit(
|
||||
@router.get("/platform-homepage", include_in_schema=False)
|
||||
async def admin_platform_homepage_manager(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1225,14 +1293,13 @@ async def admin_platform_homepage_manager(
|
||||
- /admin/platforms → Select platform → Homepage button
|
||||
- Or directly: /admin/content-pages?platform_code={code}&slug=home
|
||||
"""
|
||||
from starlette.responses import RedirectResponse
|
||||
return RedirectResponse(url="/admin/platforms", status_code=302)
|
||||
|
||||
|
||||
@router.get("/content-pages", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_content_pages_list(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("content-pages", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1253,7 +1320,7 @@ async def admin_content_pages_list(
|
||||
)
|
||||
async def admin_content_page_create(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("content-pages", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1278,7 +1345,7 @@ async def admin_content_page_create(
|
||||
async def admin_content_page_edit(
|
||||
request: Request,
|
||||
page_id: int = Path(..., description="Content page ID"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("content-pages", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1303,7 +1370,7 @@ async def admin_content_page_edit(
|
||||
@router.get("/components", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_components_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("components", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1322,7 +1389,7 @@ async def admin_components_page(
|
||||
@router.get("/icons", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_icons_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("icons", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1341,7 +1408,7 @@ async def admin_icons_page(
|
||||
@router.get("/testing", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_testing_dashboard(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("testing", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1360,7 +1427,7 @@ async def admin_testing_dashboard(
|
||||
@router.get("/testing-hub", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_testing_hub(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("testing", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1379,7 +1446,7 @@ async def admin_testing_hub(
|
||||
@router.get("/test/auth-flow", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_test_auth_flow(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("testing", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1402,7 +1469,7 @@ async def admin_test_auth_flow(
|
||||
)
|
||||
async def admin_test_vendors_users_migration(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("testing", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1426,7 +1493,7 @@ async def admin_test_vendors_users_migration(
|
||||
@router.get("/code-quality", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_code_quality_dashboard(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("code-quality", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1447,7 +1514,7 @@ async def admin_code_quality_dashboard(
|
||||
)
|
||||
async def admin_code_quality_violations(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("code-quality", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1471,7 +1538,7 @@ async def admin_code_quality_violations(
|
||||
async def admin_code_quality_violation_detail(
|
||||
request: Request,
|
||||
violation_id: int = Path(..., description="Violation ID"),
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("code-quality", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1496,7 +1563,7 @@ async def admin_code_quality_violation_detail(
|
||||
@router.get("/platform-health", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_platform_health(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("platform-health", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
@@ -1520,7 +1587,7 @@ async def admin_platform_health(
|
||||
@router.get("/features", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def admin_features_page(
|
||||
request: Request,
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header),
|
||||
current_user: User = Depends(require_menu_access("subscription-tiers", FrontendType.ADMIN)),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user