feat: Add admin flag to user and templates

Passes an `is_admin` flag to the `CaseRecordingsTemplate` and
`case_page.html`.
This flag determines whether the full case ID is displayed in the meta
section
for administrative users. It also influences the header display on the
case page
to prioritize the oneliner when available.
This commit is contained in:
2026-04-19 17:33:29 +02:00
parent b7e54db54c
commit 6369ff1680
4 changed files with 132 additions and 30 deletions
+88
View File
@@ -25,6 +25,16 @@ fn make_user(slug: &str) -> User {
}
}
fn make_admin(slug: &str) -> User {
let mut u = make_user(slug);
u.role = "admin".into();
u
}
fn seed_oneliner(case_dir: &Path, text: &str) {
std::fs::write(case_dir.join("oneliner.txt"), text).unwrap();
}
fn config_with_llm_users(data_path: PathBuf, llm_url: String, users: Vec<User>) -> Arc<Config> {
let api_keys: HashMap<String, String> = users
.iter()
@@ -290,6 +300,84 @@ async fn case_recordings_back_link_targets_case_page() {
);
}
#[tokio::test]
async fn case_page_uses_oneliner_as_h1_when_present() {
let config = config_with_llm(unique_tmp("cp-h1"));
let case_id = "11111111-1111-1111-1111-111111111111";
let case_dir = seed_case(&config.data_path, "dr_a", case_id);
seed_oneliner(&case_dir, "Herzkatheter unauffällig");
std::fs::write(case_dir.join("document.md"), "Inhalt").unwrap();
let app = doctate_server::create_router(config);
let cookie = login(app.clone(), "dr_a").await;
let resp = app.oneshot(get_page(case_id, &cookie, "")).await.unwrap();
let body = body_string(resp).await;
// H1 wraps the oneliner; the short case_id fallback must be gone.
assert!(
body.contains("<h1>") && body.contains("Herzkatheter unauffällig"),
"h1 should show the oneliner"
);
// The prominent meta block with the full UUID is admin-only.
assert!(
!body.contains(r#"<div class="meta">"#),
"non-admin must not see the full case_id meta block"
);
}
#[tokio::test]
async fn case_page_admin_sees_full_case_id_meta() {
let data_path = unique_tmp("cp-admin");
let users = vec![make_admin("dr_admin")];
let config = config_with_llm_users(data_path, "http://unused".into(), users);
let case_id = "11111111-1111-1111-1111-111111111111";
seed_case(&config.data_path, "dr_admin", case_id);
let app = doctate_server::create_router(config);
let cookie = login(app.clone(), "dr_admin").await;
let resp = app.oneshot(get_page(case_id, &cookie, "")).await.unwrap();
let body = body_string(resp).await;
assert!(
body.contains(case_id),
"admin meta block should expose the full case_id"
);
}
#[tokio::test]
async fn case_recordings_breadcrumb_includes_oneliner() {
let config = config_with_llm(unique_tmp("rec-breadcrumb"));
let case_id = "11111111-1111-1111-1111-111111111111";
let case_dir = seed_case(&config.data_path, "dr_a", case_id);
seed_oneliner(&case_dir, "Kurzer Befund");
seed_recording(&case_dir, "10-00-00", None);
let app = doctate_server::create_router(config);
let cookie = login(app.clone(), "dr_a").await;
let resp = app
.oneshot(get_page(case_id, &cookie, "/recordings"))
.await
.unwrap();
let body = body_string(resp).await;
// Two separate breadcrumb links: back to the case list and back to the case page.
assert!(
body.contains(r#"href="/web/cases""#),
"breadcrumb must link back to the case list"
);
assert!(
body.contains(&format!(r#"href="/web/cases/{case_id}""#)),
"breadcrumb must link back to the case page"
);
assert!(
body.contains("Kurzer Befund"),
"breadcrumb must show the oneliner text"
);
}
#[tokio::test]
async fn case_recordings_has_no_action_buttons() {
let config = config_with_llm(unique_tmp("rec-ro"));