add preference db

This commit is contained in:
rubikscraft 2022-03-04 12:24:49 +01:00
parent f26c71c429
commit 9cbfdf92fb
No known key found for this signature in database
GPG key ID: 3570A2BB18A63D9F
9 changed files with 104 additions and 7 deletions

3
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"vsicons.presets.angular": true
}

View file

@ -1,14 +1,70 @@
import { Injectable } from '@nestjs/common';
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { validate } from 'class-validator';
import { SysPreferences } from 'picsur-shared/dist/dto/syspreferences.dto';
import { AsyncFailable, Fail } from 'picsur-shared/dist/types';
import { Repository } from 'typeorm';
import { SysPreferenceDefaults } from '../../models/dto/syspreference.dto';
import { ESysPreferenceBackend } from '../../models/entities/syspreference.entity';
@Injectable()
export class SysPreferenceService {
private readonly logger = new Logger('SysPreferenceService');
constructor(
@InjectRepository(ESysPreferenceBackend)
private usersRepository: Repository<ESysPreferenceBackend>,
private sysPreferenceRepository: Repository<ESysPreferenceBackend>,
) {}
public async setPreference(
key: SysPreferences,
value: string,
): AsyncFailable<ESysPreferenceBackend> {
let sysPreference = new ESysPreferenceBackend();
sysPreference.key = key;
sysPreference.value = value;
const errors = await validate(sysPreference);
if (errors.length > 0) {
this.logger.warn(errors);
return Fail('Invalid preference');
}
try {
sysPreference = await this.sysPreferenceRepository.save(sysPreference, {
reload: true,
});
} catch (e: any) {
this.logger.warn(e);
return Fail('Could not save preference');
}
return sysPreference;
}
public async getPreference(
key: SysPreferences,
): AsyncFailable<ESysPreferenceBackend> {
let sysPreference: ESysPreferenceBackend | undefined;
try {
sysPreference = await this.sysPreferenceRepository.findOne({
key,
});
} catch (e: any) {
this.logger.warn(e);
return Fail('Could not get preference');
}
if (!sysPreference) {
return this.saveDefault(key);
}
return sysPreference;
}
private async saveDefault(
key: SysPreferences,
): AsyncFailable<ESysPreferenceBackend> {
return this.setPreference(key, SysPreferenceDefaults[key]());
}
}

View file

@ -0,0 +1,12 @@
import { SysPreferences } from 'picsur-shared/dist/dto/syspreferences.dto';
import { generateRandomString } from 'picsur-shared/dist/util/random';
import Config from '../../env';
export const SysPreferenceDefaults: {
[key in SysPreferences]: () => string;
} = {
jwt_secret: () => {
if (Config.jwt.secret !== 'CHANGE_ME') return Config.jwt.secret;
return generateRandomString(32);
},
};

View file

@ -1,3 +1,4 @@
import { SysPreferences } from 'picsur-shared/dist/dto/syspreferences.dto';
import { ESysPreference } from 'picsur-shared/dist/entities/syspreference.entity';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@ -7,7 +8,7 @@ export class ESysPreferenceBackend extends ESysPreference {
override id?: number;
@Column()
override name: string;
override key: SysPreferences;
@Column()
override value: string;

View file

@ -1,4 +1,4 @@
const tuple = <T extends string[]>(...args: T): T => args;
import tuple from '../types/tuple';
// Config

View file

@ -0,0 +1,8 @@
import { generateRandomString } from '../util/random';
import tuple from '../types/tuple';
import { randomBytes } from 'crypto';
const SysPreferencesTuple = tuple('jwt_secret');
export const SysPreferences: string[] = SysPreferencesTuple;
export type SysPreferences = typeof SysPreferencesTuple[number];

View file

@ -1,11 +1,13 @@
import { IsNotEmpty, IsOptional } from 'class-validator';
import { IsEnum, IsNotEmpty, IsOptional } from 'class-validator';
import { SysPreferences } from '../dto/syspreferences.dto';
export class ESysPreference {
@IsOptional()
id?: number;
@IsNotEmpty()
name: string;
@IsEnum(SysPreferences)
key: SysPreferences;
@IsNotEmpty()
value: string;

View file

@ -0,0 +1,3 @@
const tuple = <T extends string[]>(...args: T): T => args;
export default tuple;

12
shared/src/util/random.ts Normal file
View file

@ -0,0 +1,12 @@
import crypto from 'crypto';
const randomCharacters =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
export function generateRandomString(length: number): string {
let out = '';
for (let i = 0; i < length; i++) {
out += randomCharacters[crypto.randomInt(0, randomCharacters.length - 1)];
}
return out;
}