Files
windmill/backend/tests/path_autocomplete_scope.rs
T
Ruben FiszelandClaude Opus 5.5 f4dcaf3e45 fix: list only the paths the caller can read in path autocomplete (#11388)
* fix: list only the paths the caller can read in path autocomplete

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: bound the path autocomplete cache by total path count

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 17:55:16 +02:00

63 lines
1.9 KiB
Rust

//! `GET /path_autocomplete/list_paths` returns only the paths the caller can read,
//! and its cache never serves one caller's list to another.
use sqlx::{Pool, Postgres};
use windmill_test_utils::*;
async fn list_paths(port: u16, token: &str) -> anyhow::Result<Vec<String>> {
let resp = reqwest::Client::new()
.get(format!(
"http://localhost:{port}/api/w/test-workspace/path_autocomplete/list_paths"
))
.header("Authorization", format!("Bearer {token}"))
.send()
.await?;
assert_eq!(resp.status(), 200, "list_paths: {}", resp.text().await?);
let body: serde_json::Value = resp.json().await?;
Ok(serde_json::from_value(body["paths"].clone())?)
}
#[sqlx::test(fixtures("base"))]
async fn test_list_paths_is_scoped_to_caller(db: Pool<Postgres>) -> anyhow::Result<()> {
initialize_tracing().await;
sqlx::query(
"INSERT INTO folder (workspace_id, name, display_name, owners, extra_perms)
VALUES ('test-workspace', 'secret', 'secret', '{}', '{}')",
)
.execute(&db)
.await?;
for path in [
"f/secret/hidden",
"u/test-user/private",
"u/test-user-2/mine",
] {
sqlx::query(
"INSERT INTO variable (workspace_id, path, value, is_secret, description)
VALUES ('test-workspace', $1, 'x', false, '')",
)
.bind(path)
.execute(&db)
.await?;
}
let server = ApiServer::start(db.clone()).await?;
let port = server.addr.port();
// The admin's call fills the cache first, so a cache shared across callers
// would hand the admin's list to the non-admin.
assert_eq!(
list_paths(port, "SECRET_TOKEN").await?,
[
"f/secret/hidden",
"u/test-user-2/mine",
"u/test-user/private"
]
);
assert_eq!(
list_paths(port, "SECRET_TOKEN_2").await?,
["u/test-user-2/mine"]
);
Ok(())
}