diff --git a/app/api/deps.py b/app/api/deps.py
index d9537bd3..327be628 100644
--- a/app/api/deps.py
+++ b/app/api/deps.py
@@ -113,6 +113,44 @@ def get_current_admin_user(current_user: User = Depends(get_current_user)):
return auth_manager.require_admin(current_user)
+def get_current_vendor_user(current_user: User = Depends(get_current_user)):
+ """
+ Require vendor user (vendor owner or vendor staff).
+
+ This dependency ensures the current user has vendor role.
+ Used for protecting vendor-only routes.
+
+ Args:
+ current_user: User object from get_current_user dependency
+
+ Returns:
+ User: Vendor user object
+
+ Raises:
+ InsufficientPermissionsException: If user is not a vendor user
+ """
+ return auth_manager.require_vendor(current_user)
+
+
+def get_current_customer_user(current_user: User = Depends(get_current_user)):
+ """
+ Require customer user.
+
+ This dependency ensures the current user has customer role.
+ Used for protecting customer account routes.
+
+ Args:
+ current_user: User object from get_current_user dependency
+
+ Returns:
+ User: Customer user object
+
+ Raises:
+ InsufficientPermissionsException: If user is not a customer
+ """
+ return auth_manager.require_customer(current_user)
+
+
def get_user_vendor(
vendor_code: str,
current_user: User = Depends(get_current_user),
diff --git a/app/api/v1/admin/pages.py b/app/api/v1/admin/pages.py
index 8740bec8..bafdafb0 100644
--- a/app/api/v1/admin/pages.py
+++ b/app/api/v1/admin/pages.py
@@ -3,17 +3,25 @@
Admin HTML page routes using Jinja2 templates.
These routes return rendered HTML pages (response_class=HTMLResponse).
-Separate from other admin routes which return JSON data.
+Separate from admin API routes which return JSON data.
+
+All routes require admin authentication except /login.
+Authentication failures redirect to /admin/login.
Routes:
-- GET / - Admin root (redirects to login)
-- GET /login - Admin login page (no auth required)
-- GET /dashboard - Admin dashboard (requires auth)
-- GET /vendors - Vendor management page (requires auth)
-- GET /users - User management page (requires auth)
+- GET / → Redirect to /admin/login
+- GET /login → Admin login page (no auth)
+- GET /dashboard → Admin dashboard (auth required)
+- GET /vendors → Vendor list page (auth required)
+- GET /vendors/create → Create vendor form (auth required)
+- GET /vendors/{vendor_code} → Vendor details (auth required)
+- GET /vendors/{vendor_code}/edit → Edit vendor form (auth required)
+- GET /users → User management page (auth required)
+- GET /imports → Import history page (auth required)
+- GET /settings → Settings page (auth required)
"""
-from fastapi import APIRouter, Request, Depends
+from fastapi import APIRouter, Request, Depends, Path
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session
@@ -25,18 +33,18 @@ router = APIRouter()
templates = Jinja2Templates(directory="app/templates")
+# ============================================================================
+# PUBLIC ROUTES (No Authentication Required)
+# ============================================================================
+
@router.get("/", response_class=RedirectResponse, include_in_schema=False)
async def admin_root():
"""
Redirect /admin/ to /admin/login.
-
- This is the simplest approach:
- - Unauthenticated users: see login form
- - Authenticated users: login page clears token and shows form
- (they can manually navigate to dashboard if needed)
-
- Alternative: Could redirect to /admin/dashboard and let auth
- dependency handle the redirect, but that's an extra hop.
+
+ Simple approach:
+ - Unauthenticated users → see login form
+ - Authenticated users → login page shows form (they can navigate to dashboard)
"""
return RedirectResponse(url="/admin/login", status_code=302)
@@ -53,15 +61,19 @@ async def admin_login_page(request: Request):
)
+# ============================================================================
+# AUTHENTICATED ROUTES (Admin Only)
+# ============================================================================
+
@router.get("/dashboard", response_class=HTMLResponse, include_in_schema=False)
async def admin_dashboard_page(
- request: Request,
- current_user: User = Depends(get_current_admin_user),
- db: Session = Depends(get_db)
+ request: Request,
+ current_user: User = Depends(get_current_admin_user),
+ db: Session = Depends(get_db)
):
"""
Render admin dashboard page.
- Requires admin authentication - will redirect to login if not authenticated.
+ Shows platform statistics and recent activity.
"""
return templates.TemplateResponse(
"admin/dashboard.html",
@@ -72,15 +84,19 @@ async def admin_dashboard_page(
)
+# ============================================================================
+# VENDOR MANAGEMENT ROUTES
+# ============================================================================
+
@router.get("/vendors", response_class=HTMLResponse, include_in_schema=False)
-async def admin_vendors_page(
- request: Request,
- current_user: User = Depends(get_current_admin_user),
- db: Session = Depends(get_db)
+async def admin_vendors_list_page(
+ request: Request,
+ current_user: User = Depends(get_current_admin_user),
+ db: Session = Depends(get_db)
):
"""
Render vendors management page.
- Requires admin authentication.
+ Shows list of all vendors with stats.
"""
return templates.TemplateResponse(
"admin/vendors.html",
@@ -91,15 +107,78 @@ async def admin_vendors_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_user),
+ db: Session = Depends(get_db)
+):
+ """
+ Render vendor creation form.
+ """
+ return templates.TemplateResponse(
+ "admin/vendor-create.html",
+ {
+ "request": request,
+ "user": current_user,
+ }
+ )
+
+
+@router.get("/vendors/{vendor_code}", response_class=HTMLResponse, include_in_schema=False)
+async def admin_vendor_detail_page(
+ request: Request,
+ vendor_code: str = Path(..., description="Vendor code"),
+ current_user: User = Depends(get_current_admin_user),
+ db: Session = Depends(get_db)
+):
+ """
+ Render vendor detail page.
+ Shows full vendor information.
+ """
+ return templates.TemplateResponse(
+ "admin/vendor-detail.html",
+ {
+ "request": request,
+ "user": current_user,
+ "vendor_code": vendor_code,
+ }
+ )
+
+
+@router.get("/vendors/{vendor_code}/edit", response_class=HTMLResponse, include_in_schema=False)
+async def admin_vendor_edit_page(
+ request: Request,
+ vendor_code: str = Path(..., description="Vendor code"),
+ current_user: User = Depends(get_current_admin_user),
+ db: Session = Depends(get_db)
+):
+ """
+ Render vendor edit form.
+ """
+ return templates.TemplateResponse(
+ "admin/vendor-edit.html",
+ {
+ "request": request,
+ "user": current_user,
+ "vendor_code": vendor_code,
+ }
+ )
+
+
+# ============================================================================
+# USER MANAGEMENT ROUTES
+# ============================================================================
+
@router.get("/users", response_class=HTMLResponse, include_in_schema=False)
async def admin_users_page(
- request: Request,
- current_user: User = Depends(get_current_admin_user),
- db: Session = Depends(get_db)
+ request: Request,
+ current_user: User = Depends(get_current_admin_user),
+ db: Session = Depends(get_db)
):
"""
Render users management page.
- Requires admin authentication.
+ Shows list of all platform users.
"""
return templates.TemplateResponse(
"admin/users.html",
@@ -108,3 +187,49 @@ async def admin_users_page(
"user": current_user,
}
)
+
+
+# ============================================================================
+# IMPORT MANAGEMENT ROUTES
+# ============================================================================
+
+@router.get("/imports", response_class=HTMLResponse, include_in_schema=False)
+async def admin_imports_page(
+ request: Request,
+ current_user: User = Depends(get_current_admin_user),
+ db: Session = Depends(get_db)
+):
+ """
+ Render imports management page.
+ Shows import history and status.
+ """
+ return templates.TemplateResponse(
+ "admin/imports.html",
+ {
+ "request": request,
+ "user": current_user,
+ }
+ )
+
+
+# ============================================================================
+# SETTINGS ROUTES
+# ============================================================================
+
+@router.get("/settings", response_class=HTMLResponse, include_in_schema=False)
+async def admin_settings_page(
+ request: Request,
+ current_user: User = Depends(get_current_admin_user),
+ db: Session = Depends(get_db)
+):
+ """
+ Render admin settings page.
+ Platform configuration and preferences.
+ """
+ return templates.TemplateResponse(
+ "admin/settings.html",
+ {
+ "request": request,
+ "user": current_user,
+ }
+ )
diff --git a/app/templates/admin/base.html b/app/templates/admin/base.html
index bee5be62..e16f8678 100644
--- a/app/templates/admin/base.html
+++ b/app/templates/admin/base.html
@@ -37,24 +37,27 @@
-
+
-
+
+
+
+
-
+
-
-
-
-
+
-
+
+
+
+
-
+
{% block extra_scripts %}{% endblock %}