main
vue 170 lines 3.86 KB
Raw
1 <template>
2 <div class="active-response-invoke-form flex grow flex-col justify-between">
3 <div class="form-box">
4 <n-spin v-model:show="loading">
5 <n-form ref="formRef" :label-width="80" :model="form" :rules>
6 <div class="grid-auto-fit-200 grid gap-6">
7 <n-form-item label="Action" path="action">
8 <n-select v-model:value="form.action" :options="invokeActionOptions" />
9 </n-form-item>
10 <n-form-item label="IP Address" path="ip">
11 <n-input v-model:value.trim="form.ip" placeholder="Input the IP Address..." clearable />
12 </n-form-item>
13 </div>
14 </n-form>
15 <p v-if="agentId">
16 This action will be submitted only for the Agent:
17 <code>{{ agentId }}</code>
18 </p>
19 </n-spin>
20 </div>
21 <div class="buttons-box flex justify-between gap-3">
22 <div class="flex gap-3">
23 <slot name="additionalActions"></slot>
24 </div>
25 <n-button type="primary" :disabled="!isValid" :loading @click="validate()">Submit</n-button>
26 </div>
27 </div>
28 </template>
29
30 <script setup lang="ts">
31 import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
32 import type { InvokeRequest, InvokeRequestAction } from "@/api/endpoints/activeResponse"
33 import type { SupportedActiveResponse } from "@/types/activeResponse.d"
34 import { NButton, NForm, NFormItem, NInput, NSelect, NSpin, useMessage } from "naive-ui"
35 import isIP from "validator/es/lib/isIP"
36 import { computed, onMounted, ref, watch } from "vue"
37 import Api from "@/api"
38
39 interface InvokeForm {
40 action: null | InvokeRequestAction
41 ip: string
42 }
43
44 const { activeResponse, agentId } = defineProps<{
45 activeResponse: SupportedActiveResponse
46 agentId?: string | number
47 }>()
48
49 const emit = defineEmits<{
50 (e: "submitted"): void
51 (e: "startLoading"): void
52 (e: "stopLoading"): void
53 (
54 e: "mounted",
55 value: {
56 reset: () => void
57 }
58 ): void
59 }>()
60
61 const message = useMessage()
62 const form = ref<InvokeForm>(getClearForm())
63 const formRef = ref<FormInst | null>(null)
64 const invokeActionOptions = [
65 { label: "Block", value: "block" },
66 { label: "Unblock", value: "unblock" }
67 ]
68 const isValid = computed(() => {
69 return !!form.value.action && isIP(form.value.ip)
70 })
71 const loading = ref(false)
72
73 watch(loading, val => {
74 if (val) {
75 emit("startLoading")
76 } else {
77 emit("stopLoading")
78 }
79 })
80
81 const rules: FormRules = {
82 action: {
83 required: true,
84 message: "Please Select an Action",
85 trigger: ["input", "blur"]
86 },
87 ip: {
88 required: true,
89 validator: validateIp,
90 trigger: ["blur"]
91 }
92 }
93
94 function validateIp(_rule: FormItemRule, value: string) {
95 if (!value || !isIP(value)) {
96 return new Error("Please input a valid IP Address")
97 }
98
99 return true
100 }
101
102 function getClearForm(): InvokeForm {
103 return {
104 action: null,
105 ip: ""
106 }
107 }
108
109 function reset() {
110 if (!loading.value) {
111 resetForm()
112 formRef.value?.restoreValidation()
113 }
114 }
115
116 function resetForm() {
117 form.value = getClearForm()
118 }
119
120 function validate() {
121 if (!formRef.value) return
122
123 formRef.value.validate((errors?: Array<FormValidationError>) => {
124 if (!errors) {
125 submit()
126 } else {
127 message.warning("You must fill in the required fields correctly.")
128 return false
129 }
130 })
131 }
132
133 function submit() {
134 loading.value = true
135
136 const payload: InvokeRequest = {
137 activeResponseName: activeResponse.name,
138 action: form.value.action as InvokeRequestAction,
139 ip: form.value.ip
140 }
141
142 if (agentId) {
143 payload.agentId = agentId.toString()
144 }
145
146 Api.activeResponse
147 .invoke(payload)
148 .then(res => {
149 if (res.data.success) {
150 message.success(res.data?.message || "Active Response invoked successfully")
151 emit("submitted")
152 resetForm()
153 } else {
154 message.warning(res.data?.message || "An error occurred. Please try again later.")
155 }
156 })
157 .catch(err => {
158 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
159 })
160 .finally(() => {
161 loading.value = false
162 })
163 }
164
165 onMounted(() => {
166 emit("mounted", {
167 reset
168 })
169 })
170 </script>