diff --git a/src/server/database/migrations/0000_short_skin.sql b/src/server/database/migrations/0000_short_skin.sql index 64d44bf0..921c4b5c 100644 --- a/src/server/database/migrations/0000_short_skin.sql +++ b/src/server/database/migrations/0000_short_skin.sql @@ -24,6 +24,9 @@ CREATE TABLE `general_table` ( `setupStep` integer NOT NULL, `session_password` text NOT NULL, `session_timeout` integer NOT NULL, + `metricsPrometheus` integer NOT NULL, + `metricsJson` integer NOT NULL, + `metricsPassword` text, `created_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL, `updated_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL ); @@ -54,14 +57,6 @@ CREATE TABLE `interfaces_table` ( ); --> statement-breakpoint CREATE UNIQUE INDEX `interfaces_table_port_unique` ON `interfaces_table` (`port`);--> statement-breakpoint -CREATE TABLE `prometheus_table` ( - `id` text PRIMARY KEY NOT NULL, - `password` text NOT NULL, - `created_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL, - `updated_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL, - FOREIGN KEY (`id`) REFERENCES `interfaces_table`(`name`) ON UPDATE cascade ON DELETE cascade -); ---> statement-breakpoint CREATE TABLE `one_time_links_table` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, `one_time_link` text NOT NULL, diff --git a/src/server/database/migrations/0001_classy_the_stranger.sql b/src/server/database/migrations/0001_classy_the_stranger.sql index c1dfd3fe..f305f0e7 100644 --- a/src/server/database/migrations/0001_classy_the_stranger.sql +++ b/src/server/database/migrations/0001_classy_the_stranger.sql @@ -1,6 +1,6 @@ PRAGMA journal_mode=WAL;--> statement-breakpoint -INSERT INTO `general_table` (`setupStep`, `session_password`, `session_timeout`) -VALUES (1, hex(randomblob(256)), 3600); +INSERT INTO `general_table` (`setupStep`, `session_password`, `session_timeout`, `metricsPrometheus`, `metricsJson`) +VALUES (1, hex(randomblob(256)), 3600, 0, 0); --> statement-breakpoint INSERT INTO `interfaces_table` (`name`, `device`, `port`, `private_key`, `public_key`, `ipv4_cidr`, `ipv6_cidr`, `mtu`, `enabled`) VALUES ('wg0', 'eth0', 51820, '---default---', '---default---', '10.8.0.0/24', 'fdcc:ad94:bacf:61a4::cafe:0/112', 1420, 1); diff --git a/src/server/database/migrations/meta/0000_snapshot.json b/src/server/database/migrations/meta/0000_snapshot.json index abc6ade7..4d28e70c 100644 --- a/src/server/database/migrations/meta/0000_snapshot.json +++ b/src/server/database/migrations/meta/0000_snapshot.json @@ -1,7 +1,7 @@ { "version": "6", "dialect": "sqlite", - "id": "25907c5f-be21-4ae6-88c4-1a72b2f335e7", + "id": "2c4694af-5916-430f-96d3-55aac2653e7e", "prevId": "00000000-0000-0000-0000-000000000000", "tables": { "clients_table": { @@ -175,6 +175,27 @@ "notNull": true, "autoincrement": false }, + "metricsPrometheus": { + "name": "metricsPrometheus", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "metricsJson": { + "name": "metricsJson", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "metricsPassword": { + "name": "metricsPassword", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, "created_at": { "name": "created_at", "type": "text", @@ -370,60 +391,6 @@ "uniqueConstraints": {}, "checkConstraints": {} }, - "prometheus_table": { - "name": "prometheus_table", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true, - "autoincrement": false - }, - "password": { - "name": "password", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "created_at": { - "name": "created_at", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false, - "default": "(CURRENT_TIMESTAMP)" - }, - "updated_at": { - "name": "updated_at", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false, - "default": "(CURRENT_TIMESTAMP)" - } - }, - "indexes": {}, - "foreignKeys": { - "prometheus_table_id_interfaces_table_name_fk": { - "name": "prometheus_table_id_interfaces_table_name_fk", - "tableFrom": "prometheus_table", - "tableTo": "interfaces_table", - "columnsFrom": [ - "id" - ], - "columnsTo": [ - "name" - ], - "onDelete": "cascade", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, "one_time_links_table": { "name": "one_time_links_table", "columns": { diff --git a/src/server/database/migrations/meta/0001_snapshot.json b/src/server/database/migrations/meta/0001_snapshot.json index d0d7078b..07cb02f8 100644 --- a/src/server/database/migrations/meta/0001_snapshot.json +++ b/src/server/database/migrations/meta/0001_snapshot.json @@ -1,6 +1,6 @@ { - "id": "60af732f-adc0-405d-96cc-2f818585f593", - "prevId": "25907c5f-be21-4ae6-88c4-1a72b2f335e7", + "id": "91d39ed5-2c45-4af6-ba39-4cd72ba71f6a", + "prevId": "2c4694af-5916-430f-96d3-55aac2653e7e", "version": "6", "dialect": "sqlite", "tables": { @@ -175,6 +175,27 @@ "notNull": true, "autoincrement": false }, + "metricsPrometheus": { + "name": "metricsPrometheus", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "metricsJson": { + "name": "metricsJson", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "metricsPassword": { + "name": "metricsPassword", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, "created_at": { "name": "created_at", "type": "text", @@ -370,60 +391,6 @@ "uniqueConstraints": {}, "checkConstraints": {} }, - "prometheus_table": { - "name": "prometheus_table", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true, - "autoincrement": false - }, - "password": { - "name": "password", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "created_at": { - "name": "created_at", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false, - "default": "(CURRENT_TIMESTAMP)" - }, - "updated_at": { - "name": "updated_at", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false, - "default": "(CURRENT_TIMESTAMP)" - } - }, - "indexes": {}, - "foreignKeys": { - "prometheus_table_id_interfaces_table_name_fk": { - "name": "prometheus_table_id_interfaces_table_name_fk", - "tableFrom": "prometheus_table", - "columnsFrom": [ - "id" - ], - "tableTo": "interfaces_table", - "columnsTo": [ - "name" - ], - "onUpdate": "cascade", - "onDelete": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, "one_time_links_table": { "name": "one_time_links_table", "columns": { diff --git a/src/server/database/migrations/meta/_journal.json b/src/server/database/migrations/meta/_journal.json index 0e72d1fe..4029303b 100644 --- a/src/server/database/migrations/meta/_journal.json +++ b/src/server/database/migrations/meta/_journal.json @@ -5,14 +5,14 @@ { "idx": 0, "version": "6", - "when": 1737122352401, + "when": 1739191645161, "tag": "0000_short_skin", "breakpoints": true }, { "idx": 1, "version": "6", - "when": 1737122356601, + "when": 1739191678456, "tag": "0001_classy_the_stranger", "breakpoints": true } diff --git a/src/server/database/repositories/general/schema.ts b/src/server/database/repositories/general/schema.ts index a2baec6c..3945573d 100644 --- a/src/server/database/repositories/general/schema.ts +++ b/src/server/database/repositories/general/schema.ts @@ -3,9 +3,16 @@ import { sqliteTable, text, int } from 'drizzle-orm/sqlite-core'; export const general = sqliteTable('general_table', { id: int().primaryKey({ autoIncrement: false }).default(1), + setupStep: int().notNull(), + sessionPassword: text('session_password').notNull(), sessionTimeout: int('session_timeout').notNull(), + + metricsPrometheus: int({ mode: 'boolean' }).notNull(), + metricsJson: int({ mode: 'boolean' }).notNull(), + metricsPassword: text(), + createdAt: text('created_at') .notNull() .default(sql`(CURRENT_TIMESTAMP)`), diff --git a/src/server/database/repositories/general/service.ts b/src/server/database/repositories/general/service.ts index af48262d..590a6e5d 100644 --- a/src/server/database/repositories/general/service.ts +++ b/src/server/database/repositories/general/service.ts @@ -5,7 +5,30 @@ import type { GeneralUpdateType } from './types'; function createPreparedStatement(db: DBType) { return { - find: db.query.general.findFirst().prepare(), + getSetupStep: db.query.general + .findFirst({ + columns: { + setupStep: true, + }, + }) + .prepare(), + getSessionConfig: db.query.general + .findFirst({ + columns: { + sessionPassword: true, + sessionTimeout: true, + }, + }) + .prepare(), + getMetricsConfig: db.query.general + .findFirst({ + columns: { + metricsPrometheus: true, + metricsJson: true, + metricsPassword: true, + }, + }) + .prepare(), updateSetupStep: db .update(general) .set({ @@ -31,19 +54,13 @@ export class GeneralService { /** * @throws */ - private async get() { - const result = await this.#statements.find.execute(); + async getSetupStep() { + const result = await this.#statements.getSetupStep.execute(); + if (!result) { throw new Error('General Config not found'); } - return result; - } - /** - * @throws - */ - async getSetupStep() { - const result = await this.get(); return { step: result.setupStep, done: result.setupStep === 0 }; } @@ -55,13 +72,35 @@ export class GeneralService { * @throws */ async getSessionConfig() { - const result = await this.get(); + const result = await this.#statements.getSessionConfig.execute(); + + if (!result) { + throw new Error('General Config not found'); + } + return { sessionPassword: result.sessionPassword, sessionTimeout: result.sessionTimeout, }; } + /** + * @throws + */ + async getMetricsConfig() { + const result = await this.#statements.getMetricsConfig.execute(); + + if (!result) { + throw new Error('General Config not found'); + } + + return { + prometheus: result.metricsPrometheus, + json: result.metricsJson, + password: result.metricsPassword, + }; + } + update(data: GeneralUpdateType) { return this.#statements.update.execute(data); } diff --git a/src/server/database/repositories/interface/schema.ts b/src/server/database/repositories/interface/schema.ts index 41dd898d..aa7a5b5e 100644 --- a/src/server/database/repositories/interface/schema.ts +++ b/src/server/database/repositories/interface/schema.ts @@ -1,7 +1,7 @@ import { sql, relations } from 'drizzle-orm'; import { int, sqliteTable, text } from 'drizzle-orm/sqlite-core'; -import { userConfig, hooks, prometheus } from '../../schema'; +import { userConfig, hooks } from '../../schema'; // maybe support multiple interfaces in the future export const wgInterface = sqliteTable('interfaces_table', { @@ -28,10 +28,6 @@ export const wgInterfaceRelations = relations(wgInterface, ({ one }) => ({ fields: [wgInterface.name], references: [hooks.id], }), - prometheus: one(prometheus, { - fields: [wgInterface.name], - references: [prometheus.id], - }), userConfig: one(userConfig, { fields: [wgInterface.name], references: [userConfig.id], diff --git a/src/server/database/repositories/metrics/schema.ts b/src/server/database/repositories/metrics/schema.ts deleted file mode 100644 index 894bc0c3..00000000 --- a/src/server/database/repositories/metrics/schema.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { sql } from 'drizzle-orm'; -import { sqliteTable, text } from 'drizzle-orm/sqlite-core'; - -import { wgInterface } from '../../schema'; - -export const prometheus = sqliteTable('prometheus_table', { - id: text() - .primaryKey() - .references(() => wgInterface.name, { - onDelete: 'cascade', - onUpdate: 'cascade', - }), - password: text().notNull(), - createdAt: text('created_at') - .notNull() - .default(sql`(CURRENT_TIMESTAMP)`), - updatedAt: text('updated_at') - .notNull() - .default(sql`(CURRENT_TIMESTAMP)`) - .$onUpdate(() => sql`(CURRENT_TIMESTAMP)`), -}); diff --git a/src/server/database/repositories/metrics/service.ts b/src/server/database/repositories/metrics/service.ts deleted file mode 100644 index 38685749..00000000 --- a/src/server/database/repositories/metrics/service.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { DBType } from '#db/sqlite'; -import { eq, sql } from 'drizzle-orm'; -import { prometheus } from './schema'; - -function createPreparedStatement(db: DBType) { - return { - get: db.query.prometheus - .findFirst({ where: eq(prometheus.id, sql.placeholder('interface')) }) - .prepare(), - }; -} - -export class PrometheusService { - #statements: ReturnType; - - constructor(db: DBType) { - this.#statements = createPreparedStatement(db); - } - - get(infName: string) { - return this.#statements.get.execute({ interface: infName }); - } -} - -export class MetricsService { - prometheus: PrometheusService; - - constructor(db: DBType) { - this.prometheus = new PrometheusService(db); - } -} diff --git a/src/server/database/repositories/metrics/types.ts b/src/server/database/repositories/metrics/types.ts deleted file mode 100644 index 45c4bcad..00000000 --- a/src/server/database/repositories/metrics/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -import type { InferSelectModel } from 'drizzle-orm'; -import type { prometheus } from './schema'; - -export type PrometheusType = InferSelectModel; diff --git a/src/server/database/schema.ts b/src/server/database/schema.ts index 73edce69..ba56016f 100644 --- a/src/server/database/schema.ts +++ b/src/server/database/schema.ts @@ -3,7 +3,6 @@ export * from './repositories/client/schema'; export * from './repositories/general/schema'; export * from './repositories/hooks/schema'; export * from './repositories/interface/schema'; -export * from './repositories/metrics/schema'; export * from './repositories/oneTimeLink/schema'; export * from './repositories/user/schema'; export * from './repositories/userConfig/schema'; diff --git a/src/server/database/sqlite.ts b/src/server/database/sqlite.ts index 738e1192..222fea3b 100644 --- a/src/server/database/sqlite.ts +++ b/src/server/database/sqlite.ts @@ -11,7 +11,6 @@ import { UserConfigService } from './repositories/userConfig/service'; import { InterfaceService } from './repositories/interface/service'; import { HooksService } from './repositories/hooks/service'; import { OneTimeLinkService } from './repositories/oneTimeLink/service'; -import { MetricsService } from './repositories/metrics/service'; const DB_DEBUG = debug('Database'); @@ -31,7 +30,6 @@ class DBService { interfaces: InterfaceService; hooks: HooksService; oneTimeLinks: OneTimeLinkService; - metrics: MetricsService; constructor(db: DBType) { this.clients = new ClientService(db); @@ -41,7 +39,6 @@ class DBService { this.interfaces = new InterfaceService(db); this.hooks = new HooksService(db); this.oneTimeLinks = new OneTimeLinkService(db); - this.metrics = new MetricsService(db); } } diff --git a/src/server/routes/metrics/json.get.ts b/src/server/routes/metrics/json.get.ts index e06569a1..ff757e8c 100644 --- a/src/server/routes/metrics/json.get.ts +++ b/src/server/routes/metrics/json.get.ts @@ -1,4 +1,4 @@ -export default defineMetricsHandler('prometheus', async () => { +export default defineMetricsHandler('json', async () => { return getMetricsJSON(); }); diff --git a/src/server/utils/handler.ts b/src/server/utils/handler.ts index 20b3c852..bddf2a45 100644 --- a/src/server/utils/handler.ts +++ b/src/server/utils/handler.ts @@ -58,7 +58,7 @@ export const defineSetupEventHandler = < }); }; -type Metrics = 'prometheus'; +type Metrics = 'prometheus' | 'json'; type MetricsHandler< TReq extends EventHandlerRequest, @@ -94,22 +94,24 @@ export const defineMetricsHandler = < }); } - const metricsConfig = await Database.metrics[type].get('wg0'); + const metricsConfig = await Database.general.getMetricsConfig(); - if (!metricsConfig) { + if (metricsConfig[type] !== true) { throw createError({ statusCode: 400, statusMessage: 'Metrics not enabled', }); } - const tokenValid = await isPasswordValid(value, metricsConfig.password); + if (metricsConfig.password) { + const tokenValid = await isPasswordValid(value, metricsConfig.password); - if (!tokenValid) { - throw createError({ - statusCode: 401, - statusMessage: 'Incorrect token', - }); + if (!tokenValid) { + throw createError({ + statusCode: 401, + statusMessage: 'Incorrect token', + }); + } } return await handler({ event });