fix: update variable and resources now return error if nothing was updated

This commit is contained in:
Ruben Fiszel
2022-07-29 11:07:59 +02:00
parent a28a93baf1
commit 771de0990a
7 changed files with 136 additions and 119 deletions
+8 -2
View File
@@ -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(
+7 -3
View File
@@ -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
View File
@@ -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}`)
}
}
+99 -95
View File
@@ -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>
+2 -2
View File
@@ -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>