mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 00:02:30 +00:00
fix: discard acting-user lookups that no longer describe the acting workspace
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YLxwAsiXJ1Au8CBDBmH7iY
This commit is contained in:
co-authored by
Claude Opus 5
parent
abd50563c6
commit
9166bc06d3
@@ -336,9 +336,12 @@
|
||||
if (!ws || !initialPath) return
|
||||
if (ws in states) return
|
||||
untrack(() => {
|
||||
// `actingUserIn` answers from `$userStore` for the navigation workspace, so only
|
||||
// another one is worth asking.
|
||||
const needsUser = ws !== $workspaceStore
|
||||
Promise.all([
|
||||
ResourceService.getResource({ workspace: ws, path: initialPath, getDraft: true }),
|
||||
getUserExt(ws)
|
||||
needsUser ? getUserExt(ws) : undefined
|
||||
]).then(([r, user]) => {
|
||||
// `.draft` already holds the editor's `ResourceState` shape.
|
||||
const savedDraftState = (r as any).draft as ResourceState | undefined
|
||||
@@ -366,7 +369,7 @@
|
||||
// Draft-only paths (`no_deployed`) have no row — saving must
|
||||
// CREATE, not update (update 404s).
|
||||
existedInitially[ws] = !(r as any).no_deployed
|
||||
perWsUser[ws] = user
|
||||
if (needsUser) perWsUser[ws] = user
|
||||
// Keep resource_type in sync for the base workspace (controls the schema)
|
||||
if (ws === effectiveWorkspace) {
|
||||
resource_type = r.resource_type
|
||||
|
||||
@@ -69,9 +69,13 @@
|
||||
() => (path && historyWorkspace !== $workspaceStore ? historyWorkspace : undefined),
|
||||
async (ws) => (ws ? await getUserExt(ws) : undefined)
|
||||
)
|
||||
const historyUser = $derived(
|
||||
historyWorkspace === $workspaceStore ? $userStore : otherWsUser.current
|
||||
)
|
||||
const historyUser = $derived.by(() => {
|
||||
if (historyWorkspace === $workspaceStore) return $userStore
|
||||
const u = otherWsUser.current
|
||||
// `resource` keeps the previous result across a refetch, and a superseded lookup can
|
||||
// still land last, so a user only answers for the workspace they were fetched for.
|
||||
return u?.workspace_id === historyWorkspace ? u : undefined
|
||||
})
|
||||
// Clearing is irreversible and the backend gates it on ownership, not write access, so the
|
||||
// verdict has to come from the membership `historyWorkspace` knows about. An unresolved
|
||||
// user gets no Clear button rather than one computed from another workspace's rights.
|
||||
|
||||
@@ -181,6 +181,9 @@
|
||||
if (!ws || !p) return
|
||||
if (ws in states) return
|
||||
untrack(() => {
|
||||
// `actingUserIn` answers from `$userStore` for the navigation workspace, so only
|
||||
// another one is worth asking.
|
||||
const needsUser = ws !== $workspaceStore
|
||||
Promise.all([
|
||||
VariableService.getVariable({
|
||||
workspace: ws,
|
||||
@@ -188,7 +191,7 @@
|
||||
decryptSecret: false,
|
||||
getDraft: true
|
||||
}),
|
||||
getUserExt(ws)
|
||||
needsUser ? getUserExt(ws) : undefined
|
||||
]).then(([v, user]) => {
|
||||
// `.draft` already holds the editor's `VariableState` shape.
|
||||
const savedDraftState = (v as any).draft as VariableState | undefined
|
||||
@@ -212,7 +215,7 @@
|
||||
// CREATE, not update (update 404s).
|
||||
existedInitially[ws] = !(v as any).no_deployed
|
||||
extraPerms[ws] = v.extra_perms ?? {}
|
||||
perWsUser[ws] = user
|
||||
if (needsUser) perWsUser[ws] = user
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -147,9 +147,13 @@
|
||||
)
|
||||
// `undefined` while that lookup is in flight or after it failed; the checks below then
|
||||
// refuse rather than fall back to rights that belong to another workspace.
|
||||
const actingUser: UserExt | undefined = $derived(
|
||||
wsId === $workspaceStore ? $userStore : otherWsUser.current
|
||||
)
|
||||
const actingUser: UserExt | undefined = $derived.by(() => {
|
||||
if (wsId === $workspaceStore) return $userStore
|
||||
const u = otherWsUser.current
|
||||
// `resource` keeps the previous result across a refetch, and a superseded lookup can
|
||||
// still land last, so a user only answers for the workspace they were fetched for.
|
||||
return u?.workspace_id === wsId ? u : undefined
|
||||
})
|
||||
const can_write = $derived(
|
||||
permsPath === undefined ? true : canWrite(permsPath, extraPerms, actingUser)
|
||||
)
|
||||
@@ -859,7 +863,7 @@
|
||||
namePlaceholder="schedule"
|
||||
kind="schedule"
|
||||
disableEditing={!can_write}
|
||||
{actingUser}
|
||||
actingUser={actingUser ?? null}
|
||||
/>
|
||||
{:else}
|
||||
<div class="flex justify-start w-full">
|
||||
|
||||
Reference in New Issue
Block a user