move some files
This commit is contained in:
parent
1e0e41ad80
commit
9469090614
|
@ -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: [
|
|
@ -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 {
|
227
backend/src/collections/preferencesdb/usrpreferencedb.service.ts
Normal file
227
backend/src/collections/preferencesdb/usrpreferencedb.service.ts
Normal 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');
|
||||
}
|
||||
}
|
|
@ -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({
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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,
|
||||
];
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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({
|
||||
|
|
Loading…
Reference in a new issue