mirror of https://github.com/wg-easy/wg-easy
20 changed files with 227 additions and 199 deletions
@ -1,8 +1,11 @@ |
|||
import { ClientCreateSchema } from '#db/repositories/client/types'; |
|||
|
|||
export default defineEventHandler(async (event) => { |
|||
const { name, expireDate } = await readValidatedBody( |
|||
const { name, expiresAt } = await readValidatedBody( |
|||
event, |
|||
validateZod(createType) |
|||
validateZod(ClientCreateSchema) |
|||
); |
|||
await WireGuard.createClient({ name, expireDate }); |
|||
await Database.clients.create({ name, expiresAt }); |
|||
await WireGuard.saveConfig(); |
|||
return { success: true }; |
|||
}); |
|||
|
@ -0,0 +1,106 @@ |
|||
import type { DBType } from '#db/sqlite'; |
|||
import { eq, sql } from 'drizzle-orm'; |
|||
import { client } from './schema'; |
|||
import type { ClientCreateType } from './types'; |
|||
import { wgInterface, userConfig } from '../../schema'; |
|||
import { parseCidr } from 'cidr-tools'; |
|||
|
|||
function createPreparedStatement(db: DBType) { |
|||
return { |
|||
findAll: db.query.client |
|||
.findMany({ |
|||
with: { |
|||
oneTimeLink: true, |
|||
}, |
|||
}) |
|||
.prepare(), |
|||
findById: db.query.client |
|||
.findFirst({ where: eq(client.id, sql.placeholder('id')) }) |
|||
.prepare(), |
|||
}; |
|||
} |
|||
|
|||
export class ClientService { |
|||
#db: DBType; |
|||
#statements: ReturnType<typeof createPreparedStatement>; |
|||
|
|||
constructor(db: DBType) { |
|||
this.#db = db; |
|||
this.#statements = createPreparedStatement(db); |
|||
} |
|||
|
|||
async getAll() { |
|||
const result = await this.#statements.findAll.all(); |
|||
return result.map((row) => ({ |
|||
...row, |
|||
createdAt: new Date(row.createdAt), |
|||
updatedAt: new Date(row.updatedAt), |
|||
})); |
|||
} |
|||
|
|||
async get(id: number) { |
|||
return this.#statements.findById.all({ id }); |
|||
} |
|||
|
|||
async create({ name, expiresAt }: ClientCreateType) { |
|||
const privateKey = await wg.generatePrivateKey(); |
|||
const publicKey = await wg.getPublicKey(privateKey); |
|||
const preSharedKey = await wg.generatePreSharedKey(); |
|||
|
|||
let parsedExpiresAt = expiresAt; |
|||
if (parsedExpiresAt) { |
|||
const expiresAtDate = new Date(parsedExpiresAt); |
|||
expiresAtDate.setHours(23); |
|||
expiresAtDate.setMinutes(59); |
|||
expiresAtDate.setSeconds(59); |
|||
parsedExpiresAt = expiresAtDate.toISOString(); |
|||
} |
|||
|
|||
await this.#db.transaction(async (tx) => { |
|||
const clients = await tx.query.client.findMany().execute(); |
|||
const clientInterface = await tx.query.wgInterface |
|||
.findFirst({ |
|||
where: eq(wgInterface.name, 'wg0'), |
|||
}) |
|||
.execute(); |
|||
|
|||
if (!clientInterface) { |
|||
throw new Error('WireGuard interface not found'); |
|||
} |
|||
|
|||
const clientConfig = await tx.query.userConfig |
|||
.findFirst({ |
|||
where: eq(userConfig.id, clientInterface.name), |
|||
}) |
|||
.execute(); |
|||
|
|||
if (!clientConfig) { |
|||
throw new Error('WireGuard interface configuration not found'); |
|||
} |
|||
|
|||
const ipv4Cidr = parseCidr(clientInterface.ipv4Cidr); |
|||
const ipv4Address = nextIP(4, ipv4Cidr, clients); |
|||
const ipv6Cidr = parseCidr(clientInterface.ipv6Cidr); |
|||
const ipv6Address = nextIP(6, ipv6Cidr, clients); |
|||
|
|||
return await tx |
|||
.insert(client) |
|||
.values({ |
|||
name, |
|||
expiresAt: parsedExpiresAt, |
|||
privateKey, |
|||
publicKey, |
|||
preSharedKey, |
|||
ipv4Address, |
|||
ipv6Address, |
|||
mtu: clientConfig.defaultMtu, |
|||
allowedIps: clientConfig.defaultAllowedIps, |
|||
dns: clientConfig.defaultDns, |
|||
persistentKeepalive: clientConfig.defaultPersistentKeepalive, |
|||
serverAllowedIps: [], |
|||
enabled: true, |
|||
}) |
|||
.execute(); |
|||
}); |
|||
} |
|||
} |
@ -1,39 +0,0 @@ |
|||
import type { DBType } from '#db/sqlite'; |
|||
import { eq, sql } from 'drizzle-orm'; |
|||
import { clients } from './schema'; |
|||
|
|||
function createPreparedStatement(db: DBType) { |
|||
return { |
|||
findAll: db.query.clients |
|||
.findMany({ |
|||
with: { |
|||
oneTimeLink: true, |
|||
}, |
|||
}) |
|||
.prepare(), |
|||
findById: db.query.clients |
|||
.findFirst({ where: eq(clients.id, sql.placeholder('id')) }) |
|||
.prepare(), |
|||
}; |
|||
} |
|||
|
|||
export class ClientsService { |
|||
#statements: ReturnType<typeof createPreparedStatement>; |
|||
|
|||
constructor(db: DBType) { |
|||
this.#statements = createPreparedStatement(db); |
|||
} |
|||
|
|||
async findAll() { |
|||
const result = await this.#statements.findAll.all(); |
|||
return result.map((row) => ({ |
|||
...row, |
|||
createdAt: new Date(row.createdAt), |
|||
updatedAt: new Date(row.updatedAt), |
|||
})); |
|||
} |
|||
|
|||
async findById(id: number) { |
|||
return this.#statements.findById.all({ id }); |
|||
} |
|||
} |
@ -0,0 +1,4 @@ |
|||
import type { InferSelectModel } from 'drizzle-orm'; |
|||
import type { hooks } from './schema'; |
|||
|
|||
export type HooksType = InferSelectModel<typeof hooks>; |
@ -0,0 +1,4 @@ |
|||
import type { InferSelectModel } from 'drizzle-orm'; |
|||
import type { wgInterface } from './schema'; |
|||
|
|||
export type InterfaceType = InferSelectModel<typeof wgInterface>; |
@ -1,7 +1,7 @@ |
|||
import { sql } from 'drizzle-orm'; |
|||
import { int, sqliteTable, text } from 'drizzle-orm/sqlite-core'; |
|||
|
|||
export const users = sqliteTable('users_table', { |
|||
export const user = sqliteTable('users_table', { |
|||
id: int().primaryKey({ autoIncrement: true }), |
|||
username: text().notNull(), |
|||
password: text().notNull(), |
@ -0,0 +1,4 @@ |
|||
import type { InferSelectModel } from 'drizzle-orm'; |
|||
import type { userConfig } from './schema'; |
|||
|
|||
export type UserConfigType = InferSelectModel<typeof userConfig>; |
@ -1,9 +1,9 @@ |
|||
// Make sure to not use any Path Aliases in these files
|
|||
export * from './repositories/clients/schema'; |
|||
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/oneTimeLinks/schema'; |
|||
export * from './repositories/oneTimeLink/schema'; |
|||
export * from './repositories/userConfig/schema'; |
|||
export * from './repositories/users/schema'; |
|||
export * from './repositories/user/schema'; |
|||
|
Loading…
Reference in new issue