fix : securite middle et execfile
This commit is contained in:
@@ -55,6 +55,7 @@
|
|||||||
import {Icon as IconifyIcon} from "@iconify/vue"
|
import {Icon as IconifyIcon} from "@iconify/vue"
|
||||||
import CircleSkeleton from "~/components/skeleton/CircleSkeleton.vue"
|
import CircleSkeleton from "~/components/skeleton/CircleSkeleton.vue"
|
||||||
import TextSkeleton from "~/components/skeleton/TextSkeleton.vue"
|
import TextSkeleton from "~/components/skeleton/TextSkeleton.vue"
|
||||||
|
import { downloadApiFile, useApiAuthHeader } from "~/composables/useApiAuth"
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
folder: string | null
|
folder: string | null
|
||||||
@@ -62,15 +63,16 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const backups = ref<string[]>([])
|
const backups = ref<string[]>([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
const apiAuthHeader = useApiAuthHeader()
|
||||||
const title = computed(() => {
|
const title = computed(() => {
|
||||||
if (!props.folder) return "Fichiers"
|
if (!props.folder) return "Fichiers"
|
||||||
return `Backup — ${props.folder.toUpperCase()}`
|
return `Backup — ${props.folder.toUpperCase()}`
|
||||||
})
|
})
|
||||||
|
|
||||||
const downloadBackup = (file: string) => {
|
const downloadBackup = async (file: string) => {
|
||||||
if (!props.folder) return
|
if (!props.folder) return
|
||||||
const url = `/api/download?folder=${encodeURIComponent(props.folder)}&file=${encodeURIComponent(file)}`
|
const url = `/api/download?folder=${encodeURIComponent(props.folder)}&file=${encodeURIComponent(file)}`
|
||||||
window.location.href = url
|
await downloadApiFile(url, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => props.folder, async (folder) => {
|
watch(() => props.folder, async (folder) => {
|
||||||
@@ -82,7 +84,9 @@ watch(() => props.folder, async (folder) => {
|
|||||||
|
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const data = await $fetch<string[]>(`/api/backups?folder=${encodeURIComponent(folder)}`)
|
const data = await $fetch<string[]>(`/api/backups?folder=${encodeURIComponent(folder)}`, {
|
||||||
|
headers: apiAuthHeader
|
||||||
|
})
|
||||||
backups.value = data
|
backups.value = data
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Erreur récupération backups:", error)
|
console.error("Erreur récupération backups:", error)
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref } from "vue"
|
import { computed, onMounted, ref } from "vue"
|
||||||
import { Icon as IconifyIcon } from "@iconify/vue"
|
import { Icon as IconifyIcon } from "@iconify/vue"
|
||||||
|
import { useApiAuthHeader } from "~/composables/useApiAuth"
|
||||||
|
|
||||||
type BackupScript = {
|
type BackupScript = {
|
||||||
key: string
|
key: string
|
||||||
@@ -118,6 +119,7 @@ const scripts = ref<BackupScript[]>([])
|
|||||||
const output = ref<string>("")
|
const output = ref<string>("")
|
||||||
const message = ref<string>("")
|
const message = ref<string>("")
|
||||||
const isError = ref(false)
|
const isError = ref(false)
|
||||||
|
const apiAuthHeader = useApiAuthHeader()
|
||||||
|
|
||||||
const statusClass = computed(() => (isError.value ? "status-error" : "status-success"))
|
const statusClass = computed(() => (isError.value ? "status-error" : "status-success"))
|
||||||
|
|
||||||
@@ -134,7 +136,9 @@ const loadScripts = async () => {
|
|||||||
downloadFolders: []
|
downloadFolders: []
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const data = await $fetch<BackupScriptListResponse>("/api/backup-script")
|
const data = await $fetch<BackupScriptListResponse>("/api/backup-script", {
|
||||||
|
headers: apiAuthHeader
|
||||||
|
})
|
||||||
scripts.value = data.scripts
|
scripts.value = data.scripts
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
scripts.value = []
|
scripts.value = []
|
||||||
@@ -162,7 +166,8 @@ const runScript = async (key: string) => {
|
|||||||
try {
|
try {
|
||||||
const data = await $fetch<BackupScriptRunResponse>("/api/backup-script", {
|
const data = await $fetch<BackupScriptRunResponse>("/api/backup-script", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: { key }
|
body: { key },
|
||||||
|
headers: apiAuthHeader
|
||||||
})
|
})
|
||||||
message.value = `${data.label} execute avec succes`
|
message.value = `${data.label} execute avec succes`
|
||||||
output.value = data.output || "Aucune sortie retournee."
|
output.value = data.output || "Aucune sortie retournee."
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {Icon as IconifyIcon} from "@iconify/vue"
|
import {Icon as IconifyIcon} from "@iconify/vue"
|
||||||
const { data: messages } = await useFetch('/api/discord/messages')
|
import { useApiAuthHeader } from "~/composables/useApiAuth"
|
||||||
|
|
||||||
|
const { data: messages } = await useFetch('/api/discord/messages', {
|
||||||
|
headers: useApiAuthHeader()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -42,11 +42,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, ref} from "vue"
|
import {computed, ref} from "vue"
|
||||||
import {Icon as IconifyIcon} from "@iconify/vue"
|
import {Icon as IconifyIcon} from "@iconify/vue"
|
||||||
|
import { useApiAuthHeader, withApiAuth } from "~/composables/useApiAuth"
|
||||||
|
|
||||||
const ping = ref<number | null>(null)
|
const ping = ref<number | null>(null)
|
||||||
const download = ref<number | null>(null)
|
const download = ref<number | null>(null)
|
||||||
const upload = ref<number | null>(null)
|
const upload = ref<number | null>(null)
|
||||||
const isTesting = ref(false)
|
const isTesting = ref(false)
|
||||||
|
const apiAuthHeader = useApiAuthHeader()
|
||||||
|
|
||||||
const metrics = computed(() => [
|
const metrics = computed(() => [
|
||||||
{ label: "Download", icon: "mdi:arrow-down-bold", value: download.value, unit: "Mbps" },
|
{ label: "Download", icon: "mdi:arrow-down-bold", value: download.value, unit: "Mbps" },
|
||||||
@@ -56,7 +58,9 @@ const metrics = computed(() => [
|
|||||||
|
|
||||||
async function testDownload() {
|
async function testDownload() {
|
||||||
const start = performance.now()
|
const start = performance.now()
|
||||||
const res = await fetch('/api/download')
|
const res = await fetch('/api/download', {
|
||||||
|
headers: apiAuthHeader
|
||||||
|
})
|
||||||
const blob = await res.blob()
|
const blob = await res.blob()
|
||||||
const end = performance.now()
|
const end = performance.now()
|
||||||
const size = blob.size
|
const size = blob.size
|
||||||
@@ -68,7 +72,7 @@ async function testUpload() {
|
|||||||
const size = 5 * 1024 * 1024
|
const size = 5 * 1024 * 1024
|
||||||
const data = new Uint8Array(size)
|
const data = new Uint8Array(size)
|
||||||
const start = performance.now()
|
const start = performance.now()
|
||||||
await fetch('/api/upload', { method: 'POST', body: data })
|
await fetch('/api/upload', withApiAuth({ method: 'POST', body: data }))
|
||||||
const end = performance.now()
|
const end = performance.now()
|
||||||
const seconds = (end - start) / 1000
|
const seconds = (end - start) / 1000
|
||||||
upload.value = Math.round((size * 8) / seconds / 1000000)
|
upload.value = Math.round((size * 8) / seconds / 1000000)
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
import CircleSkeleton from "~/components/skeleton/CircleSkeleton.vue"
|
import CircleSkeleton from "~/components/skeleton/CircleSkeleton.vue"
|
||||||
import TextSkeleton from "~/components/skeleton/TextSkeleton.vue"
|
import TextSkeleton from "~/components/skeleton/TextSkeleton.vue"
|
||||||
import {onBeforeUnmount, onMounted, ref} from "vue"
|
import {onBeforeUnmount, onMounted, ref} from "vue"
|
||||||
|
import { useApiAuthHeader } from "~/composables/useApiAuth"
|
||||||
|
|
||||||
interface StatusRow {
|
interface StatusRow {
|
||||||
label: string
|
label: string
|
||||||
@@ -71,6 +72,7 @@ const props = withDefaults(
|
|||||||
const rows = ref<StatusRow[]>([])
|
const rows = ref<StatusRow[]>([])
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
const initialized = ref(false)
|
const initialized = ref(false)
|
||||||
|
const apiAuthHeader = useApiAuthHeader()
|
||||||
let timer: ReturnType<typeof setInterval> | null = null
|
let timer: ReturnType<typeof setInterval> | null = null
|
||||||
|
|
||||||
const statusLabel = (status: number) => {
|
const statusLabel = (status: number) => {
|
||||||
@@ -84,7 +86,9 @@ const checkStatus = async () => {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const data = await $fetch<StatusResponse>(props.endpoint)
|
const data = await $fetch<StatusResponse>(props.endpoint, {
|
||||||
|
headers: apiAuthHeader
|
||||||
|
})
|
||||||
rows.value = data.results
|
rows.value = data.results
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
rows.value = [
|
rows.value = [
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ export default defineNuxtConfig({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
runtimeConfig: {
|
runtimeConfig: {
|
||||||
|
apiSecretKey: process.env.API_SECRET_KEY,
|
||||||
public: {
|
public: {
|
||||||
|
apiSecretKey: process.env.API_SECRET_KEY || "",
|
||||||
appVersion: getRepoVersion()
|
appVersion: getRepoVersion()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -96,6 +96,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue"
|
import { ref } from "vue"
|
||||||
import BackupRun from "~/components/BackupRun.vue"
|
import BackupRun from "~/components/BackupRun.vue"
|
||||||
|
import { downloadApiFile, useApiAuthHeader } from "~/composables/useApiAuth"
|
||||||
|
|
||||||
definePageMeta({ layout: false })
|
definePageMeta({ layout: false })
|
||||||
|
|
||||||
@@ -117,35 +118,30 @@ const emptyScriptResult = (): ScriptResult => ({
|
|||||||
|
|
||||||
const selectedBackup = ref<string | null>(null)
|
const selectedBackup = ref<string | null>(null)
|
||||||
const scriptResult = ref<ScriptResult>(emptyScriptResult())
|
const scriptResult = ref<ScriptResult>(emptyScriptResult())
|
||||||
|
const apiAuthHeader = useApiAuthHeader()
|
||||||
|
|
||||||
const fetchLatestBackup = async (folder: string) => {
|
const fetchLatestBackup = async (folder: string) => {
|
||||||
const files = await $fetch<string[]>(`/api/backups?folder=${encodeURIComponent(folder)}`)
|
const files = await $fetch<string[]>(`/api/backups?folder=${encodeURIComponent(folder)}`, {
|
||||||
|
headers: apiAuthHeader
|
||||||
|
})
|
||||||
return files[0] || null
|
return files[0] || null
|
||||||
}
|
}
|
||||||
|
|
||||||
const triggerDownload = (folder: string, file: string) => {
|
const triggerDownload = async (folder: string, file: string) => {
|
||||||
const link = document.createElement("a")
|
const url = `/api/download?folder=${encodeURIComponent(folder)}&file=${encodeURIComponent(file)}`
|
||||||
link.href = `/api/download?folder=${encodeURIComponent(folder)}&file=${encodeURIComponent(file)}`
|
await downloadApiFile(url, file)
|
||||||
link.style.display = "none"
|
|
||||||
document.body.appendChild(link)
|
|
||||||
link.click()
|
|
||||||
link.remove()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const triggerBatchDownload = (folders: string[]) => {
|
const triggerBatchDownload = async (folders: string[]) => {
|
||||||
const link = document.createElement("a")
|
const url = `/api/download-latest?folders=${encodeURIComponent(folders.join(","))}`
|
||||||
link.href = `/api/download-latest?folders=${encodeURIComponent(folders.join(","))}`
|
await downloadApiFile(url, "backup-latest.tar.gz")
|
||||||
link.style.display = "none"
|
|
||||||
document.body.appendChild(link)
|
|
||||||
link.click()
|
|
||||||
link.remove()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const downloadLatestBackup = async (folder: string) => {
|
const downloadLatestBackup = async (folder: string) => {
|
||||||
const latestFile = await fetchLatestBackup(folder)
|
const latestFile = await fetchLatestBackup(folder)
|
||||||
|
|
||||||
if (latestFile) {
|
if (latestFile) {
|
||||||
triggerDownload(folder, latestFile)
|
await triggerDownload(folder, latestFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +153,7 @@ const handleScriptResult = async (payload: ScriptResult) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (payload.downloadFolders.length > 1) {
|
if (payload.downloadFolders.length > 1) {
|
||||||
triggerBatchDownload(payload.downloadFolders)
|
await triggerBatchDownload(payload.downloadFolders)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
definePageMeta({layout: false})
|
definePageMeta({layout: false})
|
||||||
import {computed, onMounted, ref} from "vue"
|
import {computed, onMounted, ref} from "vue"
|
||||||
|
import { useApiAuthHeader } from "~/composables/useApiAuth"
|
||||||
|
|
||||||
type DiskSourceResult = {
|
type DiskSourceResult = {
|
||||||
key: string
|
key: string
|
||||||
@@ -77,6 +78,7 @@ type DiagramItem = {
|
|||||||
const selectedBackup = ref<string | null>(null)
|
const selectedBackup = ref<string | null>(null)
|
||||||
const rawResults = ref<DiskSourceResult[]>([])
|
const rawResults = ref<DiskSourceResult[]>([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
const apiAuthHeader = useApiAuthHeader()
|
||||||
const chartRadius = 52
|
const chartRadius = 52
|
||||||
const chartCircumference = 2 * Math.PI * chartRadius
|
const chartCircumference = 2 * Math.PI * chartRadius
|
||||||
|
|
||||||
@@ -151,7 +153,9 @@ const runScript = async () => {
|
|||||||
rawResults.value = []
|
rawResults.value = []
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const output = await $fetch<DiskApiResponse>("/api/disk")
|
const output = await $fetch<DiskApiResponse>("/api/disk", {
|
||||||
|
headers: apiAuthHeader
|
||||||
|
})
|
||||||
rawResults.value = output.results
|
rawResults.value = output.results
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = `Erreur: ${error instanceof Error ? error.message : String(error)}`
|
const message = `Erreur: ${error instanceof Error ? error.message : String(error)}`
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { exec } from "node:child_process"
|
import { execFile } from "node:child_process"
|
||||||
import scripts from "../config/backup-script.json"
|
import scripts from "../config/backup-script.json"
|
||||||
|
|
||||||
type BackupScript = {
|
type BackupScript = {
|
||||||
@@ -6,11 +6,12 @@ type BackupScript = {
|
|||||||
label: string
|
label: string
|
||||||
downloadFolders?: string[]
|
downloadFolders?: string[]
|
||||||
command: string
|
command: string
|
||||||
|
args?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
function runCommand(command: string): Promise<string> {
|
function runCommand(command: string, args: string[] = []): Promise<string> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
exec(command, { timeout: 10 * 60 * 1000 }, (error, stdout, stderr) => {
|
execFile(command, args, { timeout: 10 * 60 * 1000 }, (error, stdout, stderr) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(stderr || error.message)
|
reject(stderr || error.message)
|
||||||
return
|
return
|
||||||
@@ -40,7 +41,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const output = await runCommand(script.command)
|
const output = await runCommand(script.command, script.args || [])
|
||||||
return {
|
return {
|
||||||
ok: true,
|
ok: true,
|
||||||
key: script.key,
|
key: script.key,
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { exec } from "child_process"
|
import { execFile } from "child_process"
|
||||||
import diskSources from "../config/disk-commands.json"
|
import diskSources from "../config/disk-commands.json"
|
||||||
|
|
||||||
type DiskSource = {
|
type DiskSource = {
|
||||||
key: string
|
key: string
|
||||||
label: string
|
label: string
|
||||||
command: string
|
command: string
|
||||||
|
args?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCommand(source: DiskSource) {
|
function getCommand(source: DiskSource) {
|
||||||
@@ -15,9 +16,9 @@ function getCommand(source: DiskSource) {
|
|||||||
return process.env[envKey] || (legacyEnvKey ? process.env[legacyEnvKey] : undefined) || source.command
|
return process.env[envKey] || (legacyEnvKey ? process.env[legacyEnvKey] : undefined) || source.command
|
||||||
}
|
}
|
||||||
|
|
||||||
function runCommand(command: string): Promise<string> {
|
function runCommand(command: string, args: string[] = []): Promise<string> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
exec(command, (error, stdout, stderr) => {
|
execFile(command, args, (error, stdout, stderr) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(stderr || error.message)
|
reject(stderr || error.message)
|
||||||
return
|
return
|
||||||
@@ -31,7 +32,7 @@ export default defineEventHandler(async () => {
|
|||||||
const results = await Promise.all(
|
const results = await Promise.all(
|
||||||
(diskSources as DiskSource[]).map(async (source) => {
|
(diskSources as DiskSource[]).map(async (source) => {
|
||||||
try {
|
try {
|
||||||
const output = await runCommand(getCommand(source))
|
const output = await runCommand(source.command, source.args || [])
|
||||||
return {
|
return {
|
||||||
key: source.key,
|
key: source.key,
|
||||||
label: source.label,
|
label: source.label,
|
||||||
|
|||||||
@@ -4,19 +4,31 @@
|
|||||||
"label": "Backup BDD recette",
|
"label": "Backup BDD recette",
|
||||||
"icon": "mdi:database-export",
|
"icon": "mdi:database-export",
|
||||||
"downloadFolders": ["ferme", "inventory", "sirh", "user"],
|
"downloadFolders": ["ferme", "inventory", "sirh", "user"],
|
||||||
"command": "ssh ferme 'cd /home/malio/Malio-ops/RecetteScripts && bash backup-bdd-recette.sh && exit'"
|
"command": "ssh",
|
||||||
|
"args": [
|
||||||
|
"ferme",
|
||||||
|
"cd /home/malio/Malio-ops/RecetteScripts && bash backup-bdd-recette.sh"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "check-statut-recette",
|
"key": "check-statut-recette",
|
||||||
"label": "Check statut recette",
|
"label": "Check statut recette",
|
||||||
"icon": "mdi:server-network",
|
"icon": "mdi:server-network",
|
||||||
"command": "ssh ferme 'cd /home/malio/Malio-ops/RecetteScripts && bash check-statut-recette.sh && exit'"
|
"command": "ssh",
|
||||||
|
"args": [
|
||||||
|
"ferme",
|
||||||
|
"cd /home/malio/Malio-ops/RecetteScripts && bash check-statut-recette.sh"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "backup-vaultwarden",
|
"key": "backup-vaultwarden",
|
||||||
"label": "Backup vaultwarden",
|
"label": "Backup vaultwarden",
|
||||||
"icon": "mdi:data",
|
"icon": "mdi:data",
|
||||||
"downloadFolders": ["bitwarden"],
|
"downloadFolders": ["bitwarden"],
|
||||||
"command": "ssh bitwarden 'cd /home/matt/vaultwarden/Malio-ops/BackupVaultWarden && bash backup-vaultwarden.sh && exit'"
|
"command": "ssh",
|
||||||
|
"args": [
|
||||||
|
"bitwarden",
|
||||||
|
"cd /home/matt/vaultwarden/Malio-ops/BackupVaultWarden && bash backup-vaultwarden.sh"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -2,11 +2,18 @@
|
|||||||
{
|
{
|
||||||
"key": "remote",
|
"key": "remote",
|
||||||
"label": "Serveur distant",
|
"label": "Serveur distant",
|
||||||
"command": "ssh malio-b 'cd /home/malio-b/Malio-ops/CheckStorage && bash check-storage.sh && exit'"
|
"command": "ssh",
|
||||||
|
"args": [
|
||||||
|
"malio-b",
|
||||||
|
"cd /home/malio-b/Malio-ops/CheckStorage && bash check-storage.sh"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "local",
|
"key": "local",
|
||||||
"label": "Machine locale",
|
"label": "Machine locale",
|
||||||
"command": "bash /home/kevin/check_storage.sh"
|
"command": "bash",
|
||||||
|
"args": [
|
||||||
|
"/home/kevin/check_storage.sh"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
30
server/middleware/auth.ts
Normal file
30
server/middleware/auth.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
export default defineEventHandler((event) => {
|
||||||
|
const path = event.path || event.node.req.url || ""
|
||||||
|
|
||||||
|
// Le middleware ne s'applique qu'aux routes API, sauf l'endpoint de ping
|
||||||
|
// qui reste public pour les tests de connectivite.
|
||||||
|
if (!path.startsWith("/api/") || path === "/api/ping") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const runtimeConfig = useRuntimeConfig(event)
|
||||||
|
const authorization = getHeader(event, "authorization")
|
||||||
|
const expectedToken = runtimeConfig.apiSecretKey
|
||||||
|
|
||||||
|
// Si aucun secret n'est configure cote serveur, on refuse la requete.
|
||||||
|
if (!expectedToken) {
|
||||||
|
throw createError({
|
||||||
|
statusCode: 401,
|
||||||
|
statusMessage: "Unauthorized"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Le header doit correspondre exactement au format attendu :
|
||||||
|
// Authorization: Bearer <token>
|
||||||
|
if (authorization !== `Bearer ${expectedToken}`) {
|
||||||
|
throw createError({
|
||||||
|
statusCode: 401,
|
||||||
|
statusMessage: "Unauthorized"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user