From 4c47b0b7d14127c91b36ab4e232f136ee085a457 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 26 Mar 2025 15:17:50 +0700 Subject: [PATCH] feat: add signature endpoints --- src/controllers/02-user-controller.ts | 40 +++++++++++++++++++++++++++ src/utils/minio.ts | 7 +++++ 2 files changed, 47 insertions(+) diff --git a/src/controllers/02-user-controller.ts b/src/controllers/02-user-controller.ts index f5ddbde..d28ef34 100644 --- a/src/controllers/02-user-controller.ts +++ b/src/controllers/02-user-controller.ts @@ -37,6 +37,7 @@ import { getPresigned, listFile, setFile, + uploadFile, } from "../utils/minio"; import { filterStatus } from "../services/prisma"; import { @@ -878,3 +879,42 @@ export class UserAttachmentController extends Controller { ); } } + +@Route("api/v1/user/{userId}/signature") +@Security("keycloak") +export class UserSignatureController extends Controller { + #checkPermission(req: RequestWithUser, userId: string) { + if (req.user.sub !== userId) { + throw new HttpError( + HttpStatus.FORBIDDEN, + "You do not have permission to perform this action.", + "noPermission", + ); + } + } + + @Get() + async getSignature(@Request() req: RequestWithUser, @Path() userId: string) { + this.#checkPermission(req, userId); + return req.res?.redirect(await getFile(fileLocation.user.signature(userId))); + } + + @Put() + async setSignature( + @Request() req: RequestWithUser, + @Path() userId: string, + @Body() signature?: { data: string }, + ) { + this.#checkPermission(req, userId); + + const base64 = signature?.data; + + if (base64) { + const buffer = Buffer.from(base64.replace(/^data:image\/\w+;base64,/, ""), "base64"); + const mime = "image/" + base64.split(";")[0].split("/")[1]; + await uploadFile(fileLocation.user.signature(userId), buffer, mime); + } else { + return await setFile(fileLocation.user.signature(userId)); + } + } +} diff --git a/src/utils/minio.ts b/src/utils/minio.ts index dc5e244..e80108d 100644 --- a/src/utils/minio.ts +++ b/src/utils/minio.ts @@ -35,6 +35,12 @@ export async function setFile(path: string, exp = 6 * 60 * 60) { return await minio.presignedPutObject(MINIO_BUCKET, path, exp); } +export async function uploadFile(path: string, buffer: Buffer, contentType?: string) { + await minio.putObject(MINIO_BUCKET, path, buffer, Buffer.byteLength(buffer), { + ["Content-Type"]: contentType, + }); +} + export async function deleteFile(path: string) { await minio.removeObject(MINIO_BUCKET, path, { forceDelete: true }); } @@ -70,6 +76,7 @@ export const fileLocation = { `${ROOT}/user/profile-image-${userId}/${name || ""}`, attachment: (userId: string, name?: string) => `${ROOT}/user/attachment-${userId}/${name || ""}`, + signature: (userId: string) => `${ROOT}/user/signature-${userId}`, }, customer: { img: (customerId: string, name?: string) => `${ROOT}/customer/img-${customerId}/${name || ""}`,