Files
eventsphere/apps/api/src/modules/settings/settings.controller.ts
2026-04-25 21:57:48 +01:00

83 lines
3.1 KiB
TypeScript

import { BadRequestException, Body, Controller, Get, Patch, Query, Req, UploadedFile, UseGuards, UseInterceptors } from "@nestjs/common";
import type { Request } from "express";
import { FileInterceptor } from "@nestjs/platform-express";
import { diskStorage } from "multer";
import path from "node:path";
import { randomBytes } from "node:crypto";
import { JwtAuthGuard, PermissionsGuard, RequirePermissions, TenantGuard } from "../auth/guards";
import { UpdateTenantSettingsDto } from "./dto";
import { SettingsService } from "./settings.service";
import { PrismaService } from "../../prisma/prisma.service";
@Controller("settings")
export class SettingsController {
constructor(
private readonly service: SettingsService,
private readonly prisma: PrismaService
) {}
@UseGuards(JwtAuthGuard, TenantGuard, PermissionsGuard)
@RequirePermissions("settings.read")
@Get()
get(@Req() req: Request) {
const tenantId = (req.user as any).tenantId as string;
return this.service.get(tenantId);
}
@UseGuards(JwtAuthGuard, TenantGuard, PermissionsGuard)
@RequirePermissions("settings.write")
@Patch()
update(@Req() req: Request, @Body() dto: UpdateTenantSettingsDto) {
const tenantId = (req.user as any).tenantId as string;
return this.service.update(tenantId, dto);
}
@UseGuards(JwtAuthGuard, TenantGuard, PermissionsGuard)
@RequirePermissions("settings.write")
@Patch("logo")
@UseInterceptors(
FileInterceptor("file", {
storage: diskStorage({
destination: (_req, _file, cb) => {
const dir = process.env.UPLOADS_DIR ?? path.join(process.cwd(), "uploads");
cb(null, dir);
},
filename: (_req, file, cb) => {
const ext = path.extname(file.originalname || "").slice(0, 10);
cb(null, `logo-${Date.now()}-${randomBytes(6).toString("hex")}${ext}`);
}
}),
limits: { fileSize: 5 * 1024 * 1024 }
})
)
async uploadLogo(@Req() req: Request, @UploadedFile() file?: any) {
const tenantId = (req.user as any).tenantId as string;
if (!file) throw new BadRequestException("Missing file");
const base = process.env.PUBLIC_API_URL ?? "";
const url = `${base.replace(/\/$/, "")}/uploads/${encodeURIComponent(file.filename)}`;
return this.service.setLogo(tenantId, url);
}
}
@Controller("public/branding")
export class PublicBrandingController {
constructor(private readonly prisma: PrismaService) {}
@Get()
async get(@Query("tenantSlug") tenantSlug?: string) {
const slug = tenantSlug ?? process.env.DEFAULT_TENANT_SLUG ?? "";
if (!slug) throw new BadRequestException("Missing tenantSlug");
const tenant = await this.prisma.tenant.findUnique({ where: { slug } });
if (!tenant) throw new BadRequestException("Tenant not found");
const settings = await this.prisma.tenantSetting.findUnique({ where: { tenantId: tenant.id } });
return {
tenant: { id: tenant.id, slug: tenant.slug, name: tenant.name },
branding: {
appName: settings?.appName ?? tenant.name,
logoUrl: settings?.logoUrl ?? null
},
modules: (settings?.modules as any) ?? null
};
}
}