mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-27 08:02:39 +00:00
Add on behaklft of selector for script flow apps (#8117)
This commit is contained in:
@@ -26,15 +26,25 @@
|
||||
targetWorkspace: string
|
||||
targetEmail: string | undefined
|
||||
selected: OnBehalfOfChoice
|
||||
onSelect: (choice: OnBehalfOfChoice, email?: string) => void
|
||||
onSelect: (choice: OnBehalfOfChoice, email?: string, username?: string) => void
|
||||
kind: string
|
||||
canPreserve: boolean
|
||||
/** The email of the custom-selected user (for display) */
|
||||
customEmail?: string | undefined
|
||||
/** When false, labels say "current" instead of "target" and modal text refers to "this workspace" */
|
||||
isDeployment?: boolean
|
||||
}
|
||||
|
||||
let { targetWorkspace, targetEmail, selected, onSelect, kind, canPreserve, customEmail }: Props =
|
||||
$props()
|
||||
let {
|
||||
targetWorkspace,
|
||||
targetEmail,
|
||||
selected,
|
||||
onSelect,
|
||||
kind,
|
||||
canPreserve,
|
||||
customEmail,
|
||||
isDeployment = true
|
||||
}: Props = $props()
|
||||
|
||||
let label = $derived(
|
||||
kind === 'trigger'
|
||||
@@ -96,7 +106,7 @@
|
||||
}
|
||||
|
||||
function selectUser(user: User) {
|
||||
onSelect('custom', user.email)
|
||||
onSelect('custom', user.email, user.username)
|
||||
modalOpen = false
|
||||
}
|
||||
|
||||
@@ -130,7 +140,7 @@
|
||||
>
|
||||
<Check class="w-3 h-3 {selected === 'target' ? 'opacity-100' : 'opacity-0'}" />
|
||||
<span class="truncate max-w-40">{targetUsername}</span>
|
||||
<span class="text-xs text-tertiary">(target)</span>
|
||||
<span class="text-xs text-tertiary">{isDeployment ? '(target)' : '(current)'}</span>
|
||||
</button>
|
||||
{/if}
|
||||
<!-- Me option -->
|
||||
@@ -171,9 +181,9 @@
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="text-xs text-secondary">
|
||||
{#if kind === 'trigger'}
|
||||
Choose the user this trigger will be recorded as edited by in the target workspace.
|
||||
Choose the user this trigger will be recorded as edited by {isDeployment ? 'in the target workspace' : 'in this workspace'}.
|
||||
{:else}
|
||||
Choose the user this {kind} will run on behalf of in the target workspace. The selected
|
||||
Choose the user this {kind} will run on behalf of {isDeployment ? 'in the target workspace' : 'in this workspace'}. The selected
|
||||
user's permissions will be used when executing.
|
||||
{/if}
|
||||
<a
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
import { inputSizeClasses } from './text_input/TextInput.svelte'
|
||||
import type { ButtonType } from './common/button/model'
|
||||
import DebounceLimit from './flows/DebounceLimit.svelte'
|
||||
import OnBehalfOfSelector, { type OnBehalfOfChoice } from './OnBehalfOfSelector.svelte'
|
||||
|
||||
let {
|
||||
script = $bindable(),
|
||||
@@ -161,13 +162,10 @@
|
||||
|
||||
const WM_DEPLOYERS_GROUP = 'wm_deployers'
|
||||
let isDeployer = $derived($userStore?.groups?.includes(WM_DEPLOYERS_GROUP) ?? false)
|
||||
let canPreserve = $derived(!!$userStore?.is_admin || !!$userStore?.is_super_admin || isDeployer)
|
||||
let originalOnBehalfOfEmail = $derived(savedScript?.on_behalf_of_email)
|
||||
let showPreserveToggle = $derived(
|
||||
isDeployer &&
|
||||
script.on_behalf_of_email &&
|
||||
originalOnBehalfOfEmail &&
|
||||
originalOnBehalfOfEmail !== $userStore?.email
|
||||
)
|
||||
let onBehalfOfChoice: OnBehalfOfChoice = $state(undefined)
|
||||
let customOnBehalfOfEmail: string = $state('')
|
||||
|
||||
let metadataOpen = $state(
|
||||
!neverShowMeta &&
|
||||
@@ -1468,9 +1466,9 @@
|
||||
>
|
||||
In this mode, the script is meant to be run on dedicated workers that run
|
||||
the script at native speed. Can reach >1500rps per dedicated worker. Only
|
||||
available on enterprise edition and for Python3, Deno, Bun and Bunnative. For other
|
||||
languages, the efficiency is already on par with dedicated workers since
|
||||
they do not spawn a full runtime</Tooltip
|
||||
available on enterprise edition and for Python3, Deno, Bun and Bunnative.
|
||||
For other languages, the efficiency is already on par with dedicated workers
|
||||
since they do not spawn a full runtime</Tooltip
|
||||
>
|
||||
{/snippet}
|
||||
</Section>
|
||||
@@ -1597,30 +1595,51 @@
|
||||
</Tooltip>
|
||||
{/snippet}
|
||||
<div class="flex gap-2 shrink flex-col">
|
||||
<Toggle
|
||||
size="sm"
|
||||
checked={Boolean(script.on_behalf_of_email)}
|
||||
on:change={() => {
|
||||
if (script.on_behalf_of_email) {
|
||||
script.on_behalf_of_email = undefined
|
||||
preserveOnBehalfOf = false
|
||||
} else {
|
||||
script.on_behalf_of_email = $userStore?.email
|
||||
}
|
||||
}}
|
||||
options={{
|
||||
right: 'Run on behalf of last editor'
|
||||
}}
|
||||
/>
|
||||
{#if showPreserveToggle}
|
||||
<span class="inline-flex gap-2">
|
||||
<Toggle
|
||||
size="sm"
|
||||
bind:checked={preserveOnBehalfOf}
|
||||
checked={Boolean(script.on_behalf_of_email)}
|
||||
on:change={() => {
|
||||
if (script.on_behalf_of_email) {
|
||||
script.on_behalf_of_email = undefined
|
||||
preserveOnBehalfOf = false
|
||||
onBehalfOfChoice = undefined
|
||||
} else {
|
||||
script.on_behalf_of_email = $userStore?.email
|
||||
}
|
||||
}}
|
||||
options={{
|
||||
right: `Keep original author (${originalOnBehalfOfEmail})`
|
||||
right: `Run on behalf of ${canPreserve ? 'a specified user' : 'last editor'}`
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
{#if script.on_behalf_of_email && canPreserve}
|
||||
→ <OnBehalfOfSelector
|
||||
targetWorkspace={$workspaceStore ?? ''}
|
||||
targetEmail={originalOnBehalfOfEmail}
|
||||
selected={onBehalfOfChoice}
|
||||
onSelect={(choice, email) => {
|
||||
onBehalfOfChoice = choice
|
||||
if (choice === 'me') {
|
||||
script.on_behalf_of_email = $userStore?.email
|
||||
customOnBehalfOfEmail = ''
|
||||
preserveOnBehalfOf = false
|
||||
} else if (choice === 'target') {
|
||||
script.on_behalf_of_email = originalOnBehalfOfEmail
|
||||
customOnBehalfOfEmail = ''
|
||||
preserveOnBehalfOf = true
|
||||
} else if (choice === 'custom' && email) {
|
||||
script.on_behalf_of_email = email
|
||||
customOnBehalfOfEmail = email
|
||||
preserveOnBehalfOf = true
|
||||
}
|
||||
}}
|
||||
kind="script"
|
||||
{canPreserve}
|
||||
customEmail={customOnBehalfOfEmail}
|
||||
isDeployment={false}
|
||||
/>
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
</Section>
|
||||
{#if !isCloudHosted()}
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import EEOnly from '$lib/components/EEOnly.svelte'
|
||||
import TextInput from '$lib/components/text_input/TextInput.svelte'
|
||||
import OnBehalfOfSelector, {
|
||||
type OnBehalfOfChoice
|
||||
} from '$lib/components/OnBehalfOfSelector.svelte'
|
||||
|
||||
const WM_DEPLOYERS_GROUP = 'wm_deployers'
|
||||
|
||||
@@ -51,13 +54,12 @@
|
||||
} = $props()
|
||||
|
||||
let isDeployer = $derived($userStore?.groups?.includes(WM_DEPLOYERS_GROUP) ?? false)
|
||||
let savedOnBehalfOfEmail = $derived(savedApp?.policy?.on_behalf_of_email)
|
||||
let showPreserveToggle = $derived(
|
||||
isDeployer &&
|
||||
policy?.on_behalf_of_email &&
|
||||
savedOnBehalfOfEmail &&
|
||||
savedOnBehalfOfEmail !== $userStore?.email
|
||||
let canPreserve = $derived(
|
||||
!!$userStore?.is_admin || !!$userStore?.is_super_admin || isDeployer
|
||||
)
|
||||
let savedOnBehalfOfEmail = $derived(savedApp?.policy?.on_behalf_of_email)
|
||||
let onBehalfOfChoice: OnBehalfOfChoice = $state(undefined)
|
||||
let customOnBehalfOfEmail: string = $state('')
|
||||
let dirtyCustomPath = $state(false)
|
||||
let path: Path | undefined = $state(undefined)
|
||||
|
||||
@@ -193,19 +195,40 @@
|
||||
Hence, users will only be able to use the app as intended by the publisher without risk for
|
||||
leaking resources not used in the app.
|
||||
</Tooltip>
|
||||
{#if canPreserve}
|
||||
<div class="mt-4">
|
||||
Because you are either an admin or part of the {WM_DEPLOYERS_GROUP} group, you can select another user to run this app on behalf of. Once deployed the app will be run on behalf of
|
||||
<OnBehalfOfSelector
|
||||
targetWorkspace={$workspaceStore ?? ''}
|
||||
targetEmail={savedOnBehalfOfEmail}
|
||||
selected={onBehalfOfChoice}
|
||||
onSelect={(choice, email, username) => {
|
||||
onBehalfOfChoice = choice
|
||||
if (choice === 'me') {
|
||||
policy.on_behalf_of_email = $userStore?.email
|
||||
policy.on_behalf_of = `u/${$userStore?.username}`
|
||||
customOnBehalfOfEmail = ''
|
||||
preserveOnBehalfOf = false
|
||||
} else if (choice === 'target') {
|
||||
policy.on_behalf_of_email = savedOnBehalfOfEmail
|
||||
customOnBehalfOfEmail = ''
|
||||
preserveOnBehalfOf = true
|
||||
} else if (choice === 'custom' && email) {
|
||||
policy.on_behalf_of_email = email
|
||||
policy.on_behalf_of = username ? `u/${username}` : undefined
|
||||
customOnBehalfOfEmail = email
|
||||
preserveOnBehalfOf = true
|
||||
}
|
||||
}}
|
||||
kind="app"
|
||||
{canPreserve}
|
||||
customEmail={customOnBehalfOfEmail}
|
||||
isDeployment={false}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</Alert>
|
||||
|
||||
{#if showPreserveToggle}
|
||||
<div class="mt-4">
|
||||
<Toggle
|
||||
size="sm"
|
||||
bind:checked={preserveOnBehalfOf}
|
||||
options={{
|
||||
right: `Keep original author (${savedOnBehalfOfEmail})`
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="mt-10"></div>
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import { Alert, Button, SecondsInput } from '$lib/components/common'
|
||||
import { getContext } from 'svelte'
|
||||
import type { FlowEditorContext } from '../types'
|
||||
import { enterpriseLicense, userStore } from '$lib/stores'
|
||||
import { enterpriseLicense, userStore, workspaceStore } from '$lib/stores'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
|
||||
@@ -26,6 +26,9 @@
|
||||
import { slide } from 'svelte/transition'
|
||||
import DebounceLimit from '../DebounceLimit.svelte'
|
||||
import EEOnly from '$lib/components/EEOnly.svelte'
|
||||
import OnBehalfOfSelector, {
|
||||
type OnBehalfOfChoice
|
||||
} from '$lib/components/OnBehalfOfSelector.svelte'
|
||||
|
||||
interface Props {
|
||||
noEditor: boolean
|
||||
@@ -46,12 +49,9 @@
|
||||
|
||||
const WM_DEPLOYERS_GROUP = 'wm_deployers'
|
||||
let isDeployer = $derived($userStore?.groups?.includes(WM_DEPLOYERS_GROUP) ?? false)
|
||||
let showPreserveToggle = $derived(
|
||||
isDeployer &&
|
||||
flowStore.val.on_behalf_of_email &&
|
||||
$savedOnBehalfOfEmail &&
|
||||
$savedOnBehalfOfEmail !== $userStore?.email
|
||||
)
|
||||
let canPreserve = $derived(!!$userStore?.is_admin || !!$userStore?.is_super_admin || isDeployer)
|
||||
let onBehalfOfChoice: OnBehalfOfChoice = $state(undefined)
|
||||
let customOnBehalfOfEmail: string = $state('')
|
||||
|
||||
function asSchema(x: any) {
|
||||
return x as Schema
|
||||
@@ -382,34 +382,54 @@
|
||||
/>
|
||||
|
||||
<!-- On behalf of last editor section -->
|
||||
<Toggle
|
||||
textClass="font-medium"
|
||||
size="xs"
|
||||
checked={Boolean(flowStore.val.on_behalf_of_email)}
|
||||
on:change={() => {
|
||||
if (flowStore.val.on_behalf_of_email) {
|
||||
flowStore.val.on_behalf_of_email = undefined
|
||||
$preserveOnBehalfOf = false
|
||||
} else {
|
||||
flowStore.val.on_behalf_of_email = $userStore?.email
|
||||
}
|
||||
}}
|
||||
options={{
|
||||
right: 'Run on behalf of last editor',
|
||||
rightTooltip:
|
||||
'When this option is enabled, the flow will be run with the permissions of the last editor.'
|
||||
}}
|
||||
/>
|
||||
{#if showPreserveToggle}
|
||||
<span class="inline-flex gap-2">
|
||||
<Toggle
|
||||
textClass="font-medium"
|
||||
size="xs"
|
||||
bind:checked={$preserveOnBehalfOf}
|
||||
checked={Boolean(flowStore.val.on_behalf_of_email)}
|
||||
on:change={() => {
|
||||
if (flowStore.val.on_behalf_of_email) {
|
||||
flowStore.val.on_behalf_of_email = undefined
|
||||
$preserveOnBehalfOf = false
|
||||
onBehalfOfChoice = undefined
|
||||
} else {
|
||||
flowStore.val.on_behalf_of_email = $userStore?.email
|
||||
}
|
||||
}}
|
||||
options={{
|
||||
right: `Keep original author (${$savedOnBehalfOfEmail})`
|
||||
right: `Run on behalf of ${canPreserve ? 'a specified user' : 'last editor'}`,
|
||||
rightTooltip:
|
||||
'When this option is enabled, the flow will be run with the permissions of the corresponding user.'
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
{#if flowStore.val.on_behalf_of_email && canPreserve}
|
||||
→ <OnBehalfOfSelector
|
||||
targetWorkspace={$workspaceStore ?? ''}
|
||||
targetEmail={$savedOnBehalfOfEmail}
|
||||
selected={onBehalfOfChoice}
|
||||
onSelect={(choice, email) => {
|
||||
onBehalfOfChoice = choice
|
||||
if (choice === 'me') {
|
||||
flowStore.val.on_behalf_of_email = $userStore?.email
|
||||
customOnBehalfOfEmail = ''
|
||||
$preserveOnBehalfOf = false
|
||||
} else if (choice === 'target') {
|
||||
flowStore.val.on_behalf_of_email = $savedOnBehalfOfEmail
|
||||
customOnBehalfOfEmail = ''
|
||||
$preserveOnBehalfOf = true
|
||||
} else if (choice === 'custom' && email) {
|
||||
flowStore.val.on_behalf_of_email = email
|
||||
customOnBehalfOfEmail = email
|
||||
$preserveOnBehalfOf = true
|
||||
}
|
||||
}}
|
||||
kind="flow"
|
||||
{canPreserve}
|
||||
customEmail={customOnBehalfOfEmail}
|
||||
isDeployment={false}
|
||||
/>
|
||||
{/if}
|
||||
</span>
|
||||
|
||||
<!-- Error Handler Section -->
|
||||
<div class="flex flex-row items-center py-1">
|
||||
@@ -581,8 +601,8 @@
|
||||
{#if flowStore.val.dedicated_worker}
|
||||
<div class="mt-2">
|
||||
<Alert type="info" title="Require dedicated workers">
|
||||
A worker group needs to be configured to listen to this flow. Select it in the dedicated
|
||||
workers section of the worker group configuration.
|
||||
A worker group needs to be configured to listen to this flow. Select it in the
|
||||
dedicated workers section of the worker group configuration.
|
||||
</Alert>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user