From bc93e95ca0b92e483d488d143880cea175184f97 Mon Sep 17 00:00:00 2001
From: Bernd Storath <999999bst@gmail.com>
Date: Fri, 17 Jan 2025 14:58:30 +0100
Subject: [PATCH] migrate to sqlite
---
src/app/components/ClientCard/Address.vue | 2 +-
.../components/ClientCard/OneTimeLinkBtn.vue | 6 +-
src/app/components/ui/UserMenu.vue | 2 +-
src/app/utils/api.ts | 6 -
src/i18n/locales/en.json | 78 ++++---
src/server/api/admin/hooks.get.ts | 7 +-
src/server/api/admin/hooks.post.ts | 2 +-
.../client/[clientId]/configuration.get.ts | 10 +-
.../api/client/[clientId]/disable.post.ts | 7 +-
.../api/client/[clientId]/enable.post.ts | 7 +-
.../[clientId]/generateOneTimeLink.post.ts | 6 +-
.../api/client/[clientId]/index.delete.ts | 7 +-
src/server/api/client/[clientId]/index.get.ts | 13 +-
.../api/client/[clientId]/index.post.ts | 15 +-
.../api/client/[clientId]/qrcode.svg.get.ts | 4 +-
src/server/api/session.post.ts | 4 +-
src/server/api/setup/4.post.ts | 4 +-
src/server/api/setup/5.post.ts | 4 +-
.../database/repositories/client/service.ts | 18 +-
.../database/repositories/client/types.ts | 46 ++--
.../database/repositories/general/types.ts | 4 +
.../database/repositories/metrics/service.ts | 0
.../database/repositories/metrics/types.ts | 4 +
.../repositories/oneTimeLink/schema.ts | 2 +-
.../repositories/oneTimeLink/service.ts | 17 ++
.../repositories/oneTimeLink/types.ts | 4 +
.../database/repositories/user/types.ts | 38 ++++
.../database/repositories/userConfig/types.ts | 15 ++
src/server/middleware/auth.ts | 9 +-
src/server/utils/types.ts | 212 +-----------------
src/{server => shared}/utils/permissions.ts | 0
31 files changed, 248 insertions(+), 305 deletions(-)
create mode 100644 src/server/database/repositories/general/types.ts
create mode 100644 src/server/database/repositories/metrics/service.ts
create mode 100644 src/server/database/repositories/metrics/types.ts
create mode 100644 src/server/database/repositories/oneTimeLink/types.ts
rename src/{server => shared}/utils/permissions.ts (100%)
diff --git a/src/app/components/ClientCard/Address.vue b/src/app/components/ClientCard/Address.vue
index e7957d30..c405ef83 100644
--- a/src/app/components/ClientCard/Address.vue
+++ b/src/app/components/ClientCard/Address.vue
@@ -1,6 +1,6 @@
- {{ client.address4 }}, {{ client.address6 }}
+ {{ client.ipv4Address }}, {{ client.ipv6Address }}
diff --git a/src/app/components/ClientCard/OneTimeLinkBtn.vue b/src/app/components/ClientCard/OneTimeLinkBtn.vue
index 303559c6..9979a025 100644
--- a/src/app/components/ClientCard/OneTimeLinkBtn.vue
+++ b/src/app/components/ClientCard/OneTimeLinkBtn.vue
@@ -27,8 +27,10 @@ defineProps<{ client: LocalClient }>();
const clientsStore = useClientsStore();
function showOneTimeLink(client: LocalClient) {
- api
- .showOneTimeLink({ clientId: client.id })
+ // TODO: improve
+ $fetch(`/api/client/${client.id}/generateOneTimeLink`, {
+ method: 'post',
+ })
.catch((err) => alert(err.message || err.toString()))
.finally(() => clientsStore.refresh().catch(console.error));
}
diff --git a/src/app/components/ui/UserMenu.vue b/src/app/components/ui/UserMenu.vue
index 8e956567..31547319 100644
--- a/src/app/components/ui/UserMenu.vue
+++ b/src/app/components/ui/UserMenu.vue
@@ -37,7 +37,7 @@
Account
-
+
{
- const system = await Database.system.get();
- return system.hooks;
+ const hooks = await Database.hooks.get('wg0');
+ if (!hooks) {
+ throw new Error('Hooks not found');
+ }
+ return hooks;
});
diff --git a/src/server/api/admin/hooks.post.ts b/src/server/api/admin/hooks.post.ts
index 7a0702fd..820c60f4 100644
--- a/src/server/api/admin/hooks.post.ts
+++ b/src/server/api/admin/hooks.post.ts
@@ -3,7 +3,7 @@ export default defineEventHandler(async (event) => {
event,
validateZod(hooksUpdateType, event)
);
- await Database.system.updateHooks(data);
+ await Database.hooks.update(data);
await WireGuard.saveConfig();
return { success: true };
});
diff --git a/src/server/api/client/[clientId]/configuration.get.ts b/src/server/api/client/[clientId]/configuration.get.ts
index 97349f5a..e20645b5 100644
--- a/src/server/api/client/[clientId]/configuration.get.ts
+++ b/src/server/api/client/[clientId]/configuration.get.ts
@@ -1,11 +1,19 @@
+import { ClientGetSchema } from '#db/repositories/client/types';
+
export default definePermissionEventHandler(
actions.CLIENT,
async ({ event }) => {
const { clientId } = await getValidatedRouterParams(
event,
- validateZod(clientIdType)
+ validateZod(ClientGetSchema)
);
const client = await Database.clients.get(clientId);
+ if (!client) {
+ throw createError({
+ statusCode: 404,
+ statusMessage: 'Client not found',
+ });
+ }
const config = await WireGuard.getClientConfiguration({ clientId });
const configName = client.name
.replace(/[^a-zA-Z0-9_=+.-]/g, '-')
diff --git a/src/server/api/client/[clientId]/disable.post.ts b/src/server/api/client/[clientId]/disable.post.ts
index aa6a506f..d4746e2d 100644
--- a/src/server/api/client/[clientId]/disable.post.ts
+++ b/src/server/api/client/[clientId]/disable.post.ts
@@ -1,11 +1,14 @@
+import { ClientGetSchema } from '#db/repositories/client/types';
+
export default definePermissionEventHandler(
actions.CLIENT,
async ({ event }) => {
const { clientId } = await getValidatedRouterParams(
event,
- validateZod(clientIdType)
+ validateZod(ClientGetSchema)
);
- await WireGuard.disableClient({ clientId });
+ await Database.clients.toggle(clientId, false);
+ await WireGuard.saveConfig();
return { success: true };
}
);
diff --git a/src/server/api/client/[clientId]/enable.post.ts b/src/server/api/client/[clientId]/enable.post.ts
index e1e8788c..d4746e2d 100644
--- a/src/server/api/client/[clientId]/enable.post.ts
+++ b/src/server/api/client/[clientId]/enable.post.ts
@@ -1,11 +1,14 @@
+import { ClientGetSchema } from '#db/repositories/client/types';
+
export default definePermissionEventHandler(
actions.CLIENT,
async ({ event }) => {
const { clientId } = await getValidatedRouterParams(
event,
- validateZod(clientIdType)
+ validateZod(ClientGetSchema)
);
- await WireGuard.enableClient({ clientId });
+ await Database.clients.toggle(clientId, false);
+ await WireGuard.saveConfig();
return { success: true };
}
);
diff --git a/src/server/api/client/[clientId]/generateOneTimeLink.post.ts b/src/server/api/client/[clientId]/generateOneTimeLink.post.ts
index 0b1f82f1..dc4287ad 100644
--- a/src/server/api/client/[clientId]/generateOneTimeLink.post.ts
+++ b/src/server/api/client/[clientId]/generateOneTimeLink.post.ts
@@ -1,11 +1,13 @@
+import { ClientGetSchema } from '#db/repositories/client/types';
+
export default definePermissionEventHandler(
actions.CLIENT,
async ({ event }) => {
const { clientId } = await getValidatedRouterParams(
event,
- validateZod(clientIdType)
+ validateZod(ClientGetSchema)
);
- await WireGuard.generateOneTimeLink({ clientId });
+ await Database.oneTimeLinks.generate(clientId);
return { success: true };
}
);
diff --git a/src/server/api/client/[clientId]/index.delete.ts b/src/server/api/client/[clientId]/index.delete.ts
index edd100e7..686a39ac 100644
--- a/src/server/api/client/[clientId]/index.delete.ts
+++ b/src/server/api/client/[clientId]/index.delete.ts
@@ -1,11 +1,14 @@
+import { ClientGetSchema } from '#db/repositories/client/types';
+
export default definePermissionEventHandler(
actions.CLIENT,
async ({ event }) => {
const { clientId } = await getValidatedRouterParams(
event,
- validateZod(clientIdType)
+ validateZod(ClientGetSchema)
);
- await WireGuard.deleteClient({ clientId });
+ await Database.clients.delete(clientId);
+ await WireGuard.saveConfig();
return { success: true };
}
);
diff --git a/src/server/api/client/[clientId]/index.get.ts b/src/server/api/client/[clientId]/index.get.ts
index 6d5b1b49..0a4f78db 100644
--- a/src/server/api/client/[clientId]/index.get.ts
+++ b/src/server/api/client/[clientId]/index.get.ts
@@ -1,10 +1,19 @@
+import { ClientGetSchema } from '~~/server/database/repositories/client/types';
+
export default definePermissionEventHandler(
actions.CLIENT,
async ({ event }) => {
const { clientId } = await getValidatedRouterParams(
event,
- validateZod(clientIdType)
+ validateZod(ClientGetSchema)
);
- return WireGuard.getClient({ clientId });
+ const result = await Database.clients.get(clientId);
+ if (!result) {
+ throw createError({
+ statusCode: 404,
+ statusMessage: 'Client not found',
+ });
+ }
+ return result;
}
);
diff --git a/src/server/api/client/[clientId]/index.post.ts b/src/server/api/client/[clientId]/index.post.ts
index bb18bd1a..78ff38e3 100644
--- a/src/server/api/client/[clientId]/index.post.ts
+++ b/src/server/api/client/[clientId]/index.post.ts
@@ -1,20 +1,23 @@
+import {
+ ClientGetSchema,
+ ClientUpdateSchema,
+} from '#db/repositories/client/types';
+
export default definePermissionEventHandler(
actions.CLIENT,
async ({ event }) => {
const { clientId } = await getValidatedRouterParams(
event,
- validateZod(clientIdType)
+ validateZod(ClientGetSchema)
);
const data = await readValidatedBody(
event,
- validateZod(clientUpdateType, event)
+ validateZod(ClientUpdateSchema, event)
);
- await WireGuard.updateClient({
- clientId,
- client: data,
- });
+ await Database.clients.update(clientId, data);
+ await WireGuard.saveConfig();
return { success: true };
}
diff --git a/src/server/api/client/[clientId]/qrcode.svg.get.ts b/src/server/api/client/[clientId]/qrcode.svg.get.ts
index 494b36a0..381054cd 100644
--- a/src/server/api/client/[clientId]/qrcode.svg.get.ts
+++ b/src/server/api/client/[clientId]/qrcode.svg.get.ts
@@ -1,9 +1,11 @@
+import { ClientGetSchema } from '#db/repositories/client/types';
+
export default definePermissionEventHandler(
actions.CLIENT,
async ({ event }) => {
const { clientId } = await getValidatedRouterParams(
event,
- validateZod(clientIdType)
+ validateZod(ClientGetSchema)
);
const svg = await WireGuard.getClientQRCodeSVG({ clientId });
setHeader(event, 'Content-Type', 'image/svg+xml');
diff --git a/src/server/api/session.post.ts b/src/server/api/session.post.ts
index 7b5df3e9..4cfbf35d 100644
--- a/src/server/api/session.post.ts
+++ b/src/server/api/session.post.ts
@@ -1,7 +1,9 @@
+import { UserLoginSchema } from '#db/repositories/user/types';
+
export default defineEventHandler(async (event) => {
const { username, password, remember } = await readValidatedBody(
event,
- validateZod(credentialsType, event)
+ validateZod(UserLoginSchema, event)
);
const user = await Database.users.getByUsername(username);
diff --git a/src/server/api/setup/4.post.ts b/src/server/api/setup/4.post.ts
index de8a9c33..fd7f29c0 100644
--- a/src/server/api/setup/4.post.ts
+++ b/src/server/api/setup/4.post.ts
@@ -1,3 +1,5 @@
+import { UserSetupType } from '#db/repositories/user/types';
+
export default defineEventHandler(async (event) => {
const { done } = await Database.general.getSetupStep();
if (done) {
@@ -9,7 +11,7 @@ export default defineEventHandler(async (event) => {
const { username, password } = await readValidatedBody(
event,
- validateZod(passwordSetupType, event)
+ validateZod(UserSetupType, event)
);
await Database.users.create(username, password);
diff --git a/src/server/api/setup/5.post.ts b/src/server/api/setup/5.post.ts
index a9b8f5e2..514c4166 100644
--- a/src/server/api/setup/5.post.ts
+++ b/src/server/api/setup/5.post.ts
@@ -1,3 +1,5 @@
+import { UserConfigSetupType } from '#db/repositories/userConfig/types';
+
export default defineEventHandler(async (event) => {
const { done } = await Database.general.getSetupStep();
if (done) {
@@ -9,7 +11,7 @@ export default defineEventHandler(async (event) => {
const { host, port } = await readValidatedBody(
event,
- validateZod(hostPortType, event)
+ validateZod(UserConfigSetupType, event)
);
await Database.userConfigs.updateHostPort('wg0', host, port);
await Database.general.setSetupStep(0);
diff --git a/src/server/database/repositories/client/service.ts b/src/server/database/repositories/client/service.ts
index f4d31776..7c8971e1 100644
--- a/src/server/database/repositories/client/service.ts
+++ b/src/server/database/repositories/client/service.ts
@@ -1,7 +1,7 @@
import type { DBType } from '#db/sqlite';
import { eq, sql } from 'drizzle-orm';
import { client } from './schema';
-import type { ClientCreateType } from './types';
+import type { ClientCreateType, UpdateClientType } from './types';
import type { ID } from '../../schema';
import { wgInterface, userConfig } from '../../schema';
import { parseCidr } from 'cidr-tools';
@@ -23,6 +23,10 @@ function createPreparedStatement(db: DBType) {
.set({ enabled: sql.placeholder('enabled') as never as boolean })
.where(eq(client.id, sql.placeholder('id')))
.prepare(),
+ delete: db
+ .delete(client)
+ .where(eq(client.id, sql.placeholder('id')))
+ .prepare(),
};
}
@@ -44,7 +48,7 @@ export class ClientService {
}));
}
- async get(id: ID) {
+ get(id: ID) {
return this.#statements.findById.execute({ id });
}
@@ -110,7 +114,15 @@ export class ClientService {
});
}
- async toggle(id: ID, enabled: boolean) {
+ toggle(id: ID, enabled: boolean) {
return this.#statements.toggle.execute({ id, enabled });
}
+
+ delete(id: ID) {
+ return this.#statements.delete.execute({ id });
+ }
+
+ update(id: ID, data: UpdateClientType) {
+ return this.#db.update(client).set(data).where(eq(client.id, id)).prepare();
+ }
}
diff --git a/src/server/database/repositories/client/types.ts b/src/server/database/repositories/client/types.ts
index a6731cec..45a5bd69 100644
--- a/src/server/database/repositories/client/types.ts
+++ b/src/server/database/repositories/client/types.ts
@@ -25,52 +25,54 @@ export type UpdateClientType = Omit<
>;
const name = zod
- .string({ message: 'zod.name' })
- .min(1, 'zod.nameMin')
+ .string({ message: 'zod.client.name' })
+ .min(1, 'zod.client.nameMin')
.pipe(safeStringRefine);
const expiresAt = zod
- .string({ message: 'zod.expireDate' })
- .min(1, 'zod.expireDateMin')
+ .string({ message: 'zod.client.expireDate' })
+ .min(1, 'zod.client.expireDateMin')
.pipe(safeStringRefine)
.nullable();
const address = zod
- .string({ message: 'zod.address' })
- .min(1, { message: 'zod.addressMin' })
+ .string({ message: 'zod.client.address' })
+ .min(1, { message: 'zod.client.addressMin' })
.pipe(safeStringRefine);
const address4 = zod
- .string({ message: 'zod.address4' })
- .min(1, { message: 'zod.address4Min' })
+ .string({ message: 'zod.client.address4' })
+ .min(1, { message: 'zod.client.address4Min' })
.pipe(safeStringRefine);
const address6 = zod
- .string({ message: 'zod.address6' })
- .min(1, { message: 'zod.address6Min' })
+ .string({ message: 'zod.client.address6' })
+ .min(1, { message: 'zod.client.address6Min' })
.pipe(safeStringRefine);
const allowedIps = zod
- .array(address, { message: 'zod.allowedIps' })
- .min(1, { message: 'zod.allowedIpsMin' });
+ .array(address, { message: 'zod.client.allowedIps' })
+ .min(1, { message: 'zod.client.allowedIpsMin' });
const serverAllowedIps = zod.array(address, {
message: 'zod.serverAllowedIps',
});
const mtu = zod
- .number({ message: 'zod.mtu' })
- .min(1280, { message: 'zod.mtuMin' })
- .max(9000, { message: 'zod.mtuMax' });
+ .number({ message: 'zod.client.mtu' })
+ .min(1280, { message: 'zod.client.mtuMin' })
+ .max(9000, { message: 'zod.client.mtuMax' });
const persistentKeepalive = zod
- .number({ message: 'zod.persistentKeepalive' })
- .min(0, 'zod.persistentKeepaliveMin')
- .max(65535, 'zod.persistentKeepaliveMax');
+ .number({ message: 'zod.client.persistentKeepalive' })
+ .min(0, 'zod.client.persistentKeepaliveMin')
+ .max(65535, 'zod.client.persistentKeepaliveMax');
const enabled = zod.boolean({ message: 'zod.enabled' });
-const dns = zod.array(address, { message: 'zod.dns' }).min(1, 'zod.dnsMin');
+const dns = zod
+ .array(address, { message: 'zod.client.dns' })
+ .min(1, 'zod.client.dnsMin');
export const ClientCreateSchema = zod.object({
name: name,
@@ -93,3 +95,9 @@ export const ClientUpdateSchema = schemaForType()(
dns: dns,
})
);
+
+const clientId = zod.number({ message: 'zod.client.id' });
+
+export const ClientGetSchema = zod.object({
+ clientId: clientId,
+});
diff --git a/src/server/database/repositories/general/types.ts b/src/server/database/repositories/general/types.ts
new file mode 100644
index 00000000..902859cb
--- /dev/null
+++ b/src/server/database/repositories/general/types.ts
@@ -0,0 +1,4 @@
+import type { InferSelectModel } from 'drizzle-orm';
+import type { general } from './schema';
+
+export type GeneralType = InferSelectModel;
diff --git a/src/server/database/repositories/metrics/service.ts b/src/server/database/repositories/metrics/service.ts
new file mode 100644
index 00000000..e69de29b
diff --git a/src/server/database/repositories/metrics/types.ts b/src/server/database/repositories/metrics/types.ts
new file mode 100644
index 00000000..45c4bcad
--- /dev/null
+++ b/src/server/database/repositories/metrics/types.ts
@@ -0,0 +1,4 @@
+import type { InferSelectModel } from 'drizzle-orm';
+import type { prometheus } from './schema';
+
+export type PrometheusType = InferSelectModel;
diff --git a/src/server/database/repositories/oneTimeLink/schema.ts b/src/server/database/repositories/oneTimeLink/schema.ts
index 3903e778..dd69c2fd 100644
--- a/src/server/database/repositories/oneTimeLink/schema.ts
+++ b/src/server/database/repositories/oneTimeLink/schema.ts
@@ -5,7 +5,7 @@ import { client } from '../../schema';
export const oneTimeLink = sqliteTable('one_time_links_table', {
id: int().primaryKey({ autoIncrement: true }),
- oneTimeLink: text('one_time_link').notNull(),
+ oneTimeLink: text('one_time_link').notNull().unique(),
expiresAt: text('expires_at').notNull(),
clientId: int()
.notNull()
diff --git a/src/server/database/repositories/oneTimeLink/service.ts b/src/server/database/repositories/oneTimeLink/service.ts
index 8d1ec5b3..48b8d8d1 100644
--- a/src/server/database/repositories/oneTimeLink/service.ts
+++ b/src/server/database/repositories/oneTimeLink/service.ts
@@ -2,6 +2,7 @@ import type { DBType } from '#db/sqlite';
import { eq, sql } from 'drizzle-orm';
import { oneTimeLink } from './schema';
import type { ID } from '../../schema';
+import CRC32 from 'crc-32';
function createPreparedStatement(db: DBType) {
return {
@@ -9,6 +10,14 @@ function createPreparedStatement(db: DBType) {
.delete(oneTimeLink)
.where(eq(oneTimeLink.id, sql.placeholder('id')))
.prepare(),
+ create: db
+ .insert(oneTimeLink)
+ .values({
+ clientId: sql.placeholder('id'),
+ oneTimeLink: sql.placeholder('oneTimeLink'),
+ expiresAt: sql.placeholder('expiresAt'),
+ })
+ .prepare(),
};
}
@@ -22,4 +31,12 @@ export class OneTimeLinkService {
delete(id: ID) {
return this.#statements.delete.execute({ id });
}
+
+ generate(id: ID) {
+ const key = `${id}-${Math.floor(Math.random() * 1000)}`;
+ const oneTimeLink = Math.abs(CRC32.str(key)).toString(16);
+ const expiresAt = new Date(Date.now() + 5 * 60 * 1000).toISOString();
+
+ return this.#statements.create.execute({ id, oneTimeLink, expiresAt });
+ }
}
diff --git a/src/server/database/repositories/oneTimeLink/types.ts b/src/server/database/repositories/oneTimeLink/types.ts
new file mode 100644
index 00000000..ea0ac729
--- /dev/null
+++ b/src/server/database/repositories/oneTimeLink/types.ts
@@ -0,0 +1,4 @@
+import type { InferSelectModel } from 'drizzle-orm';
+import type { oneTimeLink } from './schema';
+
+export type OneTimeLinkType = InferSelectModel;
diff --git a/src/server/database/repositories/user/types.ts b/src/server/database/repositories/user/types.ts
index 500d309d..2a1017e4 100644
--- a/src/server/database/repositories/user/types.ts
+++ b/src/server/database/repositories/user/types.ts
@@ -2,3 +2,41 @@ import type { InferSelectModel } from 'drizzle-orm';
import type { user } from './schema';
export type UserType = InferSelectModel;
+
+const username = zod
+ .string({ message: 'zod.user.username' })
+ .min(8, 'zod.user.usernameMin')
+ .pipe(safeStringRefine);
+
+const password = zod
+ .string({ message: 'zod.user.password' })
+ .min(12, 'zod.user.passwordMin')
+ .regex(/[A-Z]/, 'zod.user.passwordUppercase')
+ .regex(/[a-z]/, 'zod.user.passwordLowercase')
+ .regex(/\d/, 'zod.user.passwordNumber')
+ .regex(/[!@#$%^&*(),.?":{}|<>]/, 'zod.user.passwordSpecial')
+ .pipe(safeStringRefine);
+
+const remember = zod.boolean({ message: 'zod.user.remember' });
+
+export const UserLoginSchema = zod.object(
+ {
+ username: username,
+ password: password,
+ remember: remember,
+ },
+ { message: objectMessage }
+);
+
+const accept = zod.boolean().refine((val) => val === true, {
+ message: 'zod.user.accept',
+});
+
+export const UserSetupType = zod.object(
+ {
+ username: username,
+ password: password,
+ accept: accept,
+ },
+ { message: objectMessage }
+);
diff --git a/src/server/database/repositories/userConfig/types.ts b/src/server/database/repositories/userConfig/types.ts
index db253669..91a4721b 100644
--- a/src/server/database/repositories/userConfig/types.ts
+++ b/src/server/database/repositories/userConfig/types.ts
@@ -2,3 +2,18 @@ import type { InferSelectModel } from 'drizzle-orm';
import type { userConfig } from './schema';
export type UserConfigType = InferSelectModel;
+
+const host = zod
+ .string({ message: 'zod.userConfig.host' })
+ .min(1, 'zod.userConfig.hostMin')
+ .pipe(safeStringRefine);
+
+const port = zod
+ .number({ message: 'zod.userConfig.port' })
+ .min(1, 'zod.userConfig.portMin')
+ .max(65535, 'zod.userConfig.portMax');
+
+export const UserConfigSetupType = zod.object({
+ host: host,
+ port: port,
+});
diff --git a/src/server/middleware/auth.ts b/src/server/middleware/auth.ts
index 91410ea2..2f608d0f 100644
--- a/src/server/middleware/auth.ts
+++ b/src/server/middleware/auth.ts
@@ -1,5 +1,6 @@
export default defineEventHandler(async (event) => {
- /*const url = getRequestURL(event);
+ // TODO: improve, wrapper or smth
+ const url = getRequestURL(event);
const session = await useWGSession(event);
// Api handled by session, Setup handled with setup middleware
@@ -21,15 +22,15 @@ export default defineEventHandler(async (event) => {
}
if (url.pathname.startsWith('/admin')) {
- const user = await Database.user.findById(session.data.userId);
+ const user = await Database.users.get(session.data.userId);
if (!user) {
return sendRedirect(event, '/login', 302);
}
- if (user.role !== 'ADMIN') {
+ if (user.role !== roles.ADMIN) {
throw createError({
statusCode: 403,
statusMessage: 'Not allowed to access Admin Panel',
});
}
- }*/
+ }
});
diff --git a/src/server/utils/types.ts b/src/server/utils/types.ts
index 5d1b9910..b25a2e5c 100644
--- a/src/server/utils/types.ts
+++ b/src/server/utils/types.ts
@@ -1,10 +1,10 @@
-import type { ZodSchema, ZodTypeDef } from 'zod';
+import type { ZodSchema } from 'zod';
import z from 'zod';
import type { H3Event, EventHandlerRequest } from 'h3';
export { default as zod } from 'zod';
-const objectMessage = 'zod.body';
+export const objectMessage = 'zod.body';
export const safeStringRefine = z
.string()
@@ -13,210 +13,8 @@ export const safeStringRefine = z
{ message: 'zod.stringMalformed' }
);
-const host = z
- .string({ message: 'zod.host' })
- .min(1, 'zod.hostMin')
- .pipe(safeStringRefine);
-
-const port = z
- .number({ message: 'zod.port' })
- .min(1, 'zod.portMin')
- .max(65535, 'zod.portMax');
-
-export const hostPortType = z.object({
- host: host,
- port: port,
-});
-
-const id = z.string().uuid('zod.id').pipe(safeStringRefine);
-
-export const clientIdType = z.object(
- {
- clientId: id,
- },
- { message: objectMessage }
-);
-
-const oneTimeLink = z
- .string({ message: 'zod.otl' })
- .min(1, 'zod.otlMin')
- .pipe(safeStringRefine);
-
-export const oneTimeLinkType = z.object(
- {
- oneTimeLink: oneTimeLink,
- },
- { message: objectMessage }
-);
-
-const name = z
- .string({ message: 'zod.name' })
- .min(1, 'zod.nameMin')
- .pipe(safeStringRefine);
-
-const expireDate = z
- .string({ message: 'zod.expireDate' })
- .min(1, 'zod.expireDateMin')
- .pipe(safeStringRefine)
- .nullable();
-
-export const createType = z.object(
- {
- name: name,
- expireDate: expireDate,
- },
- { message: objectMessage }
-);
-
-const file = z.string({ message: 'zod.file' }).pipe(safeStringRefine);
-const file_ = z.instanceof(File, { message: 'zod.file' });
-
-export const fileType = z.object(
- {
- file: file,
- },
- { message: objectMessage }
-);
-export const fileType_ = z.object(
- {
- file: file_,
- },
- { message: objectMessage }
-);
-
-const username = z
- .string({ message: 'zod.username' })
- .min(8, 'zod.usernameMin')
- .pipe(safeStringRefine);
-
-const password = z
- .string({ message: 'zod.password' })
- .min(12, 'zod.passwordMin')
- .regex(/[A-Z]/, 'zod.passwordUppercase')
- .regex(/[a-z]/, 'zod.passwordLowercase')
- .regex(/\d/, 'zod.passwordNumber')
- .regex(/[!@#$%^&*(),.?":{}|<>]/, 'zod.passwordSpecial')
- .pipe(safeStringRefine);
-
-const remember = z.boolean({ message: 'zod.remember' });
-
-export const credentialsType = z.object(
- {
- username: username,
- password: password,
- remember: remember,
- },
- { message: objectMessage }
-);
-
-export const passwordType = z.object(
- {
- username: username,
- password: password,
- },
- { message: objectMessage }
-);
-
-const accept = z.boolean().refine((val) => val === true, {
- message: 'zod.accept',
-});
-
-export const passwordSetupType = z.object(
- {
- username: username,
- password: password,
- accept: accept,
- },
- { message: objectMessage }
-);
-
-const address = z
- .string({ message: 'zod.address' })
- .min(1, { message: 'zod.addressMin' })
- .pipe(safeStringRefine);
-
-const address4 = z
- .string({ message: 'zod.address4' })
- .min(1, { message: 'zod.address4Min' })
- .pipe(safeStringRefine);
-
-const address6 = z
- .string({ message: 'zod.address6' })
- .min(1, { message: 'zod.address6Min' })
- .pipe(safeStringRefine);
-
-const allowedIps = z
- .array(address, { message: 'zod.allowedIps' })
- .min(1, { message: 'zod.allowedIpsMin' });
-
-const mtu = z
- .number({ message: 'zod.mtu' })
- .min(1280, { message: 'zod.mtuMin' })
- .max(9000, { message: 'zod.mtuMax' });
-
-const persistentKeepalive = z
- .number({ message: 'zod.persistentKeepalive' })
- .min(0, 'zod.persistentKeepaliveMin')
- .max(65535, 'zod.persistentKeepaliveMax');
-
-export const clientUpdateType = z.object({
- name: name,
- enabled: z.boolean(),
- expiresAt: expireDate,
- address4: address4,
- address6: address6,
- allowedIps: allowedIps,
- serverAllowedIPs: z.array(address, { message: 'zod.serverAllowedIPs' }),
- mtu: mtu,
- persistentKeepalive: persistentKeepalive,
-});
-
-export const generalUpdateType = z.object({
- sessionTimeout: z.number({ message: 'zod.sessionTimeout' }),
-});
-
-const device = z
- .string({ message: 'zod.device' })
- .min(1, 'zod.deviceMin')
- .pipe(safeStringRefine);
-
-export const interfaceUpdateType = z.object({
- mtu: mtu,
- port: port,
- device: device,
-});
-
-export const userConfigUpdateType = z.object({
- host: host,
- port: port,
- allowedIps: allowedIps,
- defaultDns: z.array(address, { message: 'zod.dns' }),
- mtu: mtu,
- persistentKeepalive: persistentKeepalive,
-});
-
-const hook = z.string({ message: 'zod.hook' }).pipe(safeStringRefine);
-
-export const hooksUpdateType = z.object({
- PreUp: hook,
- PostUp: hook,
- PreDown: hook,
- PostDown: hook,
-});
-
-export const cidrUpdateType = z.object({
- address4: address,
- address6: address,
-});
-
-// from https://github.com/airjp73/rvf/blob/7e7c35d98015ea5ecff5affaf89f78296e84e8b9/packages/zod-form-data/src/helpers.ts#L117
-type FormDataLikeInput = {
- [Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>;
- entries(): IterableIterator<[string, FormDataEntryValue]>;
-};
-
export function validateZod(
- schema: ZodSchema | ZodSchema,
+ schema: ZodSchema,
event?: H3Event
) {
return async (data: unknown) => {
@@ -247,7 +45,3 @@ export function validateZod(
}
};
}
-
-export type DeepWriteable = {
- -readonly [P in keyof T]: DeepWriteable;
-};
diff --git a/src/server/utils/permissions.ts b/src/shared/utils/permissions.ts
similarity index 100%
rename from src/server/utils/permissions.ts
rename to src/shared/utils/permissions.ts