mvoe syspref to backend
This commit is contained in:
parent
2c150c3027
commit
ac98db10df
|
@ -3,8 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||
import { plainToClass } from 'class-transformer';
|
||||
import {
|
||||
InternalSysprefRepresentation,
|
||||
SysPreferences,
|
||||
SysPreferenceValueTypes,
|
||||
SysPreference,
|
||||
SysPrefValueType
|
||||
} from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import {
|
||||
|
@ -15,6 +14,10 @@ import {
|
|||
} from 'picsur-shared/dist/types';
|
||||
import { strictValidate } from 'picsur-shared/dist/util/validate';
|
||||
import { Repository } from 'typeorm';
|
||||
import {
|
||||
SysPreferenceList,
|
||||
SysPreferenceValueTypes
|
||||
} from '../../models/dto/syspreferences.dto';
|
||||
import { ESysPreferenceBackend } from '../../models/entities/syspreference.entity';
|
||||
import { SysPreferenceDefaultsService } from './syspreferencedefaults.service';
|
||||
|
||||
|
@ -29,7 +32,7 @@ export class SysPreferenceService {
|
|||
) {}
|
||||
|
||||
public async setPreference(
|
||||
key: SysPreferences,
|
||||
key: string,
|
||||
value: SysPrefValueType,
|
||||
): AsyncFailable<InternalSysprefRepresentation> {
|
||||
// Validate
|
||||
|
@ -50,12 +53,13 @@ export class SysPreferenceService {
|
|||
return {
|
||||
key: sysPreference.key,
|
||||
value,
|
||||
type: SysPreferenceValueTypes[key],
|
||||
// key has to be valid here, we validated it
|
||||
type: SysPreferenceValueTypes[key as SysPreference],
|
||||
};
|
||||
}
|
||||
|
||||
public async getPreference(
|
||||
key: SysPreferences,
|
||||
key: string,
|
||||
): AsyncFailable<InternalSysprefRepresentation> {
|
||||
// Validate
|
||||
let validatedKey = this.validatePrefKey(key);
|
||||
|
@ -92,7 +96,7 @@ export class SysPreferenceService {
|
|||
return this.retrieveConvertedValue(foundSysPreference);
|
||||
}
|
||||
|
||||
public async getStringPreference(key: SysPreferences): AsyncFailable<string> {
|
||||
public async getStringPreference(key: string): AsyncFailable<string> {
|
||||
const pref = await this.getPreference(key);
|
||||
if (HasFailed(pref)) return pref;
|
||||
if (pref.type !== 'string') return Fail('Invalid preference type');
|
||||
|
@ -100,7 +104,7 @@ export class SysPreferenceService {
|
|||
return pref.value as string;
|
||||
}
|
||||
|
||||
public async getNumberPreference(key: SysPreferences): AsyncFailable<number> {
|
||||
public async getNumberPreference(key: string): AsyncFailable<number> {
|
||||
const pref = await this.getPreference(key);
|
||||
if (HasFailed(pref)) return pref;
|
||||
if (pref.type !== 'number') return Fail('Invalid preference type');
|
||||
|
@ -108,9 +112,7 @@ export class SysPreferenceService {
|
|||
return pref.value as number;
|
||||
}
|
||||
|
||||
public async getBooleanPreference(
|
||||
key: SysPreferences,
|
||||
): AsyncFailable<boolean> {
|
||||
public async getBooleanPreference(key: string): AsyncFailable<boolean> {
|
||||
const pref = await this.getPreference(key);
|
||||
if (HasFailed(pref)) return pref;
|
||||
if (pref.type !== 'boolean') return Fail('Invalid preference type');
|
||||
|
@ -122,7 +124,7 @@ export class SysPreferenceService {
|
|||
InternalSysprefRepresentation[]
|
||||
> {
|
||||
let internalSysPrefs = await Promise.all(
|
||||
SysPreferences.map((key) => this.getPreference(key as SysPreferences)),
|
||||
SysPreferenceList.map((key) => this.getPreference(key)),
|
||||
);
|
||||
if (internalSysPrefs.some((pref) => HasFailed(pref))) {
|
||||
return Fail('Could not get all preferences');
|
||||
|
@ -133,7 +135,7 @@ export class SysPreferenceService {
|
|||
// Private
|
||||
|
||||
private async saveDefault(
|
||||
key: SysPreferences,
|
||||
key: SysPreference, // Force enum here because we dont validate
|
||||
): AsyncFailable<InternalSysprefRepresentation> {
|
||||
return this.setPreference(key, this.defaultsService.defaults[key]());
|
||||
}
|
||||
|
@ -141,7 +143,10 @@ export class SysPreferenceService {
|
|||
private retrieveConvertedValue(
|
||||
preference: ESysPreferenceBackend,
|
||||
): Failable<InternalSysprefRepresentation> {
|
||||
const type = SysPreferenceValueTypes[preference.key];
|
||||
const key = this.validatePrefKey(preference.key);
|
||||
if (HasFailed(key)) return key;
|
||||
|
||||
const type = SysPreferenceValueTypes[key];
|
||||
switch (type) {
|
||||
case 'string':
|
||||
return {
|
||||
|
@ -190,16 +195,16 @@ export class SysPreferenceService {
|
|||
return verifySysPreference;
|
||||
}
|
||||
|
||||
private validatePrefKey(key: string): Failable<SysPreferences> {
|
||||
if (!SysPreferences.includes(key)) {
|
||||
private validatePrefKey(key: string): Failable<SysPreference> {
|
||||
if (!SysPreferenceList.includes(key)) {
|
||||
return Fail('Invalid preference key');
|
||||
}
|
||||
|
||||
return key as SysPreferences;
|
||||
return key as SysPreference;
|
||||
}
|
||||
|
||||
private validatePrefValue(
|
||||
key: SysPreferences,
|
||||
key: SysPreference,
|
||||
value: SysPrefValueType,
|
||||
): Failable<string> {
|
||||
const expectedType = SysPreferenceValueTypes[key];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import {
|
||||
SysPreferences,
|
||||
SysPreference,
|
||||
SysPrefValueType
|
||||
} from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import { generateRandomString } from 'picsur-shared/dist/util/random';
|
||||
|
@ -13,9 +13,9 @@ export class SysPreferenceDefaultsService {
|
|||
constructor(private jwtConfigService: EnvJwtConfigService) {}
|
||||
|
||||
public readonly defaults: {
|
||||
[key in SysPreferences]: () => SysPrefValueType;
|
||||
[key in SysPreference]: () => SysPrefValueType;
|
||||
} = {
|
||||
jwt_secret: () => {
|
||||
[SysPreference.JwtSecret]: () => {
|
||||
const envSecret = this.jwtConfigService.getJwtSecret();
|
||||
if (envSecret) {
|
||||
return envSecret;
|
||||
|
@ -26,10 +26,10 @@ export class SysPreferenceDefaultsService {
|
|||
return generateRandomString(64);
|
||||
}
|
||||
},
|
||||
jwt_expires_in: () => this.jwtConfigService.getJwtExpiresIn() ?? '7d',
|
||||
[SysPreference.JwtExpiresIn]: () => this.jwtConfigService.getJwtExpiresIn() ?? '7d',
|
||||
|
||||
test_string: () => 'test_string',
|
||||
test_number: () => 123,
|
||||
test_boolean: () => true,
|
||||
[SysPreference.TestString]: () => 'test_string',
|
||||
[SysPreference.TestNumber]: () => 123,
|
||||
[SysPreference.TestBoolean]: () => true,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,5 +6,4 @@ export { Permission } from 'picsur-shared/dist/dto/permissions.dto';
|
|||
// Derivatives
|
||||
|
||||
export const PermissionsList: Permission[] = Object.values(Permission);
|
||||
|
||||
export type Permissions = Permission[];
|
||||
|
|
19
backend/src/models/dto/syspreferences.dto.ts
Normal file
19
backend/src/models/dto/syspreferences.dto.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import {
|
||||
SysPreference,
|
||||
SysPrefValueTypeStrings
|
||||
} from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
|
||||
export type SysPreferences = SysPreference[];
|
||||
export const SysPreferenceList: string[] = Object.values(SysPreference);
|
||||
|
||||
// Syspref Values
|
||||
|
||||
export const SysPreferenceValueTypes: {
|
||||
[key in SysPreference]: SysPrefValueTypeStrings;
|
||||
} = {
|
||||
[SysPreference.JwtSecret]: 'string',
|
||||
[SysPreference.JwtExpiresIn]: 'string',
|
||||
[SysPreference.TestString]: 'string',
|
||||
[SysPreference.TestNumber]: 'number',
|
||||
[SysPreference.TestBoolean]: 'boolean',
|
||||
};
|
|
@ -1,4 +1,3 @@
|
|||
import { SysPreferences } from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import { ESysPreference } from 'picsur-shared/dist/entities/syspreference.entity';
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
|
@ -8,7 +7,7 @@ export class ESysPreferenceBackend extends ESysPreference {
|
|||
override id?: number;
|
||||
|
||||
@Column({ nullable: false, unique: true })
|
||||
override key: SysPreferences;
|
||||
override key: string;
|
||||
|
||||
@Column({ nullable: false })
|
||||
override value: string;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { Controller, Get } from '@nestjs/common';
|
||||
import { plainToClass } from 'class-transformer';
|
||||
import { InfoResponse } from 'picsur-shared/dist/dto/api/info.dto';
|
||||
import { AllPermissionsResponse } from 'picsur-shared/dist/dto/api/roles.dto';
|
||||
import { AllPermissionsResponse, InfoResponse } from 'picsur-shared/dist/dto/api/info.dto';
|
||||
import { HostConfigService } from '../../../config/host.config.service';
|
||||
import { NoPermissions } from '../../../decorators/permissions.decorator';
|
||||
import { PermissionsList } from '../../../models/dto/permissions.dto';
|
||||
|
|
|
@ -15,7 +15,6 @@ import {
|
|||
UpdateSysPreferenceRequest,
|
||||
UpdateSysPreferenceResponse
|
||||
} from 'picsur-shared/dist/dto/api/pref.dto';
|
||||
import { SysPreferences } from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import { HasFailed } from 'picsur-shared/dist/types';
|
||||
import { SysPreferenceService } from '../../../collections/syspreferencesdb/syspreferencedb.service';
|
||||
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
|
||||
|
@ -50,7 +49,7 @@ export class PrefController {
|
|||
async getSysPref(
|
||||
@Param('key') key: string,
|
||||
): Promise<GetSyspreferenceResponse> {
|
||||
const pref = await this.prefService.getPreference(key as SysPreferences);
|
||||
const pref = await this.prefService.getPreference(key);
|
||||
if (HasFailed(pref)) {
|
||||
this.logger.warn(pref.getReason());
|
||||
throw new InternalServerErrorException('Could not get preference');
|
||||
|
@ -66,20 +65,18 @@ export class PrefController {
|
|||
): Promise<UpdateSysPreferenceResponse> {
|
||||
const value = body.value;
|
||||
|
||||
const pref = await this.prefService.setPreference(
|
||||
key as SysPreferences,
|
||||
value,
|
||||
);
|
||||
const pref = await this.prefService.setPreference(key, value);
|
||||
if (HasFailed(pref)) {
|
||||
this.logger.warn(pref.getReason());
|
||||
throw new InternalServerErrorException('Could not set preference');
|
||||
}
|
||||
|
||||
const returned = new UpdateSysPreferenceResponse();
|
||||
returned.key = key as SysPreferences;
|
||||
returned.value = pref.value;
|
||||
returned.type = pref.type;
|
||||
const returned = {
|
||||
key,
|
||||
value: pref.value,
|
||||
type: pref.type,
|
||||
};
|
||||
|
||||
return returned;
|
||||
return plainToClass(UpdateSysPreferenceResponse, returned);
|
||||
}
|
||||
}
|
||||
|
|
11
frontend/src/app/i18n/syspref.i18n.ts
Normal file
11
frontend/src/app/i18n/syspref.i18n.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { SysPreference } from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
|
||||
export const SysPreferenceFriendlyNames: {
|
||||
[key in SysPreference]: string;
|
||||
} = {
|
||||
[SysPreference.JwtSecret]: 'JWT Secret',
|
||||
[SysPreference.JwtExpiresIn]: 'JWT Expiry Time',
|
||||
[SysPreference.TestString]: 'Test String',
|
||||
[SysPreference.TestNumber]: 'Test Number',
|
||||
[SysPreference.TestBoolean]: 'Test Boolean',
|
||||
};
|
|
@ -1,12 +1,10 @@
|
|||
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 {
|
||||
SysPreferenceFriendlyNames,
|
||||
SysPrefValueType
|
||||
} from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import { SysPreference, SysPrefValueType } 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';
|
||||
import { SnackBarType } from 'src/app/models/snack-bar-type';
|
||||
import { SysprefService } from 'src/app/services/api/syspref.service';
|
||||
import { UtilService } from 'src/app/util/util.service';
|
||||
|
@ -31,7 +29,7 @@ export class SettingsSysprefOptionComponent implements OnInit {
|
|||
}
|
||||
|
||||
get name(): string {
|
||||
return SysPreferenceFriendlyNames[this.pref.key];
|
||||
return SysPreferenceFriendlyNames[this.pref.key as SysPreference] ?? this.pref.key;
|
||||
}
|
||||
|
||||
get valString(): string {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
|
||||
import { AllPermissionsResponse } from 'picsur-shared/dist/dto/api/roles.dto';
|
||||
import { AllPermissionsResponse } from 'picsur-shared/dist/dto/api/info.dto';
|
||||
import { UserMePermissionsResponse } from 'picsur-shared/dist/dto/api/user.dto';
|
||||
import { AsyncFailable, HasFailed } from 'picsur-shared/dist/types';
|
||||
import { BehaviorSubject, filter, map, Observable, take } from 'rxjs';
|
||||
|
|
|
@ -8,15 +8,13 @@ import {
|
|||
UpdateSysPreferenceResponse
|
||||
} from 'picsur-shared/dist/dto/api/pref.dto';
|
||||
import { Permission } from 'picsur-shared/dist/dto/permissions.dto';
|
||||
import {
|
||||
SysPreferences,
|
||||
SysPrefValueType
|
||||
} from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import { SysPrefValueType } from 'picsur-shared/dist/dto/syspreferences.dto';
|
||||
import { AsyncFailable, Fail, HasFailed } from 'picsur-shared/dist/types';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { ApiService } from './api.service';
|
||||
import { PermissionService } from './permission.service';
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
|
@ -60,7 +58,7 @@ export class SysprefService {
|
|||
}
|
||||
|
||||
public async getPreference(
|
||||
key: SysPreferences
|
||||
key: string,
|
||||
): AsyncFailable<GetSyspreferenceResponse> {
|
||||
if (!this.hasPermission)
|
||||
return Fail('You do not have permission to edit system preferences');
|
||||
|
@ -79,7 +77,7 @@ export class SysprefService {
|
|||
}
|
||||
|
||||
public async setPreference(
|
||||
key: SysPreferences,
|
||||
key: string,
|
||||
value: SysPrefValueType
|
||||
): AsyncFailable<UpdateSysPreferenceResponse> {
|
||||
if (!this.hasPermission)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { IsBoolean, IsDefined, IsSemVer, IsString } from 'class-validator';
|
||||
import { IsStringList } from '../../validators/string-list.validator';
|
||||
|
||||
export class InfoResponse {
|
||||
@IsBoolean()
|
||||
|
@ -14,3 +15,10 @@ export class InfoResponse {
|
|||
@IsSemVer()
|
||||
version: string;
|
||||
}
|
||||
|
||||
// AllPermissions
|
||||
export class AllPermissionsResponse {
|
||||
@IsDefined()
|
||||
@IsStringList()
|
||||
Permissions: string[];
|
||||
}
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
import { Type } from 'class-transformer';
|
||||
import {
|
||||
IsArray, IsEnum, IsNotEmpty, ValidateNested
|
||||
IsArray, IsEnum, IsNotEmpty, IsString, ValidateNested
|
||||
} from 'class-validator';
|
||||
import { IsPosInt } from '../../validators/positive-int.validator';
|
||||
import { IsSysPrefValue } from '../../validators/syspref.validator';
|
||||
import {
|
||||
SysPreferences,
|
||||
SysPrefValueType,
|
||||
SysPrefValueTypes,
|
||||
SysPrefValueTypeStrings
|
||||
} from '../syspreferences.dto';
|
||||
import { SysPrefValueType, SysPrefValueTypes, SysPrefValueTypeStrings } from '../syspreferences.dto';
|
||||
|
||||
export class SysPreferenceBaseResponse {
|
||||
@IsNotEmpty()
|
||||
@IsEnum(SysPreferences)
|
||||
key: SysPreferences;
|
||||
@IsString()
|
||||
key: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsSysPrefValue()
|
||||
|
|
|
@ -54,10 +54,3 @@ export class SpecialRolesResponse {
|
|||
@IsStringList()
|
||||
DefaultRoles: string[];
|
||||
}
|
||||
|
||||
// AllPermissions
|
||||
export class AllPermissionsResponse {
|
||||
@IsDefined()
|
||||
@IsStringList()
|
||||
Permissions: string[];
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
// Only add no rename
|
||||
// This enum only makes permissions easier to program,
|
||||
// This does not have to be a complete list of all permissions
|
||||
// -> the frontend and backend can be somewhat out of sync
|
||||
export enum Permission {
|
||||
ImageView = 'image-view',
|
||||
ImageUpload = 'image-upload',
|
||||
|
|
|
@ -1,51 +1,19 @@
|
|||
import tuple from '../types/tuple';
|
||||
|
||||
// Syspref keys
|
||||
|
||||
const SysPreferencesTuple = tuple(
|
||||
'jwt_secret',
|
||||
'jwt_expires_in',
|
||||
'test_string',
|
||||
'test_number',
|
||||
'test_boolean',
|
||||
);
|
||||
|
||||
export const SysPreferences: string[] = SysPreferencesTuple;
|
||||
export type SysPreferences = typeof SysPreferencesTuple[number];
|
||||
|
||||
export const SysPreferenceFriendlyNames: {
|
||||
[key in SysPreferences]: string;
|
||||
} = {
|
||||
jwt_secret: 'JWT Secret',
|
||||
jwt_expires_in: 'JWT Expiry Time',
|
||||
test_string: 'Test String',
|
||||
test_number: 'Test Number',
|
||||
test_boolean: 'Test Boolean',
|
||||
};
|
||||
|
||||
// Syspref Values
|
||||
export enum SysPreference {
|
||||
JwtSecret = 'jwt_secret',
|
||||
JwtExpiresIn = 'jwt_expires_in',
|
||||
TestString = 'test_string',
|
||||
TestNumber = 'test_number',
|
||||
TestBoolean = 'test_boolean',
|
||||
}
|
||||
|
||||
// Variable value type
|
||||
export type SysPrefValueType = string | number | boolean;
|
||||
export type SysPrefValueTypeStrings = 'string' | 'number' | 'boolean';
|
||||
export const SysPrefValueTypes = ['string', 'number', 'boolean'];
|
||||
|
||||
export const SysPreferenceValueTypes: {
|
||||
[key in SysPreferences]: SysPrefValueTypeStrings;
|
||||
} = {
|
||||
jwt_secret: 'string',
|
||||
jwt_expires_in: 'string',
|
||||
test_string: 'string',
|
||||
test_number: 'number',
|
||||
test_boolean: 'boolean',
|
||||
};
|
||||
|
||||
// Validators
|
||||
|
||||
|
||||
// interfaces
|
||||
|
||||
// Interfaces
|
||||
export interface InternalSysprefRepresentation {
|
||||
key: SysPreferences;
|
||||
key: string;
|
||||
value: SysPrefValueType;
|
||||
type: SysPrefValueTypeStrings;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||
import { SysPreferences } from '../dto/syspreferences.dto';
|
||||
import { IsNotEmpty, IsString } from 'class-validator';
|
||||
import { EntityID } from '../validators/entity-id.validator';
|
||||
|
||||
export class ESysPreference {
|
||||
|
@ -7,8 +6,8 @@ export class ESysPreference {
|
|||
id?: number;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsEnum(SysPreferences)
|
||||
key: SysPreferences;
|
||||
@IsString()
|
||||
key: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
|
|
Loading…
Reference in a new issue