Files
hedena_gold/apps/api/src/modules/customer-profile/customer-profile.controller.ts
T

80 lines
2.9 KiB
TypeScript
Raw Normal View History

import {
Controller,
HttpCode,
Post,
UploadedFile,
UseInterceptors,
} from '@nestjs/common';
import { Body } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { CustomerProfileService } from './customer-profile.service';
import { AdminUploadsService } from '../admin-uploads/admin-uploads.service';
import { CompleteProfileDto } from './dto/complete-profile.dto';
import { CurrentCustomer, CustomerAuth } from '../customer-auth/customer.guards';
import type { AuthenticatedCustomer } from '../customer-auth/customer-jwt.strategy';
/** See AdminUploadsController — the same locally-declared multer subset. */
interface UploadedMulterFile {
originalname: string;
mimetype: string;
size: number;
buffer: Buffer;
}
/**
* The customer's own profile writes.
*
* Legacy endpoints:
* POST file/create -> the PWA's SingleImageUploader posted here with the
* customer token (routes/api.php:95, inside the
* `auth:api-customer` group)
* POST major/complete -> Major\CustomerController::complete
* (routes/api.php:114)
*
* Both are mounted under /customer/me here so the customer surface stays in one
* place. The subject always comes from the token — no id is accepted from the
* client, per D21.
*/
@Controller('customer/me')
export class CustomerProfileController {
constructor(
private readonly profile: CustomerProfileService,
private readonly uploads: AdminUploadsService,
) {}
/**
* A customer uploading one of their own documents.
*
* The reference let the app upload through the very same `file/create` the
* admin panel used, behind the customer guard (routes/api.php:95). The
* target's copy of that route sits behind an ADMIN guard
* (AdminUploadsController), which no app token can pass — so without this
* route the page could not upload at all.
*
* It reuses AdminUploadsService unchanged, so the size limit, the MIME
* whitelist and the stored-name scheme are identical on both paths. The
* uploader is recorded as null rather than as an admin, because
* `UploadedFile.uploadedByAdminUserId` is an AdminUser FK and this caller is
* a customer; `purpose` carries the document kind instead.
*/
@CustomerAuth()
@Post('documents')
@HttpCode(200)
@UseInterceptors(FileInterceptor('file'))
upload(
@UploadedFile() file: UploadedMulterFile | undefined,
@Body('purpose') purpose: string | undefined,
@CurrentCustomer() _me: AuthenticatedCustomer,
) {
return this.uploads.store(file, purpose ?? 'customer-document', null);
}
/** Ports POST major/complete. The customer is the token's. */
@CustomerAuth()
@Post('complete-profile')
@HttpCode(200)
complete(@Body() dto: CompleteProfileDto, @CurrentCustomer() me: AuthenticatedCustomer) {
return this.profile.complete(me.id, dto);
}
}