Files
windmill/frontend/src/lib/components/datatableUsableRoles.ts
T
Diego ImbertandClaude Opus 5 4416283b17 fix: read the roles of a data table whose name contains '?'
The generated client leaves a '?' in a path param unencoded, so the lookup
404'd and the raw-app picker blocked Start on such a data table.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 16:32:36 +02:00

45 lines
1.8 KiB
TypeScript

import { OpenAPI, type ListUsableDatatableRolesResponse } from '$lib/gen'
import { request } from '$lib/gen/core/request'
import { isCloudHosted } from '$lib/cloud'
import { ADMIN_DATATABLE_ROLE } from './dbTypes'
// `datatable_roles_unavailable` on the server, which is a plain 400: rewording it there without
// here makes every role picker on a non-Enterprise build fail instead of reading "not under roles".
const ROLES_UNAVAILABLE = 'Data table roles are a Windmill Enterprise Edition feature'
const NOT_UNDER_ROLES: ListUsableDatatableRolesResponse = {
permissioned: false,
roles: [],
default_role: ADMIN_DATATABLE_ROLE
}
/**
* The roles the caller may connect as on a data table. Cloud has no instance database, so no data
* table there is under roles, and none of the role pickers show. Without the Enterprise Edition
* every roles route refuses, which reads the same way: the data table is then used the way it was
* before roles, and one that is under roles is refused when something connects to it.
*/
export async function listUsableDatatableRoles(
workspace: string,
datatableName: string
): Promise<ListUsableDatatableRolesResponse> {
if (isCloudHosted()) return NOT_UNDER_ROLES
try {
// The generated client encodes path params with `encodeURI`, which leaves a '?' in a
// data table name created before names were restricted to cut the path short.
return await request(
{ ...OpenAPI, ENCODE_PATH: encodeURIComponent },
{
method: 'GET',
url: '/w/{workspace}/workspaces/datatable_usable_roles/{datatable_name}',
path: { workspace, datatable_name: datatableName }
}
)
} catch (e) {
const body = (e as { body?: unknown })?.body
const detail = `${typeof body === 'string' ? body : JSON.stringify(body ?? '')} ${(e as Error)?.message ?? e}`
if (detail.includes(ROLES_UNAVAILABLE)) return NOT_UNDER_ROLES
throw e
}
}