mirror of
https://github.com/CaramelFur/Picsur.git
synced 2026-05-07 02:17:29 +02:00
add usrpreference entity, and refactor syspref
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { PrefValueType, PrefValueTypeStrings } from 'picsur-shared/dist/dto/preferences.dto';
|
||||
import {
|
||||
InternalSysprefRepresentation,
|
||||
SysPreference,
|
||||
SysPrefValueType,
|
||||
SysPrefValueTypeStrings
|
||||
InternalSysPrefRepresentation,
|
||||
SysPreference
|
||||
} from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import {
|
||||
AsyncFailable,
|
||||
@@ -33,8 +32,8 @@ export class SysPreferenceService {
|
||||
|
||||
public async setPreference(
|
||||
key: string,
|
||||
value: SysPrefValueType,
|
||||
): AsyncFailable<InternalSysprefRepresentation> {
|
||||
value: PrefValueType,
|
||||
): AsyncFailable<InternalSysPrefRepresentation> {
|
||||
// Validate
|
||||
let sysPreference = await this.validatePref(key, value);
|
||||
if (HasFailed(sysPreference)) return sysPreference;
|
||||
@@ -61,7 +60,7 @@ export class SysPreferenceService {
|
||||
|
||||
public async getPreference(
|
||||
key: string,
|
||||
): AsyncFailable<InternalSysprefRepresentation> {
|
||||
): AsyncFailable<InternalSysPrefRepresentation> {
|
||||
// Validate
|
||||
let validatedKey = this.validatePrefKey(key);
|
||||
if (HasFailed(validatedKey)) return validatedKey;
|
||||
@@ -108,8 +107,8 @@ export class SysPreferenceService {
|
||||
|
||||
private async getPreferencePinned(
|
||||
key: string,
|
||||
type: SysPrefValueTypeStrings,
|
||||
): AsyncFailable<SysPrefValueType> {
|
||||
type: PrefValueTypeStrings,
|
||||
): AsyncFailable<PrefValueType> {
|
||||
let pref = await this.getPreference(key);
|
||||
if (HasFailed(pref)) return pref;
|
||||
if (pref.type !== type) return Fail('Invalid preference type');
|
||||
@@ -118,7 +117,7 @@ export class SysPreferenceService {
|
||||
}
|
||||
|
||||
public async getAllPreferences(): AsyncFailable<
|
||||
InternalSysprefRepresentation[]
|
||||
InternalSysPrefRepresentation[]
|
||||
> {
|
||||
// TODO: We are fetching each value invidually, we should fetch all at once
|
||||
let internalSysPrefs = await Promise.all(
|
||||
@@ -128,21 +127,21 @@ export class SysPreferenceService {
|
||||
return Fail('Could not get all preferences');
|
||||
}
|
||||
|
||||
return internalSysPrefs as InternalSysprefRepresentation[];
|
||||
return internalSysPrefs as InternalSysPrefRepresentation[];
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
private async saveDefault(
|
||||
key: SysPreference, // Force enum here because we dont validate
|
||||
): AsyncFailable<InternalSysprefRepresentation> {
|
||||
): AsyncFailable<InternalSysPrefRepresentation> {
|
||||
return this.setPreference(key, this.defaultsService.defaults[key]());
|
||||
}
|
||||
|
||||
// This converts the raw string representation of the value to the correct type
|
||||
private retrieveConvertedValue(
|
||||
preference: ESysPreferenceBackend,
|
||||
): Failable<InternalSysprefRepresentation> {
|
||||
): Failable<InternalSysPrefRepresentation> {
|
||||
const key = this.validatePrefKey(preference.key);
|
||||
if (HasFailed(key)) return key;
|
||||
|
||||
@@ -173,7 +172,7 @@ export class SysPreferenceService {
|
||||
|
||||
private async validatePref(
|
||||
key: string,
|
||||
value: SysPrefValueType,
|
||||
value: PrefValueType,
|
||||
): AsyncFailable<ESysPreferenceBackend> {
|
||||
const validatedKey = this.validatePrefKey(key);
|
||||
if (HasFailed(validatedKey)) return validatedKey;
|
||||
@@ -204,7 +203,7 @@ export class SysPreferenceService {
|
||||
private validatePrefValue(
|
||||
// Key is required, because the type of the value depends on the key
|
||||
key: SysPreference,
|
||||
value: SysPrefValueType,
|
||||
value: PrefValueType,
|
||||
): Failable<string> {
|
||||
const expectedType = SysPreferenceValueTypes[key];
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { PrefValueType } from 'picsur-shared/dist/dto/preferences.dto';
|
||||
import {
|
||||
SysPreference,
|
||||
SysPrefValueType
|
||||
SysPreference
|
||||
} from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import { generateRandomString } from 'picsur-shared/dist/util/random';
|
||||
import { EarlyJwtConfigService } from '../../config/early/earlyjwt.config.service';
|
||||
@@ -16,7 +16,7 @@ export class SysPreferenceDefaultsService {
|
||||
constructor(private jwtConfigService: EarlyJwtConfigService) {}
|
||||
|
||||
public readonly defaults: {
|
||||
[key in SysPreference]: () => SysPrefValueType;
|
||||
[key in SysPreference]: () => PrefValueType;
|
||||
} = {
|
||||
[SysPreference.JwtSecret]: () => {
|
||||
const envSecret = this.jwtConfigService.getJwtSecret();
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import {
|
||||
SysPreference,
|
||||
SysPrefValueTypeStrings
|
||||
} from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import { PrefValueTypeStrings } from 'picsur-shared/dist/dto/preferences.dto';
|
||||
import { SysPreference } from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
|
||||
export type SysPreferences = SysPreference[];
|
||||
export const SysPreferenceList: string[] = Object.values(SysPreference);
|
||||
|
||||
// Syspref Value types
|
||||
export const SysPreferenceValueTypes: {
|
||||
[key in SysPreference]: SysPrefValueTypeStrings;
|
||||
[key in SysPreference]: PrefValueTypeStrings;
|
||||
} = {
|
||||
[SysPreference.JwtSecret]: 'string',
|
||||
[SysPreference.JwtExpiresIn]: 'string',
|
||||
|
||||
18
backend/src/models/entities/preference.entity.ts
Normal file
18
backend/src/models/entities/preference.entity.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { EUsrPreference } from 'picsur-shared/dist/entities/usrpreference';
|
||||
import { Column, Index, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
export class EUsrPreferenceBackend extends EUsrPreference {
|
||||
@PrimaryGeneratedColumn()
|
||||
override id?: number;
|
||||
|
||||
@Index()
|
||||
@Column({ nullable: false, unique: true })
|
||||
override key: string;
|
||||
|
||||
@Column({ nullable: false })
|
||||
override value: string;
|
||||
|
||||
@Index()
|
||||
@Column({ nullable: false })
|
||||
override userId: number;
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
GetSyspreferenceResponse,
|
||||
MultipleSysPreferencesResponse, UpdateSysPreferenceRequest,
|
||||
UpdateSysPreferenceResponse
|
||||
} from 'picsur-shared/dist/dto/api/pref.dto';
|
||||
} from 'picsur-shared/dist/dto/api/syspref.dto';
|
||||
import { HasFailed } from 'picsur-shared/dist/types';
|
||||
import { SysPreferenceService } from '../../../collections/syspreferencesdb/syspreferencedb.service';
|
||||
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { SysPreferenceBaseResponse } from 'picsur-shared/dist/dto/api/pref.dto';
|
||||
import { SysPreferenceBaseResponse } from 'picsur-shared/dist/dto/api/syspref.dto';
|
||||
import { Observable } from 'rxjs';
|
||||
import { SysprefService as SysPrefService } from 'src/app/services/api/syspref.service';
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
|
||||
import { SysPreferenceBaseResponse } from 'picsur-shared/dist/dto/api/pref.dto';
|
||||
import {
|
||||
SysPreference,
|
||||
SysPrefValueType
|
||||
} from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import { SysPreferenceBaseResponse } from 'picsur-shared/dist/dto/api/syspref.dto';
|
||||
import { PrefValueType } from 'picsur-shared/dist/dto/preferences.dto';
|
||||
import { SysPreference } from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import { HasFailed } from 'picsur-shared/dist/types';
|
||||
import { Subject, throttleTime } from 'rxjs';
|
||||
import { SysPreferenceFriendlyNames } from 'src/app/i18n/syspref.i18n';
|
||||
@@ -20,7 +18,7 @@ import { UtilService } from 'src/app/util/util.service';
|
||||
export class SettingsSysprefOptionComponent implements OnInit {
|
||||
@Input() pref: SysPreferenceBaseResponse;
|
||||
|
||||
private updateSubject = new Subject<SysPrefValueType>();
|
||||
private updateSubject = new Subject<PrefValueType>();
|
||||
|
||||
constructor(
|
||||
private sysprefService: SysprefService,
|
||||
@@ -71,7 +69,7 @@ export class SettingsSysprefOptionComponent implements OnInit {
|
||||
this.update((e.target as HTMLInputElement).valueAsNumber);
|
||||
}
|
||||
|
||||
private async updatePreference(value: SysPrefValueType) {
|
||||
private async updatePreference(value: PrefValueType) {
|
||||
const result = await this.sysprefService.setPreference(
|
||||
this.pref.key,
|
||||
value
|
||||
|
||||
@@ -28,11 +28,12 @@ export class InfoService {
|
||||
private infoSubject = new BehaviorSubject<ServerInfo>(new ServerInfo());
|
||||
|
||||
constructor(private api: ApiService, private utilService: UtilService) {
|
||||
this.pollInfo()
|
||||
.then(() => {
|
||||
this.checkCompatibility();
|
||||
})
|
||||
.catch(this.logger.error);
|
||||
this.init().catch(this.logger.error);
|
||||
}
|
||||
|
||||
private async init() {
|
||||
await this.pollInfo();
|
||||
this.checkCompatibility();
|
||||
}
|
||||
|
||||
public async pollInfo(): AsyncFailable<ServerInfo> {
|
||||
|
||||
@@ -6,9 +6,9 @@ import {
|
||||
SysPreferenceBaseResponse,
|
||||
UpdateSysPreferenceRequest,
|
||||
UpdateSysPreferenceResponse
|
||||
} from 'picsur-shared/dist/dto/api/pref.dto';
|
||||
} from 'picsur-shared/dist/dto/api/syspref.dto';
|
||||
import { Permission } from 'picsur-shared/dist/dto/permissions.dto';
|
||||
import { SysPrefValueType } from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import { PrefValueType } from 'picsur-shared/dist/dto/preferences.dto';
|
||||
import { AsyncFailable, Fail, HasFailed, Map } from 'picsur-shared/dist/types';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { SnackBarType } from 'src/app/models/dto/snack-bar-type.dto';
|
||||
@@ -67,7 +67,7 @@ export class SysprefService {
|
||||
);
|
||||
|
||||
return Map(response, (pref) => {
|
||||
this.sysprefObservable.next(pref.preferences)
|
||||
this.sysprefObservable.next(pref.preferences);
|
||||
return pref.preferences;
|
||||
});
|
||||
}
|
||||
@@ -89,7 +89,7 @@ export class SysprefService {
|
||||
|
||||
public async setPreference(
|
||||
key: string,
|
||||
value: SysPrefValueType
|
||||
value: PrefValueType
|
||||
): AsyncFailable<UpdateSysPreferenceResponse> {
|
||||
if (!this.hasPermission)
|
||||
return Fail('You do not have permission to edit system preferences');
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
} from 'class-validator';
|
||||
import { IsPosInt } from '../../validators/positive-int.validator';
|
||||
import { IsSysPrefValue } from '../../validators/syspref.validator';
|
||||
import { SysPrefValueType, SysPrefValueTypes, SysPrefValueTypeStrings } from '../syspreferences.dto';
|
||||
import { PrefValueType, PrefValueTypes, PrefValueTypeStrings } from '../preferences.dto';
|
||||
|
||||
export class SysPreferenceBaseResponse {
|
||||
@IsNotEmpty()
|
||||
@@ -13,11 +13,11 @@ export class SysPreferenceBaseResponse {
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsSysPrefValue()
|
||||
value: SysPrefValueType;
|
||||
value: PrefValueType;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsEnum(SysPrefValueTypes)
|
||||
type: SysPrefValueTypeStrings;
|
||||
@IsEnum(PrefValueTypes)
|
||||
type: PrefValueTypeStrings;
|
||||
}
|
||||
|
||||
// Get Syspreference
|
||||
@@ -40,7 +40,7 @@ export class MultipleSysPreferencesResponse {
|
||||
export class UpdateSysPreferenceRequest {
|
||||
@IsNotEmpty()
|
||||
@IsSysPrefValue()
|
||||
value: SysPrefValueType;
|
||||
value: PrefValueType;
|
||||
}
|
||||
export class UpdateSysPreferenceResponse extends SysPreferenceBaseResponse {}
|
||||
|
||||
4
shared/src/dto/preferences.dto.ts
Normal file
4
shared/src/dto/preferences.dto.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
// Variable value type
|
||||
export type PrefValueType = string | number | boolean;
|
||||
export type PrefValueTypeStrings = 'string' | 'number' | 'boolean';
|
||||
export const PrefValueTypes = ['string', 'number', 'boolean'];
|
||||
@@ -1,3 +1,5 @@
|
||||
import { PrefValueType, PrefValueTypeStrings } from './preferences.dto';
|
||||
|
||||
// This enum is only here to make accessing the values easier, and type checking in the backend
|
||||
export enum SysPreference {
|
||||
JwtSecret = 'jwt_secret',
|
||||
@@ -8,14 +10,9 @@ export enum SysPreference {
|
||||
TestBoolean = 'test_boolean',
|
||||
}
|
||||
|
||||
// Variable value type
|
||||
export type SysPrefValueType = string | number | boolean;
|
||||
export type SysPrefValueTypeStrings = 'string' | 'number' | 'boolean';
|
||||
export const SysPrefValueTypes = ['string', 'number', 'boolean'];
|
||||
|
||||
// Interfaces
|
||||
export interface InternalSysprefRepresentation {
|
||||
export interface InternalSysPrefRepresentation {
|
||||
key: string;
|
||||
value: SysPrefValueType;
|
||||
type: SysPrefValueTypeStrings;
|
||||
value: PrefValueType;
|
||||
type: PrefValueTypeStrings;
|
||||
}
|
||||
|
||||
19
shared/src/dto/usrpreferences.dto.ts
Normal file
19
shared/src/dto/usrpreferences.dto.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { PrefValueType, PrefValueTypeStrings } from './preferences.dto';
|
||||
|
||||
// This enum is only here to make accessing the values easier, and type checking in the backend
|
||||
export enum UsrPreference {
|
||||
JwtSecret = 'jwt_secret',
|
||||
JwtExpiresIn = 'jwt_expires_in',
|
||||
BCryptStrength = 'bcrypt_strength',
|
||||
TestString = 'test_string',
|
||||
TestNumber = 'test_number',
|
||||
TestBoolean = 'test_boolean',
|
||||
}
|
||||
|
||||
// Interfaces
|
||||
export interface InternalUsrPrefRepresentation {
|
||||
key: string;
|
||||
value: PrefValueType;
|
||||
type: PrefValueTypeStrings;
|
||||
user: number;
|
||||
}
|
||||
20
shared/src/entities/usrpreference.ts
Normal file
20
shared/src/entities/usrpreference.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { IsDefined, IsNotEmpty, IsString } from 'class-validator';
|
||||
import { EntityID } from '../validators/entity-id.validator';
|
||||
import { IsPosInt } from '../validators/positive-int.validator';
|
||||
|
||||
export class EUsrPreference {
|
||||
@EntityID()
|
||||
id?: number;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
key: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
value: string;
|
||||
|
||||
@IsDefined()
|
||||
@IsPosInt()
|
||||
userId: number;
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { registerDecorator, ValidationArguments, ValidationOptions } from 'class-validator';
|
||||
import { SysPrefValueTypes } from '../dto/syspreferences.dto';
|
||||
import { PrefValueTypes } from '../dto/preferences.dto';
|
||||
|
||||
export function isSysPrefValue(value: any, args: ValidationArguments) {
|
||||
const type = typeof value;
|
||||
return SysPrefValueTypes.includes(type);
|
||||
return PrefValueTypes.includes(type);
|
||||
}
|
||||
|
||||
export function IsSysPrefValue(validationOptions?: ValidationOptions) {
|
||||
|
||||
Reference in New Issue
Block a user