mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-18 16:02:10 +00:00
fix: update variable and resources now return error if nothing was updated
This commit is contained in:
@@ -283,10 +283,16 @@ async fn update_resource(
|
||||
if let Some(ndesc) = ns.description {
|
||||
sqlb.set_str("description", ndesc);
|
||||
}
|
||||
|
||||
sqlb.returning("path");
|
||||
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
|
||||
let sql = sqlb.sql().map_err(|e| Error::InternalErr(e.to_string()))?;
|
||||
sqlx::query(&sql).execute(&mut tx).await?;
|
||||
let npath_o: Option<String> = sqlx::query_scalar(&sql).fetch_optional(&mut tx).await?;
|
||||
|
||||
let npath = crate::utils::not_found_if_none(npath_o, "Resource", path)?;
|
||||
|
||||
audit_log(
|
||||
&mut tx,
|
||||
&authed.username,
|
||||
@@ -299,7 +305,7 @@ async fn update_resource(
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
|
||||
Ok(format!("resource {} updated (npath: {:?})", path, ns.path))
|
||||
Ok(format!("resource {} updated (npath: {:?})", path, npath))
|
||||
}
|
||||
|
||||
async fn list_resource_types(
|
||||
|
||||
@@ -356,7 +356,6 @@ async fn delete_variable(
|
||||
async fn update_variable(
|
||||
authed: Authed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
Json(ns): Json<EditVariable>,
|
||||
) -> Result<String> {
|
||||
@@ -404,9 +403,14 @@ async fn update_variable(
|
||||
}
|
||||
sqlb.set_str("is_secret", nbool);
|
||||
}
|
||||
sqlb.returning("path");
|
||||
|
||||
let sql = sqlb.sql().map_err(|e| Error::InternalErr(e.to_string()))?;
|
||||
|
||||
sqlx::query(&sql).execute(&db).await?;
|
||||
let npath_o: Option<String> = sqlx::query_scalar(&sql).fetch_optional(&mut tx).await?;
|
||||
|
||||
let npath = crate::utils::not_found_if_none(npath_o, "Variable", path)?;
|
||||
|
||||
audit_log(
|
||||
&mut tx,
|
||||
&authed.username,
|
||||
@@ -419,7 +423,7 @@ async fn update_variable(
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
|
||||
Ok(format!("variable {} updated (npath: {:?})", path, ns.path))
|
||||
Ok(format!("variable {} updated (npath: {:?})", path, npath))
|
||||
}
|
||||
|
||||
pub async fn build_crypt<'c>(
|
||||
|
||||
+7
-8
@@ -69,14 +69,13 @@ export function getInternalStatePath(suffix?: string): string {
|
||||
*/
|
||||
export async function setResource(path: string, value: any, initializeToTypeIfNotExist?: string): Promise<void> {
|
||||
const conf = createConf()
|
||||
try {
|
||||
await new ResourceApi(conf).updateResource(conf.workspace_id, path, { value })
|
||||
} catch (e) {
|
||||
if (initializeToTypeIfNotExist && e.code === 404) {
|
||||
await new ResourceApi(conf).createResource(conf.workspace_id, { path, value, resourceType: initializeToTypeIfNotExist })
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
const resourceApi = new ResourceApi(conf)
|
||||
if (await resourceApi.existsResource(conf.workspace_id, path)) {
|
||||
await resourceApi.updateResource(conf.workspace_id, path, { value })
|
||||
} else if (initializeToTypeIfNotExist) {
|
||||
await resourceApi.createResource(conf.workspace_id, { path, value, resourceType: initializeToTypeIfNotExist })
|
||||
} else {
|
||||
throw Error(`Resoucr at path ${path} does not exist and no type was provided to initialize it`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,11 @@
|
||||
let jsonValue: string = ''
|
||||
|
||||
async function loadSchedule() {
|
||||
try {
|
||||
const existsSchedule = await ScheduleService.existsSchedule({
|
||||
workspace: $workspaceStore ?? '',
|
||||
path: initialPath
|
||||
})
|
||||
if (existsSchedule) {
|
||||
const schedule = await ScheduleService.getSchedule({
|
||||
workspace: $workspaceStore ?? '',
|
||||
path: initialPath
|
||||
@@ -46,8 +50,6 @@
|
||||
scheduleCron = schedule.schedule
|
||||
scheduleArgs = scheduleArgs
|
||||
console.log(schedule.enabled, schedule.schedule)
|
||||
} catch (e) {
|
||||
console.log(`no primary schedule found for ${initialPath}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,105 +61,109 @@
|
||||
<div class="w-full">
|
||||
{#if Object.keys(schema?.properties ?? {}).length > 0}
|
||||
{#each Object.keys(schema?.properties ?? {}) as argName, index}
|
||||
{#if inputTransform && args[argName] != undefined}
|
||||
<div class={index > 0 ? 'mt-8' : ''} />
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex items-center">
|
||||
<FieldHeader
|
||||
label={argName}
|
||||
format={schema.properties[argName].format}
|
||||
contentEncoding={schema.properties[argName].contentEncoding}
|
||||
required={schema.required.includes(argName)}
|
||||
type={schema.properties[argName].type}
|
||||
itemsType={schema.properties[argName].items}
|
||||
/>
|
||||
{#if propertiesTypes[argName] === InputTransform.type.STATIC && args[argName].type === InputTransform.type.JAVASCRIPT}
|
||||
<span
|
||||
class="bg-blue-100 text-blue-800 text-sm font-medium mr-2 px-2.5 py-0.5 rounded ml-2"
|
||||
>
|
||||
{'${...}'}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<Toggle
|
||||
options={{
|
||||
left: { label: '', value: InputTransform.type.STATIC },
|
||||
right: { label: 'Raw Javascript Editor', value: InputTransform.type.JAVASCRIPT }
|
||||
}}
|
||||
bind:value={propertiesTypes[argName]}
|
||||
on:change={(e) => {
|
||||
if (e.detail === InputTransform.type.JAVASCRIPT) {
|
||||
args[argName].expr = getDefaultExpr(i ?? -1, argName, args[argName].value)
|
||||
args[argName].value = undefined
|
||||
} else {
|
||||
args[argName].expr = undefined
|
||||
args[argName].value = undefined
|
||||
}
|
||||
|
||||
args[argName].type = e.detail
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="max-w-xs" />
|
||||
|
||||
{#if propertiesTypes[argName] === undefined || propertiesTypes[argName] === InputTransform.type.STATIC}
|
||||
<OverlayPropertyPicker
|
||||
bind:this={overlays[argName]}
|
||||
bind:pickableProperties
|
||||
disabled={!hasOverlay(inputCats[argName])}
|
||||
on:select={(event) => {
|
||||
const toAppend = `\$\{${event.detail}}`
|
||||
args[argName].value = `${args[argName].value ?? ''}${toAppend}`
|
||||
setPropertyType(argName, args[argName].value, false)
|
||||
}}
|
||||
>
|
||||
<ArgInput
|
||||
on:focus={() => {
|
||||
Object.keys(overlays).forEach((k) => {
|
||||
if (k == argName) {
|
||||
overlays[k].focus()
|
||||
} else {
|
||||
overlays[k].unfocus()
|
||||
}
|
||||
})
|
||||
}}
|
||||
label={argName}
|
||||
bind:description={schema.properties[argName].description}
|
||||
bind:value={args[argName].value}
|
||||
type={schema.properties[argName].type}
|
||||
required={schema.required.includes(argName)}
|
||||
bind:pattern={schema.properties[argName].pattern}
|
||||
bind:valid={inputCheck[argName]}
|
||||
defaultValue={schema.properties[argName].default}
|
||||
bind:enum_={schema.properties[argName].enum}
|
||||
bind:format={schema.properties[argName].format}
|
||||
contentEncoding={schema.properties[argName].contentEncoding}
|
||||
bind:itemsType={schema.properties[argName].items}
|
||||
displayHeader={false}
|
||||
bind:inputCat={inputCats[argName]}
|
||||
numberAsString={true}
|
||||
on:input={(e) => {
|
||||
if (hasOverlay(inputCats[argName])) {
|
||||
setPropertyType(argName, e.detail.rawValue, e.detail.isRaw)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</OverlayPropertyPicker>
|
||||
{:else if propertiesTypes[argName] === InputTransform.type.JAVASCRIPT}
|
||||
{#if args[argName].expr != undefined}
|
||||
<div class="border rounded p-2 mt-2 border-gray-300">
|
||||
<Editor
|
||||
bind:code={args[argName].expr}
|
||||
lang="javascript"
|
||||
class="few-lines-editor"
|
||||
{extraLib}
|
||||
extraLibPath="file:///node_modules/@types/windmill@{i}/index.d.ts"
|
||||
{#if inputTransform}
|
||||
{#if args[argName] != undefined}
|
||||
<div class={index > 0 ? 'mt-8' : ''} />
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex items-center">
|
||||
<FieldHeader
|
||||
label={argName}
|
||||
format={schema.properties[argName].format}
|
||||
contentEncoding={schema.properties[argName].contentEncoding}
|
||||
required={schema.required.includes(argName)}
|
||||
type={schema.properties[argName].type}
|
||||
itemsType={schema.properties[argName].items}
|
||||
/>
|
||||
{#if propertiesTypes[argName] === InputTransform.type.STATIC && args[argName].type === InputTransform.type.JAVASCRIPT}
|
||||
<span
|
||||
class="bg-blue-100 text-blue-800 text-sm font-medium mr-2 px-2.5 py-0.5 rounded ml-2"
|
||||
>
|
||||
{'${...}'}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<DynamicInputHelpBox />
|
||||
<Toggle
|
||||
options={{
|
||||
left: { label: '', value: InputTransform.type.STATIC },
|
||||
right: { label: 'Raw Javascript Editor', value: InputTransform.type.JAVASCRIPT }
|
||||
}}
|
||||
bind:value={propertiesTypes[argName]}
|
||||
on:change={(e) => {
|
||||
if (e.detail === InputTransform.type.JAVASCRIPT) {
|
||||
args[argName].expr = getDefaultExpr(i ?? -1, argName, args[argName].value)
|
||||
args[argName].value = undefined
|
||||
} else {
|
||||
args[argName].expr = undefined
|
||||
args[argName].value = undefined
|
||||
}
|
||||
|
||||
args[argName].type = e.detail
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="max-w-xs" />
|
||||
|
||||
{#if propertiesTypes[argName] === undefined || propertiesTypes[argName] === InputTransform.type.STATIC}
|
||||
<OverlayPropertyPicker
|
||||
bind:this={overlays[argName]}
|
||||
bind:pickableProperties
|
||||
disabled={!hasOverlay(inputCats[argName])}
|
||||
on:select={(event) => {
|
||||
const toAppend = `\$\{${event.detail}}`
|
||||
args[argName].value = `${args[argName].value ?? ''}${toAppend}`
|
||||
setPropertyType(argName, args[argName].value, false)
|
||||
}}
|
||||
>
|
||||
<ArgInput
|
||||
on:focus={() => {
|
||||
Object.keys(overlays).forEach((k) => {
|
||||
if (k == argName) {
|
||||
overlays[k].focus()
|
||||
} else {
|
||||
overlays[k].unfocus()
|
||||
}
|
||||
})
|
||||
}}
|
||||
label={argName}
|
||||
bind:description={schema.properties[argName].description}
|
||||
bind:value={args[argName].value}
|
||||
type={schema.properties[argName].type}
|
||||
required={schema.required.includes(argName)}
|
||||
bind:pattern={schema.properties[argName].pattern}
|
||||
bind:valid={inputCheck[argName]}
|
||||
defaultValue={schema.properties[argName].default}
|
||||
bind:enum_={schema.properties[argName].enum}
|
||||
bind:format={schema.properties[argName].format}
|
||||
contentEncoding={schema.properties[argName].contentEncoding}
|
||||
bind:itemsType={schema.properties[argName].items}
|
||||
displayHeader={false}
|
||||
bind:inputCat={inputCats[argName]}
|
||||
numberAsString={true}
|
||||
on:input={(e) => {
|
||||
if (hasOverlay(inputCats[argName])) {
|
||||
setPropertyType(argName, e.detail.rawValue, e.detail.isRaw)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</OverlayPropertyPicker>
|
||||
{:else if propertiesTypes[argName] === InputTransform.type.JAVASCRIPT}
|
||||
{#if args[argName].expr != undefined}
|
||||
<div class="border rounded p-2 mt-2 border-gray-300">
|
||||
<Editor
|
||||
bind:code={args[argName].expr}
|
||||
lang="javascript"
|
||||
class="few-lines-editor"
|
||||
{extraLib}
|
||||
extraLibPath="file:///node_modules/@types/windmill@{i}/index.d.ts"
|
||||
/>
|
||||
</div>
|
||||
<DynamicInputHelpBox />
|
||||
{/if}
|
||||
{:else}
|
||||
<p>Not recognized arg type {args[argName].type}</p>
|
||||
{/if}
|
||||
{:else}
|
||||
<p>Not recognized arg type {args[argName].type}</p>
|
||||
<p>Arg at {argName} is undefined</p>
|
||||
{/if}
|
||||
{:else}
|
||||
<ArgInput
|
||||
|
||||
@@ -149,18 +149,20 @@
|
||||
</div>
|
||||
{/if}
|
||||
</label>
|
||||
<div class="font-semibold text-gray-700 col-span-10 }">
|
||||
{#if variable.is_secret}
|
||||
{#if variable.is_secret}
|
||||
<div class="font-semibold text-gray-700 col-span-10 }">
|
||||
<Password
|
||||
bind:password={variable.value}
|
||||
placeholder={'******** (only fill to update value)'}
|
||||
label={'variable (max 3000 characters)'}
|
||||
/>
|
||||
{:else}
|
||||
<span>variable (max 3000 characters)</span>
|
||||
</div>
|
||||
{:else}
|
||||
<div>
|
||||
<span>Variable (max 3000 characters)</span>
|
||||
<AutosizedTextarea bind:value={variable.value} minRows={5} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex flex-col w-full">
|
||||
<span class="text-gray-700">Description<Required required={false} /></span>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { canWrite, sendUserToast } from '$lib/utils'
|
||||
import { canWrite, sendUserToast, truncate } from '$lib/utils'
|
||||
import { OauthService, VariableService } from '$lib/gen'
|
||||
import type { ListableVariable, ContextualVariable } from '$lib/gen'
|
||||
import Dropdown from '$lib/components/Dropdown.svelte'
|
||||
@@ -96,7 +96,7 @@
|
||||
>
|
||||
<div><SharedBadge {canWrite} extraPerms={extra_perms} /></div>
|
||||
</td>
|
||||
<td>{value ?? '******'}</td>
|
||||
<td>{truncate(value ?? '******', 40)}</td>
|
||||
<td>{is_secret ? 'secret' : 'visible'}</td>
|
||||
<td>{description}</td>
|
||||
<td>
|
||||
|
||||
Reference in New Issue
Block a user