From a88e36319bc16d99f16cb2ff55d368981193ce9f Mon Sep 17 00:00:00 2001 From: Bernd Storath <999999bst@gmail.com> Date: Fri, 16 May 2025 12:39:56 +0200 Subject: [PATCH] start refactoring --- src/eslint.config.js | 27 ++++++ src/eslint.config.mjs | 11 --- .../database/repositories/client/schema.ts | 5 +- src/server/routes/metrics/prometheus.get.ts | 8 +- src/server/utils/Database.ts | 4 +- src/server/utils/WireGuard.ts | 13 ++- src/server/utils/cmd.ts | 9 +- src/server/utils/handler.ts | 10 +- src/server/utils/ip.ts | 15 ++- src/server/utils/release.ts | 2 +- src/server/utils/template.ts | 7 +- src/server/utils/types.ts | 95 +++++++++---------- src/server/utils/wgHelper.ts | 2 +- src/shared/utils/permissions.ts | 2 +- 14 files changed, 116 insertions(+), 94 deletions(-) create mode 100644 src/eslint.config.js delete mode 100644 src/eslint.config.mjs diff --git a/src/eslint.config.js b/src/eslint.config.js new file mode 100644 index 00000000..1d819231 --- /dev/null +++ b/src/eslint.config.js @@ -0,0 +1,27 @@ +// @ts-check + +import eslintConfigPrettier from 'eslint-config-prettier'; +import withNuxt from './.nuxt/eslint.config.mjs'; + +export default withNuxt([ + { + rules: { + 'import/order': 'warn', + }, + }, + eslintConfigPrettier, +]).override('nuxt/typescript/rules', { + rules: { + '@typescript-eslint/restrict-template-expressions': [ + 'error', + { + allowAny: false, + allowBoolean: true, + allowNever: false, + allowNullish: false, + allowNumber: true, + allowRegExp: false, + }, + ], + }, +}); diff --git a/src/eslint.config.mjs b/src/eslint.config.mjs deleted file mode 100644 index a63a9f85..00000000 --- a/src/eslint.config.mjs +++ /dev/null @@ -1,11 +0,0 @@ -import eslintConfigPrettier from 'eslint-config-prettier'; -import withNuxt from './.nuxt/eslint.config.mjs'; - -export default withNuxt([ - { - rules: { - 'import/order': 'warn', - }, - }, - eslintConfigPrettier, -]); diff --git a/src/server/database/repositories/client/schema.ts b/src/server/database/repositories/client/schema.ts index 97c8e8a9..de80e975 100644 --- a/src/server/database/repositories/client/schema.ts +++ b/src/server/database/repositories/client/schema.ts @@ -43,10 +43,7 @@ export const client = sqliteTable('clients_table', { }); export const clientsRelations = relations(client, ({ one }) => ({ - oneTimeLink: one(oneTimeLink, { - fields: [client.id], - references: [oneTimeLink.id], - }), + oneTimeLink: one(oneTimeLink), user: one(user, { fields: [client.userId], references: [user.id], diff --git a/src/server/routes/metrics/prometheus.get.ts b/src/server/routes/metrics/prometheus.get.ts index 837a094e..73e9218f 100644 --- a/src/server/routes/metrics/prometheus.get.ts +++ b/src/server/routes/metrics/prometheus.get.ts @@ -14,7 +14,7 @@ async function getPrometheusResponse() { const wireguardLatestHandshakeSeconds = []; for (const client of clients) { wireguardPeerCount++; - if (client.enabled === true) { + if (client.enabled) { wireguardEnabledPeersCount++; } @@ -55,15 +55,15 @@ async function getPrometheusResponse() { '', '# HELP wireguard_sent_bytes Bytes sent to the peer', '# TYPE wireguard_sent_bytes counter', - `${wireguardSentBytes.join('\n')}`, + wireguardSentBytes.join('\n'), '', '# HELP wireguard_received_bytes Bytes received from the peer', '# TYPE wireguard_received_bytes counter', - `${wireguardReceivedBytes.join('\n')}`, + wireguardReceivedBytes.join('\n'), '', '# HELP wireguard_latest_handshake_seconds UNIX timestamp seconds of the last handshake', '# TYPE wireguard_latest_handshake_seconds gauge', - `${wireguardLatestHandshakeSeconds.join('\n')}`, + wireguardLatestHandshakeSeconds.join('\n'), ]; return returnText.join('\n'); diff --git a/src/server/utils/Database.ts b/src/server/utils/Database.ts index 76ae6797..0d9dbe41 100644 --- a/src/server/utils/Database.ts +++ b/src/server/utils/Database.ts @@ -16,9 +16,9 @@ const nullObject = new Proxy( // eslint-disable-next-line import/no-mutable-exports let provider = nullObject as never as DBServiceType; -connect().then((db) => { +void connect().then((db) => { provider = db; - WireGuard.Startup(); + void WireGuard.Startup(); }); export default provider; diff --git a/src/server/utils/WireGuard.ts b/src/server/utils/WireGuard.ts index a44a3b11..fbe2fff0 100644 --- a/src/server/utils/WireGuard.ts +++ b/src/server/utils/WireGuard.ts @@ -158,10 +158,12 @@ class WireGuard { WG_DEBUG(`Starting Wireguard Interface ${wgInterface.name}...`); await this.#saveWireguardConfig(wgInterface); await wg.down(wgInterface.name).catch(() => {}); - await wg.up(wgInterface.name).catch((err) => { + await wg.up(wgInterface.name).catch((err: unknown) => { if ( err && - err.message && + typeof err === 'object' && + 'message' in err && + typeof err.message === 'string' && err.message.includes(`Cannot find device "${wgInterface.name}"`) ) { throw new Error( @@ -181,13 +183,15 @@ class WireGuard { } // TODO: handle as worker_thread + // eslint-disable-next-line @typescript-eslint/require-await async startCronJob() { setIntervalImmediately(() => { - this.cronJob().catch((err) => { + this.cronJob().catch((err: unknown) => { WG_DEBUG('Running Cron Job failed.'); console.error(err); }); }, 60 * 1000); + return; } // Shutdown wireguard @@ -206,7 +210,7 @@ class WireGuard { let needsSave = false; // Expires Feature for (const client of clients) { - if (client.enabled !== true) continue; + if (!client.enabled) continue; if ( client.expiresAt !== null && new Date() > new Date(client.expiresAt) @@ -234,6 +238,7 @@ class WireGuard { } } +// eslint-disable-next-line @typescript-eslint/no-deprecated if (OLD_ENV.PASSWORD || OLD_ENV.PASSWORD_HASH) { throw new Error( ` diff --git a/src/server/utils/cmd.ts b/src/server/utils/cmd.ts index 6fd4ad9b..88c28241 100644 --- a/src/server/utils/cmd.ts +++ b/src/server/utils/cmd.ts @@ -9,7 +9,7 @@ export function exec( ) { if (typeof log === 'string') { CMD_DEBUG(`$ ${log}`); - } else if (log === true) { + } else if (log) { CMD_DEBUG(`$ ${cmd}`); } @@ -24,8 +24,11 @@ export function exec( shell: 'bash', }, (err, stdout) => { - if (err) return reject(err); - return resolve(String(stdout).trim()); + if (err) { + reject(err); + return; + } + resolve(String(stdout).trim()); } ); }); diff --git a/src/server/utils/handler.ts b/src/server/utils/handler.ts index 5f0baa08..9f885e94 100644 --- a/src/server/utils/handler.ts +++ b/src/server/utils/handler.ts @@ -99,16 +99,16 @@ export const defineSetupEventHandler = < }); } - const validSetupSteps = - ValidSetupSteps[setup.step as keyof typeof ValidSetupSteps]; - - if (!validSetupSteps) { + if (!(setup.step in ValidSetupSteps)) { throw createError({ statusCode: 500, statusMessage: 'Invalid setup step', }); } + const validSetupSteps = + ValidSetupSteps[setup.step as keyof typeof ValidSetupSteps]; + if (!validSetupSteps.includes(step as never)) { throw createError({ statusCode: 400, @@ -169,7 +169,7 @@ export const defineMetricsHandler = < } } - if (metricsConfig[type] !== true) { + if (!metricsConfig[type]) { throw createError({ statusCode: 400, statusMessage: 'Metrics not enabled', diff --git a/src/server/utils/ip.ts b/src/server/utils/ip.ts index c3c097e1..1a1e121d 100644 --- a/src/server/utils/ip.ts +++ b/src/server/utils/ip.ts @@ -104,17 +104,22 @@ function getPrivateInformation() { if (internal) { continue; } - if (!obj[name]) { + if (!(name in obj)) { obj[name] = { ipv4: [], ipv6: [], }; } - if (family === 'IPv4') { - obj[name].ipv4.push(address); - } else if (family === 'IPv6') { - obj[name].ipv6.push(address); + + switch (family) { + case 'IPv4': + obj[name].ipv4.push(address); + continue; + case 'IPv6': + obj[name].ipv6.push(address); + continue; } + assertUnreachable(family); } } diff --git a/src/server/utils/release.ts b/src/server/utils/release.ts index f5dfdc46..32898124 100644 --- a/src/server/utils/release.ts +++ b/src/server/utils/release.ts @@ -5,7 +5,7 @@ type GithubRelease = { async function fetchLatestRelease() { try { - const response = await $fetch( + const response = await $fetch( 'https://api.github.com/repos/wg-easy/wg-easy/releases/latest', { method: 'get', timeout: 5000 } ); diff --git a/src/server/utils/template.ts b/src/server/utils/template.ts index 12f775ed..22d931f1 100644 --- a/src/server/utils/template.ts +++ b/src/server/utils/template.ts @@ -4,8 +4,11 @@ import type { InterfaceType } from '#db/repositories/interface/types'; * Replace all {{key}} in the template with the values[key] */ export function template(templ: string, values: Record) { - return templ.replace(/\{\{(\w+)\}\}/g, (match, key) => { - return values[key] !== undefined ? values[key] : match; + return templ.replace(/\{\{(\w+)\}\}/g, (match, key: string) => { + if (key in values) { + return values[key]; + } + return match; }); } diff --git a/src/server/utils/types.ts b/src/server/utils/types.ts index ad43fd1c..39c3baa7 100644 --- a/src/server/utils/types.ts +++ b/src/server/utils/types.ts @@ -1,6 +1,6 @@ import type { ZodSchema } from 'zod'; import z from 'zod'; -import type { H3Event, EventHandlerRequest } from 'h3'; +import type { H3Event } from 'h3'; export type ID = number; @@ -63,10 +63,7 @@ export const schemaForType = return arg; }; -export function validateZod( - schema: ZodSchema, - event: H3Event -) { +export function validateZod(schema: ZodSchema, event: H3Event) { return async (data: unknown) => { try { return await schema.parseAsync(data); @@ -79,64 +76,60 @@ export function validateZod( .map((v) => { let m = v.message; - if (t) { - let newMessage = null; - if (v.message.startsWith('zod.')) { - switch (v.code) { - case 'too_small': - switch (v.type) { + let newMessage = null; + if (v.message.startsWith('zod.')) { + switch (v.code) { + case 'too_small': + switch (v.type) { + case 'string': + newMessage = t('zod.generic.stringMin', [ + t(v.message), + v.minimum, + ]); + break; + case 'number': + newMessage = t('zod.generic.numberMin', [ + t(v.message), + v.minimum, + ]); + break; + } + break; + case 'invalid_type': { + if (v.received === 'null' || v.received === 'undefined') { + newMessage = t('zod.generic.required', [v.path.join('.')]); + } else { + switch (v.expected) { case 'string': - newMessage = t('zod.generic.stringMin', [ + newMessage = t('zod.generic.validString', [ + t(v.message), + ]); + break; + case 'boolean': + newMessage = t('zod.generic.validBoolean', [ t(v.message), - v.minimum, ]); break; case 'number': - newMessage = t('zod.generic.numberMin', [ + newMessage = t('zod.generic.validNumber', [ + t(v.message), + ]); + break; + case 'array': + newMessage = t('zod.generic.validArray', [ t(v.message), - v.minimum, ]); break; } - break; - case 'invalid_type': { - if (v.received === 'null' || v.received === 'undefined') { - newMessage = t('zod.generic.required', [ - v.path.join('.'), - ]); - } else { - switch (v.expected) { - case 'string': - newMessage = t('zod.generic.validString', [ - t(v.message), - ]); - break; - case 'boolean': - newMessage = t('zod.generic.validBoolean', [ - t(v.message), - ]); - break; - case 'number': - newMessage = t('zod.generic.validNumber', [ - t(v.message), - ]); - break; - case 'array': - newMessage = t('zod.generic.validArray', [ - t(v.message), - ]); - break; - } - } - break; } + break; } } - if (newMessage) { - m = newMessage; - } else { - m = t(v.message); - } + } + if (newMessage) { + m = newMessage; + } else { + m = t(v.message); } return m; diff --git a/src/server/utils/wgHelper.ts b/src/server/utils/wgHelper.ts index 7f1c44ec..e7d96b34 100644 --- a/src/server/utils/wgHelper.ts +++ b/src/server/utils/wgHelper.ts @@ -10,7 +10,7 @@ export const wg = { const allowedIps = [ `${client.ipv4Address}/32`, `${client.ipv6Address}/128`, - ...(client.serverAllowedIps ?? []), + ...client.serverAllowedIps, ]; const extraLines = []; diff --git a/src/shared/utils/permissions.ts b/src/shared/utils/permissions.ts index 912b5ac1..f946ce87 100644 --- a/src/shared/utils/permissions.ts +++ b/src/shared/utils/permissions.ts @@ -134,7 +134,7 @@ export function hasPermissionsWithData( ) { let checked = false; return { - check(data?: Permissions[Resource]['dataType']) { + check(this: void, data?: Permissions[Resource]['dataType']) { checked = true; const isAllowed = hasPermissions(user, resource, action, data);