feat(settings): admin-only Import & Export page for tenant data #423
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/mapps-364-import-export"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements MAPPS-364 (slice of PMS-646): an admin-only "Import & Export" page in mokosh-apps for tenant data backup/restore, entirely in the UI (no CLI/docker).
What changed
New page
/settings/import-export(settings::ImportExportSettingsPage), admin-gated viause_is_admin+AdminOnlyNotice, filed under the Integrations settings group (route + wrapper +SETTINGS_SURFACESrow).Export panel - a Download button calls
GET /api/v1/data/exportwith the bearer and saves the returned JSON attachment using the server'sContent-Dispositionfilename. The bearer lives in WASM memory (not a cookie), so a plain<a href>can't carry it; this adds:fetch::api::get_authed_bytes(path)- bearer GET returning raw bytes + the parsedContent-Dispositionfilename.utils::download::save_bytes_as_file(bytes, filename)- wraps bytes in a Blob and clicks a synthesized anchor.Blob,Url,HtmlAnchorElement.Import panel - a file picker reads the exported JSON via Dioxus
evt.files()/FileData::read_string; a destructive-confirmation input requires typing the current tenant's name (auth.active_org_name(), which matches the backendconfirmcheck againsttenants.name) before the Import button enables. On submit it POSTs{ confirm, export }toPOST /api/v1/data/importvia the existing JSONpost_authed_typed(import is JSON, not multipart) and renders the per-table row-count summary. A clear red warning states import replaces all current tenant data. The write is also blocked while the server is unreachable (use_can_mutate).Verified locally
Ran the CI gate against the
rust-builder-glibcimage:cargo fmt --all --check,cargo clippy --all-targets -- -D warnings,cargo check --target wasm32-unknown-unknown, andcargo test --lib(214 passed) all pass. Notably this caught that Dioxus 0.7.7's file API isevt.files() -> Vec<FileData>(not the olderFileEngine), which is what the code now uses.Acceptance criteria
GET /data/exportusing the server filename; errors surfaced.Notes
active_org_name()(the org name shown in the switcher, =tenants.name). If that ever diverged fromtenants.namethe server would 400 with "confirmation does not match"; the same string is displayed and client-gated, so they stay consistent.group:change) if preferred.mokosh-export-<tenant_uuid>.json(server-set); the client just honors it.Add an admin-only "Import & Export" settings page (MAPPS-364, server PMS-646) so a tenant admin can back up and restore data entirely from the UI, no CLI or docker step. Export: a Download button fetches GET /api/v1/data/export with the bearer and saves the returned JSON attachment, honoring the server Content-Disposition filename. Because the bearer lives in WASM memory (not a cookie), a plain <a href> cannot carry it, so this adds a fetch-layer helper `get_authed_bytes` (bearer GET returning raw bytes + the parsed filename) and a `utils::download::save_bytes_as_file` helper that wraps the bytes in a Blob and clicks a synthesized anchor. Enables the web-sys Blob/Url/HtmlAnchorElement features. Import: a file picker reads the exported JSON via Dioxus `evt.files()`/`FileData::read_string`, and a destructive-confirmation input requires the admin to type the current tenant's name (matching the backend `confirm` guard against tenants.name) before the Import button enables. On submit it POSTs { confirm, export } to /api/v1/data/import via the existing JSON `post_authed_typed` (import is JSON, not multipart) and renders the per-table row-count summary the server returns. A clear warning states that import replaces all current tenant data. Both actions are admin-gated (use_is_admin + AdminOnlyNotice); the page is filed under the Integrations settings group. Verified locally against the rust-builder image: fmt, clippy -D warnings, wasm check, and cargo test --lib all pass. #MAPPS-364 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>