diff --git a/src/package.json b/src/package.json index 353e40a8..85b2482d 100644 --- a/src/package.json +++ b/src/package.json @@ -35,7 +35,6 @@ "qrcode": "^1.5.4", "tailwindcss": "^3.4.10", "timeago.js": "^4.0.2", - "uuid": "^10.0.0", "vue": "latest", "vue3-apexcharts": "^1.5.3", "zod": "^3.23.8" @@ -45,7 +44,6 @@ "@types/bcryptjs": "^2.4.6", "@types/debug": "^4.1.12", "@types/qrcode": "^1.5.5", - "@types/uuid": "^10.0.0", "eslint": "^9.8.0", "eslint-config-prettier": "^9.1.0", "prettier": "^3.3.3", diff --git a/src/pnpm-lock.yaml b/src/pnpm-lock.yaml index 8c566a60..a55a8750 100644 --- a/src/pnpm-lock.yaml +++ b/src/pnpm-lock.yaml @@ -56,9 +56,6 @@ importers: timeago.js: specifier: ^4.0.2 version: 4.0.2 - uuid: - specifier: ^10.0.0 - version: 10.0.0 vue: specifier: latest version: 3.4.37(typescript@5.5.4) @@ -81,9 +78,6 @@ importers: '@types/qrcode': specifier: ^1.5.5 version: 1.5.5 - '@types/uuid': - specifier: ^10.0.0 - version: 10.0.0 eslint: specifier: ^9.8.0 version: 9.8.0 @@ -1260,9 +1254,6 @@ packages: '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - '@types/uuid@10.0.0': - resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} - '@typescript-eslint/eslint-plugin@8.0.0': resolution: {integrity: sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4212,10 +4203,6 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - uuid@10.0.0: - resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} - hasBin: true - validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -5740,8 +5727,6 @@ snapshots: '@types/resolve@1.20.2': {} - '@types/uuid@10.0.0': {} - '@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4)': dependencies: '@eslint-community/regexpp': 4.11.0 @@ -9078,8 +9063,6 @@ snapshots: util-deprecate@1.0.2: {} - uuid@10.0.0: {} - validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 diff --git a/src/repositories/database.ts b/src/repositories/database.ts index 1615d4e4..a01e1e6a 100644 --- a/src/repositories/database.ts +++ b/src/repositories/database.ts @@ -1,5 +1,5 @@ -import type SystemRepository from './system/interface'; -import type UserRepository from './user/interface'; +import type SystemRepository from './system/repository'; +import type UserRepository from './user/repository.ts'; import type { Undefined, Lang, ID } from './types'; import type { User } from './user/model'; import type { System } from './system/model'; diff --git a/src/repositories/system/model.ts b/src/repositories/system/model.ts index 7c1d656a..6d19c13d 100644 --- a/src/repositories/system/model.ts +++ b/src/repositories/system/model.ts @@ -37,6 +37,9 @@ export type System = { trafficStats: TrafficStats; wgEnableExpiresTime: boolean; + wgEnableOneTimeLinks: boolean; + wgEnableSortClients: boolean; + prometheus: Prometheus; sessionConfig: SessionConfig; }; diff --git a/src/repositories/system/interface.ts b/src/repositories/system/repository.ts similarity index 100% rename from src/repositories/system/interface.ts rename to src/repositories/system/repository.ts diff --git a/src/repositories/types.ts b/src/repositories/types.ts index ef2e62be..1437cf30 100644 --- a/src/repositories/types.ts +++ b/src/repositories/types.ts @@ -1,3 +1,5 @@ +import type * as crypto from 'node:crypto'; + export type Undefined = null | undefined | 0 | ''; export enum Lang { /* english */ @@ -5,7 +7,8 @@ export enum Lang { /* french */ FR = 'fr', } -export type ID = string; + +export type ID = crypto.UUID; export type Version = string; export type SessionTimeOut = number; export type Port = number; diff --git a/src/repositories/user/interface.ts b/src/repositories/user/repository.ts.ts similarity index 100% rename from src/repositories/user/interface.ts rename to src/repositories/user/repository.ts.ts diff --git a/src/server/api/cnf/[clientOneTimeLink].ts b/src/server/api/cnf/[clientOneTimeLink].ts index 0ff88d62..79ef77e2 100644 --- a/src/server/api/cnf/[clientOneTimeLink].ts +++ b/src/server/api/cnf/[clientOneTimeLink].ts @@ -1,5 +1,11 @@ export default defineEventHandler(async (event) => { - if (WG_ENABLE_ONE_TIME_LINKS === 'false') { + const system = await Database.getSystem(); + if (!system) + throw createError({ + statusCode: 500, + statusMessage: 'Invalid', + }); + if (!system.wgEnableOneTimeLinks) { throw createError({ status: 404, message: 'Invalid state', diff --git a/src/server/api/release.get.ts b/src/server/api/release.get.ts index 22004610..6fe97555 100644 --- a/src/server/api/release.get.ts +++ b/src/server/api/release.get.ts @@ -2,7 +2,7 @@ export default defineEventHandler(async () => { const system = await Database.getSystem(); if (!system) throw createError({ - statusCode: 400, + statusCode: 500, statusMessage: 'Invalid', }); diff --git a/src/server/api/session.get.ts b/src/server/api/session.get.ts index d0f3e826..9aa91658 100644 --- a/src/server/api/session.get.ts +++ b/src/server/api/session.get.ts @@ -1,6 +1,6 @@ export default defineEventHandler(async (event) => { const session = await useWGSession(event); - const authenticated = session.data.authenticated === true; + const authenticated = session.data.authenticated; return { requiresPassword: true, diff --git a/src/server/api/ui-chart-type.get.ts b/src/server/api/ui-chart-type.get.ts index 2d2f9d23..46bb0566 100644 --- a/src/server/api/ui-chart-type.get.ts +++ b/src/server/api/ui-chart-type.get.ts @@ -1,6 +1,13 @@ -export default defineEventHandler((event) => { +export default defineEventHandler(async (event) => { setHeader(event, 'Content-Type', 'application/json'); - const number = Number.parseInt(UI_CHART_TYPE, 10); + const system = await Database.getSystem(); + if (!system) + throw createError({ + statusCode: 500, + statusMessage: 'Invalid', + }); + + const number = system.trafficStats.type; if (Number.isNaN(number)) { return 0; } diff --git a/src/server/api/ui-traffic-stats.get.ts b/src/server/api/ui-traffic-stats.get.ts index f8353308..12d969c8 100644 --- a/src/server/api/ui-traffic-stats.get.ts +++ b/src/server/api/ui-traffic-stats.get.ts @@ -1,6 +1,11 @@ -export default defineEventHandler((event) => { +export default defineEventHandler(async (event) => { setHeader(event, 'Content-Type', 'application/json'); - // Weird issue with auto import not working. This alias is needed - const stats = UI_TRAFFIC_STATS; - return stats === 'true' ? true : false; + const system = await Database.getSystem(); + if (!system) + throw createError({ + statusCode: 500, + statusMessage: 'Invalid', + }); + + return system.trafficStats.enabled; }); diff --git a/src/server/api/wg-enable-expire-time.get.ts b/src/server/api/wg-enable-expire-time.get.ts index 9d17d2ba..8d3031e7 100644 --- a/src/server/api/wg-enable-expire-time.get.ts +++ b/src/server/api/wg-enable-expire-time.get.ts @@ -1,5 +1,11 @@ -export default defineEventHandler((event) => { +export default defineEventHandler(async (event) => { setHeader(event, 'Content-Type', 'application/json'); - const expires = WG_ENABLE_EXPIRES_TIME; - return expires === 'true' ? true : false; + const system = await Database.getSystem(); + if (!system) + throw createError({ + statusCode: 500, + statusMessage: 'Invalid', + }); + + return system.wgEnableExpiresTime; }); diff --git a/src/server/api/wg-enable-one-time-links.get.ts b/src/server/api/wg-enable-one-time-links.get.ts index ff734e2b..12488126 100644 --- a/src/server/api/wg-enable-one-time-links.get.ts +++ b/src/server/api/wg-enable-one-time-links.get.ts @@ -1,5 +1,11 @@ -export default defineEventHandler((event) => { +export default defineEventHandler(async (event) => { setHeader(event, 'Content-Type', 'application/json'); - const otl = WG_ENABLE_ONE_TIME_LINKS; - return otl === 'true' ? true : false; + const system = await Database.getSystem(); + if (!system) + throw createError({ + statusCode: 500, + statusMessage: 'Invalid', + }); + + return system.wgEnableOneTimeLinks; }); diff --git a/src/server/utils/config.ts b/src/server/utils/config.ts index f147e3ba..a5f9e6f5 100644 --- a/src/server/utils/config.ts +++ b/src/server/utils/config.ts @@ -47,8 +47,10 @@ iptables -D FORWARD -o wg0 -j ACCEPT; .split('\n') .join(' '); export const LANG = process.env.LANG || 'en'; + export const UI_TRAFFIC_STATS = process.env.UI_TRAFFIC_STATS || 'false'; export const UI_CHART_TYPE = process.env.UI_CHART_TYPE || '0'; + export const WG_ENABLE_ONE_TIME_LINKS = process.env.WG_ENABLE_ONE_TIME_LINKS || 'false'; export const UI_ENABLE_SORT_CLIENTS = diff --git a/src/services/database/inmemory.ts b/src/services/database/inmemory.ts index 35f64b3d..0a674680 100644 --- a/src/services/database/inmemory.ts +++ b/src/services/database/inmemory.ts @@ -1,5 +1,6 @@ import debug from 'debug'; import packageJson from '@/package.json'; +import crypto from 'node:crypto'; import DatabaseProvider, { DatabaseError } from '~/repositories/database'; import { ChartType, Lang } from '~/repositories/types'; @@ -58,6 +59,8 @@ export default class InMemory extends DatabaseProvider { type: ChartType.None, }, wgEnableExpiresTime: false, + wgEnableOneTimeLinks: false, + wgEnableSortClients: false, prometheus: { enabled: false, password: null, @@ -117,7 +120,7 @@ export default class InMemory extends DatabaseProvider { const isUserEmpty = this.data.users.length === 0; const newUser: User = { - id: `${this.data.users.length + 1}`, + id: crypto.randomUUID(), password: hashPassword(password), username, role: isUserEmpty ? 'ADMIN' : 'CLIENT',