Compare commits
No commits in common. "4529017748a60803846bf0af0f70713b59a121e2" and "feb3db0decff292e5ddab49e47655b8fa17823bb" have entirely different histories.
4529017748
...
feb3db0dec
12 changed files with 838 additions and 889 deletions
778
dist/assets/index-CG7kEUoH.js
vendored
778
dist/assets/index-CG7kEUoH.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
778
dist/assets/index-D76yy8_K.js
vendored
Normal file
778
dist/assets/index-D76yy8_K.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
dist/index.html
vendored
4
dist/index.html
vendored
|
@ -5,8 +5,8 @@
|
|||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Vite App</title>
|
||||
<script type="module" crossorigin src="/assets/index-CG7kEUoH.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DlglK08D.css">
|
||||
<script type="module" crossorigin src="/assets/index-D76yy8_K.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CvXX7jiP.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
|
|
@ -9,7 +9,6 @@ from urllib.parse import parse_qs
|
|||
|
||||
|
||||
VERBOSE_MODE = False
|
||||
NOTIFICATION_COUNT = 1
|
||||
|
||||
|
||||
def set_verbose_mode(enabled: bool):
|
||||
|
@ -108,9 +107,6 @@ def is_api_request(data: dict) -> bool:
|
|||
|
||||
|
||||
def get_notification_message(data: dict) -> dict:
|
||||
global NOTIFICATION_COUNT
|
||||
id = NOTIFICATION_COUNT
|
||||
NOTIFICATION_COUNT += 1
|
||||
user = db.USER_ID_TO_EMAIL_MAPPING.get(int(data['user_id']), '?')
|
||||
time = data['created'].split(' ')[1].split('.')[0]
|
||||
url = data['url']
|
||||
|
@ -121,7 +117,6 @@ def get_notification_message(data: dict) -> dict:
|
|||
http_method = 'DELETE' if (http_method == 'POST' or http_method == 'PUT') and action == 'delete' else http_method # small override for UI
|
||||
payload = get_request_post_body(data)
|
||||
return {
|
||||
'id': id,
|
||||
'user': user,
|
||||
'time': time,
|
||||
'url': url,
|
||||
|
|
7
package-lock.json
generated
7
package-lock.json
generated
|
@ -13,7 +13,6 @@
|
|||
"@fortawesome/free-regular-svg-icons": "^6.5.2",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
||||
"@fortawesome/vue-fontawesome": "^3.0.8",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"vue": "^3.4.29"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -2348,12 +2347,6 @@
|
|||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
"@fortawesome/free-regular-svg-icons": "^6.5.2",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
||||
"@fortawesome/vue-fontawesome": "^3.0.8",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"vue": "^3.4.29"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -16,7 +16,6 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<main>
|
||||
<h1 class="text-2xl text-center text-slate-500 dark:text-slate-400 absolute top-1 left-1">MISP Exercise Dashboard</h1>
|
||||
<div class="absolute top-1 right-1">
|
||||
<div class="flex gap-2">
|
||||
<TheThemeButton></TheThemeButton>
|
||||
|
|
|
@ -19,6 +19,7 @@ onMounted(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<h1 class="text-3xl font-bold text-center text-slate-600 dark:text-slate-300">MISP Exercise Dashboard</h1>
|
||||
<TheScores></TheScores>
|
||||
<TheLiveLogs></TheLiveLogs>
|
||||
</template>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { exercises, selected_exercises, diagnostic, resetAllExerciseProgress, resetLiveLogs, changeExerciseSelection, debouncedGetDiangostic } from "@/socket";
|
||||
import { exercises, selected_exercises, diagnostic, resetAllExerciseProgress, resetLiveLoggs, changeExerciseSelection, fetchDiagnostic } from "@/socket";
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||
import { faScrewdriverWrench, faTrash, faSuitcaseMedical, faGraduationCap, faBan } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
|||
|
||||
function showTheModal() {
|
||||
admin_modal.value.showModal()
|
||||
debouncedGetDiangostic()
|
||||
fetchDiagnostic()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -52,7 +52,7 @@
|
|||
Reset All Exercises
|
||||
</button>
|
||||
<button
|
||||
@click="resetLiveLogs()"
|
||||
@click="resetLiveLoggs()"
|
||||
class="h-10 min-h-10 px-2 py-1 font-semibold bg-amber-600 text-slate-200 hover:bg-amber-700 btn btn-sm"
|
||||
>
|
||||
<FontAwesomeIcon :icon="faBan" class=""></FontAwesomeIcon>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
<template v-else>
|
||||
<tr v-for="notification in notifications" :key="notification.id">
|
||||
<tr v-for="(notification, index) in notifications" :key="index">
|
||||
<td
|
||||
class="border-b border-slate-100 dark:border-slate-700 text-slate-600 dark:text-slate-400 p-1 pl-2 w-12 whitespace-nowrap"
|
||||
>
|
||||
|
|
136
src/socket.js
136
src/socket.js
|
@ -1,6 +1,5 @@
|
|||
import { reactive, computed } from "vue";
|
||||
import { io } from "socket.io-client";
|
||||
import debounce from 'lodash.debounce'
|
||||
|
||||
// "undefined" means the URL will be computed from the `window.location` object
|
||||
const URL = process.env.NODE_ENV === "production" ? undefined : "http://localhost:3000";
|
||||
|
@ -19,16 +18,7 @@ const initial_state = {
|
|||
const state = reactive({ ...initial_state });
|
||||
const connectionState = reactive({
|
||||
connected: false
|
||||
})
|
||||
|
||||
|
||||
const socket = io(URL, {
|
||||
autoConnect: true
|
||||
});
|
||||
|
||||
|
||||
/* Public */
|
||||
/* ------ */
|
||||
})
|
||||
|
||||
export const exercises = computed(() => state.exercises)
|
||||
export const selected_exercises = computed(() => state.selected_exercises)
|
||||
|
@ -46,10 +36,25 @@ export function resetState() {
|
|||
}
|
||||
|
||||
export function fullReload() {
|
||||
getExercises()
|
||||
getSelectedExercises()
|
||||
getNotifications()
|
||||
getProgress()
|
||||
socket.emit("get_exercises", (all_exercises) => {
|
||||
state.exercises = all_exercises
|
||||
})
|
||||
socket.emit("get_selected_exercises", (all_selected_exercises) => {
|
||||
state.selected_exercises = all_selected_exercises
|
||||
})
|
||||
socket.emit("get_notifications", (all_notifications) => {
|
||||
state.notificationEvents = all_notifications
|
||||
})
|
||||
socket.emit("get_progress", (all_progress) => {
|
||||
state.progresses = all_progress
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchDiagnostic() {
|
||||
state.diagnostic = {}
|
||||
socket.emit("get_diagnostic", (diagnostic) => {
|
||||
state.diagnostic = diagnostic
|
||||
})
|
||||
}
|
||||
|
||||
export function setCompletedState(completed, user_id, exec_uuid, task_uuid) {
|
||||
|
@ -58,15 +63,28 @@ export function setCompletedState(completed, user_id, exec_uuid, task_uuid) {
|
|||
exercise_uuid: exec_uuid,
|
||||
task_uuid: task_uuid,
|
||||
}
|
||||
sendCompletedState(completed, payload)
|
||||
const event_name = !completed ? "mark_task_completed": "mark_task_incomplete"
|
||||
socket.emit(event_name, payload, () => {
|
||||
socket.emit("get_progress", (all_progress) => {
|
||||
state.progresses = all_progress
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function resetAllExerciseProgress() {
|
||||
sendResetAllExerciseProgress()
|
||||
socket.emit("reset_all_exercise_progress", () => {
|
||||
socket.emit("get_progress", (all_progress) => {
|
||||
state.progresses = all_progress
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function resetLiveLogs() {
|
||||
sendResetLiveLogs()
|
||||
export function resetLiveLoggs() {
|
||||
socket.emit("reset_notifications", () => {
|
||||
socket.emit("get_notifications", (all_notifications) => {
|
||||
state.notificationEvents = all_notifications
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function changeExerciseSelection(exec_uuid, state_enabled) {
|
||||
|
@ -74,84 +92,24 @@ export function changeExerciseSelection(exec_uuid, state_enabled) {
|
|||
exercise_uuid: exec_uuid,
|
||||
selected: state_enabled,
|
||||
}
|
||||
sendChangeExerciseSelection(payload)
|
||||
}
|
||||
|
||||
export function toggleVerboseMode(enabled) {
|
||||
sendToggleVerboseMode(enabled)
|
||||
}
|
||||
|
||||
export const debouncedGetProgress = debounce(getProgress, 200, {leading: true})
|
||||
export const debouncedGetDiangostic = debounce(getDiangostic, 1000, {leading: true})
|
||||
|
||||
|
||||
/* Private */
|
||||
/* ------- */
|
||||
|
||||
function getExercises() {
|
||||
socket.emit("get_exercises", (all_exercises) => {
|
||||
state.exercises = all_exercises
|
||||
})
|
||||
}
|
||||
|
||||
function getSelectedExercises() {
|
||||
socket.emit("change_exercise_selection", payload, () => {
|
||||
socket.emit("get_selected_exercises", (all_selected_exercises) => {
|
||||
state.selected_exercises = all_selected_exercises
|
||||
})
|
||||
}
|
||||
|
||||
function getNotifications() {
|
||||
socket.emit("get_notifications", (all_notifications) => {
|
||||
state.notificationEvents = all_notifications
|
||||
})
|
||||
}
|
||||
|
||||
function getProgress() {
|
||||
socket.emit("get_progress", (all_progress) => {
|
||||
state.progresses = all_progress
|
||||
})
|
||||
}
|
||||
|
||||
function getDiangostic() {
|
||||
state.diagnostic = {}
|
||||
socket.emit("get_diagnostic", (diagnostic) => {
|
||||
state.diagnostic = diagnostic
|
||||
})
|
||||
}
|
||||
|
||||
function sendCompletedState(completed, payload) {
|
||||
const event_name = !completed ? "mark_task_completed": "mark_task_incomplete"
|
||||
socket.emit(event_name, payload, () => {
|
||||
getProgress()
|
||||
})
|
||||
}
|
||||
|
||||
function sendResetAllExerciseProgress() {
|
||||
socket.emit("reset_all_exercise_progress", () => {
|
||||
getProgress()
|
||||
})
|
||||
}
|
||||
|
||||
function sendResetLiveLogs() {
|
||||
socket.emit("reset_notifications", () => {
|
||||
getNotifications()
|
||||
})
|
||||
}
|
||||
|
||||
function sendChangeExerciseSelection(payload) {
|
||||
socket.emit("change_exercise_selection", payload, () => {
|
||||
getSelectedExercises()
|
||||
})
|
||||
}
|
||||
|
||||
function sendToggleVerboseMode(enabled) {
|
||||
export function toggleVerboseMode(enabled) {
|
||||
const payload = {
|
||||
verbose: enabled
|
||||
}
|
||||
socket.emit("toggle_verbose_mode", payload, () => {})
|
||||
}
|
||||
|
||||
/* Event listener */
|
||||
|
||||
const socket = io(URL, {
|
||||
autoConnect: true
|
||||
});
|
||||
|
||||
socket.on("connect", () => {
|
||||
connectionState.connected = true;
|
||||
|
@ -170,11 +128,15 @@ socket.on("notification", (message) => {
|
|||
});
|
||||
|
||||
socket.on("new_user", (new_user) => {
|
||||
debouncedGetProgress()
|
||||
socket.emit("get_progress", (all_progress) => {
|
||||
state.progresses = all_progress
|
||||
})
|
||||
});
|
||||
|
||||
socket.on("refresh_score", (new_user) => {
|
||||
debouncedGetProgress()
|
||||
socket.emit("get_progress", (all_progress) => {
|
||||
state.progresses = all_progress
|
||||
})
|
||||
});
|
||||
|
||||
function addLimited(target, message, maxCount) {
|
||||
|
|
Loading…
Reference in a new issue