Files
windmill/backend/windmill-common/tests/workspace_roles_declarative.rs
T
21d2a49971 feat: configurable workspace roles with per-workspace overrides (#11821)
* feat: configurable workspace roles with per-workspace overrides

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: close role review gaps in pickers, declarative sync and removal

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: keep resolve_role_name doc on its function

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: validate overrides on instance role changes and bill admins fully

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: allow pipeline drafts and keep role checks on one connection

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: list data pipelines in operator_can_draft

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: expect a 403 role refusal when an operator resolves jobs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: require a valid license for custom workspace roles

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: freeze workspace roles when the license lapses

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: pin the ee companion for workspace roles

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor: broadcast role override changes from the write path, not a trigger

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: update ee-repo-ref to b5294d38db082bdd104d5358a47695390694c05d

This commit updates the EE repository reference after PR #891 was merged in windmill-ee-private.

Previous ee-repo-ref: 688e00c5982865b14098f530d54280e2311994c0

New ee-repo-ref: b5294d38db082bdd104d5358a47695390694c05d

Automated by sync-ee-ref workflow.

* fix: let an admin row that kept the operator flag hold full rights everywhere

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: treat superadmin members as admins and return role names from get user

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-10-21 15:51:54 +02:00

81 lines
2.7 KiB
Rust

#![cfg(feature = "enterprise")]
use std::collections::BTreeMap;
use sqlx::{Pool, Postgres};
use windmill_common::global_settings::WORKSPACE_ROLES_SETTING;
use windmill_common::instance_config::sync_global_settings_declarative;
/// The declarative config sync writes `workspace_roles` without the HTTP settings handler, so it
/// must validate the value and rebuild `role_seat` itself, or billing misprices the new roles.
#[sqlx::test(migrations = "../migrations", fixtures("base"))]
async fn declarative_workspace_roles_validates_and_rebuilds_seats(db: Pool<Postgres>) {
windmill_common::roles::invalidate_all_roles_cache();
let desired =
|roles: serde_json::Value| BTreeMap::from([(WORKSPACE_ROLES_SETTING.to_string(), roles)]);
sync_global_settings_declarative(
&db,
&BTreeMap::new(),
&desired(serde_json::json!([{"name": "x", "capabilities": {"flows": "full"}}])),
&(),
)
.await
.expect_err("full flows without code must be refused");
sync_global_settings_declarative(
&db,
&BTreeMap::new(),
&desired(serde_json::json!([
{"name": "developer"},
{"name": "builder", "capabilities": {"flows": "compose"}},
{"name": "operator"}
])),
&(),
)
.await
.unwrap();
let author: bool = sqlx::query_scalar(
"SELECT author FROM role_seat WHERE workspace_id = '' AND role = 'builder'",
)
.fetch_one(&db)
.await
.unwrap();
assert!(author, "a role that composes flows costs a full seat");
// A workspace grants `builder` full flows on top of an instance definition that codes; the
// instance then withdrawing `code` would leave that workspace with inline code and no code.
sync_global_settings_declarative(
&db,
&BTreeMap::new(),
&desired(serde_json::json!([
{"name": "developer"},
{"name": "builder", "capabilities": {"code": true, "flows": "compose"}},
{"name": "operator"}
])),
&(),
)
.await
.unwrap();
sqlx::query(
"UPDATE workspace_settings SET role_overrides =
'{\"builder\": {\"capabilities\": {\"flows\": \"full\"}}}'
WHERE workspace_id = 'test-workspace'",
)
.execute(&db)
.await
.unwrap();
sync_global_settings_declarative(
&db,
&BTreeMap::new(),
&desired(serde_json::json!([
{"name": "developer"},
{"name": "builder", "capabilities": {"code": false, "flows": "compose"}},
{"name": "operator"}
])),
&(),
)
.await
.expect_err("an instance change that invalidates a workspace override must be refused");
}