2022-12-30 14:22:06 +01:00
|
|
|
import { SystemConfig, SystemConfigEntity, SystemConfigKey } from '@app/database';
|
2022-12-16 21:26:12 +01:00
|
|
|
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
2022-11-15 05:39:32 +01:00
|
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
2022-12-09 21:51:42 +01:00
|
|
|
import * as _ from 'lodash';
|
2022-12-16 21:26:12 +01:00
|
|
|
import { Subject } from 'rxjs';
|
2022-12-09 21:51:42 +01:00
|
|
|
import { DeepPartial, In, Repository } from 'typeorm';
|
|
|
|
|
2022-12-16 21:26:12 +01:00
|
|
|
export type SystemConfigValidator = (config: SystemConfig) => void | Promise<void>;
|
|
|
|
|
2022-12-09 21:51:42 +01:00
|
|
|
const defaults: SystemConfig = Object.freeze({
|
|
|
|
ffmpeg: {
|
|
|
|
crf: '23',
|
|
|
|
preset: 'ultrafast',
|
|
|
|
targetVideoCodec: 'libx264',
|
|
|
|
targetAudioCodec: 'mp3',
|
|
|
|
targetScaling: '1280:-2',
|
2022-11-15 05:39:32 +01:00
|
|
|
},
|
2022-12-09 21:51:42 +01:00
|
|
|
oauth: {
|
|
|
|
enabled: false,
|
|
|
|
issuerUrl: '',
|
|
|
|
clientId: '',
|
|
|
|
clientSecret: '',
|
2022-12-29 21:47:30 +01:00
|
|
|
mobileOverrideEnabled: false,
|
|
|
|
mobileRedirectUri: '',
|
2022-12-09 21:51:42 +01:00
|
|
|
scope: 'openid email profile',
|
|
|
|
buttonText: 'Login with OAuth',
|
|
|
|
autoRegister: true,
|
2023-01-09 22:32:58 +01:00
|
|
|
autoLaunch: false,
|
|
|
|
},
|
|
|
|
passwordLogin: {
|
|
|
|
enabled: true,
|
2022-11-15 05:39:32 +01:00
|
|
|
},
|
2022-12-16 21:26:12 +01:00
|
|
|
|
|
|
|
storageTemplate: {
|
|
|
|
template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
|
|
|
},
|
2022-12-09 21:51:42 +01:00
|
|
|
});
|
2022-11-15 05:39:32 +01:00
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
export class ImmichConfigService {
|
2022-12-16 21:26:12 +01:00
|
|
|
private logger = new Logger(ImmichConfigService.name);
|
|
|
|
private validators: SystemConfigValidator[] = [];
|
|
|
|
|
|
|
|
public config$ = new Subject<SystemConfig>();
|
|
|
|
|
2022-11-15 05:39:32 +01:00
|
|
|
constructor(
|
|
|
|
@InjectRepository(SystemConfigEntity)
|
|
|
|
private systemConfigRepository: Repository<SystemConfigEntity>,
|
|
|
|
) {}
|
|
|
|
|
2022-12-09 21:51:42 +01:00
|
|
|
public getDefaults(): SystemConfig {
|
|
|
|
return defaults;
|
2022-11-15 05:39:32 +01:00
|
|
|
}
|
|
|
|
|
2022-12-16 21:26:12 +01:00
|
|
|
public addValidator(validator: SystemConfigValidator) {
|
|
|
|
this.validators.push(validator);
|
|
|
|
}
|
|
|
|
|
2022-12-09 21:51:42 +01:00
|
|
|
public async getConfig() {
|
|
|
|
const overrides = await this.systemConfigRepository.find();
|
|
|
|
const config: DeepPartial<SystemConfig> = {};
|
|
|
|
for (const { key, value } of overrides) {
|
|
|
|
// set via dot notation
|
|
|
|
_.set(config, key, value);
|
2022-11-15 05:39:32 +01:00
|
|
|
}
|
|
|
|
|
2022-12-09 21:51:42 +01:00
|
|
|
return _.defaultsDeep(config, defaults) as SystemConfig;
|
2022-11-15 05:39:32 +01:00
|
|
|
}
|
|
|
|
|
2022-12-16 21:26:12 +01:00
|
|
|
public async updateConfig(config: SystemConfig): Promise<SystemConfig> {
|
|
|
|
try {
|
|
|
|
for (const validator of this.validators) {
|
|
|
|
await validator(config);
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
this.logger.warn(`Unable to save system config due to a validation error: ${e}`);
|
|
|
|
throw new BadRequestException(e instanceof Error ? e.message : e);
|
|
|
|
}
|
|
|
|
|
2022-11-15 05:39:32 +01:00
|
|
|
const updates: SystemConfigEntity[] = [];
|
2022-12-09 21:51:42 +01:00
|
|
|
const deletes: SystemConfigEntity[] = [];
|
|
|
|
|
|
|
|
for (const key of Object.values(SystemConfigKey)) {
|
|
|
|
// get via dot notation
|
|
|
|
const item = { key, value: _.get(config, key) };
|
|
|
|
const defaultValue = _.get(defaults, key);
|
|
|
|
const isMissing = !_.has(config, key);
|
2022-11-15 05:39:32 +01:00
|
|
|
|
2022-12-09 21:51:42 +01:00
|
|
|
if (isMissing || item.value === null || item.value === '' || item.value === defaultValue) {
|
2022-11-15 05:39:32 +01:00
|
|
|
deletes.push(item);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
updates.push(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (updates.length > 0) {
|
|
|
|
await this.systemConfigRepository.save(updates);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (deletes.length > 0) {
|
|
|
|
await this.systemConfigRepository.delete({ key: In(deletes.map((item) => item.key)) });
|
|
|
|
}
|
2022-12-16 21:26:12 +01:00
|
|
|
|
|
|
|
const newConfig = await this.getConfig();
|
|
|
|
|
|
|
|
this.config$.next(newConfig);
|
|
|
|
|
|
|
|
return newConfig;
|
2022-11-15 05:39:32 +01:00
|
|
|
}
|
2022-12-19 19:13:10 +01:00
|
|
|
|
|
|
|
public async refreshConfig() {
|
|
|
|
const newConfig = await this.getConfig();
|
|
|
|
|
|
|
|
this.config$.next(newConfig);
|
|
|
|
}
|
2022-11-15 05:39:32 +01:00
|
|
|
}
|