feat: Implement pre-signed URL generation for message attachments with dedicated DTO, controller endpoint, and service logic.

This commit is contained in:
pradeepkumar
2026-02-21 22:12:19 +05:30
parent 89a036b410
commit dd6636dbb3
3 changed files with 50 additions and 1 deletions

View File

@@ -6,6 +6,7 @@ export enum UploadFolder {
DOCUMENTS = 'documents',
PROPERTIES = 'properties',
VERIFICATION = 'verification',
MESSAGES = 'messages',
}
export class PresignedUrlDto {
@@ -52,6 +53,22 @@ export class PresignedUrlResponseDto {
key: string;
}
export class MessagePresignedUrlDto {
@ApiProperty({
example: 'photo.jpg',
description: 'Original filename',
})
@IsString()
filename: string;
@ApiProperty({
example: 'image/jpeg',
description: 'MIME type of the file',
})
@IsString()
contentType: string;
}
export class AvatarPresignedUrlDto {
@ApiProperty({
example: 'profile.jpg',

View File

@@ -20,7 +20,8 @@ import {
} from '@nestjs/swagger';
import type { Response } from 'express';
import { UploadService } from './upload.service';
import { PresignedUrlDto, PresignedUrlResponseDto, AvatarPresignedUrlDto } from './dto';
import { PresignedUrlDto, PresignedUrlResponseDto, AvatarPresignedUrlDto, MessagePresignedUrlDto } from './dto';
import { UploadFolder } from './dto';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../auth/guards/roles.guard';
import { Roles } from '../auth/decorators/roles.decorator';
@@ -53,6 +54,27 @@ export class UploadController {
return this.uploadService.getPresignedUrl(dto);
}
@Post('message-presigned-url')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles(UserRole.USER, UserRole.AGENT)
@ApiBearerAuth()
@ApiOperation({ summary: 'Get a pre-signed URL for message attachment upload (images and documents)' })
@ApiResponse({
status: 200,
description: 'Pre-signed URL generated successfully',
type: PresignedUrlResponseDto,
})
@ApiResponse({ status: 400, description: 'Invalid content type' })
async getMessagePresignedUrl(
@Body() dto: MessagePresignedUrlDto,
): Promise<PresignedUrlResponseDto> {
return this.uploadService.getPresignedUrl({
filename: dto.filename,
contentType: dto.contentType,
folder: UploadFolder.MESSAGES,
});
}
@Post('avatar-presigned-url')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles(UserRole.AGENT)

View File

@@ -66,6 +66,7 @@ export class UploadService {
[UploadFolder.DOCUMENTS]: 7 * 24 * 60 * 60, // 7 days
[UploadFolder.PROPERTIES]: 30 * 24 * 60 * 60, // 30 days
[UploadFolder.VERIFICATION]: 1 * 24 * 60 * 60, // 1 day
[UploadFolder.MESSAGES]: 30 * 24 * 60 * 60, // 30 days
};
return `public, max-age=${cacheDurations[folder] || 86400}`;
}
@@ -92,6 +93,15 @@ export class UploadService {
'image/jpeg',
'image/png',
],
[UploadFolder.MESSAGES]: [
'image/jpeg',
'image/png',
'image/webp',
'image/gif',
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
],
};
const allowed = allowedTypes[folder];