From efb695d0b1b04b694631948624c0c786eb336760 Mon Sep 17 00:00:00 2001 From: charlzyx Date: Wed, 31 Jan 2024 22:49:09 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=F0=9F=A4=96=20jwt=20and=20friendly=20?= =?UTF-8?q?errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 +- bun.lockb | Bin 265004 -> 265738 bytes package.json | 1 + src/config.ts | 43 +++++++++++----- src/index.ts | 89 ++++++++++++++++++++++++++++------ src/routes/meta.ts | 3 +- src/utils/npm.ts | 8 +-- src/utils/sqlite-lru-cache.ts | 1 + src/utils/stream.ts | 4 ++ src/utils/user.ts | 29 +++++++++++ 10 files changed, 146 insertions(+), 34 deletions(-) create mode 100644 src/utils/user.ts diff --git a/Dockerfile b/Dockerfile index 635789b..328f7e3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM oven/bun:alpine +FROM oven/bun:slim # FROM oven/bun WORKDIR /app # RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories diff --git a/bun.lockb b/bun.lockb index dcfa59fc3b40a1ae0db4b624f6bb82334b89d956..7bd773fa7d50d58dd4335c15dab2bbf471092d0c 100755 GIT binary patch delta 49985 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 M-@MoX@`=O$0~&z}6aWAK delta 49444 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 diff --git a/package.json b/package.json index 3cc6cee..8430dfb 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "dependencies": { "@elysiajs/cors": "^0.8.0", "@elysiajs/html": "^0.8.0", + "@elysiajs/jwt": "^0.8.0", "@elysiajs/static": "^0.8.1", "elysia": "latest", "gunzip-maybe": "^1.4.2", diff --git a/src/config.ts b/src/config.ts index 8a18831..838a1d2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -10,11 +10,7 @@ export const BunPkgConfig = { return process.env.HOST_NAME ?? "0.0.0.0"; }, get origin() { - return ( - process.env.ORIGIN || - `${process.env.HOST_NAME}:${process.env.PORT}` || - "0.0.0.0" - ); + return process.env.ORIGIN || `http://localhost${process.env.PORT}`; }, cors: { origin: /^\//.test(Bun.env.CORS_ORIGIN ?? "") @@ -28,19 +24,40 @@ export const BunPkgConfig = { const maybe = Number(Bun.env.CACHE_GIB); return Number.isNaN(maybe) ? 4 : maybe; }, - set cacheDir(dir: string) { - Bun.env.CACHEW_DIR = dir; - }, - get npmAuthToken() { - return Bun.env.NPM_AUTH_TOKEN; - }, + get npmRegistryURL() { return (Bun.env.NPM_REGISTRY_URL || "https://registry.npmjs.org").replace( /\/$/, "", ); }, - set npmRegistryURL(neo: string) { - Bun.env.NPM_REGISTRY_URL = neo; + get npmAuthToken() { + return Bun.env.NPM_AUTH_TOKEN; }, + get jwtSecret() { + return Bun.env.JWT_SECRET; + }, + get jwtUserList() { + return (Bun.env.JWT_USERS || "").split(",").map((item) => item.trim()); + }, + // TODO: The list to ban some packages or scopes. + // banList: { + // packages: ["@some_scope/package_name"], + // scopes: [ + // { + // name: "@your_scope", + // excludes: ["package_name"], + // }, + // ], + // }, + + // // TODO: The list to only allow some packages or scopes. + // allowList: { + // packages: ["@some_scope/package_name"], + // scopes: [ + // { + // name: "@your_scope", + // }, + // ], + // }, }; diff --git a/src/index.ts b/src/index.ts index 8c1bd3a..19b9a7a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,9 @@ +import { cors } from "@elysiajs/cors"; import { Elysia } from "elysia"; -import fs from "fs"; import { router } from "./routes/router"; -import { cors } from "@elysiajs/cors"; - -import { BunPkgConfig } from "./config"; import path from "path"; +import { jwt } from "@elysiajs/jwt"; +import { BunPkgConfig } from "./config"; import { err } from "./templates"; // static file server @@ -18,23 +17,70 @@ Bun.serve({ }, }); -new Elysia() +const app = new Elysia(); + +app .use(cors(BunPkgConfig.cors)) + .use( + jwt({ + name: "jwt", + secret: BunPkgConfig.jwtSecret || "NONE", + }), + ) .get("favicon.ico", () => { return new Response(""); }) .get("", ({ set }) => { set.redirect = "/"; }) - .get("/browser/*", (ctx) => { - return "TODO: file browser"; - }) - .get("/", () => { - const resp = new Response(Bun.file("src/templates/BUNPKG.html")); - resp.headers.set("Content-Type", "text/html; charset=utf8"); - return resp; - }) - .use(router) + .guard( + { + async beforeHandle({ set, jwt, path, cookie: { auth } }) { + const hasJwt = BunPkgConfig.jwtSecret; + if (!hasJwt) return; + const isSign = /\/_sign\/\w+/.test(path); + if (isSign) return; + + const profile = await jwt.verify(auth.value); + // console.log("๐Ÿš€ ~ beforeHandle ~ profile:", profile); + + if (!profile) { + set.status = 401; + return "Unauthorized"; + } + }, + }, + + (app) => + app + .get("/_sign/:name", async ({ jwt, set, cookie: { auth }, params }) => { + const userlist = BunPkgConfig.jwtUserList; + // TODO: sqlite user.db + if (!userlist.includes(params.name)) { + set.status = 401; + return "Unauthorized"; + } else { + auth.set({ + value: await jwt.sign(params), + httpOnly: true, + maxAge: 7 * 86400, + path: "/", + }); + + return "welcome"; + } + }) + + .get("/browser/*", (ctx) => { + return "TODO: file browser"; + }) + .get("/", () => { + const resp = new Response(Bun.file("src/templates/BUNPKG.html")); + resp.headers.set("Content-Type", "text/html; charset=utf8"); + return resp; + }) + .use(router), + ) .onError(({ code, error }) => { const resp = new Response( @@ -53,8 +99,21 @@ new Elysia() port: BunPkgConfig.PORT, }); +const black = /npmAuthToken|jwtSecret/; + console.log( `BUNPKG is Running at http://${BunPkgConfig.HOST_NAME}:${BunPkgConfig.PORT}`, "with BunConfig :\n", - JSON.stringify(BunPkgConfig, null, 2), + JSON.stringify( + Object.keys(BunPkgConfig).reduce( + (ok: any, key) => { + if (black.test(key)) return ok; + ok[key] = BunPkgConfig[key as keyof typeof BunPkgConfig]; + return ok; + }, + {} as typeof BunPkgConfig, + ), + null, + 2, + ), ); diff --git a/src/routes/meta.ts b/src/routes/meta.ts index b384eb0..dc69638 100644 --- a/src/routes/meta.ts +++ b/src/routes/meta.ts @@ -18,8 +18,7 @@ export const meta: WithPkgInfo = async ( } catch (error: any) { set.status = 404; throw new Error( - error.toString() || - `Cannot find an meta of ${filename} in ${packageName}@${packageVersion}`, + `Cannot find meta of ${filename} in ${packageName}@${packageVersion}. Case by ${error.toString()}`, ); } }; diff --git a/src/utils/npm.ts b/src/utils/npm.ts index b177a8c..8df01ec 100644 --- a/src/utils/npm.ts +++ b/src/utils/npm.ts @@ -180,7 +180,7 @@ export const searchPackageEntry = async ( const result = await search(tarball!, filename); - const { foundEntry: entry, matchingEntries: entries } = result; + const { foundEntry: entry, matchingEntries: entries, tried } = result; if (meta) { return { entry, entries }; @@ -188,7 +188,9 @@ export const searchPackageEntry = async ( if (!entry) { throw new Error( - `Cannot find entry ${filename} in ${packageName}@${packageVersion}`, + `Cannot find entry ${filename} in ${packageName}@${packageVersion}. tried ${tried.join( + "\n", + )}`, ); } if (entry.type === "file" && entry.path !== filename) { @@ -208,7 +210,7 @@ export const searchPackageEntry = async ( filename = indexEntry.path!; } else { throw new Error( - `Cannot find an index in ${filename} in ${packageName}@${packageVersion}`, + `Cannot find an index in ${filename} in ${packageName}@${packageVersion}, tried ${indexEntry}.`, ); } } diff --git a/src/utils/sqlite-lru-cache.ts b/src/utils/sqlite-lru-cache.ts index 570e1ba..72616e1 100644 --- a/src/utils/sqlite-lru-cache.ts +++ b/src/utils/sqlite-lru-cache.ts @@ -64,6 +64,7 @@ export class SqliteLRUCache { maxByteSize: maxSize = 1 * Math.pow(2, 30), onRemove = () => {}, }: SqlCacheOptions) { + console.log("๐Ÿš€ ~ SqliteLRUCache ~ database:", database); this.db = new Database(database ?? ":memory:", { create: true }); this.maxLen = maxLen; this.maxByteSize = maxSize; diff --git a/src/utils/stream.ts b/src/utils/stream.ts index 3904562..aaddf9c 100644 --- a/src/utils/stream.ts +++ b/src/utils/stream.ts @@ -41,6 +41,7 @@ export const search = async (tarball: IncomingMessage, filename: string) => { type SearchResult = { foundEntry: IFileMeta; matchingEntries: Record; + tried: string[]; }; return new Promise((accept, reject) => { const jsEntryFilename = `${filename}.js`; @@ -52,6 +53,7 @@ export const search = async (tarball: IncomingMessage, filename: string) => { if (filename === "/") { foundEntry = matchingEntries["/"] = { name: "/", type: "directory" }; } + const tried: string[] = []; tarball .pipe(gunzip()) @@ -68,6 +70,7 @@ export const search = async (tarball: IncomingMessage, filename: string) => { type: header.type, }; + tried.push(`[${entry.type ?? ""}] ${entry.path}`); // Skip non-files and files that don't match the entryName. if (entry.type !== "file" || !entry?.path?.startsWith(filename)) { stream.resume(); @@ -137,6 +140,7 @@ export const search = async (tarball: IncomingMessage, filename: string) => { // try a directory entry with the same name. foundEntry: foundEntry || matchingEntries[filename] || null, matchingEntries: matchingEntries, + tried, }); }); }); diff --git a/src/utils/user.ts b/src/utils/user.ts new file mode 100644 index 0000000..e351571 --- /dev/null +++ b/src/utils/user.ts @@ -0,0 +1,29 @@ +import { Database, Statement } from "bun:sqlite"; +import { serialize, deserialize } from "v8"; + +export class UserDB { + db: Database; + + constructor() { + this.db = new Database("user.db", { create: true }); + this._initdb(this.db); + } + + private _initdb(db: Database) { + db.exec("PRAGMA journal_mode = WAL;"); + db.transaction(() => { + // ๅˆๅง‹ๅŒ– + db.prepare( + `CREATE TABLE IF NOT EXISTS user ( + username TEXT PRIMARY KEY, + passwd BLOB, + ban INT + )`, + ).run(); + // ๅˆ›ๅปบ็ดขๅผ• + db.prepare( + "CREATE INDEX IF NOT EXISTS username ON cache (username)", + ).run(); + })(); + } +}