mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-13 16:02:59 +00:00
test: pin that an app draft read resolves no address
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYWxvwmteVyzcWenJfbnzs
This commit is contained in:
co-authored by
Claude Opus 5
parent
e744adb238
commit
f2f7ce8e96
@@ -2885,6 +2885,70 @@ async fn test_schedule_permissions_superadmin_not_in_workspace(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// An app read derives the address from the principal the *server* stored, and only from that
|
||||
/// one. A draft's principal is whatever its editor last typed, so deriving one would answer
|
||||
/// "which address is `u/x`?" for any principal a caller names — `superadmin-external` is a
|
||||
/// superadmin of no workspace, whose address `resolve_username_to_email` reaches instance-wide.
|
||||
#[sqlx::test(fixtures("preserve_on_behalf_of"))]
|
||||
async fn test_app_draft_read_does_not_derive_an_address(db: Pool<Postgres>) -> anyhow::Result<()> {
|
||||
initialize_tracing().await;
|
||||
|
||||
let server = ApiServer::start(db.clone()).await?;
|
||||
let base = format!(
|
||||
"http://localhost:{}/api/w/test-workspace",
|
||||
server.addr.port()
|
||||
);
|
||||
|
||||
let resp = authed(client().post(format!("{base}/apps/create")), "SECRET_TOKEN")
|
||||
.json(&new_app_with_on_behalf_of(
|
||||
"u/test-user/app_with_draft",
|
||||
Some("u/original-user"),
|
||||
None,
|
||||
true,
|
||||
))
|
||||
.send()
|
||||
.await?;
|
||||
assert_eq!(resp.status(), 201, "{}", resp.text().await?);
|
||||
|
||||
sqlx::query(
|
||||
r#"INSERT INTO draft (workspace_id, path, typ, value, email)
|
||||
VALUES ('test-workspace', 'u/test-user/app_with_draft', 'app', $1::text::json, 'test@windmill.dev')"#,
|
||||
)
|
||||
.bind(json!({ "policy": { "on_behalf_of": "u/superadmin-external" } }).to_string())
|
||||
.execute(&db)
|
||||
.await?;
|
||||
|
||||
let resp = authed(
|
||||
client().get(format!(
|
||||
"{base}/apps/get/p/u/test-user/app_with_draft?get_draft=true"
|
||||
)),
|
||||
"SECRET_TOKEN",
|
||||
)
|
||||
.send()
|
||||
.await?;
|
||||
let body: serde_json::Value = resp.json().await?;
|
||||
|
||||
assert_eq!(
|
||||
body["policy"]["on_behalf_of_email"].as_str(),
|
||||
Some("original@windmill.dev"),
|
||||
"the deployed policy carries the address derived from its principal"
|
||||
);
|
||||
// Asserted before the absence below, so that a response carrying no draft at all cannot
|
||||
// pass this test by having nothing to derive from.
|
||||
assert_eq!(
|
||||
body["draft"]["policy"]["on_behalf_of"].as_str(),
|
||||
Some("u/superadmin-external"),
|
||||
"the draft is returned, principal and all: {body}"
|
||||
);
|
||||
assert!(
|
||||
body["draft"]["policy"]["on_behalf_of_email"].is_null(),
|
||||
"the draft's principal must not be resolved: {}",
|
||||
body["draft"]
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Forged-superadmin on_behalf_of guard (GHSA-hfh4-cx4h-3fcr)
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user