feat: custom branding (#112)

* add first concept

* remove setup status

* split config page in multiple components

* add custom branding docs

* add test email button

* fix invalid email from header

* add migration

* mount images to host

* update docs

* remove unused endpoint

* run formatter
This commit is contained in:
Elias Schneider
2023-03-04 23:29:00 +01:00
committed by GitHub
parent f9840505b8
commit fddad3ef70
66 changed files with 908 additions and 623 deletions

View File

@@ -1,4 +1,12 @@
import { Body, Controller, Get, Patch, Post, UseGuards } from "@nestjs/common";
import {
Body,
Controller,
Get,
Param,
Patch,
Post,
UseGuards,
} from "@nestjs/common";
import { SkipThrottle } from "@nestjs/throttler";
import { AdministratorGuard } from "src/auth/guard/isAdmin.guard";
import { JwtGuard } from "src/auth/guard/jwt.guard";
@@ -22,24 +30,20 @@ export class ConfigController {
return new ConfigDTO().fromList(await this.configService.list());
}
@Get("admin")
@Get("admin/:category")
@UseGuards(JwtGuard, AdministratorGuard)
async listForAdmin() {
async getByCategory(@Param("category") category: string) {
return new AdminConfigDTO().fromList(
await this.configService.listForAdmin()
await this.configService.getByCategory(category)
);
}
@Patch("admin")
@UseGuards(JwtGuard, AdministratorGuard)
async updateMany(@Body() data: UpdateConfigDTO[]) {
await this.configService.updateMany(data);
}
@Post("admin/finishSetup")
@UseGuards(JwtGuard, AdministratorGuard)
async finishSetup() {
return await this.configService.changeSetupStatus("FINISHED");
return new AdminConfigDTO().fromList(
await this.configService.updateMany(data)
);
}
@Post("admin/testEmail")

View File

@@ -14,9 +14,9 @@ export class ConfigService {
private prisma: PrismaService
) {}
get(key: string): any {
get(key: `${string}.${string}`): any {
const configVariable = this.configVariables.filter(
(variable) => variable.key == key
(variable) => `${variable.category}.${variable.name}` == key
)[0];
if (!configVariable) throw new Error(`Config variable ${key} not found`);
@@ -27,30 +27,51 @@ export class ConfigService {
return configVariable.value;
}
async listForAdmin() {
return await this.prisma.config.findMany({
async getByCategory(category: string) {
const configVariables = await this.prisma.config.findMany({
orderBy: { order: "asc" },
where: { locked: { equals: false } },
where: { category, locked: { equals: false } },
});
return configVariables.map((variable) => {
return {
key: `${variable.category}.${variable.name}`,
...variable,
};
});
}
async list() {
return await this.prisma.config.findMany({
const configVariables = await this.prisma.config.findMany({
where: { secret: { equals: false } },
});
return configVariables.map((variable) => {
return {
key: `${variable.category}.${variable.name}`,
...variable,
};
});
}
async updateMany(data: { key: string; value: string | number | boolean }[]) {
const response: Config[] = [];
for (const variable of data) {
await this.update(variable.key, variable.value);
response.push(await this.update(variable.key, variable.value));
}
return data;
return response;
}
async update(key: string, value: string | number | boolean) {
const configVariable = await this.prisma.config.findUnique({
where: { key },
where: {
name_category: {
category: key.split(".")[0],
name: key.split(".")[1],
},
},
});
if (!configVariable || configVariable.locked)
@@ -67,7 +88,12 @@ export class ConfigService {
}
const updatedVariable = await this.prisma.config.update({
where: { key },
where: {
name_category: {
category: key.split(".")[0],
name: key.split(".")[1],
},
},
data: { value: value.toString() },
});
@@ -75,15 +101,4 @@ export class ConfigService {
return updatedVariable;
}
async changeSetupStatus(status: "STARTED" | "REGISTERED" | "FINISHED") {
const updatedVariable = await this.prisma.config.update({
where: { key: "SETUP_STATUS" },
data: { value: status },
});
this.configVariables = await this.prisma.config.findMany();
return updatedVariable;
}
}

View File

@@ -2,6 +2,9 @@ import { Expose, plainToClass } from "class-transformer";
import { ConfigDTO } from "./config.dto";
export class AdminConfigDTO extends ConfigDTO {
@Expose()
name: string;
@Expose()
secret: boolean;
@@ -14,9 +17,6 @@ export class AdminConfigDTO extends ConfigDTO {
@Expose()
obscured: boolean;
@Expose()
category: string;
from(partial: Partial<AdminConfigDTO>) {
return plainToClass(AdminConfigDTO, partial, {
excludeExtraneousValues: true,