mirror of
https://github.com/SecurityBrewery/catalyst.git
synced 2025-12-25 16:33:10 +01:00
feat: scheduler (#1108)
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import ActionPythonFormFields from '@/components/reaction/ActionPythonFormFields.vue'
|
||||
import ActionWebhookFormFields from '@/components/reaction/ActionWebhookFormFields.vue'
|
||||
import TriggerHookFormFields from '@/components/reaction/TriggerHookFormFields.vue'
|
||||
import TriggerScheduleFormFields from '@/components/reaction/TriggerScheduleFormFields.vue'
|
||||
import TriggerWebhookFormFields from '@/components/reaction/TriggerWebhookFormFields.vue'
|
||||
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
|
||||
import { Button } from '@/components/ui/button'
|
||||
@@ -67,6 +68,25 @@ defineRule('required', (value: string) => {
|
||||
return true
|
||||
})
|
||||
|
||||
defineRule('triggerdata.expression', (value: string) => {
|
||||
if (values.trigger !== 'schedule') {
|
||||
return true
|
||||
}
|
||||
if (!value) {
|
||||
return 'This field is required'
|
||||
}
|
||||
const macros = ['@yearly', '@annually', '@monthly', '@weekly', '@daily', '@midnight', '@hourly']
|
||||
if (macros.includes(value)) {
|
||||
return true
|
||||
}
|
||||
const expression =
|
||||
/^(\*|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])) (\*|([0-9]|1[0-9]|2[0-3])|\*\/([0-9]|1[0-9]|2[0-3])) (\*|([1-9]|1[0-9]|2[0-9]|3[0-1])|\*\/([1-9]|1[0-9]|2[0-9]|3[0-1])) (\*|([1-9]|1[0-2])|\*\/([1-9]|1[0-2])) (\*|([0-6])|\*\/([0-6]))$/
|
||||
if (value.match(expression)) {
|
||||
return true
|
||||
}
|
||||
return 'Invalid cron expression'
|
||||
})
|
||||
|
||||
defineRule('triggerdata.token', (value: string) => {
|
||||
return true
|
||||
})
|
||||
@@ -160,6 +180,7 @@ const { handleSubmit, validate, values } = useForm({
|
||||
validationSchema: {
|
||||
name: 'required',
|
||||
trigger: 'required',
|
||||
'triggerdata.expression': 'triggerdata.expression',
|
||||
'triggerdata.token': 'triggerdata.token',
|
||||
'triggerdata.path': 'triggerdata.path',
|
||||
'triggerdata.collections': 'triggerdata.collections',
|
||||
@@ -263,6 +284,7 @@ const curlExample = computed(() => {
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="schedule">Schedule</SelectItem>
|
||||
<SelectItem value="webhook">HTTP / Webhook</SelectItem>
|
||||
<SelectItem value="hook">Collection Hook</SelectItem>
|
||||
</SelectGroup>
|
||||
@@ -277,7 +299,8 @@ const curlExample = computed(() => {
|
||||
</FormItem>
|
||||
</FormField>
|
||||
|
||||
<TriggerWebhookFormFields v-if="values.trigger === 'webhook'" />
|
||||
<TriggerScheduleFormFields v-if="values.trigger === 'schedule'" />
|
||||
<TriggerWebhookFormFields v-else-if="values.trigger === 'webhook'" />
|
||||
<TriggerHookFormFields v-else-if="values.trigger === 'hook'" />
|
||||
|
||||
<div v-if="values.trigger === 'webhook'">
|
||||
|
||||
@@ -32,7 +32,9 @@ const subtitle = (reaction: Reaction) =>
|
||||
triggerNiceName(reaction) + ' to ' + reactionNiceName(reaction)
|
||||
|
||||
const triggerNiceName = (reaction: Reaction) => {
|
||||
if (reaction.trigger === 'hook') {
|
||||
if (reaction.trigger === 'schedule') {
|
||||
return 'Schedule'
|
||||
} else if (reaction.trigger === 'hook') {
|
||||
return 'Collection Hook'
|
||||
} else if (reaction.trigger === 'webhook') {
|
||||
return 'HTTP / Webhook'
|
||||
|
||||
42
ui/src/components/reaction/TriggerScheduleFormFields.vue
Normal file
42
ui/src/components/reaction/TriggerScheduleFormFields.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage
|
||||
} from '@/components/ui/form'
|
||||
import { Input } from '@/components/ui/input'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FormField name="triggerdata.expression" v-slot="{ componentField }" validate-on-input>
|
||||
<FormItem>
|
||||
<FormLabel for="expression" class="text-right"> Cron Expression </FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="expression"
|
||||
class="col-span-3"
|
||||
v-bind="componentField"
|
||||
placeholder="Enter a cron expression"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
<p class="text-sm text-gray-500">
|
||||
A cron expression or macro to schedule the trigger. Example: <code>0 * * * *</code> (every
|
||||
hour) or <code>@daily</code> (every day).
|
||||
<a
|
||||
href="https://en.wikipedia.org/wiki/Cron#CRON_expression"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-blue-600 underline"
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</p>
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</template>
|
||||
@@ -15,15 +15,11 @@ import { Input } from '@/components/ui/input'
|
||||
<FormItem>
|
||||
<FormLabel for="token" class="text-right">Token</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="token"
|
||||
class="col-span-3"
|
||||
v-bind="componentField"
|
||||
placeholder="Enter a token (e.g. 'xyz...')"
|
||||
/>
|
||||
<Input id="token" class="col-span-3" v-bind="componentField" placeholder="Enter a token" />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Optional. Include an authorization token in the request headers.
|
||||
Optional. Include an authorization token in the request headers. Example:
|
||||
<code>Bearer YOUR_TOKEN</code>
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@@ -33,14 +29,11 @@ import { Input } from '@/components/ui/input'
|
||||
<FormItem>
|
||||
<FormLabel for="path" class="text-right">Path</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="path"
|
||||
class="col-span-3"
|
||||
v-bind="componentField"
|
||||
placeholder="Enter a path (e.g. 'action1')"
|
||||
/>
|
||||
<Input id="path" class="col-span-3" v-bind="componentField" placeholder="Enter a path" />
|
||||
</FormControl>
|
||||
<FormDescription> Specify the path to trigger the reaction. </FormDescription>
|
||||
<FormDescription>
|
||||
Specify the path to trigger the reaction. Example: <code>action1</code>
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
|
||||
Reference in New Issue
Block a user