-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathlookupshare.ts
More file actions
108 lines (94 loc) · 3.44 KB
/
lookupshare.ts
File metadata and controls
108 lines (94 loc) · 3.44 KB
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
import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3";
import type { VercelRequest, VercelResponse } from "@vercel/node";
export const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
export default async function handler(req: VercelRequest, res: VercelResponse) {
const shareid = req.query.shareid ?? "";
if (typeof shareid !== "string") {
return res.status(400).json({ error: "Invalid shareid" });
}
if (!shareid) {
return res.status(400).json({ error: "Share ID is required" });
}
// Validate shareid contains only allowed characters
for (const char of shareid) {
if (!encodeURL.includes(char)) {
return res.status(400).json({ error: "Invalid characters in share ID" });
}
}
// Check for required environment variables
const s3Endpoint = process.env.S3_ENDPOINT;
const s3Bucket = process.env.S3_BUCKET;
if (!s3Endpoint || !s3Bucket) {
console.warn("S3_ENDPOINT or S3_BUCKET environment variables are not set");
return res.status(404).json({ error: "Share not found" });
}
try {
// Initialize S3 client
const s3Client = new S3Client({
endpoint: s3Endpoint,
region: "auto",
});
// Get object from S3
const command = new GetObjectCommand({
Bucket: s3Bucket,
Key: `shared/${shareid}`,
});
const response = await s3Client.send(command);
if (!response.Body) {
return res.status(404).json({ error: "Share not found" });
}
// Read the stream and convert to string
const bodyContents = await response.Body.transformToString();
// Parse JSON
let shareData;
try {
shareData = JSON.parse(bodyContents);
} catch (error) {
console.error("Error parsing JSON for share store:", shareid, error);
return res.status(400).json({ error: "Invalid JSON in share data" });
}
// Validate version
if (shareData.version !== "2") {
return res.status(400).json({ error: "Older version is unsupported" });
}
// Validate required string keys if present
const requiredStringKeys = [
"schema",
"relationships_yaml",
"validation_yaml",
"assertions_yaml",
];
for (const key of requiredStringKeys) {
if (key in shareData && typeof shareData[key] !== "string") {
return res.status(400).json({ error: "Share data is not supported" });
}
}
if ("check_watches" in shareData) {
if (!Array.isArray(shareData.check_watches)) {
return res.status(400).json({ error: "Share data is not supported" });
}
for (const w of shareData.check_watches) {
if (typeof w !== "object" || w === null) {
return res.status(400).json({ error: "Share data is not supported" });
}
if (
typeof w.object !== "string" ||
typeof w.action !== "string" ||
typeof w.subject !== "string"
) {
return res.status(400).json({ error: "Share data is not supported" });
}
if ("context" in w && typeof w.context !== "string") {
return res.status(400).json({ error: "Share data is not supported" });
}
}
}
return res.status(200).send(bodyContents);
} catch (error) {
if (error instanceof Error && error.name === "NoSuchKey") {
return res.status(404).json({ error: "Share not found" });
}
console.error("Error retrieving share data:", error);
return res.status(500).json({ error: "Internal server error" });
}
}