diff options
| author | 2023-04-18 03:02:17 +0800 | |
|---|---|---|
| committer | 2023-04-18 03:02:17 +0800 | |
| commit | 4919f028c884a041da7ff098abb02389b4eac598 (patch) | |
| tree | b0f482568c4b8c8a680ce6e2e70a7b7ca87dc190 /pages/api/v1 | |
| parent | b135aac8531c1e1488147ad8c6f98eddbdbe0c99 (diff) | |
| download | HydroRoll-4919f028c884a041da7ff098abb02389b4eac598.tar.gz HydroRoll-4919f028c884a041da7ff098abb02389b4eac598.zip | |
✨add envshare docs
Diffstat (limited to 'pages/api/v1')
| -rw-r--r-- | pages/api/v1/load.ts | 36 | ||||
| -rw-r--r-- | pages/api/v1/og.tsx | 64 | ||||
| -rw-r--r-- | pages/api/v1/secret/[id].ts | 58 | ||||
| -rw-r--r-- | pages/api/v1/secret/index.ts | 96 | ||||
| -rw-r--r-- | pages/api/v1/store.ts | 38 |
5 files changed, 0 insertions, 292 deletions
diff --git a/pages/api/v1/load.ts b/pages/api/v1/load.ts deleted file mode 100644 index ddbfac0..0000000 --- a/pages/api/v1/load.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { NextRequest, NextResponse } from "next/server"; -import { Redis } from "@upstash/redis"; - -const redis = Redis.fromEnv(); -export default async function handler(req: NextRequest) { - const url = new URL(req.url); - const id = url.searchParams.get("id"); - if (!id) { - return new NextResponse("id param is missing", { status: 400 }); - } - const key = ["envshare", id].join(":"); - - const [data, _] = await Promise.all([ - await redis.hgetall<{ encrypted: string; remainingReads: number | null; iv: string }>(key), - await redis.incr("envshare:metrics:reads"), - ]); - if (!data) { - return new NextResponse("Not Found", { status: 404 }); - } - if (data.remainingReads !== null && data.remainingReads < 1) { - await redis.del(key); - return new NextResponse("Not Found", { status: 404 }); - } - - let remainingReads: number | null = null; - if (data.remainingReads !== null) { - // Decrement the number of reads and return the remaining reads - remainingReads = await redis.hincrby(key, "remainingReads", -1); - } - - return NextResponse.json({ iv: data.iv, encrypted: data.encrypted, remainingReads }); -} - -export const config = { - runtime: "edge", -}; diff --git a/pages/api/v1/og.tsx b/pages/api/v1/og.tsx deleted file mode 100644 index dad6531..0000000 --- a/pages/api/v1/og.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { ImageResponse } from "@vercel/og"; -import { NextRequest } from "next/server"; - -export const config = { - runtime: "edge", -}; - -export default async function handler(req: NextRequest) { - try { - const { searchParams } = new URL(req.url); - // Redundant fallback alternate tagline - const title = searchParams.get("title") ?? "Share Environment Variables Securely"; - const subtitle = searchParams.get("subtitle") ?? "EnvShare"; - - const inter = await fetch(new URL("../../../public/fonts/Inter-SemiBold.ttf", import.meta.url)).then((res) => - res.arrayBuffer(), - ); - - // TODO: Fix tailwind classes on this route - return new ImageResponse( - <div tw='w-[1200px] h-[630px] flex flex-col items-center justify-center text-center'> - {/* backgroundImage: bg-gradient-to-tr from-zinc-900/50 to-zinc-700/30 */} - <div - tw="bg-black w-full h-full flex" - style={{ backgroundImage: "linear-gradient(to top right, rgba(24,24,27,.5), rgba(63,63,70,.3))" }} - > - <div tw="flex flex-col text-3xl tracking-tight text-gray-300 w-full items-center h-full justify-center text-center"> - {/* font-semibold bg-gradient-to-t bg-clip-text from-zinc-100/50 to-white whitespace-pre */} - <h1 - tw="text-white text-7xl" - style={{ - color: "transparent", - paddingLeft: "12rem", - paddingRight: "12rem", - backgroundImage: "linear-gradient(to top, rgba(244, 244, 245, .5), rgba(255,255,255,1))", - backgroundClip: "text", - }} - > - {title} - </h1> - <p tw="mt-4 font-bold">{subtitle}</p> - </div> - </div> - </div>, - { - height: 630, - width: 1200, - emoji: "twemoji", - fonts: [ - { - name: "Inter", - data: inter, - style: "normal", - }, - ], - }, - ); - } catch (e) { - console.log(`${(e as Error).message}`); - return new Response("Failed to generate the image", { - status: 500, - }); - } -} diff --git a/pages/api/v1/secret/[id].ts b/pages/api/v1/secret/[id].ts deleted file mode 100644 index 8b5f082..0000000 --- a/pages/api/v1/secret/[id].ts +++ /dev/null @@ -1,58 +0,0 @@ -import { NextRequest, NextResponse } from "next/server"; -import { Redis } from "@upstash/redis"; -import { z } from "zod"; - -const responseValidation = z.union([ - z.object({ - data: z.object({ - remainingReads: z.number().int().optional(), - secret: z.string(), - }), - }), - z.object({ - error: z.string(), - }), -]); - -const redis = Redis.fromEnv(); -export default async function handler(req: NextRequest): Promise<NextResponse> { - try { - if (req.method !== "GET") { - return NextResponse.json({ error: "Method Not Allowed" }, { status: 405 }); - } - const id = new URL(req.url).searchParams.get("id"); - if (!id) { - return NextResponse.json({ error: "Missing `id` parameter" }, { status: 400 }); - } - - const redisKey = ["envshare", id].join(":"); - - const [data, _] = await Promise.all([ - await redis.hgetall<{ secret: string; remainingReads: number | null }>(redisKey), - await redis.incr("envshare:metrics:reads"), - ]); - - if (!data) { - return NextResponse.json({ error: "Not Found" }, { status: 404 }); - } - if (data.remainingReads !== null && data.remainingReads < 1) { - await redis.del(redisKey); - return NextResponse.json({ error: "Not Found" }, { status: 404 }); - } - - let remainingReads: number | null = null; - if (data.remainingReads !== null) { - // Decrement the number of reads and return the remaining reads - remainingReads = await redis.hincrby(redisKey, "remainingReads", -1); - } - - return NextResponse.json({ data: { secret: data.secret, remainingReads: remainingReads ?? undefined } }); - } catch (e) { - console.error(e); - return NextResponse.json({ error: "Internal Server Error" }, { status: 500 }); - } -} - -export const config = { - runtime: "edge", -}; diff --git a/pages/api/v1/secret/index.ts b/pages/api/v1/secret/index.ts deleted file mode 100644 index 423e7a0..0000000 --- a/pages/api/v1/secret/index.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { NextRequest, NextResponse } from "next/server"; -import { Redis } from "@upstash/redis"; -import { generateId } from "pkg/id"; -import { z } from "zod"; - -export const requestValidation = z.object({ - // ttl in seconds - // defaults to 30 days - // not more than 1 year - // 0 means no expiration - ttl: z - .string() - .nullable() - .transform((v) => (v ? parseInt(v, 10) : 43260)) - .refine((v) => v >= 0 && v <= 30758400, "ttl must be between 0 and 30758400 seconds"), - - // number of reads before deletion - // defaults to null (no limit) - reads: z - .string() - .nullable() - .transform((v) => (v ? parseInt(v, 10) : null)) - .refine((v) => v === null || v > 0, "reads must be greater than 0"), - secret: z.string().min(1), -}); -export const responseValidation = z.union([ - z.object({ - data: z.object({ - id: z.string(), - ttl: z.number().optional(), - reads: z.number().optional(), - expiresAt: z.string(), - url: z.string().url(), - }), - }), - z.object({ - error: z.string(), - }), -]); - -const redis = Redis.fromEnv(); - -export default async function handler(req: NextRequest): Promise<NextResponse> { - try { - if (req.method !== "POST") { - return NextResponse.json({ error: "Method Not Allowed" }, { status: 405 }); - } - - const parsed = requestValidation.safeParse({ - ttl: req.headers.get("envshare-ttl"), - reads: req.headers.get("envshare-reads"), - secret: await req.text(), - }); - if (!parsed.success) { - return NextResponse.json({ error: JSON.parse(parsed.error.message) }, { status: 400 }); - } - const { ttl, reads, secret } = parsed.data; - - const id = generateId(); - const rediskey = ["envshare", id].join(":"); - - const tx = redis.multi(); - - tx.hset(rediskey, { - remainingReads: reads ?? null, - secret, - }); - tx.incr("envshare:metrics:writes"); - if (ttl > 0) { - tx.expire(rediskey, ttl); - } - - await tx.exec(); - const url = new URL(req.url); - url.pathname = `/api/v1/secret/${id}`; - - return NextResponse.json( - responseValidation.parse({ - data: { - id, - ttl: ttl > 0 ? ttl : undefined, - reads: reads ?? undefined, - expiresAt: ttl > 0 ? new Date(Date.now() + ttl * 1000).toISOString() : undefined, - url: url.toString(), - }, - }), - ); - } catch (e) { - console.error(e); - return NextResponse.json({ error: "Internal Server Error" }, { status: 500 }); - } -} - -export const config = { - runtime: "edge", -}; diff --git a/pages/api/v1/store.ts b/pages/api/v1/store.ts deleted file mode 100644 index c35e9b4..0000000 --- a/pages/api/v1/store.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { NextRequest, NextResponse } from "next/server"; -import { Redis } from "@upstash/redis"; -import { generateId } from "pkg/id"; - -type Request = { - encrypted: string; - ttl?: number; - reads: number; - iv: string; -}; - -const redis = Redis.fromEnv(); -export default async function handler(req: NextRequest) { - const { encrypted, ttl, reads, iv } = (await req.json()) as Request; - - const id = generateId(); - const key = ["envshare", id].join(":"); - - const tx = redis.multi(); - - tx.hset(key, { - remainingReads: reads > 0 ? reads : null, - encrypted, - iv, - }); - if (ttl) { - tx.expire(key, ttl); - } - tx.incr("envshare:metrics:writes"); - - await tx.exec(); - - return NextResponse.json({ id }); -} - -export const config = { - runtime: "edge", -}; |
