aboutsummaryrefslogtreecommitdiffstats
path: root/packages/api/routes/public.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/api/routes/public.ts')
-rw-r--r--packages/api/routes/public.ts47
1 files changed, 47 insertions, 0 deletions
diff --git a/packages/api/routes/public.ts b/packages/api/routes/public.ts
new file mode 100644
index 00000000..d17049c4
--- /dev/null
+++ b/packages/api/routes/public.ts
@@ -0,0 +1,47 @@
+import { zValidator } from "@hono/zod-validator";
+import { and, eq } from "drizzle-orm";
+import { Hono } from "hono";
+import { z } from "zod";
+
+import { assets } from "@karakeep/db/schema";
+import { verifySignedToken } from "@karakeep/shared/signedTokens";
+import { zAssetSignedTokenSchema } from "@karakeep/shared/types/assets";
+
+import { unauthedMiddleware } from "../middlewares/auth";
+import { serveAsset } from "../utils/assets";
+
+const app = new Hono().get(
+ "/assets/:assetId",
+ unauthedMiddleware,
+ zValidator(
+ "query",
+ z.object({
+ token: z.string(),
+ }),
+ ),
+ async (c) => {
+ const assetId = c.req.param("assetId");
+ const tokenPayload = verifySignedToken(
+ c.req.valid("query").token,
+ zAssetSignedTokenSchema,
+ );
+ if (!tokenPayload) {
+ return c.json({ error: "Invalid or expired token" }, { status: 403 });
+ }
+ if (tokenPayload.assetId !== assetId) {
+ return c.json({ error: "Invalid or expired token" }, { status: 403 });
+ }
+ const userId = tokenPayload.userId;
+
+ const assetDb = await c.var.ctx.db.query.assets.findFirst({
+ where: and(eq(assets.id, assetId), eq(assets.userId, userId)),
+ });
+
+ if (!assetDb) {
+ return c.json({ error: "Asset not found" }, { status: 404 });
+ }
+ return await serveAsset(c, assetId, userId);
+ },
+);
+
+export default app;