move some files

This commit is contained in:
rubikscraft 2022-04-13 14:33:18 +02:00
parent 1e0e41ad80
commit 9469090614
No known key found for this signature in database
GPG key ID: 1463EBE9200A5CD4
12 changed files with 245 additions and 11 deletions

View file

@ -2,8 +2,8 @@ import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { EarlyConfigModule } from '../../config/early/earlyconfig.module';
import { ESysPreferenceBackend } from '../../models/entities/syspreference.entity';
import { PreferenceDefaultsService } from './preferencedefaults.service';
import { SysPreferenceService } from './syspreferencedb.service';
import { PreferenceDefaultsService } from './syspreferencedefaults.service';
@Module({
imports: [

View file

@ -19,7 +19,7 @@ import {
SysPreferenceValueTypes
} from '../../models/dto/syspreferences.dto';
import { ESysPreferenceBackend } from '../../models/entities/syspreference.entity';
import { PreferenceDefaultsService } from './syspreferencedefaults.service';
import { PreferenceDefaultsService } from './preferencedefaults.service';
@Injectable()
export class SysPreferenceService {

View file

@ -0,0 +1,227 @@
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import {
DecodedUsrPref,
PrefValueType,
PrefValueTypeStrings
} from 'picsur-shared/dist/dto/preferences.dto';
import { UsrPreference } from 'picsur-shared/dist/dto/usrpreferences.dto';
import { EUsrPreferenceSchema } from 'picsur-shared/dist/entities/usrpreference';
import {
AsyncFailable,
Fail,
Failable,
HasFailed
} from 'picsur-shared/dist/types';
import { Repository } from 'typeorm';
import {
UsrPreferenceList,
UsrPreferenceValueTypes
} from '../../models/dto/usrpreferences.dto';
import { EUsrPreferenceBackend } from '../../models/entities/usrpreference.entity';
import { PreferenceDefaultsService } from './preferencedefaults.service';
@Injectable()
export class UsrPreferenceService {
private readonly logger = new Logger('UsrPreferenceService');
constructor(
@InjectRepository(EUsrPreferenceBackend)
private sysPreferenceRepository: Repository<EUsrPreferenceBackend>,
private defaultsService: PreferenceDefaultsService,
) {}
public async setPreference(
key: string,
value: PrefValueType,
): AsyncFailable<DecodedUsrPref> {
// Validate
let sysPreference = await this.validatePref(key, value);
if (HasFailed(sysPreference)) return sysPreference;
// Set
try {
// Upsert here, because we want to create a new record if it does not exist
await this.sysPreferenceRepository.upsert(sysPreference, {
conflictPaths: ['key'],
});
} catch (e: any) {
this.logger.warn(e);
return Fail('Could not save preference');
}
// Return
return {
key: sysPreference.key,
value,
// key has to be valid here, we validated it
type: UsrPreferenceValueTypes[key as UsrPreference],
user: '',
};
}
public async getPreference(key: string): AsyncFailable<DecodedUsrPref> {
// Validate
let validatedKey = this.validatePrefKey(key);
if (HasFailed(validatedKey)) return validatedKey;
// Fetch
let foundSysPreference: EUsrPreferenceBackend | null;
try {
foundSysPreference = await this.sysPreferenceRepository.findOne({
where: { key: validatedKey },
cache: 60000,
});
} catch (e: any) {
this.logger.warn(e);
return Fail('Could not get preference');
}
// Fallback
if (!foundSysPreference) {
return this.saveDefault(validatedKey);
}
// Validate
const result = EUsrPreferenceSchema.safeParse(foundSysPreference);
if (!result.success) {
this.logger.warn(result.error);
return Fail('Invalid preference');
}
// Return
return this.retrieveConvertedValue(result.data);
}
public async getStringPreference(key: string): AsyncFailable<string> {
return this.getPreferencePinned(key, 'string') as AsyncFailable<string>;
}
public async getNumberPreference(key: string): AsyncFailable<number> {
return this.getPreferencePinned(key, 'number') as AsyncFailable<number>;
}
public async getBooleanPreference(key: string): AsyncFailable<boolean> {
return this.getPreferencePinned(key, 'boolean') as AsyncFailable<boolean>;
}
private async getPreferencePinned(
key: string,
type: PrefValueTypeStrings,
): AsyncFailable<PrefValueType> {
let pref = await this.getPreference(key);
if (HasFailed(pref)) return pref;
if (pref.type !== type) return Fail('Invalid preference type');
return pref.value;
}
public async getAllPreferences(): AsyncFailable<DecodedUsrPref[]> {
// TODO: We are fetching each value invidually, we should fetch all at once
let internalSysPrefs = await Promise.all(
UsrPreferenceList.map((key) => this.getPreference(key)),
);
if (internalSysPrefs.some((pref) => HasFailed(pref))) {
return Fail('Could not get all preferences');
}
return internalSysPrefs as DecodedUsrPref[];
}
// Private
private async saveDefault(
key: UsrPreference, // Force enum here because we dont validate
): AsyncFailable<DecodedUsrPref> {
return this.setPreference(key, this.defaultsService.sysDefaults[key]());
}
// This converts the raw string representation of the value to the correct type
private retrieveConvertedValue(
preference: EUsrPreferenceBackend,
): Failable<DecodedUsrPref> {
const key = this.validatePrefKey(preference.key);
if (HasFailed(key)) return key;
const type = UsrPreferenceValueTypes[key];
switch (type) {
case 'string':
return {
key: preference.key,
value: preference.value,
type: 'string',
user: '',
};
case 'number':
return {
key: preference.key,
value: parseInt(preference.value, 10),
type: 'number',
user: '',
};
case 'boolean':
return {
key: preference.key,
value: preference.value == 'true',
type: 'boolean',
user: '',
};
}
return Fail('Invalid preference value');
}
private async validatePref(
key: string,
value: PrefValueType,
): AsyncFailable<EUsrPreferenceBackend> {
const validatedKey = this.validatePrefKey(key);
if (HasFailed(validatedKey)) return validatedKey;
const validatedValue = this.validatePrefValue(validatedKey, value);
if (HasFailed(validatedValue)) return validatedValue;
let verifySysPreference = new EUsrPreferenceBackend();
verifySysPreference.key = validatedKey;
verifySysPreference.value = validatedValue;
// It should already be valid, but these two validators might go out of sync
const result = EUsrPreferenceSchema.safeParse(verifySysPreference);
if (!result.success) {
this.logger.warn(result.error);
return Fail('Invalid preference');
}
return result.data;
}
private validatePrefKey(key: string): Failable<UsrPreference> {
if (!UsrPreferenceList.includes(key)) return Fail('Invalid preference key');
return key as UsrPreference;
}
private validatePrefValue(
// Key is required, because the type of the value depends on the key
key: UsrPreference,
value: PrefValueType,
): Failable<string> {
const expectedType = UsrPreferenceValueTypes[key];
const type = typeof value;
if (type != expectedType) {
return Fail('Invalid preference value');
}
switch (type) {
case 'string':
return value as string;
case 'number':
return value.toString();
case 'boolean':
return value ? 'true' : 'false';
}
return Fail('Invalid preference value');
}
}

View file

@ -5,8 +5,8 @@ import { generateRandomString } from 'picsur-shared/dist/util/random';
import { AuthConfigService } from '../../config/early/auth.config.service';
import { EarlyConfigModule } from '../../config/early/earlyconfig.module';
import { EUserBackend } from '../../models/entities/user.entity';
import { SysPreferenceModule } from '../preferencesdb/preferencedb.module';
import { RolesModule } from '../roledb/roledb.module';
import { SysPreferenceModule } from '../syspreferencesdb/syspreferencedb.module';
import { UsersService } from './userdb.service';
@Module({

View file

@ -22,8 +22,8 @@ import {
} from '../../models/dto/specialusers.dto';
import { EUserBackend } from '../../models/entities/user.entity';
import { GetCols } from '../../models/util/collection';
import { SysPreferenceService } from '../preferencesdb/syspreferencedb.service';
import { RolesService } from '../roledb/roledb.service';
import { SysPreferenceService } from '../syspreferencesdb/syspreferencedb.service';
@Injectable()
export class UsersService {

View file

@ -1,7 +1,7 @@
import { FactoryProvider, Injectable, Logger } from '@nestjs/common';
import { JwtModuleOptions, JwtOptionsFactory } from '@nestjs/jwt';
import { HasFailed } from 'picsur-shared/dist/types';
import { SysPreferenceService } from '../../collections/syspreferencesdb/syspreferencedb.service';
import { SysPreferenceService } from '../../collections/preferencesdb/syspreferencedb.service';
@Injectable()
export class JwtConfigService implements JwtOptionsFactory {

View file

@ -1,6 +1,6 @@
import { Logger, Module, OnModuleInit } from '@nestjs/common';
import { SysPreferenceModule } from '../../collections/syspreferencesdb/syspreferencedb.module';
import { SysPreferenceService } from '../../collections/syspreferencesdb/syspreferencedb.service';
import { SysPreferenceModule } from '../../collections/preferencesdb/preferencedb.module';
import { SysPreferenceService } from '../../collections/preferencesdb/syspreferencedb.service';
import { EarlyConfigModule } from '../early/earlyconfig.module';
import { EarlyJwtConfigService } from '../early/earlyjwt.config.service';
import { JwtConfigService } from './jwt.config.service';

View file

@ -1,7 +1,7 @@
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { SysPreferenceModule } from '../../collections/syspreferencesdb/syspreferencedb.module';
import { SysPreferenceModule } from '../../collections/preferencesdb/preferencedb.module';
import { UsersModule } from '../../collections/userdb/userdb.module';
import { JwtConfigService, JwtSecretProvider } from '../../config/late/jwt.config.service';
import { LateConfigModule } from '../../config/late/lateconfig.module';

View file

@ -2,5 +2,12 @@ import { EImageBackend } from './image.entity';
import { ERoleBackend } from './role.entity';
import { ESysPreferenceBackend } from './syspreference.entity';
import { EUserBackend } from './user.entity';
import { EUsrPreferenceBackend } from './usrpreference.entity';
export const EntityList = [EImageBackend, EUserBackend, ERoleBackend, ESysPreferenceBackend];
export const EntityList = [
EImageBackend,
EUserBackend,
ERoleBackend,
ESysPreferenceBackend,
EUsrPreferenceBackend,
];

View file

@ -14,7 +14,7 @@ import {
UpdateSysPreferenceResponse
} from 'picsur-shared/dist/dto/api/syspref.dto';
import { HasFailed } from 'picsur-shared/dist/types';
import { SysPreferenceService } from '../../../collections/syspreferencesdb/syspreferencedb.service';
import { SysPreferenceService } from '../../../collections/preferencesdb/syspreferencedb.service';
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
import { Returns } from '../../../decorators/returns.decorator';
import { Permission } from '../../../models/dto/permissions.dto';

View file

@ -1,5 +1,5 @@
import { Module } from '@nestjs/common';
import { SysPreferenceModule } from '../../../collections/syspreferencesdb/syspreferencedb.module';
import { SysPreferenceModule } from '../../../collections/preferencesdb/preferencedb.module';
import { PrefController } from './pref.controller';
@Module({