main
vue 423 lines 11.2 KB
Raw
1 <template>
2 <div class="contents">
3 <n-button
4 v-if="networkConnector.deployed"
5 :loading="loadingDecommission"
6 type="error"
7 :size
8 secondary
9 @click.stop="decommissionNetworkConnector()"
10 >
11 <template #icon>
12 <Icon :name="DecommissionIcon" />
13 </template>
14 Decommission
15 </n-button>
16
17 <n-button
18 v-if="isFortinet && !networkConnector.deployed"
19 :loading="loadingFortinetProvision"
20 type="success"
21 :size
22 secondary
23 @click.stop="showFortinetForm = true"
24 >
25 <template #icon>
26 <Icon :name="DeployIcon" />
27 </template>
28 Deploy
29 </n-button>
30
31 <n-button
32 v-if="isSonicwall && !networkConnector.deployed"
33 :loading="loadingSonicwallProvision"
34 type="success"
35 :size
36 secondary
37 @click.stop="showSonicwallForm = true"
38 >
39 <template #icon>
40 <Icon :name="DeployIcon" />
41 </template>
42 Deploy
43 </n-button>
44
45 <n-button
46 v-if="isSentinelOne && !networkConnector.deployed"
47 :loading="loadingSentinelOneProvision"
48 type="success"
49 :size
50 secondary
51 @click.stop="showSentinelOneForm = true"
52 >
53 <template #icon>
54 <Icon :name="DeployIcon" />
55 </template>
56 Deploy
57 </n-button>
58
59 <n-button v-if="!hideDeleteButton" :size type="error" ghost :loading="loadingDelete" @click.stop="handleDelete">
60 <template #icon>
61 <Icon :name="DeleteIcon" :size="15" />
62 </template>
63 Delete
64 </n-button>
65
66 <!-- Fortinet Modal -->
67 <n-modal
68 v-model:show="showFortinetForm"
69 preset="card"
70 :style="{ maxWidth: 'min(420px, 90vw)', minHeight: 'min(300px, 90vh)', overflow: 'hidden' }"
71 title="Fortinet options"
72 :bordered="false"
73 content-class="flex flex-col"
74 segmented
75 >
76 <n-spin v-model:show="loadingFortinetProvision">
77 <FortinetForm v-model:options="fortinetOptions" />
78 </n-spin>
79
80 <template #footer>
81 <div class="flex justify-end">
82 <n-button
83 :loading="loadingFortinetProvision"
84 type="success"
85 secondary
86 :disabled="!isFortinetFormValid"
87 @click.stop="fortinetProvision()"
88 >
89 <template #icon>
90 <Icon :name="DeployIcon" />
91 </template>
92 Deploy
93 </n-button>
94 </div>
95 </template>
96 </n-modal>
97
98 <!-- SonicWall Modal -->
99 <n-modal
100 v-model:show="showSonicwallForm"
101 preset="card"
102 :style="{ maxWidth: 'min(420px, 90vw)', minHeight: 'min(300px, 90vh)', overflow: 'hidden' }"
103 title="SonicWall options"
104 :bordered="false"
105 content-class="flex flex-col"
106 segmented
107 >
108 <n-spin v-model:show="loadingSonicwallProvision">
109 <SonicwallForm v-model:options="sonicwallOptions" />
110 </n-spin>
111
112 <template #footer>
113 <div class="flex justify-end">
114 <n-button
115 :loading="loadingSonicwallProvision"
116 type="success"
117 secondary
118 :disabled="!isSonicwallFormValid"
119 @click.stop="sonicwallProvision()"
120 >
121 <template #icon>
122 <Icon :name="DeployIcon" />
123 </template>
124 Deploy
125 </n-button>
126 </div>
127 </template>
128 </n-modal>
129
130 <!-- SentinelOne Modal -->
131 <n-modal
132 v-model:show="showSentinelOneForm"
133 preset="card"
134 :style="{ maxWidth: 'min(420px, 90vw)', minHeight: 'min(300px, 90vh)', overflow: 'hidden' }"
135 title="SentinelOne options"
136 :bordered="false"
137 content-class="flex flex-col"
138 segmented
139 >
140 <n-spin v-model:show="loadingSentinelOneProvision">
141 <SentinelOneForm v-model:options="sentinelOneOptions" />
142 </n-spin>
143
144 <template #footer>
145 <div class="flex justify-end">
146 <n-button
147 :loading="loadingSentinelOneProvision"
148 type="success"
149 secondary
150 :disabled="!isSentinelOneFormValid"
151 @click.stop="sentinelOneProvision()"
152 >
153 <template #icon>
154 <Icon :name="DeployIcon" />
155 </template>
156 Deploy
157 </n-button>
158 </div>
159 </template>
160 </n-modal>
161 </div>
162 </template>
163
164 <script setup lang="ts">
165 import type { ButtonSize } from "naive-ui"
166 import type { FortinetModel } from "./provisions/FortinetForm.vue"
167 import type { SentinelOneModel } from "./provisions/SentinelOneForm.vue"
168 import type { SonicWallModel } from "./provisions/SonicwallForm.vue"
169 import type { FortinetProvision, SentinelOneProvision, SonicwallProvision } from "@/api/endpoints/networkConnectors"
170 import type { CustomerNetworkConnector } from "@/types/networkConnectors.d"
171 import { NButton, NModal, NSpin, useDialog, useMessage } from "naive-ui"
172 import { computed, h, ref, watch } from "vue"
173 import Api from "@/api"
174 import Icon from "@/components/common/Icon.vue"
175 import FortinetForm from "./provisions/FortinetForm.vue"
176 import SentinelOneForm from "./provisions/SentinelOneForm.vue"
177 import SonicwallForm from "./provisions/SonicwallForm.vue"
178
179 const { networkConnector, hideDeleteButton, size } = defineProps<{
180 networkConnector: CustomerNetworkConnector
181 hideDeleteButton?: boolean
182 size?: ButtonSize
183 }>()
184
185 const emit = defineEmits<{
186 (e: "startLoading"): void
187 (e: "stopLoading"): void
188 (e: "deployed"): void
189 (e: "decommissioned"): void
190 (e: "deleted"): void
191 }>()
192
193 const DeployIcon = "carbon:deploy"
194 const DeleteIcon = "ph:trash"
195 const DecommissionIcon = "carbon:delete"
196
197 const dialog = useDialog()
198 const message = useMessage()
199 const loadingFortinetProvision = ref(false)
200 const loadingSonicwallProvision = ref(false)
201 const loadingSentinelOneProvision = ref(false)
202 const loadingDelete = ref(false)
203 const loadingDecommission = ref(false)
204 const loading = computed(
205 () =>
206 loadingFortinetProvision.value ||
207 loadingSonicwallProvision.value ||
208 loadingSentinelOneProvision.value ||
209 loadingDecommission.value ||
210 loadingDelete.value
211 )
212
213 const serviceName = computed(() => networkConnector.network_connector_service_name)
214 const customerCode = computed(() => networkConnector.customer_code)
215 const isFortinet = computed(() => serviceName.value === "Fortinet")
216 const isSonicwall = computed(() => serviceName.value === "Sonicwall")
217 const isSentinelOne = computed(() => serviceName.value === "Sentinelone")
218
219 const showFortinetForm = ref(false)
220 const showSonicwallForm = ref(false)
221 const showSentinelOneForm = ref(false)
222
223 const fortinetOptions = ref<FortinetModel>({
224 protocol: "tcp",
225 hot_data_retention: 1,
226 index_replicas: 0
227 })
228
229 const sonicwallOptions = ref<SonicWallModel>({
230 protocol: "tcp",
231 hot_data_retention: 1,
232 index_replicas: 0
233 })
234
235 const sentinelOneOptions = ref<SentinelOneModel>({
236 protocol: "tls",
237 hot_data_retention: 1,
238 index_replicas: 0
239 })
240
241 const isFortinetFormValid = computed(() => {
242 if (fortinetOptions.value.hot_data_retention === null) {
243 return false
244 }
245 if (fortinetOptions.value.index_replicas === null) {
246 return false
247 }
248 return true
249 })
250
251 const isSonicwallFormValid = computed(() => {
252 if (sonicwallOptions.value.hot_data_retention === null) {
253 return false
254 }
255 if (sonicwallOptions.value.index_replicas === null) {
256 return false
257 }
258 return true
259 })
260
261 const isSentinelOneFormValid = computed(() => {
262 if (sentinelOneOptions.value.hot_data_retention === null) {
263 return false
264 }
265 if (sentinelOneOptions.value.index_replicas === null) {
266 return false
267 }
268 return true
269 })
270
271 watch(loading, val => {
272 if (val) {
273 emit("startLoading")
274 } else {
275 emit("stopLoading")
276 }
277 })
278
279 function fortinetProvision() {
280 loadingFortinetProvision.value = true
281
282 const options: FortinetProvision = {
283 tcp_enabled: fortinetOptions.value.protocol === "tcp",
284 udp_enabled: fortinetOptions.value.protocol === "udp",
285 hot_data_retention: fortinetOptions.value.hot_data_retention,
286 index_replicas: fortinetOptions.value.index_replicas
287 }
288
289 Api.networkConnectors
290 .fortinetProvision(customerCode.value, serviceName.value, options)
291 .then(res => {
292 if (res.data.success) {
293 emit("deployed")
294 showFortinetForm.value = false
295 message.success(res.data?.message || "Fortinet customer provisioned successfully.")
296 } else {
297 message.warning(res.data?.message || "An error occurred. Please try again later.")
298 }
299 })
300 .catch(err => {
301 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
302 })
303 .finally(() => {
304 loadingFortinetProvision.value = false
305 })
306 }
307
308 function sonicwallProvision() {
309 loadingSonicwallProvision.value = true
310
311 const options: SonicwallProvision = {
312 tcp_enabled: sonicwallOptions.value.protocol === "tcp",
313 hot_data_retention: sonicwallOptions.value.hot_data_retention,
314 index_replicas: sonicwallOptions.value.index_replicas
315 }
316
317 Api.networkConnectors
318 .sonicwallProvision(customerCode.value, serviceName.value, options)
319 .then(res => {
320 if (res.data.success) {
321 emit("deployed")
322 showSonicwallForm.value = false
323 message.success(res.data?.message || "SonicWall customer provisioned successfully.")
324 } else {
325 message.warning(res.data?.message || "An error occurred. Please try again later.")
326 }
327 })
328 .catch(err => {
329 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
330 })
331 .finally(() => {
332 loadingSonicwallProvision.value = false
333 })
334 }
335
336 function sentinelOneProvision() {
337 loadingSentinelOneProvision.value = true
338
339 const options: SentinelOneProvision = {
340 tls_enabled: sentinelOneOptions.value.protocol === "tls",
341 hot_data_retention: sentinelOneOptions.value.hot_data_retention,
342 index_replicas: sentinelOneOptions.value.index_replicas
343 }
344
345 Api.networkConnectors
346 .sentineloneProvision(customerCode.value, serviceName.value, options)
347 .then(res => {
348 if (res.data.success) {
349 emit("deployed")
350 showSentinelOneForm.value = false
351 message.success(res.data?.message || "SentinelOne customer provisioned successfully.")
352 } else {
353 message.warning(res.data?.message || "An error occurred. Please try again later.")
354 }
355 })
356 .catch(err => {
357 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
358 })
359 .finally(() => {
360 loadingSentinelOneProvision.value = false
361 })
362 }
363
364 function handleDelete() {
365 dialog.warning({
366 title: "Confirm",
367 content: () =>
368 h("div", {
369 innerHTML: `Are you sure you want to delete the Network Connector: <strong>${serviceName.value}</strong> ?`
370 }),
371 positiveText: "Yes I'm sure",
372 negativeText: "Cancel",
373 onPositiveClick: () => {
374 deleteNetworkConnector()
375 },
376 onNegativeClick: () => {
377 message.info("Delete canceled")
378 }
379 })
380 }
381
382 function deleteNetworkConnector() {
383 loadingDelete.value = true
384
385 Api.networkConnectors
386 .deleteNetworkConnector(customerCode.value, serviceName.value)
387 .then(res => {
388 if (res.data.success) {
389 emit("deleted")
390 message.success(res.data?.message || "Customer Network Connector successfully deleted.")
391 } else {
392 message.warning(res.data?.message || "An error occurred. Please try again later.")
393 }
394 })
395 .catch(err => {
396 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
397 })
398 .finally(() => {
399 loadingDelete.value = false
400 })
401 }
402
403 function decommissionNetworkConnector() {
404 loadingDecommission.value = true
405
406 Api.networkConnectors
407 .decommissionNetworkConnector(customerCode.value, serviceName.value)
408 .then(res => {
409 if (res.data.success) {
410 emit("decommissioned")
411 message.success(res.data?.message || "Customer Network Connector successfully decommissioned.")
412 } else {
413 message.warning(res.data?.message || "An error occurred. Please try again later.")
414 }
415 })
416 .catch(err => {
417 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
418 })
419 .finally(() => {
420 loadingDecommission.value = false
421 })
422 }
423 </script>