Bansari Akhani commited on
Commit
637e633
·
1 Parent(s): 40f79e1

activity logs and change S3 piblic access to signed urls

Browse files
src/controllers/invoice/invoice.controller.ts CHANGED
@@ -67,7 +67,7 @@ export const createInvoice = async (req: Request, res: Response) => {
67
  term: aiServiceData.terms,
68
  pw_work_order_id: aiServiceData.workOrderID,
69
  filename: file.originalname,
70
- pdf_url: (await uploadResults[index]).Location,
71
  uploaded_by: 1, // TODO : replace with logged in user when user module is implemented
72
  };
73
 
@@ -364,7 +364,7 @@ export const updateInvoiceData = async (invoiceId: number, updatedInvoiceData: a
364
 
365
  for (const key in updatedInvoiceData) {
366
  if (originalInvoiceData[key] !== updatedInvoiceData[key]) {
367
- await logInvoiceAction({ invoice_id: invoiceId, user_id: userId, activity_type: 'update', field_name: key, old_value: originalInvoiceData[key] as string, new_value: updatedInvoiceData[key] });
368
  }
369
  }
370
 
@@ -416,9 +416,6 @@ export const updateInvoice = async (req: Request, res: Response): Promise<Respon
416
  }
417
  };
418
 
419
-
420
-
421
-
422
  // Delete an invoice
423
  export const deleteInvoice = async (req: Request, res: Response): Promise<Response> => {
424
  try {
 
67
  term: aiServiceData.terms,
68
  pw_work_order_id: aiServiceData.workOrderID,
69
  filename: file.originalname,
70
+ pdf_url: (await uploadResults[index]).url,
71
  uploaded_by: 1, // TODO : replace with logged in user when user module is implemented
72
  };
73
 
 
364
 
365
  for (const key in updatedInvoiceData) {
366
  if (originalInvoiceData[key] !== updatedInvoiceData[key]) {
367
+ await logInvoiceAction({ invoice_id: invoiceId, user_id: userId, activity_type: 'update', field_name: key, old_value: originalInvoiceData[key] as string, new_value: updatedInvoiceData[key] as string });
368
  }
369
  }
370
 
 
416
  }
417
  };
418
 
 
 
 
419
  // Delete an invoice
420
  export const deleteInvoice = async (req: Request, res: Response): Promise<Response> => {
421
  try {
src/middlewares/multer.ts CHANGED
@@ -1,5 +1,6 @@
1
  import multer from 'multer';
2
  import AWS from 'aws-sdk';
 
3
 
4
  export const s3 = new AWS.S3({
5
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
@@ -12,3 +13,46 @@ const storage = multer.memoryStorage();
12
  const upload = multer({ storage });
13
 
14
  export const multipleUpload = upload.array('files');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import multer from 'multer';
2
  import AWS from 'aws-sdk';
3
+ import { GenerateDownloadUrlParams, GenerateSignedUrlParams } from 'shared/interfaces/s3.interface';
4
 
5
  export const s3 = new AWS.S3({
6
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
 
13
  const upload = multer({ storage });
14
 
15
  export const multipleUpload = upload.array('files');
16
+
17
+ export const generateSignedUrl = async ({
18
+ bucketName,
19
+ objectKey,
20
+ expiration = 3600,
21
+ contentType = 'application/octet-stream',
22
+ }: GenerateSignedUrlParams): Promise<string> => {
23
+ const params = {
24
+ Bucket: bucketName,
25
+ Key: objectKey,
26
+ Expires: expiration,
27
+ ContentType: contentType,
28
+ };
29
+
30
+ try {
31
+ const url = await s3.getSignedUrlPromise('putObject', params);
32
+
33
+ return url;
34
+ } catch (err) {
35
+ console.error('Error generating signed URL', err);
36
+ throw err;
37
+ }
38
+ };
39
+
40
+ export const generateDownloadUrl = async ({
41
+ bucketName,
42
+ objectKey,
43
+ expiration = 60 * 60 * 24 * 365 * 10 // URL EXPIRY is set to 10 years for now, TODO: change the logic in frontend to get file download url run time
44
+ }: GenerateDownloadUrlParams): Promise<string> => {
45
+ const params = {
46
+ Bucket: bucketName,
47
+ Key: objectKey,
48
+ Expires: expiration,
49
+ };
50
+
51
+ try {
52
+ const url = await s3.getSignedUrlPromise('getObject', params);
53
+ return url;
54
+ } catch (err) {
55
+ console.error('Error generating signed URL', err);
56
+ throw err;
57
+ }
58
+ };
src/shared/interfaces/s3.interface.ts ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export interface GenerateSignedUrlParams {
2
+ bucketName: string;
3
+ objectKey: string;
4
+ expiration?: number;
5
+ contentType?: string;
6
+ }
7
+ export interface GenerateDownloadUrlParams {
8
+ bucketName: string;
9
+ objectKey: string;
10
+ expiration?: number;
11
+ }
src/shared/services/invoice.service.ts CHANGED
@@ -1,17 +1,44 @@
1
- import { s3 } from '../../middlewares/multer';
2
 
3
- export const uploadInvoice = (files: Express.Multer.File[]) => {
4
- const uploadPromises = files.map(file => {
5
- const params = {
6
- Bucket: process.env.AWS_S3_BUCKET_NAME || '',
7
- Key: Date.now().toString() + '-' + file.originalname,
8
- Body: file.buffer,
9
- ContentType: 'application/pdf',
10
- ContentDisposition: 'inline'
11
- };
12
 
13
- return s3.upload(params).promise();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  });
15
 
16
- return uploadPromises;
 
 
 
 
 
 
 
 
 
17
  };
 
1
+ import { s3, generateSignedUrl, generateDownloadUrl } from '../../middlewares/multer';
2
 
3
+ export const uploadInvoice = async (files: Express.Multer.File[]) => {
4
+ const uploadPromises = files.map(async (file) => {
5
+ const objectKey = Date.now().toString() + '-' + file.originalname;
6
+ const bucketName = process.env.AWS_S3_BUCKET_NAME || '';
 
 
 
 
 
7
 
8
+ try {
9
+ const signedUrl = await generateSignedUrl({
10
+ bucketName,
11
+ objectKey,
12
+ contentType: file.mimetype,
13
+ });
14
+
15
+ // Use fetch to upload the file using the signed URL
16
+ const response = await fetch(signedUrl, {
17
+ method: 'PUT',
18
+ headers: {
19
+ 'Content-Type': file.mimetype,
20
+ },
21
+ body: file.buffer,
22
+ });
23
+
24
+ if (!response.ok) {
25
+ throw new Error('File upload failed');
26
+ }
27
+
28
+ // Generate download URL
29
+ const downloadUrl = await generateDownloadUrl({
30
+ bucketName: process.env.AWS_S3_BUCKET_NAME || '',
31
+ objectKey,
32
  });
33
 
34
+ return { file: file.originalname, url: downloadUrl };
35
+
36
+ } catch (err) {
37
+ console.error('Error uploading file', err);
38
+ throw err;
39
+ }
40
+ });
41
+
42
+ return uploadPromises;
43
+ // return Promise.all(uploadPromises);
44
  };