forked from Yara724/api
Fix 404 for invalid email of actors, added APIs for client settings
This commit is contained in:
@@ -1,10 +1,21 @@
|
||||
import { BadGatewayException, GoneException, Injectable } from "@nestjs/common";
|
||||
import {
|
||||
BadGatewayException,
|
||||
BadRequestException,
|
||||
GoneException,
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
} from "@nestjs/common";
|
||||
import { Types } from "mongoose";
|
||||
import {
|
||||
ClientDto,
|
||||
ClientDtoRs,
|
||||
ClientLists,
|
||||
} from "src/client/dto/create-client.dto";
|
||||
import {
|
||||
type ClientSettingsPanelResponseDto,
|
||||
UpdateClientSettingsDto,
|
||||
} from "src/client/dto/client-settings.dto";
|
||||
import type { ClientMediaLimits } from "./entities/schema/client.schema";
|
||||
import { ClientDbService } from "./entities/db-service/client.db.service";
|
||||
|
||||
/**
|
||||
@@ -42,6 +53,18 @@ export const DEFAULT_MEDIA_LIMITS: Record<MediaKind, MediaLimits> = {
|
||||
voice: { minBytes: 5 * 1024, maxBytes: 8 * 1024 * 1024 },
|
||||
};
|
||||
|
||||
/** Highest multer `fileSize` used on any route for each kind (policy cannot exceed this). */
|
||||
export const MEDIA_ROUTE_MAX_BYTES: Record<MediaKind, number> = {
|
||||
video: 50 * 1024 * 1024,
|
||||
image: 10 * 1024 * 1024,
|
||||
voice: 10 * 1024 * 1024,
|
||||
};
|
||||
|
||||
export const CAR_BODY_ACCIDENT_MAX_AGE_DAYS_MIN = 1;
|
||||
export const CAR_BODY_ACCIDENT_MAX_AGE_DAYS_MAX = 365;
|
||||
|
||||
const MEDIA_KINDS: MediaKind[] = ["video", "image", "voice"];
|
||||
|
||||
@Injectable()
|
||||
export class ClientService {
|
||||
constructor(private readonly clientDbService: ClientDbService) {}
|
||||
@@ -155,4 +178,138 @@ export class ClientService {
|
||||
}
|
||||
return DEFAULT_CAR_BODY_ACCIDENT_MAX_AGE_DAYS;
|
||||
}
|
||||
|
||||
private resolveClientObjectId(clientKey: string | Types.ObjectId): Types.ObjectId {
|
||||
const raw = String(clientKey ?? "").trim();
|
||||
if (!Types.ObjectId.isValid(raw)) {
|
||||
throw new BadRequestException("Invalid client key");
|
||||
}
|
||||
return new Types.ObjectId(raw);
|
||||
}
|
||||
|
||||
private async loadClientOrThrow(clientKey: string | Types.ObjectId) {
|
||||
const id = this.resolveClientObjectId(clientKey);
|
||||
const client = await this.clientDbService.findOne({ _id: id });
|
||||
if (!client) {
|
||||
throw new NotFoundException("Client not found");
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
private configuredMediaLimits(
|
||||
stored: ClientMediaLimits | undefined,
|
||||
): { minBytes?: number; maxBytes?: number } | null {
|
||||
if (!stored) return null;
|
||||
const hasMin = typeof stored.minBytes === "number";
|
||||
const hasMax = typeof stored.maxBytes === "number";
|
||||
if (!hasMin && !hasMax) return null;
|
||||
return {
|
||||
...(hasMin ? { minBytes: stored.minBytes } : {}),
|
||||
...(hasMax ? { maxBytes: stored.maxBytes } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
private validateMediaLimitsPatch(
|
||||
kind: MediaKind,
|
||||
patch: { minBytes?: number; maxBytes?: number },
|
||||
): { minBytes?: number; maxBytes?: number } {
|
||||
const defaults = DEFAULT_MEDIA_LIMITS[kind];
|
||||
const routeMax = MEDIA_ROUTE_MAX_BYTES[kind];
|
||||
const minBytes =
|
||||
patch.minBytes !== undefined ? patch.minBytes : defaults.minBytes;
|
||||
const maxBytes =
|
||||
patch.maxBytes !== undefined ? patch.maxBytes : defaults.maxBytes;
|
||||
|
||||
if (maxBytes > routeMax) {
|
||||
throw new BadRequestException(
|
||||
`${kind} maxBytes (${maxBytes}) cannot exceed the route upload limit of ${routeMax} bytes.`,
|
||||
);
|
||||
}
|
||||
if (minBytes > maxBytes) {
|
||||
throw new BadRequestException(
|
||||
`${kind} minBytes (${minBytes}) cannot be greater than maxBytes (${maxBytes}).`,
|
||||
);
|
||||
}
|
||||
|
||||
const out: { minBytes?: number; maxBytes?: number } = {};
|
||||
if (patch.minBytes !== undefined) out.minBytes = patch.minBytes;
|
||||
if (patch.maxBytes !== undefined) out.maxBytes = patch.maxBytes;
|
||||
return out;
|
||||
}
|
||||
|
||||
async getPanelSettings(
|
||||
clientKey: string | Types.ObjectId,
|
||||
): Promise<ClientSettingsPanelResponseDto> {
|
||||
const client = await this.loadClientOrThrow(clientKey);
|
||||
const clientId = client._id.toString();
|
||||
|
||||
const configuredDays = client.settings?.carBodyAccidentMaxAgeDays;
|
||||
const effectiveDays = await this.getCarBodyAccidentMaxAgeDays(client._id);
|
||||
|
||||
const media = {} as ClientSettingsPanelResponseDto["media"];
|
||||
for (const kind of MEDIA_KINDS) {
|
||||
const effective = await this.getMediaLimits(client._id, kind);
|
||||
media[kind] = {
|
||||
configured: this.configuredMediaLimits(client.settings?.media?.[kind]),
|
||||
effective,
|
||||
systemDefault: { ...DEFAULT_MEDIA_LIMITS[kind] },
|
||||
routeMaxBytes: MEDIA_ROUTE_MAX_BYTES[kind],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
clientId,
|
||||
carBodyAccidentMaxAgeDays: {
|
||||
configured:
|
||||
typeof configuredDays === "number" && Number.isFinite(configuredDays)
|
||||
? configuredDays
|
||||
: null,
|
||||
effective: effectiveDays,
|
||||
systemDefault: DEFAULT_CAR_BODY_ACCIDENT_MAX_AGE_DAYS,
|
||||
minDays: CAR_BODY_ACCIDENT_MAX_AGE_DAYS_MIN,
|
||||
maxDays: CAR_BODY_ACCIDENT_MAX_AGE_DAYS_MAX,
|
||||
},
|
||||
media,
|
||||
};
|
||||
}
|
||||
|
||||
async updatePanelSettings(
|
||||
clientKey: string | Types.ObjectId,
|
||||
body: UpdateClientSettingsDto,
|
||||
): Promise<ClientSettingsPanelResponseDto> {
|
||||
const client = await this.loadClientOrThrow(clientKey);
|
||||
const $set: Record<string, unknown> = {};
|
||||
|
||||
if (body.carBodyAccidentMaxAgeDays !== undefined) {
|
||||
$set["settings.carBodyAccidentMaxAgeDays"] = body.carBodyAccidentMaxAgeDays;
|
||||
}
|
||||
|
||||
if (body.media) {
|
||||
for (const kind of MEDIA_KINDS) {
|
||||
const patch = body.media[kind];
|
||||
if (!patch) continue;
|
||||
const validated = this.validateMediaLimitsPatch(kind, patch);
|
||||
if (validated.minBytes !== undefined) {
|
||||
$set[`settings.media.${kind}.minBytes`] = validated.minBytes;
|
||||
}
|
||||
if (validated.maxBytes !== undefined) {
|
||||
$set[`settings.media.${kind}.maxBytes`] = validated.maxBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys($set).length === 0) {
|
||||
throw new BadRequestException("No settings fields to update.");
|
||||
}
|
||||
|
||||
const updated = await this.clientDbService.findByIdAndUpdate(
|
||||
client._id.toString(),
|
||||
{ $set },
|
||||
);
|
||||
if (!updated) {
|
||||
throw new NotFoundException("Client not found");
|
||||
}
|
||||
|
||||
return this.getPanelSettings(client._id);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user