Files
MinglarBackendNestJS/src/modules/minglaradmin/handlers/updateProfile.ts

201 lines
6.5 KiB
TypeScript

// modules/minglar/handlers/updateProfile.ts
import config from '../../../config/config';
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
import AWS from 'aws-sdk';
import { prismaClient } from '../../../common/database/prisma.lambda.service';
import { verifyMinglarAdminToken } from '../../../common/middlewares/jwt/authForMinglarAdmin';
import { safeHandler } from '../../../common/utils/handlers/safeHandler';
import ApiError from '../../../common/utils/helper/ApiError';
import { parseJsonField, parseMultipartFormData } from '../../../common/utils/helper/parseMultipartFormData';
import { MinglarService } from '../services/minglar.service';
const minglarService = new MinglarService(prismaClient);
const s3 = new AWS.S3({
region: config.aws.region,
});
// Define uploadToS3 function with proper folder structure and file replacement
async function uploadToS3(buffer: Buffer, mimeType: string, originalName: string, folderType: 'profile' | 'documents', userId: number, documentType?: string) {
let s3Key: string;
// Sanitize file name: remove special characters and spaces
const sanitizeFileName = (name: string) => {
return name
.toLowerCase()
.replace(/[^a-z0-9.]/g, '_') // Replace special characters with underscore
.replace(/_+/g, '_') // Replace multiple underscores with single
.replace(/^_+|_+$/g, ''); // Remove leading/trailing underscores
};
// Get file extension from original file name
const fileExtension = originalName.split('.').pop() || 'jpg';
// Determine folder structure based on type
if (folderType === 'profile') {
// Profile Images: MinglarAdmin/ProfileImages/{UserID}/profile_image.{extension}
const fileName = `profile_image.${fileExtension}`;
const sanitizedFileName = sanitizeFileName(fileName);
s3Key = `MinglarAdmin/ProfileImages/${userId}/${sanitizedFileName}`;
} else if (folderType === 'documents' && documentType) {
// Documents: MinglarAdmin/Documents/{UserID}/{documentType}.{extension}
const fileName = `${documentType}.${fileExtension}`;
const sanitizedFileName = sanitizeFileName(fileName);
s3Key = `MinglarAdmin/Documents/${userId}/${sanitizedFileName}`;
} else {
throw new ApiError(400, 'Invalid folder type or missing documentType');
}
// Upload new file (S3 will automatically replace if same key exists)
await s3
.upload({
Bucket: config.aws.bucketName,
Key: s3Key,
Body: buffer,
ContentType: mimeType,
ACL: 'private',
})
.promise();
console.log(`File uploaded successfully: ${s3Key}`);
return `https://${config.aws.bucketName}.s3.${config.aws.region}.amazonaws.com/${s3Key}`;
}
export const handler = safeHandler(async (
event: APIGatewayProxyEvent,
context?: Context
): Promise<APIGatewayProxyResult> => {
try {
// Extract token from headers
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
if (!token) {
throw new ApiError(400, 'This is a protected route. Please provide a valid token.');
}
// Verify token and get user info
const userInfo = await verifyMinglarAdminToken(token);
const userId = Number(userInfo.id);
if (!userId || isNaN(userId)) {
throw new ApiError(400, 'Invalid user ID');
}
// Parse multipart form data
const contentType = event.headers['Content-Type'] || event.headers['content-type'];
const isBase64Encoded = event.isBase64Encoded || false;
const { fields, files } = parseMultipartFormData(
event.body,
contentType,
isBase64Encoded
);
// Parse JSON fields
const userData = parseJsonField(fields, 'userData') || {};
const addressData = parseJsonField(fields, 'addressData') || {};
// Extract user fields
const { firstName, lastName, mobileNumber, dateOfBirth, profileImage } = userData;
// Extract address fields
const { address1, address2, stateXid, countryXid, cityXid, pinCode } = addressData;
// Handle file uploads with proper folder structure and replacement
const uploadedFiles: Array<{ fileName: string; filePath: string; documentType?: string, documentTypeName?: string }> = [];
let profileImagePath: string | undefined = profileImage;
// Upload profile image if provided as file
const profileImageFile = files.find(f => f.fieldName === 'profileImage');
if (profileImageFile) {
profileImagePath = await uploadToS3(
profileImageFile.data,
profileImageFile.contentType,
profileImageFile.fileName,
'profile',
userId
);
console.log('Profile image uploaded:', profileImagePath);
}
// Upload documents (aadharCard, panCard) with proper naming and replacement
const aadharFile = files.find(f => f.fieldName === 'aadharCard');
const panFile = files.find(f => f.fieldName === 'panCard');
if (aadharFile) {
const filePath = await uploadToS3(
aadharFile.data,
aadharFile.contentType,
aadharFile.fileName,
'documents',
userId,
'aadhar'
);
uploadedFiles.push({
fileName: aadharFile.fileName,
filePath,
documentType: 'aadhar',
documentTypeName: 'aadhar'
});
console.log('Aadhar document uploaded:', filePath);
}
if (panFile) {
const filePath = await uploadToS3(
panFile.data,
panFile.contentType,
panFile.fileName,
'documents',
userId,
'pan'
);
uploadedFiles.push({
fileName: panFile.fileName,
filePath,
documentType: 'pan',
documentTypeName: 'pan'
});
console.log('PAN document uploaded:', filePath);
}
// Update profile using service
const result = await minglarService.updateProfile(
userId,
{
firstName,
lastName,
mobileNumber,
dateOfBirth,
profileImage: profileImagePath,
},
{
address1,
address2,
stateXid,
countryXid,
cityXid,
pinCode,
},
uploadedFiles.filter(f => f.documentType).map(f => ({
fileName: f.fileName,
filePath: f.filePath,
documentTypeName: f.documentTypeName,
}))
);
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify({
success: true,
message: 'Profile updated successfully',
data: result,
}),
};
} catch (error: any) {
console.error('❌ Error in updateProfile:', error);
throw error;
}
});