polyadmin 0.1.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- polyadmin/__init__.py +47 -0
- polyadmin/core/__init__.py +0 -0
- polyadmin/core/_async.py +21 -0
- polyadmin/core/action.py +135 -0
- polyadmin/core/admin.py +129 -0
- polyadmin/core/audit.py +65 -0
- polyadmin/core/auth.py +52 -0
- polyadmin/core/authorization.py +48 -0
- polyadmin/core/csrf.py +70 -0
- polyadmin/core/dashboard.py +41 -0
- polyadmin/core/delete.py +146 -0
- polyadmin/core/exporter.py +136 -0
- polyadmin/core/field.py +201 -0
- polyadmin/core/filter.py +305 -0
- polyadmin/core/inline.py +97 -0
- polyadmin/core/login.py +110 -0
- polyadmin/core/model_admin.py +349 -0
- polyadmin/core/page.py +62 -0
- polyadmin/core/pagination.py +70 -0
- polyadmin/core/query.py +243 -0
- polyadmin/core/relation.py +40 -0
- polyadmin/core/slug.py +57 -0
- polyadmin/core/template_context.py +679 -0
- polyadmin/core/widget.py +280 -0
- polyadmin/fastapi/__init__.py +3 -0
- polyadmin/fastapi/audit.py +52 -0
- polyadmin/fastapi/auth.py +112 -0
- polyadmin/fastapi/csrf.py +93 -0
- polyadmin/fastapi/deletes.py +76 -0
- polyadmin/fastapi/errors.py +93 -0
- polyadmin/fastapi/handlers.py +798 -0
- polyadmin/fastapi/inlines.py +177 -0
- polyadmin/fastapi/locale.py +128 -0
- polyadmin/fastapi/login.py +110 -0
- polyadmin/fastapi/pages.py +97 -0
- polyadmin/fastapi/relations.py +264 -0
- polyadmin/fastapi/responses.py +55 -0
- polyadmin/fastapi/router.py +174 -0
- polyadmin/fastapi/static.py +21 -0
- polyadmin/i18n/__init__.py +50 -0
- polyadmin/i18n/context.py +54 -0
- polyadmin/i18n/negotiation.py +56 -0
- polyadmin/i18n/setup.py +81 -0
- polyadmin/i18n/translator.py +124 -0
- polyadmin/locale/fr/LC_MESSAGES/polyadmin.mo +0 -0
- polyadmin/locale/fr/LC_MESSAGES/polyadmin.po +486 -0
- polyadmin/locale/polyadmin.pot +485 -0
- polyadmin/locale/ru/LC_MESSAGES/polyadmin.mo +0 -0
- polyadmin/locale/ru/LC_MESSAGES/polyadmin.po +496 -0
- polyadmin/templates/admin/base.html +91 -0
- polyadmin/templates/admin/components/action_confirm_modal.html +86 -0
- polyadmin/templates/admin/components/csrf-field.html +5 -0
- polyadmin/templates/admin/components/error_fragment.html +6 -0
- polyadmin/templates/admin/components/field.html +60 -0
- polyadmin/templates/admin/components/form_wrapper.html +131 -0
- polyadmin/templates/admin/components/icons.html +67 -0
- polyadmin/templates/admin/components/inline.html +251 -0
- polyadmin/templates/admin/components/inline_fragment.html +2 -0
- polyadmin/templates/admin/components/list_content.html +54 -0
- polyadmin/templates/admin/components/lookup_results.html +19 -0
- polyadmin/templates/admin/components/search.html +19 -0
- polyadmin/templates/admin/components/toasts.html +151 -0
- polyadmin/templates/admin/components/ui/breadcrumb.html +30 -0
- polyadmin/templates/admin/components/ui/bulk-actions.html +69 -0
- polyadmin/templates/admin/components/ui/calendar.html +175 -0
- polyadmin/templates/admin/components/ui/combobox.html +82 -0
- polyadmin/templates/admin/components/ui/delete-preview.html +37 -0
- polyadmin/templates/admin/components/ui/dropdown-menu.html +71 -0
- polyadmin/templates/admin/components/ui/field.html +110 -0
- polyadmin/templates/admin/components/ui/filter-panel.html +155 -0
- polyadmin/templates/admin/components/ui/locale-switcher.html +30 -0
- polyadmin/templates/admin/components/ui/multi-select.html +253 -0
- polyadmin/templates/admin/components/ui/pagination.html +81 -0
- polyadmin/templates/admin/components/ui/radio-group.html +28 -0
- polyadmin/templates/admin/components/ui/select.html +165 -0
- polyadmin/templates/admin/components/ui/sidebar.html +175 -0
- polyadmin/templates/admin/components/ui/slider.html +22 -0
- polyadmin/templates/admin/components/ui/switch.html +36 -0
- polyadmin/templates/admin/components/ui/table.html +221 -0
- polyadmin/templates/admin/components/ui/theme-toggle.html +33 -0
- polyadmin/templates/admin/dashboard.html +35 -0
- polyadmin/templates/admin/error.html +33 -0
- polyadmin/templates/admin/login.html +94 -0
- polyadmin/templates/admin/resource/delete.html +29 -0
- polyadmin/templates/admin/resource/delete_selected.html +49 -0
- polyadmin/templates/admin/resource/detail.html +78 -0
- polyadmin/templates/admin/resource/form.html +5 -0
- polyadmin/templates/admin/resource/list.html +5 -0
- polyadmin/templates/admin/theme.html +372 -0
- polyadmin/templates/admin/widgets/activity.html +8 -0
- polyadmin/templates/admin/widgets/chart.html +15 -0
- polyadmin/templates/admin/widgets/donut.html +59 -0
- polyadmin/templates/admin/widgets/metric.html +1 -0
- polyadmin/templates/admin/widgets/progress.html +7 -0
- polyadmin/templates/admin/widgets/stat.html +22 -0
- polyadmin/templates/admin/widgets/table.html +29 -0
- polyadmin/templates/admin/widgets/tabs.html +34 -0
- polyadmin/templates/admin/widgets/timeline.html +21 -0
- polyadmin/templating.py +528 -0
- polyadmin/ui.py +817 -0
- polyadmin-0.1.0b1.dist-info/METADATA +239 -0
- polyadmin-0.1.0b1.dist-info/RECORD +104 -0
- polyadmin-0.1.0b1.dist-info/WHEEL +4 -0
- polyadmin-0.1.0b1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Error responses.
|
|
2
|
+
|
|
3
|
+
Every failure the admin can produce used to be a bare text body --
|
|
4
|
+
`HTMLResponse("Permission denied.", status_code=403)` and friends.
|
|
5
|
+
Someone signed into a themed admin who followed a stale link got a
|
|
6
|
+
white page with three words on it, no navigation, and no way back.
|
|
7
|
+
These render the same failures as an actual page.
|
|
8
|
+
|
|
9
|
+
Deliberately renderer-independent: the page needs the site title and
|
|
10
|
+
the base path and nothing else, so the handlers that never took a
|
|
11
|
+
Renderer and the CSRF route class can all report errors without
|
|
12
|
+
threading one through.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from functools import lru_cache
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
from fastapi import Request
|
|
21
|
+
from fastapi.responses import HTMLResponse
|
|
22
|
+
|
|
23
|
+
from polyadmin.fastapi.responses import is_htmx_request
|
|
24
|
+
from polyadmin.i18n import N_, gettext
|
|
25
|
+
|
|
26
|
+
FORBIDDEN = (N_("Permission denied"), N_("Your account doesn't have permission to do that."))
|
|
27
|
+
NOT_FOUND = (N_("Not found"), N_("That record doesn't exist, or it was deleted."))
|
|
28
|
+
UNAUTHENTICATED = (N_("Sign-in required"), N_("You need to be signed in to view this page."))
|
|
29
|
+
CSRF_FAILED = (
|
|
30
|
+
N_("Security check failed"),
|
|
31
|
+
N_("This page expired before the form was submitted. Reload and try again."),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@lru_cache(maxsize=1)
|
|
36
|
+
def _renderer():
|
|
37
|
+
# Built once: the error page is request-independent apart from the
|
|
38
|
+
# status, the message, and two strings off the Admin. Imported here
|
|
39
|
+
# rather than at module scope to keep this module importable from
|
|
40
|
+
# templating.py's own dependencies without a cycle.
|
|
41
|
+
from polyadmin.templating import Renderer
|
|
42
|
+
|
|
43
|
+
return Renderer()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def error_response(
|
|
47
|
+
request: Request,
|
|
48
|
+
admin: Any,
|
|
49
|
+
base_path: str,
|
|
50
|
+
status: int,
|
|
51
|
+
title: str,
|
|
52
|
+
message: str,
|
|
53
|
+
) -> HTMLResponse:
|
|
54
|
+
"""Render a failure as a page -- or, for an htmx request, as just the
|
|
55
|
+
alert, since a whole document swapped into a table cell is nonsense.
|
|
56
|
+
"""
|
|
57
|
+
context = {
|
|
58
|
+
"site_title": gettext(getattr(admin, "site_title", "") or "PolyAdmin"),
|
|
59
|
+
"status": status,
|
|
60
|
+
"title": gettext(title),
|
|
61
|
+
"message": gettext(message),
|
|
62
|
+
# No point offering the link when an unauthenticated visitor
|
|
63
|
+
# cannot reach the dashboard either.
|
|
64
|
+
"home_url": "" if status == 401 else base_path,
|
|
65
|
+
}
|
|
66
|
+
template = (
|
|
67
|
+
"admin/components/error_fragment.html" if is_htmx_request(request) else "admin/error.html"
|
|
68
|
+
)
|
|
69
|
+
try:
|
|
70
|
+
renderer = getattr(request.state, "renderer", None) or _renderer()
|
|
71
|
+
html = renderer.render(template, context)
|
|
72
|
+
except Exception: # noqa: BLE001 -- see below
|
|
73
|
+
# The error page itself failed to build. Fall back to the plain
|
|
74
|
+
# body rather than returning nothing at all -- an ugly 403 beats
|
|
75
|
+
# a blank 500 that hides which failure actually happened.
|
|
76
|
+
return HTMLResponse(message, status_code=status)
|
|
77
|
+
return HTMLResponse(html, status_code=status)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def forbidden(request: Request, admin: Any, base_path: str) -> HTMLResponse:
|
|
81
|
+
return error_response(request, admin, base_path, 403, *FORBIDDEN)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def not_found(request: Request, admin: Any, base_path: str) -> HTMLResponse:
|
|
85
|
+
return error_response(request, admin, base_path, 404, *NOT_FOUND)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def unauthenticated(request: Request, admin: Any, base_path: str) -> HTMLResponse:
|
|
89
|
+
return error_response(request, admin, base_path, 401, *UNAUTHENTICATED)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def csrf_failure(request: Request, admin: Any, base_path: str) -> HTMLResponse:
|
|
93
|
+
return error_response(request, admin, base_path, 403, *CSRF_FAILED)
|