umbral-admin 0.0.12

Auto-generated CRUD admin UI for umbral models.
Documentation
[package]
name = "umbral-admin"
description = "Auto-generated CRUD admin UI for umbral models."
# Plugins live under `plugins/` (a sibling of `crates/`), so the
# workspace pointer matches what umbral-auth does.
workspace = "../.."
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
authors.workspace = true
rust-version.workspace = true

[dependencies]
umbral = { path = "../../crates/umbral", version = "0.0.12" }
# axum is needed for State + Query extractors used by the new AdminConfig
# routing surface. umbral's web re-exports don't include State.
axum = "0.8"
# Required for the auth gate. The admin uses umbral-auth's
# `authenticate` helper to verify credentials on login.
umbral-auth = { path = "../umbral-auth", version = "0.0.12" }
# Feature #75: per-model permission checks. The admin calls
# `umbral_permissions::has_perm_for_superuser` at the top of every
# CRUD handler. When PermissionsPlugin is NOT installed, all checks
# short-circuit to allow (preserves pre-#75 staff-only gating).
umbral-permissions = { path = "../umbral-permissions", version = "0.0.12" }
# Session management: create_session, login, logout, current_user.
# Used by the HTML login flow to replace the old Basic Auth challenge.
umbral-sessions = { path = "../umbral-sessions", version = "0.0.12" }
# CSRF token generation for the login form. The admin embeds a
# hidden csrf_token field and verifies it on POST /admin/login.
# We reuse umbral-security's generate_token() rather than rolling our own.
umbral-security = { path = "../umbral-security", version = "0.0.12" }
# Form decoding + row marshalling. The admin parses POST bodies
# through `serde_urlencoded` (axum's `Form` extractor under the
# hood) and writes them back through dynamic sqlx::query calls.
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_urlencoded = "0.7"
chrono = { version = "0.4", features = ["serde"] }
sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio", "chrono", "uuid"] }
uuid = { version = "1", features = ["serde", "v7"] }
# Admin owns its own minijinja Environment with the embedded
# templates from `templates/`. The framework's ambient template
# engine is OnceLock-protected so the admin can't register into it
# after `App::build` runs; a private env is cleaner anyway since the
# admin's templates are an internal API.
minijinja = "2"
# Server-side logging of admin database errors. The error response
# returns a fixed string to the browser; the full sqlx error goes
# here so operators can debug without leaking query fragments to
# (potentially compromised) staff sessions.
tracing = "0.1"
# Phase 4: on_ready spawns async table creation via tokio::runtime::Handle.
tokio = { version = "1", features = ["rt"] }
# Concurrent COUNT futures for the dashboard's per-model row counters
# (was a real N+1 from the user's perspective: every additional model
# registered added another sequential round-trip to /admin/).
futures-util = "0.3"

[dev-dependencies]
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread", "sync"] }
tempfile = "3"
tower = { version = "0.5", features = ["util"] }
http = "1"
http-body-util = "0.1"
axum = "0.8"
serde_urlencoded = "0.7"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
chrono = { version = "0.4", features = ["serde"] }
sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio", "chrono", "uuid"] }
umbral-auth = { path = "../umbral-auth" }
umbral-sessions = { path = "../umbral-sessions" }