fix(datatables): never hide access management from a workspace admin

This commit is contained in:
Diego Imbert
2026-09-01 03:11:23 +02:00
parent e3f0a22810
commit a4e6eb5e4d
2 changed files with 8 additions and 3 deletions
@@ -721,8 +721,10 @@ async fn get_datatable_acl(
let owner: String = owner_row.get(0);
// Membership in the owning role is what Postgres asks for before an ALTER
// ... OWNER or a GRANT on something you do not own; `admin` holds every role
// this feature creates, so it passes everywhere.
let can_manage: bool = owner_row.get(1);
// this feature creates, so it passes everywhere. A workspace admin manages
// the data table itself and is never shut out of it — a schema Windmill did
// not create, `public` above all, is owned by neither.
let can_manage: bool = authed.is_admin || owner_row.get::<_, bool>(1);
let mut grants = read_grants(&client, &target, &roles).await?;
grants.sort_by(|a, b| {
@@ -904,7 +906,7 @@ async fn build_acl_plan(
// want on its own — handing an object to a role you are not a member of is
// refused outright, and granting on one you own needs the grant option — so
// this is the check, and the statements run as the data table's admin below.
if !can_manage_target(&client, &req.target).await? {
if !authed.is_admin && !can_manage_target(&client, &req.target).await? {
return Err(Error::NotAuthorized(format!(
"{} is owned by a role you are not a member of",
req.target.label(&conn.dbname)
@@ -237,6 +237,9 @@
/** Whether the connected role may change access on an object: Postgres asks
* for membership of its owner, so for the rest the entry is not offered. */
function canManage(datatable: string | undefined, schemaKey: string, table?: string): boolean {
// A workspace admin manages the data table itself, so nothing in it is
// hidden from them — `public` is owned by neither Windmill nor its roles.
if (canManageDatatable) return true
const entry = datatableTree?.find((d) => d.datatable_name === datatable)
if (!entry?.manageable_schemas) return true
return table === undefined