-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgetAttachmentUrl.ts
139 lines (120 loc) · 3.8 KB
/
getAttachmentUrl.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { handleOpensearchError } from "./utils";
import { response } from "libs/handler-lib";
import { APIGatewayEvent } from "aws-lambda";
import { STSClient, AssumeRoleCommand } from "@aws-sdk/client-sts";
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { getStateFilter } from "../libs/api/auth/user";
import { getPackage, getPackageChangelog } from "../libs/api/package";
import { getDomain } from "libs/utils";
// Handler function to get Seatool data
export const handler = async (event: APIGatewayEvent) => {
try {
getDomain();
} catch (error) {
return response({
statusCode: 500,
body: { message: `ERROR: ${error?.message || error}` },
});
}
if (!event.body) {
return response({
statusCode: 400,
body: { message: "Event body required" },
});
}
try {
const body = JSON.parse(event.body);
const mainResult = await getPackage(body.id);
if (!mainResult) {
return response({
statusCode: 404,
body: { message: "No record found for the given id" },
});
}
const stateFilter = await getStateFilter(event);
if (stateFilter) {
const stateAccessAllowed = stateFilter?.terms.state.includes(
mainResult?._source?.state?.toLocaleLowerCase() || "",
);
if (!stateAccessAllowed) {
return response({
statusCode: 404,
body: { message: "state access not permitted for the given id" },
});
}
}
// add state
// Do we want to check
const changelogs = await getPackageChangelog(body.id);
const attachmentExists = changelogs.hits.hits.some((CL) => {
return CL._source.attachments?.some(
(ATT) => ATT.bucket === body.bucket && ATT.key === body.key,
);
});
if (!attachmentExists) {
return response({
statusCode: 500,
body: {
message: "Attachment details not found for given record id.",
},
});
}
// Now we can generate the presigned url
const url = await generatePresignedUrl(body.bucket, body.key, body.filename, 60);
return response<unknown>({
statusCode: 200,
body: { url },
});
} catch (error) {
return response(handleOpensearchError(error));
}
};
async function getClient(bucket: string) {
if (bucket.startsWith("uploads")) {
const stsClient = new STSClient({});
// Assume the role
const assumedRoleResponse = await stsClient.send(
new AssumeRoleCommand({
RoleArn: process.env.legacyS3AccessRoleArn,
RoleSessionName: "AssumedRoleSession",
}),
);
// Extract the assumed role credentials
const assumedCredentials = assumedRoleResponse.Credentials;
if (!assumedCredentials) {
throw new Error("No assumed redentials");
}
// Create S3 client using the assumed role's credentials
return new S3Client({
credentials: {
accessKeyId: assumedCredentials.AccessKeyId as string,
secretAccessKey: assumedCredentials.SecretAccessKey as string,
sessionToken: assumedCredentials.SessionToken,
},
});
} else {
return new S3Client({});
}
}
//TODO: add check for resource before signing URL
async function generatePresignedUrl(
bucket: string,
key: string,
filename: string,
expirationInSeconds: number,
) {
// Get an S3 client
const client = await getClient(bucket);
// Create a command to get the object (you can adjust this according to your use case)
const getObjectCommand = new GetObjectCommand({
Bucket: bucket,
Key: key,
ResponseContentDisposition: `filename ="${filename}"`,
});
// Generate a presigned URL
const presignedUrl = await getSignedUrl(client, getObjectCommand, {
expiresIn: expirationInSeconds,
});
return presignedUrl;
}