mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-07 08:02:40 +00:00
* feat: support multiline secrets in resource password fields Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: wire minRows through to password textarea instead of disabling it Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: auto-detect multiline in password field instead of always using textarea Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: switch to textarea on Enter keypress in password field Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: focus textarea after switching from single-line password input Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: simplify Password multiline logic and fix cursor position bug Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
101 lines
2.3 KiB
Svelte
101 lines
2.3 KiB
Svelte
<script lang="ts">
|
|
import { VariableService } from '$lib/gen'
|
|
import { userStore, workspaceStore } from '$lib/stores'
|
|
import { generateRandomString } from '$lib/utils'
|
|
import { Button } from './common'
|
|
import Password from './Password.svelte'
|
|
import { untrack } from 'svelte'
|
|
|
|
interface Props {
|
|
value?: string | undefined
|
|
disabled: boolean
|
|
minRows?: number
|
|
}
|
|
|
|
let { value = $bindable(undefined), disabled, minRows }: Props = $props()
|
|
|
|
let path = $state('')
|
|
let password = $state(
|
|
value && typeof value === 'string' && !value.startsWith('$var:') ? value : ''
|
|
)
|
|
|
|
let isGenerating = false
|
|
|
|
let userPrefix = $derived(
|
|
'u/' + ($userStore?.username ?? $userStore?.email)?.split('@')[0] + '/secret_arg/'
|
|
)
|
|
async function generateValue() {
|
|
if (isGenerating) return
|
|
isGenerating = true
|
|
try {
|
|
let npath = userPrefix + generateRandomString(12)
|
|
let nvalue = '$var:' + npath
|
|
await VariableService.createVariable({
|
|
workspace: $workspaceStore!,
|
|
requestBody: {
|
|
value: password,
|
|
is_secret: true,
|
|
path: npath,
|
|
description: 'Ephemeral secret variable',
|
|
expires_at: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7).toISOString()
|
|
}
|
|
})
|
|
path = npath
|
|
console.log('generated', nvalue)
|
|
value = nvalue
|
|
debouncedUpdate()
|
|
} finally {
|
|
isGenerating = false
|
|
}
|
|
}
|
|
|
|
async function updateValue() {
|
|
try {
|
|
await VariableService.updateVariable({
|
|
workspace: $workspaceStore!,
|
|
path: path,
|
|
requestBody: {
|
|
value: password
|
|
}
|
|
})
|
|
} catch (e) {
|
|
generateValue()
|
|
}
|
|
}
|
|
|
|
let timeout: number | undefined = undefined
|
|
function debouncedUpdate() {
|
|
timeout && clearTimeout(timeout)
|
|
timeout = setTimeout(updateValue, 500)
|
|
}
|
|
|
|
$effect(() => {
|
|
password && untrack(() => debouncedUpdate())
|
|
})
|
|
|
|
$effect(() => {
|
|
$workspaceStore &&
|
|
($userStore?.username || $userStore?.email) &&
|
|
path == '' &&
|
|
password != '' &&
|
|
untrack(() => generateValue())
|
|
})
|
|
</script>
|
|
|
|
{#if value?.startsWith('$var:') && !value.startsWith('$var:' + userPrefix)}
|
|
<div class="flex items-center gap-2 text-sm text-primary">
|
|
Linked to static variable
|
|
<Button
|
|
size="xs"
|
|
variant="default"
|
|
onclick={() => {
|
|
value = ''
|
|
}}
|
|
>
|
|
Reset variable link
|
|
</Button>
|
|
</div>
|
|
{:else}
|
|
<Password {disabled} {minRows} bind:password />
|
|
{/if}
|