Fix file upload for any member

This commit is contained in:
Arthur Belleville 2025-11-16 14:06:05 +01:00
parent cd309d30df
commit 9f0c3b530f
No known key found for this signature in database
2 changed files with 140 additions and 31 deletions

View file

@ -230,6 +230,116 @@ describe("TabloData Endpoint", () => {
});
});
describe("POST /tablo-data/:tabloId/:fileName - Upload File (Member Access)", () => {
// Helper function to upload file
const postTabloFileRequest = async (
user: TestUserData,
// biome-ignore lint/suspicious/noExplicitAny: testClient requires any for dynamic route access
client: any,
tabloId: string,
fileName: string,
content: string
) => {
return await client["tablo-data"][":tabloId"][":fileName"].$post(
{
param: { tabloId, fileName },
json: { content, contentType: "text/plain" },
},
{
headers: { Authorization: `Bearer ${user.accessToken}` },
}
);
};
describe("Temporary User Access", () => {
it("should allow temp user to upload file to their own tablo", async () => {
const res = await postTabloFileRequest(
temporaryUser,
client,
"test_tablo_temp_private",
"new-file.txt",
"Test content"
);
expect(res.status).toBe(200);
const data = await res.json();
expect(data.message).toBe("File uploaded successfully");
expect(data.fileName).toBe("new-file.txt");
});
it("should allow temp user to upload file to owner's shared tablo", async () => {
const res = await postTabloFileRequest(
temporaryUser,
client,
"test_tablo_owner_shared",
"temp-upload.txt",
"Temporary user content"
);
expect(res.status).toBe(200);
const data = await res.json();
expect(data.message).toBe("File uploaded successfully");
});
it("should deny temp user from uploading file to owner's private tablo", async () => {
const res = await postTabloFileRequest(
temporaryUser,
client,
"test_tablo_owner_private",
"unauthorized.txt",
"Should fail"
);
expect(res.status).toBe(403);
});
});
describe("Owner Access", () => {
it("should allow owner to upload file to their own tablo", async () => {
const res = await postTabloFileRequest(
ownerUser,
client,
"test_tablo_owner_private",
"owner-file.txt",
"Owner content"
);
expect(res.status).toBe(200);
const data = await res.json();
expect(data.message).toBe("File uploaded successfully");
});
});
describe("Validation", () => {
it("should return 400 if content is missing", async () => {
const res = await client["tablo-data"][":tabloId"][":fileName"].$post(
{
param: { tabloId: "test_tablo_owner_private", fileName: "test.txt" },
json: { contentType: "text/plain" },
},
{
headers: { Authorization: `Bearer ${ownerUser.accessToken}` },
}
);
expect(res.status).toBe(400);
const data = await res.json();
expect(data.error).toBe("Content is required");
});
});
describe("Unauthenticated Access", () => {
it("should deny unauthenticated upload attempt", async () => {
const res = await client["tablo-data"][":tabloId"][":fileName"].$post({
param: { tabloId: "test_tablo_owner_private", fileName: "test.txt" },
json: { content: "test content" },
});
expect(res.status).toBe(401);
});
});
});
describe("DELETE /tablo-data/:tabloId/:fileName - Delete File (Admin Only)", () => {
// Helper function to delete file
const deleteTabloFileRequest = async (

View file

@ -54,40 +54,39 @@ const getTabloFile = factory.createHandlers(checkTabloMember, async (c) => {
}
});
const postTabloFile = (middlewareManager: ReturnType<typeof MiddlewareManager.getInstance>) =>
factory.createHandlers(middlewareManager.regularUserCheck, checkTabloMember, async (c) => {
const tabloId = c.req.param("tabloId");
const fileName = c.req.param("fileName");
const postTabloFile = factory.createHandlers(checkTabloMember, async (c) => {
const tabloId = c.req.param("tabloId");
const fileName = c.req.param("fileName");
const s3_client = c.get("s3_client");
const s3_client = c.get("s3_client");
try {
const body = await c.req.json();
const { content, contentType = "text/plain" } = body;
try {
const body = await c.req.json();
const { content, contentType = "text/plain" } = body;
if (!content) {
return c.json({ error: "Content is required" }, 400);
}
await s3_client.send(
new PutObjectCommand({
Bucket: "tablo-data",
Key: `${tabloId}/${fileName}`,
Body: content,
ContentType: contentType,
})
);
return c.json({
message: "File uploaded successfully",
fileName,
tabloId,
});
} catch (error) {
console.error("Error uploading file:", error);
return c.json({ error: "Failed to upload file" }, 500);
if (!content) {
return c.json({ error: "Content is required" }, 400);
}
});
await s3_client.send(
new PutObjectCommand({
Bucket: "tablo-data",
Key: `${tabloId}/${fileName}`,
Body: content,
ContentType: contentType,
})
);
return c.json({
message: "File uploaded successfully",
fileName,
tabloId,
});
} catch (error) {
console.error("Error uploading file:", error);
return c.json({ error: "Failed to upload file" }, 500);
}
});
// // PUT /tablo-data/:tabloId/:fileName - Update a file
// tabloDataRouter.put("/:tabloId/:fileName", async (c) => {
@ -162,7 +161,7 @@ export const getTabloDataRouter = () => {
tabloDataRouter.get("/:tabloId/filenames", ...getTabloFilenames);
tabloDataRouter.get("/:tabloId/:fileName", ...getTabloFile);
tabloDataRouter.post("/:tabloId/:fileName", ...postTabloFile(middlewareManager));
tabloDataRouter.post("/:tabloId/:fileName", ...postTabloFile);
tabloDataRouter.delete("/:tabloId/:fileName", ...deleteTabloFile(middlewareManager));
return tabloDataRouter;