mirror of https://github.com/wg-easy/wg-easy
36 changed files with 6874 additions and 3266 deletions
@ -0,0 +1,6 @@ |
|||||
|
{ |
||||
|
"trailingComma": "es5", |
||||
|
"tabWidth": 2, |
||||
|
"semi": true, |
||||
|
"singleQuote": true |
||||
|
} |
File diff suppressed because it is too large
@ -1,6 +1,6 @@ |
|||||
[v-cloak] { |
[v-cloak] { |
||||
display: none; |
display: none; |
||||
} |
} |
||||
.line-chart .apexcharts-svg{ |
.line-chart .apexcharts-svg { |
||||
transform: translateY(3px); |
transform: translateY(3px); |
||||
} |
} |
||||
|
@ -1,3 +1,3 @@ |
|||||
import { createConfigForNuxt } from '@nuxt/eslint-config/flat' |
import { createConfigForNuxt } from '@nuxt/eslint-config/flat'; |
||||
|
|
||||
export default createConfigForNuxt({}) |
export default createConfigForNuxt({}); |
||||
|
File diff suppressed because it is too large
@ -1,5 +1,5 @@ |
|||||
export default defineNuxtRouteMiddleware(async (to) => { |
export default defineNuxtRouteMiddleware(async (to) => { |
||||
if (REQUIRES_PASSWORD || !to.path.startsWith('/api/')) { |
if (REQUIRES_PASSWORD || !to.path.startsWith('/api/')) { |
||||
return abortNavigation(); |
return abortNavigation(); |
||||
} |
} |
||||
}) |
}); |
||||
|
@ -1,5 +1,5 @@ |
|||||
import VueApexCharts from "vue3-apexcharts"; |
import VueApexCharts from 'vue3-apexcharts'; |
||||
|
|
||||
export default defineNuxtPlugin((nuxtApp) => { |
export default defineNuxtPlugin((nuxtApp) => { |
||||
nuxtApp.vueApp.use(VueApexCharts); |
nuxtApp.vueApp.use(VueApexCharts); |
||||
}); |
}); |
||||
|
File diff suppressed because it is too large
@ -1,11 +1,11 @@ |
|||||
{ |
{ |
||||
"name": "WireGuard", |
"name": "WireGuard", |
||||
"display": "standalone", |
"display": "standalone", |
||||
"background_color": "#fff", |
"background_color": "#fff", |
||||
"icons": [ |
"icons": [ |
||||
{ |
{ |
||||
"src": "/favicon.png", |
"src": "/favicon.png", |
||||
"type": "image/png" |
"type": "image/png" |
||||
} |
} |
||||
] |
] |
||||
} |
} |
||||
|
@ -1,7 +1,7 @@ |
|||||
import { LANG } from "~/utils/config"; |
import { LANG } from '~/utils/config'; |
||||
|
|
||||
export default defineEventHandler((event) => { |
export default defineEventHandler((event) => { |
||||
assertMethod(event, "GET"); |
assertMethod(event, 'GET'); |
||||
setHeader(event, 'Content-Type', 'application/json'); |
setHeader(event, 'Content-Type', 'application/json'); |
||||
return `"${LANG}"`; |
return `"${LANG}"`; |
||||
}) |
}); |
||||
|
@ -1,7 +1,7 @@ |
|||||
import { RELEASE } from "~/utils/config"; |
import { RELEASE } from '~/utils/config'; |
||||
|
|
||||
export default defineEventHandler((event) => { |
export default defineEventHandler((event) => { |
||||
assertMethod(event, "GET"); |
assertMethod(event, 'GET'); |
||||
setHeader(event, 'Content-Type', 'application/json'); |
setHeader(event, 'Content-Type', 'application/json'); |
||||
return RELEASE; |
return RELEASE; |
||||
}) |
}); |
||||
|
@ -1,51 +1,55 @@ |
|||||
import { REQUIRES_PASSWORD, SERVER_DEBUG, SESSION_CONFIG } from "~/utils/config"; |
import { |
||||
import { isPasswordValid } from "~/utils/password"; |
REQUIRES_PASSWORD, |
||||
|
SERVER_DEBUG, |
||||
|
SESSION_CONFIG, |
||||
|
} from '~/utils/config'; |
||||
|
import { isPasswordValid } from '~/utils/password'; |
||||
|
|
||||
export default defineEventHandler(async (event) => { |
export default defineEventHandler(async (event) => { |
||||
if (isMethod(event, "GET")) { |
if (isMethod(event, 'GET')) { |
||||
const session = await useSession(event, SESSION_CONFIG); |
const session = await useSession(event, SESSION_CONFIG); |
||||
const authenticated = REQUIRES_PASSWORD |
const authenticated = REQUIRES_PASSWORD |
||||
? !!(session.data && session.data.authenticated) |
? !!(session.data && session.data.authenticated) |
||||
: true; |
: true; |
||||
|
|
||||
return { |
return { |
||||
REQUIRES_PASSWORD, |
REQUIRES_PASSWORD, |
||||
authenticated, |
authenticated, |
||||
}; |
}; |
||||
} else if (isMethod(event, "POST")) { |
} else if (isMethod(event, 'POST')) { |
||||
const session = await useSession(event, SESSION_CONFIG); |
const session = await useSession(event, SESSION_CONFIG); |
||||
const { password } = await readBody(event); |
const { password } = await readBody(event); |
||||
|
|
||||
if (!REQUIRES_PASSWORD) { |
if (!REQUIRES_PASSWORD) { |
||||
// if no password is required, the API should never be called.
|
// if no password is required, the API should never be called.
|
||||
// Do not automatically authenticate the user.
|
// Do not automatically authenticate the user.
|
||||
throw createError({ |
throw createError({ |
||||
status: 401, |
status: 401, |
||||
message: 'Invalid state', |
message: 'Invalid state', |
||||
}); |
}); |
||||
} |
|
||||
|
|
||||
if (!isPasswordValid(password)) { |
|
||||
throw createError({ |
|
||||
status: 401, |
|
||||
message: 'Incorrect Password', |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
const data = await session.update({ |
|
||||
authenticated: true |
|
||||
}); |
|
||||
|
|
||||
SERVER_DEBUG(`New Session: ${data.id}`); |
|
||||
|
|
||||
return { success: true }; |
|
||||
} else if (isMethod(event, "DELETE")) { |
|
||||
const session = await useSession(event, SESSION_CONFIG); |
|
||||
const sessionId = session.id; |
|
||||
|
|
||||
await session.clear(); |
|
||||
|
|
||||
SERVER_DEBUG(`Deleted Session: ${sessionId}`); |
|
||||
return { success: true }; |
|
||||
} |
} |
||||
}) |
|
||||
|
if (!isPasswordValid(password)) { |
||||
|
throw createError({ |
||||
|
status: 401, |
||||
|
message: 'Incorrect Password', |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
const data = await session.update({ |
||||
|
authenticated: true, |
||||
|
}); |
||||
|
|
||||
|
SERVER_DEBUG(`New Session: ${data.id}`); |
||||
|
|
||||
|
return { success: true }; |
||||
|
} else if (isMethod(event, 'DELETE')) { |
||||
|
const session = await useSession(event, SESSION_CONFIG); |
||||
|
const sessionId = session.id; |
||||
|
|
||||
|
await session.clear(); |
||||
|
|
||||
|
SERVER_DEBUG(`Deleted Session: ${sessionId}`); |
||||
|
return { success: true }; |
||||
|
} |
||||
|
}); |
||||
|
@ -1,7 +1,7 @@ |
|||||
import { UI_CHART_TYPE } from "~/utils/config"; |
import { UI_CHART_TYPE } from '~/utils/config'; |
||||
|
|
||||
export default defineEventHandler((event) => { |
export default defineEventHandler((event) => { |
||||
assertMethod(event, "GET"); |
assertMethod(event, 'GET'); |
||||
setHeader(event, 'Content-Type', 'application/json'); |
setHeader(event, 'Content-Type', 'application/json'); |
||||
return `"${UI_CHART_TYPE}"`; |
return `"${UI_CHART_TYPE}"`; |
||||
}) |
}); |
||||
|
@ -1,7 +1,7 @@ |
|||||
import { UI_TRAFFIC_STATS } from "~/utils/config"; |
import { UI_TRAFFIC_STATS } from '~/utils/config'; |
||||
|
|
||||
export default defineEventHandler((event) => { |
export default defineEventHandler((event) => { |
||||
assertMethod(event, "GET"); |
assertMethod(event, 'GET'); |
||||
setHeader(event, 'Content-Type', 'application/json'); |
setHeader(event, 'Content-Type', 'application/json'); |
||||
return `"${UI_TRAFFIC_STATS}"`; |
return `"${UI_TRAFFIC_STATS}"`; |
||||
}) |
}); |
||||
|
@ -1,9 +1,9 @@ |
|||||
import WireGuard from "~/utils/WireGuard"; |
import WireGuard from '~/utils/WireGuard'; |
||||
|
|
||||
export default defineEventHandler(async (event) => { |
export default defineEventHandler(async (event) => { |
||||
assertMethod(event, "GET"); |
assertMethod(event, 'GET'); |
||||
const config = await WireGuard.backupConfiguration(); |
const config = await WireGuard.backupConfiguration(); |
||||
setHeader(event, 'Content-Disposition', 'attachment; filename="wg0.json"'); |
setHeader(event, 'Content-Disposition', 'attachment; filename="wg0.json"'); |
||||
setHeader(event, 'Content-Type', 'text/json'); |
setHeader(event, 'Content-Type', 'text/json'); |
||||
return config; |
return config; |
||||
}) |
}); |
||||
|
@ -1,12 +1,16 @@ |
|||||
import WireGuard from "~/utils/WireGuard"; |
import WireGuard from '~/utils/WireGuard'; |
||||
|
|
||||
export default defineEventHandler(async (event) => { |
export default defineEventHandler(async (event) => { |
||||
assertMethod(event, "PUT"); |
assertMethod(event, 'PUT'); |
||||
const clientId = getRouterParam(event, 'clientId'); |
const clientId = getRouterParam(event, 'clientId'); |
||||
if (clientId === '__proto__' || clientId === 'constructor' || clientId === 'prototype') { |
if ( |
||||
throw createError({ status: 403 }); |
clientId === '__proto__' || |
||||
} |
clientId === 'constructor' || |
||||
const { address } = await readBody(event); |
clientId === 'prototype' |
||||
await WireGuard.updateClientAddress({ clientId, address }); |
) { |
||||
return { success: true }; |
throw createError({ status: 403 }); |
||||
}) |
} |
||||
|
const { address } = await readBody(event); |
||||
|
await WireGuard.updateClientAddress({ clientId, address }); |
||||
|
return { success: true }; |
||||
|
}); |
||||
|
@ -1,16 +1,20 @@ |
|||||
import WireGuard from "~/utils/WireGuard"; |
import WireGuard from '~/utils/WireGuard'; |
||||
|
|
||||
export default defineEventHandler(async (event) => { |
export default defineEventHandler(async (event) => { |
||||
assertMethod(event, "GET"); |
assertMethod(event, 'GET'); |
||||
const clientId = getRouterParam(event, 'clientId'); |
const clientId = getRouterParam(event, 'clientId'); |
||||
const client = await WireGuard.getClient({ clientId }); |
const client = await WireGuard.getClient({ clientId }); |
||||
const config = await WireGuard.getClientConfiguration({ clientId }); |
const config = await WireGuard.getClientConfiguration({ clientId }); |
||||
const configName = client.name |
const configName = client.name |
||||
.replace(/[^a-zA-Z0-9_=+.-]/g, '-') |
.replace(/[^a-zA-Z0-9_=+.-]/g, '-') |
||||
.replace(/(-{2,}|-$)/g, '-') |
.replace(/(-{2,}|-$)/g, '-') |
||||
.replace(/-$/, '') |
.replace(/-$/, '') |
||||
.substring(0, 32); |
.substring(0, 32); |
||||
setHeader(event, 'Content-Disposition', `attachment; filename="${configName || clientId}.conf"`); |
setHeader( |
||||
setHeader(event, 'Content-Type', 'text/plain'); |
event, |
||||
return config; |
'Content-Disposition', |
||||
}) |
`attachment; filename="${configName || clientId}.conf"` |
||||
|
); |
||||
|
setHeader(event, 'Content-Type', 'text/plain'); |
||||
|
return config; |
||||
|
}); |
||||
|
@ -1,11 +1,15 @@ |
|||||
import WireGuard from "~/utils/WireGuard"; |
import WireGuard from '~/utils/WireGuard'; |
||||
|
|
||||
export default defineEventHandler(async (event) => { |
export default defineEventHandler(async (event) => { |
||||
assertMethod(event, "POST"); |
assertMethod(event, 'POST'); |
||||
const clientId = getRouterParam(event, 'clientId'); |
const clientId = getRouterParam(event, 'clientId'); |
||||
if (clientId === '__proto__' || clientId === 'constructor' || clientId === 'prototype') { |
if ( |
||||
throw createError({ status: 403 }); |
clientId === '__proto__' || |
||||
} |
clientId === 'constructor' || |
||||
await WireGuard.disableClient({ clientId }); |
clientId === 'prototype' |
||||
return { success: true }; |
) { |
||||
}) |
throw createError({ status: 403 }); |
||||
|
} |
||||
|
await WireGuard.disableClient({ clientId }); |
||||
|
return { success: true }; |
||||
|
}); |
||||
|
@ -1,11 +1,15 @@ |
|||||
import WireGuard from "~/utils/WireGuard"; |
import WireGuard from '~/utils/WireGuard'; |
||||
|
|
||||
export default defineEventHandler(async (event) => { |
export default defineEventHandler(async (event) => { |
||||
assertMethod(event, "POST"); |
assertMethod(event, 'POST'); |
||||
const clientId = getRouterParam(event, 'clientId'); |
const clientId = getRouterParam(event, 'clientId'); |
||||
if (clientId === '__proto__' || clientId === 'constructor' || clientId === 'prototype') { |
if ( |
||||
throw createError({ status: 403 }); |
clientId === '__proto__' || |
||||
} |
clientId === 'constructor' || |
||||
await WireGuard.enableClient({ clientId }); |
clientId === 'prototype' |
||||
return { success: true }; |
) { |
||||
}) |
throw createError({ status: 403 }); |
||||
|
} |
||||
|
await WireGuard.enableClient({ clientId }); |
||||
|
return { success: true }; |
||||
|
}); |
||||
|
@ -1,8 +1,8 @@ |
|||||
import WireGuard from "~/utils/WireGuard"; |
import WireGuard from '~/utils/WireGuard'; |
||||
|
|
||||
export default defineEventHandler(async (event) => { |
export default defineEventHandler(async (event) => { |
||||
assertMethod(event, "DELETE"); |
assertMethod(event, 'DELETE'); |
||||
const clientId = getRouterParam(event, 'clientId'); |
const clientId = getRouterParam(event, 'clientId'); |
||||
await WireGuard.deleteClient({ clientId }); |
await WireGuard.deleteClient({ clientId }); |
||||
return { success: true }; |
return { success: true }; |
||||
}); |
}); |
||||
|
@ -1,12 +1,16 @@ |
|||||
import WireGuard from "~/utils/WireGuard"; |
import WireGuard from '~/utils/WireGuard'; |
||||
|
|
||||
export default defineEventHandler(async (event) => { |
export default defineEventHandler(async (event) => { |
||||
assertMethod(event, "PUT"); |
assertMethod(event, 'PUT'); |
||||
const clientId = getRouterParam(event, 'clientId'); |
const clientId = getRouterParam(event, 'clientId'); |
||||
if (clientId === '__proto__' || clientId === 'constructor' || clientId === 'prototype') { |
if ( |
||||
throw createError({ status: 403 }); |
clientId === '__proto__' || |
||||
} |
clientId === 'constructor' || |
||||
const { name } = await readBody(event); |
clientId === 'prototype' |
||||
await WireGuard.updateClientName({ clientId, name }); |
) { |
||||
return { success: true }; |
throw createError({ status: 403 }); |
||||
}) |
} |
||||
|
const { name } = await readBody(event); |
||||
|
await WireGuard.updateClientName({ clientId, name }); |
||||
|
return { success: true }; |
||||
|
}); |
||||
|
@ -1,9 +1,9 @@ |
|||||
import WireGuard from "~/utils/WireGuard"; |
import WireGuard from '~/utils/WireGuard'; |
||||
|
|
||||
export default defineEventHandler(async (event) => { |
export default defineEventHandler(async (event) => { |
||||
assertMethod(event, "GET"); |
assertMethod(event, 'GET'); |
||||
const clientId = getRouterParam(event, 'clientId'); |
const clientId = getRouterParam(event, 'clientId'); |
||||
const svg = await WireGuard.getClientQRCodeSVG({ clientId }); |
const svg = await WireGuard.getClientQRCodeSVG({ clientId }); |
||||
setHeader(event, 'Content-Type', 'image/svg+xml'); |
setHeader(event, 'Content-Type', 'image/svg+xml'); |
||||
return svg; |
return svg; |
||||
}) |
}); |
||||
|
@ -1,11 +1,11 @@ |
|||||
import WireGuard from "~/utils/WireGuard"; |
import WireGuard from '~/utils/WireGuard'; |
||||
|
|
||||
export default defineEventHandler(async (event) => { |
export default defineEventHandler(async (event) => { |
||||
if (isMethod(event, "GET")) { |
if (isMethod(event, 'GET')) { |
||||
return WireGuard.getClients(); |
return WireGuard.getClients(); |
||||
} else if (isMethod(event, "POST")) { |
} else if (isMethod(event, 'POST')) { |
||||
const { name } = await readBody(event); |
const { name } = await readBody(event); |
||||
await WireGuard.createClient({ name }); |
await WireGuard.createClient({ name }); |
||||
return { success: true }; |
return { success: true }; |
||||
} |
} |
||||
}) |
}); |
||||
|
@ -1,8 +1,8 @@ |
|||||
import WireGuard from "~/utils/WireGuard"; |
import WireGuard from '~/utils/WireGuard'; |
||||
|
|
||||
export default defineEventHandler(async (event) => { |
export default defineEventHandler(async (event) => { |
||||
assertMethod(event, "PUT"); |
assertMethod(event, 'PUT'); |
||||
const { file } = await readBody(event); |
const { file } = await readBody(event); |
||||
await WireGuard.restoreConfiguration(file); |
await WireGuard.restoreConfiguration(file); |
||||
return { success: true }; |
return { success: true }; |
||||
}) |
}); |
||||
|
@ -1,24 +1,29 @@ |
|||||
import childProcess from 'child_process'; |
import childProcess from 'child_process'; |
||||
|
|
||||
export function exec(cmd: string, {log}: {log: boolean|string} = {log: true}) { |
export function exec( |
||||
if (typeof log === 'string') { |
cmd: string, |
||||
|
{ log }: { log: boolean | string } = { log: true } |
||||
console.log(`$ ${log}`); |
) { |
||||
} else if (log === true) { |
if (typeof log === 'string') { |
||||
|
console.log(`$ ${log}`); |
||||
console.log(`$ ${cmd}`); |
} else if (log === true) { |
||||
} |
console.log(`$ ${cmd}`); |
||||
|
} |
||||
|
|
||||
if (process.platform !== 'linux') { |
if (process.platform !== 'linux') { |
||||
return Promise.resolve(""); |
return Promise.resolve(''); |
||||
} |
} |
||||
|
|
||||
return new Promise((resolve, reject) => { |
return new Promise((resolve, reject) => { |
||||
childProcess.exec(cmd, { |
childProcess.exec( |
||||
|
cmd, |
||||
|
{ |
||||
shell: 'bash', |
shell: 'bash', |
||||
}, (err, stdout) => { |
}, |
||||
|
(err, stdout) => { |
||||
if (err) return reject(err); |
if (err) return reject(err); |
||||
return resolve(String(stdout).trim()); |
return resolve(String(stdout).trim()); |
||||
}); |
} |
||||
}); |
); |
||||
} |
}); |
||||
|
} |
||||
|
@ -1,5 +1,7 @@ |
|||||
export function getRandomHex(size: number) { |
export function getRandomHex(size: number) { |
||||
const array = new Uint8Array(size); |
const array = new Uint8Array(size); |
||||
crypto.getRandomValues(array); |
crypto.getRandomValues(array); |
||||
return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join(''); |
return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join( |
||||
} |
'' |
||||
|
); |
||||
|
} |
||||
|
@ -1,12 +1,12 @@ |
|||||
export function isValidIPv4(str) { |
export function isValidIPv4(str) { |
||||
const blocks = str.split('.'); |
const blocks = str.split('.'); |
||||
if (blocks.length !== 4) return false; |
if (blocks.length !== 4) return false; |
||||
|
|
||||
for (let value of blocks) { |
for (let value of blocks) { |
||||
value = parseInt(value, 10); |
value = parseInt(value, 10); |
||||
if (Number.isNaN(value)) return false; |
if (Number.isNaN(value)) return false; |
||||
if (value < 0 || value > 255) return false; |
if (value < 0 || value > 255) return false; |
||||
} |
} |
||||
|
|
||||
return true; |
return true; |
||||
} |
} |
||||
|
@ -1,25 +1,30 @@ |
|||||
export type Theme = 'light' | 'dark' | 'auto' |
export type Theme = 'light' | 'dark' | 'auto'; |
||||
|
|
||||
export type LocalStorage = { |
export type LocalStorage = { |
||||
theme: Theme, |
theme: Theme; |
||||
uiShowCharts: '1' | '0', |
uiShowCharts: '1' | '0'; |
||||
lang: string |
lang: string; |
||||
} |
}; |
||||
|
|
||||
export function getItem<K extends keyof LocalStorage>(item: K): LocalStorage[K]|null { |
export function getItem<K extends keyof LocalStorage>( |
||||
if (import.meta.client) { |
item: K |
||||
return localStorage.getItem(item) as LocalStorage[K]|null |
): LocalStorage[K] | null { |
||||
} else { |
if (import.meta.client) { |
||||
return null |
return localStorage.getItem(item) as LocalStorage[K] | null; |
||||
} |
} else { |
||||
|
return null; |
||||
|
} |
||||
} |
} |
||||
|
|
||||
export function setItem<K extends keyof LocalStorage>(item: K, value: LocalStorage[K]) { |
export function setItem<K extends keyof LocalStorage>( |
||||
if (import.meta.client) { |
item: K, |
||||
localStorage.setItem(item, value) |
value: LocalStorage[K] |
||||
|
) { |
||||
return true |
if (import.meta.client) { |
||||
} else { |
localStorage.setItem(item, value); |
||||
return false |
|
||||
} |
return true; |
||||
} |
} else { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
Loading…
Reference in new issue