147 lines
4.1 KiB
TypeScript
147 lines
4.1 KiB
TypeScript
import {
|
|
BadRequestException,
|
|
Inject,
|
|
Injectable,
|
|
NotFoundException,
|
|
} from "@nestjs/common";
|
|
import { Config } from "@prisma/client";
|
|
import { EventEmitter } from "events";
|
|
import { PrismaService } from "src/prisma/prisma.service";
|
|
import { stringToTimespan } from "src/utils/date.util";
|
|
|
|
/**
|
|
* ConfigService extends EventEmitter to allow listening for config updates,
|
|
* now only `update` event will be emitted.
|
|
*/
|
|
@Injectable()
|
|
export class ConfigService extends EventEmitter {
|
|
constructor(
|
|
@Inject("CONFIG_VARIABLES") private configVariables: Config[],
|
|
private prisma: PrismaService,
|
|
) {
|
|
super();
|
|
}
|
|
|
|
get(key: `${string}.${string}`): any {
|
|
const configVariable = this.configVariables.filter(
|
|
(variable) => `${variable.category}.${variable.name}` == key,
|
|
)[0];
|
|
|
|
if (!configVariable) throw new Error(`Config variable ${key} not found`);
|
|
|
|
const value = configVariable.value ?? configVariable.defaultValue;
|
|
|
|
if (configVariable.type == "number" || configVariable.type == "filesize")
|
|
return parseInt(value);
|
|
if (configVariable.type == "boolean") return value == "true";
|
|
if (configVariable.type == "string" || configVariable.type == "text")
|
|
return value;
|
|
if (configVariable.type == "timespan") return stringToTimespan(value);
|
|
}
|
|
|
|
async getByCategory(category: string) {
|
|
const configVariables = await this.prisma.config.findMany({
|
|
orderBy: { order: "asc" },
|
|
where: { category, locked: { equals: false } },
|
|
});
|
|
|
|
return configVariables.map((variable) => {
|
|
return {
|
|
...variable,
|
|
key: `${variable.category}.${variable.name}`,
|
|
value: variable.value ?? variable.defaultValue,
|
|
};
|
|
});
|
|
}
|
|
|
|
async list() {
|
|
const configVariables = await this.prisma.config.findMany({
|
|
where: { secret: { equals: false } },
|
|
});
|
|
|
|
return configVariables.map((variable) => {
|
|
return {
|
|
...variable,
|
|
key: `${variable.category}.${variable.name}`,
|
|
value: variable.value ?? variable.defaultValue,
|
|
};
|
|
});
|
|
}
|
|
|
|
async updateMany(data: { key: string; value: string | number | boolean }[]) {
|
|
const response: Config[] = [];
|
|
|
|
for (const variable of data) {
|
|
response.push(await this.update(variable.key, variable.value));
|
|
}
|
|
|
|
return response;
|
|
}
|
|
|
|
async update(key: string, value: string | number | boolean) {
|
|
const configVariable = await this.prisma.config.findUnique({
|
|
where: {
|
|
name_category: {
|
|
category: key.split(".")[0],
|
|
name: key.split(".")[1],
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!configVariable || configVariable.locked)
|
|
throw new NotFoundException("Config variable not found");
|
|
|
|
if (value === "") {
|
|
value = null;
|
|
} else if (
|
|
typeof value != configVariable.type &&
|
|
typeof value == "string" &&
|
|
configVariable.type != "text" &&
|
|
configVariable.type != "timespan"
|
|
) {
|
|
throw new BadRequestException(
|
|
`Config variable must be of type ${configVariable.type}`,
|
|
);
|
|
}
|
|
|
|
this.validateConfigVariable(key, value);
|
|
|
|
const updatedVariable = await this.prisma.config.update({
|
|
where: {
|
|
name_category: {
|
|
category: key.split(".")[0],
|
|
name: key.split(".")[1],
|
|
},
|
|
},
|
|
data: { value: value === null ? null : value.toString() },
|
|
});
|
|
|
|
this.configVariables = await this.prisma.config.findMany();
|
|
|
|
this.emit("update", key, value);
|
|
|
|
return updatedVariable;
|
|
}
|
|
|
|
validateConfigVariable(key: string, value: string | number | boolean) {
|
|
const validations = [
|
|
{
|
|
key: "share.shareIdLength",
|
|
condition: (value: number) => value >= 2 && value <= 50,
|
|
message: "Share ID length must be between 2 and 50",
|
|
},
|
|
{
|
|
key: "share.zipCompressionLevel",
|
|
condition: (value: number) => value >= 0 && value <= 9,
|
|
message: "Zip compression level must be between 0 and 9",
|
|
},
|
|
// TODO add validation for timespan type
|
|
];
|
|
|
|
const validation = validations.find((validation) => validation.key == key);
|
|
if (validation && !validation.condition(value as any)) {
|
|
throw new BadRequestException(validation.message);
|
|
}
|
|
}
|
|
}
|