Browse Source

fix: review

pull/1330/head
tetuaoro 2 years ago
parent
commit
044f1a6e45
  1. 12
      src/localeDetector.ts
  2. 2
      src/server/api/account/new.post.ts
  3. 2
      src/server/api/lang.get.ts
  4. 13
      src/server/api/session.post.ts
  5. 9
      src/server/middleware/session.ts
  6. 6
      src/server/utils/session.ts
  7. 21
      src/services/database/inmemory.ts
  8. 6
      src/services/database/repositories/database.ts
  9. 0
      src/services/database/repositories/system/model.ts
  10. 6
      src/services/database/repositories/system/repository.ts
  11. 3
      src/services/database/repositories/types.ts
  12. 0
      src/services/database/repositories/user/model.ts
  13. 6
      src/services/database/repositories/user/repository.ts.ts

12
src/localeDetector.ts

@ -1,24 +1,18 @@
// https://i18n.nuxtjs.org/docs/guide/server-side-translations
// Detect based on query, cookie, header
export default defineI18nLocaleDetector((event, config) => { export default defineI18nLocaleDetector((event, config) => {
// try to get locale from query const query = tryQueryLocale(event, { lang: '' });
const query = tryQueryLocale(event, { lang: '' }); // disable locale default value with `lang` option
if (query) { if (query) {
return query.toString(); return query.toString();
} }
// try to get locale from cookie const cookie = tryCookieLocale(event, { lang: '', name: 'i18n_locale' });
const cookie = tryCookieLocale(event, { lang: '', name: 'i18n_locale' }); // disable locale default value with `lang` option
if (cookie) { if (cookie) {
return cookie.toString(); return cookie.toString();
} }
// try to get locale from header (`accept-header`) const header = tryHeaderLocale(event, { lang: '' });
const header = tryHeaderLocale(event, { lang: '' }); // disable locale default value with `lang` option
if (header) { if (header) {
return header.toString(); return header.toString();
} }
// If the locale cannot be resolved up to this point, it is resolved with the value `defaultLocale` of the locale config passed to the function
return config.defaultLocale; return config.defaultLocale;
}); });

2
src/server/api/account/new.post.ts

@ -1,4 +1,4 @@
import { DatabaseError } from '~/repositories/database'; import { DatabaseError } from '~/services/database/repositories/database';
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
setHeader(event, 'Content-Type', 'application/json'); setHeader(event, 'Content-Type', 'application/json');

2
src/server/api/lang.get.ts

@ -1,4 +1,4 @@
export default defineEventHandler(async (event) => { export default defineEventHandler((event) => {
setHeader(event, 'Content-Type', 'application/json'); setHeader(event, 'Content-Type', 'application/json');
return Database.getLang(); return Database.getLang();
}); });

13
src/server/api/session.post.ts

