Coverage for src/lexigram/admin/controllers/error.py: 0%
29 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-24 23:18 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-24 23:18 +0800
1"""Error handler controller for Lexigram Admin.
3Provides user-friendly error pages for common HTTP errors.
4"""
6from __future__ import annotations
8from starlette.requests import Request
9from starlette.responses import HTMLResponse, RedirectResponse
11from lexigram.admin.controllers.base import AdminController
12from lexigram.admin.engine.renderer import AdminRenderer
13from lexigram.admin.lib.template import render_error_page
14from lexigram.contracts.web import get
15from lexigram.di.decorators import inject
18@inject
19class ErrorController(AdminController):
20 """Error page controller.
22 Provides styled error pages for:
23 - 401 Unauthorized - Redirects to login
24 - 403 Forbidden - Access denied
25 - 404 Not Found - Page not found
26 - 500 Internal Server Error - Server error
27 """
29 prefix = "/admin/error"
31 def __init__(self, renderer: AdminRenderer):
32 super().__init__(renderer)
34 def _render_error_page(
35 self,
36 status_code: int,
37 title: str,
38 message: str,
39 icon: str,
40 action_text: str = "Go to Dashboard",
41 action_url: str = "/admin/",
42 ) -> HTMLResponse:
43 """Render a styled error page using templates.
45 Args:
46 status_code: HTTP status code
47 title: Error title
48 message: Error message
49 icon: Emoji icon
50 action_text: Button text
51 action_url: Button URL
53 Returns:
54 HTMLResponse with styled error page
55 """
56 html = render_error_page(
57 status_code=status_code,
58 title=title,
59 message=message,
60 icon=icon,
61 action_text=action_text,
62 action_url=action_url,
63 )
64 return HTMLResponse(content=html, status_code=status_code)
66 @get("/401")
67 async def error_401(self, request: Request) -> RedirectResponse:
68 """Handle 401 Unauthorized - redirect to login."""
69 # Get the original URL for redirect after login
70 next_url = request.query_params.get("next", "/admin/")
71 return RedirectResponse(url=f"/admin/login?next={next_url}", status_code=302)
73 @get("/403")
74 async def error_403(self, request: Request) -> HTMLResponse:
75 """Handle 403 Forbidden."""
76 return self._render_error_page(
77 status_code=403,
78 title="Access Denied",
79 message="You don't have permission to access this resource. Please contact your administrator if you believe this is an error.",
80 icon="🔒",
81 )
83 @get("/404")
84 async def error_404(self, request: Request) -> HTMLResponse:
85 """Handle 404 Not Found."""
86 return self._render_error_page(
87 status_code=404,
88 title="Page Not Found",
89 message="The page you're looking for doesn't exist. It may have been moved or deleted.",
90 icon="🔍",
91 )
93 @get("/500")
94 async def error_500(self, request: Request) -> HTMLResponse:
95 """Handle 500 Internal Server Error."""
96 return self._render_error_page(
97 status_code=500,
98 title="Internal Server Error",
99 message="Something went wrong on our end. Our team has been notified and we're working to fix it.",
100 icon="⚠️",
101 )