main
vue 264 lines 8.36 KB
Raw
1 <template>
2 <div>
3 <CardEntity hoverable clickable :embedded class="@container" @click.stop="showDetails = true">
4 <template #headerMain>#{{ alert._id || alert._source.id }}</template>
5 <template #headerExtra>
6 {{ formatDate(alert._source.timestamp_utc, dFormats.datetimesec) }}
7 </template>
8 <template #default>
9 <div class="flex flex-col gap-1">
10 {{ alert._source.rule_description || alert._source.type }}
11 <p>
12 {{ alert._source.rule_groups }}
13 </p>
14 </div>
15 </template>
16 <template v-if="alert._id" #mainExtra>
17 <div class="flex flex-wrap items-center gap-3">
18 <Badge type="splitted" color="primary">
19 <template #iconLeft>
20 <Icon :name="TargetIcon" :size="13" class="opacity-80!" />
21 </template>
22 <template #label>Fired times</template>
23 <template #value>
24 {{ alert._source.rule_firedtimes }}
25 </template>
26 </Badge>
27
28 <Badge :type="alert._source.rule_mail ? 'active' : 'muted'">
29 <template #iconRight>
30 <Icon :name="alert._source.rule_mail ? MailIcon : DisabledIcon" :size="14" />
31 </template>
32 <template #label>Rule mail</template>
33 </Badge>
34
35 <n-popover overlap placement="bottom-start">
36 <template #trigger>
37 <Badge type="splitted" color="primary" hint-cursor>
38 <template #iconLeft>
39 <Icon :name="AgentIcon" :size="13" class="opacity-80!" />
40 </template>
41 <template #label>Agent</template>
42 <template #value>
43 <div class="flex flex-wrap items-center gap-2">
44 {{ alert._source.agent_name }} / {{ alert._source.agent_labels_customer }}
45 <Icon :name="InfoIcon" :size="13" class="opacity-80!" />
46 </div>
47 </template>
48 </Badge>
49 </template>
50 <div class="flex flex-col gap-1">
51 <div class="box">
52 agent_id:
53 <code
54 class="text-primary cursor-pointer"
55 @click.stop="routeAgent(alert._source.agent_id).navigate()"
56 >
57 {{ alert._source.agent_id }}
58 <Icon :name="LinkIcon" :size="13" class="relative top-0.5" />
59 </code>
60 </div>
61 <div class="box">
62 agent_ip:
63 <code>{{ alert._source.agent_ip }}</code>
64 </div>
65 <div class="box">
66 agent_name:
67 <code>{{ alert._source.agent_name }}</code>
68 </div>
69 <div class="box">
70 agent_labels_customer:
71 <code
72 class="text-primary cursor-pointer"
73 @click.stop="
74 routeCustomer({ code: alert._source.agent_labels_customer }).navigate()
75 "
76 >
77 {{ alert._source.agent_labels_customer }}
78 <Icon :name="LinkIcon" :size="13" class="relative top-0.5" />
79 </code>
80 </div>
81 </div>
82 </n-popover>
83 <Badge type="splitted" color="primary">
84 <template #label>syslog</template>
85 <template #value>{{ alert._source.syslog_type }} / {{ alert._source.syslog_level }}</template>
86 </Badge>
87 <Badge type="splitted" color="primary" class="hidden! @2xl:flex!">
88 <template #label>manager</template>
89 <template #value>
90 {{ alert._source.manager_name }}
91 </template>
92 </Badge>
93 <Badge type="splitted" color="primary" class="hidden! @2xl:flex!">
94 <template #label>decoder</template>
95 <template #value>
96 {{ alert._source.decoder_name }}
97 </template>
98 </Badge>
99 <Badge type="splitted" color="primary" class="hidden! @2xl:flex!">
100 <template #label>source</template>
101 <template #value>
102 {{ alert._source.source }}
103 </template>
104 </Badge>
105 </div>
106 </template>
107 <template v-if="!hideActions" #footerExtra>
108 <AlertActions
109 :alert
110 :soc-alert-field="socAlertCreationField"
111 size="small"
112 @start-loading="loading = true"
113 @stop-loading="loading = false"
114 @updated-url="alert._source.alert_url = $event"
115 @updated-id="alert._source.alert_id = $event"
116 @updated-ask-message="alert._source.ask_socfortress_message = $event"
117 />
118 </template>
119 </CardEntity>
120
121 <n-modal
122 v-model:show="showDetails"
123 preset="card"
124 content-class="p-0!"
125 :style="{ maxWidth: 'min(800px, 90vw)', minHeight: 'min(600px, 90vh)', overflow: 'hidden' }"
126 :title="`Alert: ${alert._id || alert._source.id}`"
127 :bordered="false"
128 segmented
129 >
130 <n-tabs type="line" animated :tabs-padding="24">
131 <n-tab-pane v-if="alert._id" name="Agent" tab="Agent" display-directive="show">
132 <div v-if="agentProperties" class="grid-auto-fit-200 grid gap-2 p-6 pt-3">
133 <CardKV v-for="(value, key) of agentProperties" :key>
134 <template #key>
135 {{ key }}
136 </template>
137 <template #value>
138 <template v-if="key === 'agent_id'">
139 <code
140 class="text-primary cursor-pointer"
141 @click.stop="routeAgent(`${value}`).navigate()"
142 >
143 {{ value }}
144 <Icon :name="LinkIcon" :size="13" class="relative top-0.5" />
145 </code>
146 </template>
147 <template v-else-if="key === 'agent_labels_customer'">
148 <code
149 class="text-primary cursor-pointer"
150 @click.stop="
151 routeCustomer(value ? { code: value.toString() } : undefined).navigate()
152 "
153 >
154 {{ value }}
155 <Icon :name="LinkIcon" :size="13" class="relative top-0.5" />
156 </code>
157 </template>
158 <template v-else>
159 {{ value || "-" }}
160 </template>
161 </template>
162 </CardKV>
163 </div>
164 </n-tab-pane>
165 <n-tab-pane
166 v-if="alert._source.ask_socfortress_message"
167 name="SOCFortress Response"
168 tab="SOCFortress Response"
169 display-directive="show"
170 >
171 <div class="p-6 pt-3">
172 <n-input
173 :value="alert._source.ask_socfortress_message"
174 type="textarea"
175 readonly
176 placeholder="Empty"
177 size="large"
178 :autosize="{
179 minRows: 3
180 }"
181 />
182 </div>
183 </n-tab-pane>
184 <n-tab-pane v-if="alert._source.message" name="Message" tab="Message" display-directive="show">
185 <div class="p-6 pt-3">
186 <CodeSource :code="alert._source.message" :decode="false" />
187 </div>
188 </n-tab-pane>
189 <n-tab-pane
190 v-if="alert._source.data_document"
191 name="Data document"
192 tab="Data document"
193 display-directive="show"
194 >
195 <div class="p-6 pt-3">
196 <n-input
197 :value="alert._source.data_document"
198 type="textarea"
199 readonly
200 placeholder="Empty"
201 size="large"
202 :autosize="{
203 minRows: 3
204 }"
205 />
206 </div>
207 </n-tab-pane>
208 <n-tab-pane name="Details" tab="Details" display-directive="show:lazy">
209 <div class="p-6 pt-3">
210 <CodeSource :code="alert._source" lang="json" :decode="false" />
211 </div>
212 </n-tab-pane>
213 </n-tabs>
214 </n-modal>
215 </div>
216 </template>
217
218 <script setup lang="ts">
219 import type { SocAlertField } from "./type.d"
220 import type { Alert } from "@/types/alerts.d"
221 import _pick from "lodash/pick"
222 import { NInput, NModal, NPopover, NTabPane, NTabs } from "naive-ui"
223 import { computed, defineAsyncComponent, inject, ref, toRefs } from "vue"
224 import Badge from "@/components/common/Badge.vue"
225 import CardEntity from "@/components/common/cards/CardEntity.vue"
226 import CardKV from "@/components/common/cards/CardKV.vue"
227 import Icon from "@/components/common/Icon.vue"
228 import { useNavigation } from "@/composables/useNavigation"
229 import { useSettingsStore } from "@/stores/settings"
230 import { formatDate } from "@/utils/format"
231
232 const props = defineProps<{ alert: Alert; hideActions?: boolean; embedded?: boolean }>()
233 const AlertActions = defineAsyncComponent(() => import("./AlertActions.vue"))
234 const CodeSource = defineAsyncComponent(() => import("@/components/common/CodeSource.vue"))
235
236 const { alert, hideActions, embedded } = toRefs(props)
237
238 const InfoIcon = "carbon:information"
239 const TargetIcon = "zondicons:target"
240 const DisabledIcon = "carbon:subtract"
241 const MailIcon = "carbon:email"
242 const AgentIcon = "carbon:police"
243 const LinkIcon = "carbon:launch"
244
245 const { routeCustomer, routeAgent } = useNavigation()
246 const loading = ref(false)
247 const showDetails = ref(false)
248 const dFormats = useSettingsStore().dateFormat
249
250 const agentProperties = computed(() => {
251 return _pick(alert.value._source, [
252 "agent_id",
253 "agent_ip_city_name",
254 "agent_ip_country_code",
255 "agent_ip_geolocation",
256 "agent_ip_reserved_ip",
257 "agent_ip",
258 "agent_labels_customer",
259 "agent_name"
260 ])
261 })
262
263 const socAlertCreationField = ref(inject<SocAlertField>("soc-alert-creation-field", "alert_url"))
264 </script>