web permissions2

This commit is contained in:
Priec
2026-08-11 14:33:24 +02:00
parent 5602140d05
commit 077d69d756
47 changed files with 2348 additions and 674 deletions

View File

@@ -139,7 +139,7 @@ fn router(state: AppState) -> Router {
.merge(pages::login::router())
.merge(pages::register::router())
.merge(pages::admin::admin::router())
.merge(pages::admin::permissions::router())
.merge(pages::permissions::router())
.merge(pages::admin::table_definition::router())
.merge(pages::add_table::router())
.merge(pages::add_logic::router())
@@ -317,6 +317,60 @@ mod tests {
}
}
/// Permissions is a nav section of its own, so its three pages are mounted
/// at the top level rather than under /admin — and each of them, like every
/// other page behind a session, sends an anonymous visitor to the login
/// page instead of calling the backend.
#[tokio::test]
async fn the_permission_sections_are_mounted_and_need_a_session() {
for path in [
"/permissions",
"/permissions/roles",
"/permissions/users",
"/permissions/grants",
] {
let (status, _) = get(path).await;
assert_eq!(
status,
axum::http::StatusCode::SEE_OTHER,
"{path} did not send an anonymous visitor to the login page"
);
}
// The forms answer a lost session the way every form does: with the
// failure rendered into the page, not a 404 from an unmounted route.
for (path, body) in [
("/permissions/roles/create", "name=sales&access=none"),
("/permissions/roles/remove", "role=sales"),
("/permissions/users/role", "username=alice&role=sales"),
(
"/permissions/users/password",
"username=alice&new_password=a&new_password_confirmation=a",
),
(
"/permissions/grants/apply",
"role=sales&mode=grant&pair=data%3A*%7Cread",
),
] {
let response = test_router()
.oneshot(
Request::builder()
.method("POST")
.uri(path)
.header("content-type", "application/x-www-form-urlencoded")
.body(Body::from(body))
.unwrap(),
)
.await
.unwrap();
assert_eq!(
response.status(),
axum::http::StatusCode::UNPROCESSABLE_ENTITY,
"{path} is not mounted"
);
}
}
#[tokio::test]
async fn stylesheet_is_served_once_for_every_page() {
let (status, body) = get("/static/app.css").await;