@ -24,16 +24,23 @@ export default defineEventHandler(async (event) => {
// TODO: timing againts timing attack // TODO: timing againts timing attack
const conf: SessionConfig = SESSION_CONFIG; const system = await Database.getSystem();
if (!system)
throw createError({
statusCode: 500,
statusMessage: 'Invalid',
});
const conf: SessionConfig = system.sessionConfig;
if (MAX_AGE && remember) { if (MAX_AGE && remember) {
conf.cookie = { conf.cookie = {
...(SESSION_CONFIG.cookie ?? {}), ...(system.sessionConfig.cookie ?? {}),
maxAge: MAX_AGE, maxAge: MAX_AGE,
}; };
} }
const session = await useSession(event, { const session = await useSession(event, {
...SESSION_CONFIG, ...system.sessionConfig,
}); });
const data = await session.update({ const data = await session.update({

9
src/server/middleware/session.ts

@ -11,7 +11,14 @@ export default defineEventHandler(async (event) => {
) { ) {
return; return;
} }
const session = await getSession(event, SESSION_CONFIG); const system = await Database.getSystem();
if (!system)
throw createError({
statusCode: 500,
statusMessage: 'Invalid',
});
const session = await getSession(event, system.sessionConfig);
if (session.id && session.data.authenticated) { if (session.id && session.data.authenticated) {
return; return;
} }

6
src/server/utils/session.ts

@ -4,6 +4,8 @@ export type WGSession = {
authenticated: boolean; authenticated: boolean;
}; };
export function useWGSession(event: H3Event) { export async function useWGSession(event: H3Event) {
return useSession<Partial<WGSession>>(event, SESSION_CONFIG); const system = await Database.getSystem();
if (!system) throw new Error('Invalid');
return useSession<Partial<WGSession>>(event, system.sessionConfig);
} }

21
src/services/database/inmemory.ts

@ -2,26 +2,25 @@ import debug from 'debug';
import packageJson from '@/package.json'; import packageJson from '@/package.json';
import crypto from 'node:crypto'; import crypto from 'node:crypto';
import DatabaseProvider, { DatabaseError } from '~/repositories/database'; import DatabaseProvider, { DatabaseError } from './repositories/database';
import { ChartType, Lang } from '~/repositories/types'; import { ChartType, Lang } from './repositories/types';
import type { SessionConfig } from 'h3'; import type { ID } from './repositories/types';
import type { ID } from '~/repositories/types'; import type { System } from './repositories/system/model';
import type { System } from '~/repositories/system/model'; import type { User } from './repositories/user/model';
import type { User } from '~/repositories/user/model';
import { hashPassword, isPasswordStrong } from '~/server/utils/password'; import { hashPassword, isPasswordStrong } from '~/server/utils/password';
const DEBUG = debug('InMemoryDB'); const DEBUG = debug('InMemoryDB');
// Represent in-memory data structure // Represent in-memory data structure
type InMemoryData = { type InMemoryData = {
system?: System; system: System | null;
users: Array<User>; users: User[];
}; };
// In-Memory Database Provider // In-Memory Database Provider
export default class InMemory extends DatabaseProvider { export default class InMemory extends DatabaseProvider {
protected data: InMemoryData = { users: [] }; protected data: InMemoryData = { system: null, users: [] };
async connect() { async connect() {
DEBUG('Connection...'); DEBUG('Connection...');
@ -69,7 +68,7 @@ export default class InMemory extends DatabaseProvider {
password: '', password: '',
name: 'wg-easy', name: 'wg-easy',
cookie: undefined, cookie: undefined,
} satisfies SessionConfig, },
}; };
this.data.system = system; this.data.system = system;
@ -77,7 +76,7 @@ export default class InMemory extends DatabaseProvider {
} }
async disconnect() { async disconnect() {
this.data = { users: [] }; this.data = { system: null, users: [] };
} }
async getSystem() { async getSystem() {

6
src/repositories/database.ts → src/services/database/repositories/database.ts

@ -1,6 +1,6 @@
import type SystemRepository from './system/repository'; import type SystemRepository from './system/repository';
import type UserRepository from './user/repository.ts'; import type UserRepository from './user/repository.ts';
import type { Undefined, Lang, ID } from './types'; import type { Lang, ID } from './types';
import type { User } from './user/model'; import type { User } from './user/model';
import type { System } from './system/model'; import type { System } from './system/model';
@ -24,11 +24,11 @@ export default abstract class DatabaseProvider
*/ */
abstract disconnect(): Promise<void>; abstract disconnect(): Promise<void>;
abstract getSystem(): Promise<System | Undefined>; abstract getSystem(): Promise<System | null>;
abstract getLang(): Promise<Lang>; abstract getLang(): Promise<Lang>;
abstract getUsers(): Promise<Array<User>>; abstract getUsers(): Promise<Array<User>>;
abstract getUser(id: ID): Promise<User | Undefined>; abstract getUser(id: ID): Promise<User | undefined>;
abstract newUserWithPassword( abstract newUserWithPassword(
username: string, username: string,
password: string password: string

0
src/repositories/system/model.ts → src/services/database/repositories/system/model.ts

6
src/repositories/system/repository.ts → src/services/database/repositories/system/repository.ts

@ -1,4 +1,4 @@
import type { Lang, Undefined } from '../types'; import type { Lang } from '../types';
import type { System } from './model'; import type { System } from './model';
/** /**
@ -9,10 +9,10 @@ import type { System } from './model';
export default interface SystemRepository { export default interface SystemRepository {
/** /**
* Retrieves the system configuration data from the database. * Retrieves the system configuration data from the database.
* @returns {Promise<System | Undefined>} A promise that resolves to the system data * @returns {Promise<System | null>} A promise that resolves to the system data
* if found, or `undefined` if the system data is not available. * if found, or `undefined` if the system data is not available.
*/ */
getSystem(): Promise<System | Undefined>; getSystem(): Promise<System | null>;
/** /**
* Retrieves the system's language setting. * Retrieves the system's language setting.

3
src/repositories/types.ts → src/services/database/repositories/types.ts

@ -1,6 +1,5 @@
import type * as crypto from 'node:crypto'; import type * as crypto from 'node:crypto';
export type Undefined = null | undefined | 0 | '';
export enum Lang { export enum Lang {
/* english */ /* english */
EN = 'en', EN = 'en',
@ -46,5 +45,5 @@ export type TrafficStats = {
}; };
export type Prometheus = { export type Prometheus = {
enabled: boolean; enabled: boolean;
password?: HashPassword | Undefined; password: HashPassword | null;
}; };

0
src/repositories/user/model.ts → src/services/database/repositories/user/model.ts

6
src/repositories/user/repository.ts.ts → src/services/database/repositories/user/repository.ts.ts

@ -1,4 +1,4 @@
import type { ID, Undefined } from '../types'; import type { ID } from '../types';
import type { User } from './model'; import type { User } from './model';
/** /**
@ -15,10 +15,10 @@ export default interface UserRepository {
/** /**
* Retrieves a user by their ID or User object from the database. * Retrieves a user by their ID or User object from the database.
* @param {ID} id - The ID of the user or a User object. * @param {ID} id - The ID of the user or a User object.
* @returns {Promise<User | Undefined>} A promise that resolves to the user data * @returns {Promise<User | undefined>} A promise that resolves to the user data
* if found, or `undefined` if the user is not available. * if found, or `undefined` if the user is not available.
*/ */
getUser(id: ID): Promise<User | Undefined>; getUser(id: ID): Promise<User | undefined>;
newUserWithPassword(username: string, password: string): Promise<void>; newUserWithPassword(username: string, password: string): Promise<void>;
Loading…
Cancel
Save