mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-27 16:02:43 +00:00
* 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. * feat: add workspace roles settings UI and role pickers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: show the server's reason when a settings save fails Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: default role pickers to a defined role and confirm resets of unknown capabilities Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: treat null role capabilities as unset and key role drafts by map Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: gate the frontend on workspace role capabilities Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: gate deploys, bulk actions and chat composition per role kind Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: treat a superadmin as full in deploy permission checks Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: leave page visibility out of isRestricted, as the server does Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: let a member discard their own draft without the authoring right Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: show custom roles as inactive without a valid license Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep the user store import on the agent page Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: show custom roles as frozen without a valid license Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: reorder instance roles with a drag handle Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * 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> * fix: move the instance role label into the expanded panel 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>
65 lines
2.4 KiB
TypeScript
65 lines
2.4 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import type { EffectiveRole } from '$lib/gen'
|
|
import {
|
|
applyCapabilitiesPatch,
|
|
baseCapabilitiesFor,
|
|
FULL_CAPABILITIES,
|
|
validRoleOr,
|
|
workspaceRolesErrors
|
|
} from './workspaceRoles'
|
|
|
|
// These mirror `windmill_common::roles`; the server refuses what they let through.
|
|
describe('role capability layering', () => {
|
|
it('falls back to full for developer and to the operator rights for any other name', () => {
|
|
expect(baseCapabilitiesFor('developer')).toEqual(FULL_CAPABILITIES)
|
|
const other = baseCapabilitiesFor('reviewer')
|
|
expect([other.code, other.flows, other.manage_schedules]).toEqual([false, 'none', true])
|
|
})
|
|
|
|
it('applies only the keys a patch sets', () => {
|
|
const caps = applyCapabilitiesPatch(baseCapabilitiesFor('x'), {
|
|
flows: 'compose',
|
|
visibility: { workers: false }
|
|
})
|
|
expect(caps.flows).toBe('compose')
|
|
expect(caps.apps).toBe('none')
|
|
expect(caps.visibility.workers).toBe(false)
|
|
expect(caps.visibility.runs).toBe(true)
|
|
})
|
|
|
|
it('treats a stored null as unset, as serde reads it', () => {
|
|
const caps = applyCapabilitiesPatch(baseCapabilitiesFor('developer'), {
|
|
code: null as any,
|
|
visibility: { runs: null as any }
|
|
})
|
|
expect(caps).toEqual(FULL_CAPABILITIES)
|
|
expect(
|
|
workspaceRolesErrors([{ name: 'developer', capabilities: { code: null as any } }])
|
|
).toEqual({})
|
|
})
|
|
|
|
it('refuses what parse_instance_roles refuses', () => {
|
|
expect(workspaceRolesErrors(undefined)).toEqual({})
|
|
expect(workspaceRolesErrors([])).toHaveProperty('list')
|
|
expect(workspaceRolesErrors([{ name: 'admin' }])).toHaveProperty('0.name')
|
|
expect(workspaceRolesErrors([{ name: 'a' }, { name: 'a' }])).toHaveProperty('1.name')
|
|
expect(workspaceRolesErrors([{ name: 'x', capabilities: { flows: 'full' } }])).toHaveProperty(
|
|
'0.capabilities'
|
|
)
|
|
expect(
|
|
workspaceRolesErrors([{ name: 'developer', capabilities: { apps: 'compose' } }])
|
|
).toEqual({})
|
|
})
|
|
})
|
|
|
|
describe('validRoleOr', () => {
|
|
const role = (name: string) => ({ name }) as EffectiveRole
|
|
|
|
it('falls back to developer, or the first role when the instance dropped it', () => {
|
|
expect(validRoleOr([role('operator'), role('developer')], undefined)).toBe('developer')
|
|
expect(validRoleOr([role('builder'), role('viewer')], undefined)).toBe('builder')
|
|
expect(validRoleOr([role('builder'), role('viewer')], 'developer')).toBe('builder')
|
|
expect(validRoleOr([role('builder')], 'admin')).toBe('admin')
|
|
})
|
|
})
|