feat(10-01): serve the embedded admin SPA at backend.uri with cookie login
- backend.uri prefix (default /backend) mounts the admin API at {prefix}/api/v1
and the embedded SPA shell at {prefix} with an api/ JSON 404 fallback
- cookie transport: an X-Requested-With login sets the HttpOnly summer_admin
cookie and returns no token; the backend guard reads the cookie after Bearer
- CSRF wrapper refuses cookie-only POST/PUT/DELETE without X-Requested-With
- boardwalk package embeds boardwalk/dist, rewrites index.html once per prefix
and sets cache and security headers
- framework admin OpenAPI pipeline (swag, swagger2openapi, openapi-typescript)
with prefix-relative paths and typed envelopes for the tracer routes
- admin/ Vite SPA: login, plugin rail, section panel and read-only list
through the openapi-fetch client typed by the generated schema
This commit is contained in:
55
admin/tests/fixtures/navigation.json
vendored
Normal file
55
admin/tests/fixtures/navigation.json
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"code": "demo",
|
||||
"label": "Demo",
|
||||
"icon": "disc-3",
|
||||
"order": 100,
|
||||
"controller": "acme.demo.widgets",
|
||||
"sideMenu": [
|
||||
{
|
||||
"code": "widgets",
|
||||
"label": "Widgets",
|
||||
"icon": "tags",
|
||||
"order": 0,
|
||||
"controller": "acme.demo.widgets",
|
||||
"sideMenu": []
|
||||
},
|
||||
{
|
||||
"code": "gadgets",
|
||||
"label": "Gadgets",
|
||||
"icon": "icon-archive",
|
||||
"order": 0,
|
||||
"controller": "acme.demo.gadgets",
|
||||
"sideMenu": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "tools",
|
||||
"label": "Tools",
|
||||
"icon": "unknown-icon-name",
|
||||
"order": 300,
|
||||
"controller": "acme.tools.hammers",
|
||||
"sideMenu": [
|
||||
{
|
||||
"code": "hammers",
|
||||
"label": "Hammers",
|
||||
"icon": "puzzle",
|
||||
"order": 0,
|
||||
"controller": "acme.tools.hammers",
|
||||
"sideMenu": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "hidden",
|
||||
"label": "Hidden",
|
||||
"icon": "users",
|
||||
"order": 200,
|
||||
"controller": "acme.hidden.items",
|
||||
"sideMenu": []
|
||||
}
|
||||
],
|
||||
"meta": { "locale": "en" }
|
||||
}
|
||||
22
admin/tests/fixtures/widgets.list-schema.json
vendored
Normal file
22
admin/tests/fixtures/widgets.list-schema.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"data": {
|
||||
"title": "Widgets",
|
||||
"recordsPerPage": 20,
|
||||
"perPageOptions": [],
|
||||
"showSearch": true,
|
||||
"showSetup": false,
|
||||
"showCheckboxes": true,
|
||||
"showSorting": true,
|
||||
"searchTerm": "",
|
||||
"toolbarButtons": ["create"],
|
||||
"columns": [
|
||||
{ "key": "name", "label": "Name", "searchable": true, "sortable": true },
|
||||
{ "key": "code", "label": "Code", "searchable": true, "sortable": true },
|
||||
{ "key": "tags", "label": "Tags", "searchable": false, "sortable": false, "type": "relation", "relation": "tags", "select": "name" }
|
||||
],
|
||||
"filters": [],
|
||||
"rowActions": [],
|
||||
"bulkActions": []
|
||||
},
|
||||
"meta": { "locale": "en" }
|
||||
}
|
||||
7
admin/tests/fixtures/widgets.list.json
vendored
Normal file
7
admin/tests/fixtures/widgets.list.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"data": [
|
||||
{ "id": 1, "name": "Blue widget", "code": "W-01", "tags": ["small", "round"] },
|
||||
{ "id": 2, "name": "Green widget", "code": "W-02", "tags": [] }
|
||||
],
|
||||
"meta": { "page": 1, "per_page": 20, "total": 2, "last_page": 1 }
|
||||
}
|
||||
Reference in New Issue
Block a user