From e780a838b6ef88ef730c6a5cf5cebfecfc99581f Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Mon, 5 Dec 2022 12:14:21 +0100 Subject: [PATCH] Fixes #139 #140 --- README.md | 2 +- cmd/server.ts | 2 +- common/spaces/http_space_primitives.ts | 8 +------- server/http_server.ts | 26 +++++++++++++++--------- silverbullet.ts | 5 ++++- web/boot.ts | 28 +++++++------------------- website/CHANGELOG.md | 6 ++++++ website/Silver Bullet.md | 2 +- 8 files changed, 38 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 8608dae8..35e24cb6 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ silverbullet By default, SB will bind to port `3000`, to use a different port use the `--port` flag. By default SB doesn’t offer any sort of authentication, to add -basic password authentication, pass the `--password` flag. +basic password authentication, pass the `--user` flag (e.g. `--user pete:1234`). Once downloaded and booted, SB will print out a URL to open SB in your browser (spoiler alert: by default this will be http://localhost:3000 ). diff --git a/cmd/server.ts b/cmd/server.ts index a8c9af0d..4a96177c 100644 --- a/cmd/server.ts +++ b/cmd/server.ts @@ -21,7 +21,7 @@ export function serveCommand(options: any, folder: string) { pagesPath: pagesPath, dbPath: path.join(pagesPath, options.db), assetBundle: new AssetBundle(assetBundle as AssetJson), - password: options.password, + user: options.user, }); httpServer.start().catch((e) => { console.error("HTTP Server error", e); diff --git a/common/spaces/http_space_primitives.ts b/common/spaces/http_space_primitives.ts index a68966b4..4da0467d 100644 --- a/common/spaces/http_space_primitives.ts +++ b/common/spaces/http_space_primitives.ts @@ -10,22 +10,16 @@ import { mime } from "../../plugos/deps.ts"; export class HttpSpacePrimitives implements SpacePrimitives { fsUrl: string; private plugUrl: string; - token?: string; - constructor(url: string, token?: string) { + constructor(url: string) { this.fsUrl = url + "/fs"; this.plugUrl = url + "/plug"; - this.token = token; } private async authenticatedFetch( url: string, options: any, ): Promise { - if (this.token) { - options.headers = options.headers || {}; - options.headers["Authorization"] = `Bearer ${this.token}`; - } const result = await fetch(url, options); if (result.status === 401) { throw Error("Unauthorized"); diff --git a/server/http_server.ts b/server/http_server.ts index 5b4e3a6b..dffbcaf5 100644 --- a/server/http_server.ts +++ b/server/http_server.ts @@ -11,7 +11,8 @@ export type ServerOptions = { pagesPath: string; dbPath: string; assetBundle: AssetBundle; - password?: string; + user?: string; + pass?: string; }; const staticLastModified = new Date().toUTCString(); @@ -20,14 +21,14 @@ export class HttpServer { app: Application; systemBoot: SpaceSystem; private port: number; - password?: string; + user?: string; settings: { [key: string]: any } = {}; abortController?: AbortController; constructor(options: ServerOptions) { this.port = options.port; this.app = new Application(); //{ serverConstructor: FlashServer }); - this.password = options.password; + this.user = options.user; this.systemBoot = new SpaceSystem( options.assetBundle, options.pagesPath, @@ -63,6 +64,7 @@ export class HttpServer { await this.systemBoot.start(); await this.systemBoot.ensureSpaceIndex(); await this.ensureAndLoadSettings(); + // Serve static files (javascript, css, html) this.app.use(async ({ request, response }, next) => { if (request.url.pathname === "/") { @@ -106,6 +108,8 @@ export class HttpServer { } }); + this.addPasswordAuth(this.app); + // Pages API const fsRouter = this.buildFsRouter(this.systemBoot.spacePrimitives); this.app.use(fsRouter.routes()); @@ -163,15 +167,20 @@ export class HttpServer { } } - private addPasswordAuth(r: Router) { - if (this.password) { - r.use(async ({ request, response }, next) => { + private addPasswordAuth(app: Application) { + if (this.user) { + app.use(async ({ request, response }, next) => { if ( - request.headers.get("Authorization") === `Bearer ${this.password}` + request.headers.get("Authorization") === + `Basic ${btoa(this.user!)}` ) { await next(); } else { response.status = 401; + response.headers.set( + "WWW-Authenticate", + `Basic realm="Please enter your username and password"`, + ); response.body = "Unauthorized"; } }); @@ -180,7 +189,6 @@ export class HttpServer { private buildFsRouter(spacePrimitives: SpacePrimitives): Router { const fsRouter = new Router(); - this.addPasswordAuth(fsRouter); // File list fsRouter.get("/", async ({ response }) => { response.headers.set("Content-type", "application/json"); @@ -276,7 +284,7 @@ export class HttpServer { private buildPlugRouter(): Router { const plugRouter = new Router(); - this.addPasswordAuth(plugRouter); + // this.addPasswordAuth(plugRouter); const system = this.systemBoot.system; plugRouter.post( diff --git a/silverbullet.ts b/silverbullet.ts index 159cc3c3..9e0e3467 100755 --- a/silverbullet.ts +++ b/silverbullet.ts @@ -23,7 +23,10 @@ await new Command() .option("--db ", "Filename for the database", { default: "data.db", }) - .option("--password ", "Password for basic authentication") + .option( + "--user ", + "'username:password' combo for BasicAuth authentication", + ) .action(serveCommand) // fix .command("fix", "Fix a broken space") diff --git a/web/boot.ts b/web/boot.ts index 5b825e91..dd0d7dcb 100644 --- a/web/boot.ts +++ b/web/boot.ts @@ -8,28 +8,14 @@ import { SilverBulletHooks } from "../common/manifest.ts"; import { System } from "../plugos/system.ts"; safeRun(async () => { - let password: string | undefined = localStorage.getItem("password") || - undefined; - - let httpPrimitives = new HttpSpacePrimitives("", password); + const httpPrimitives = new HttpSpacePrimitives(""); let settingsPageText = ""; - while (true) { - try { - settingsPageText = ( - await httpPrimitives.readFile("SETTINGS.md", "string") - ).data as string; - break; - } catch (e: any) { - if (e.message === "Unauthorized") { - password = prompt("Password: ") || undefined; - if (!password) { - alert("Sorry, need a password"); - return; - } - localStorage.setItem("password", password!); - httpPrimitives = new HttpSpacePrimitives("", password); - } - } + try { + settingsPageText = ( + await httpPrimitives.readFile("SETTINGS.md", "string") + ).data as string; + } catch (e: any) { + console.error("No settings page found", e.message); } // Instantiate a PlugOS system for the client diff --git a/website/CHANGELOG.md b/website/CHANGELOG.md index 6d519af7..176e1c50 100644 --- a/website/CHANGELOG.md +++ b/website/CHANGELOG.md @@ -3,6 +3,12 @@ release. --- +## Next + +* Replaced the `--password` flag with `--user` taking a basic auth combination of username and password, e.g. `--user pete:1234`. Authentication now uses standard basic auth. This should fix attachments not working with password protected setups. + +--- + ## 0.2.2 * New page link aliasing syntax (Obsidian compatible) is here: `[[page link|alias]]` e.g. [[CHANGELOG|this is a link to this changelog]]. Also supported for command links: `{[Plugs: Add|add a plug]}` diff --git a/website/Silver Bullet.md b/website/Silver Bullet.md index b6610727..55f985f7 100644 --- a/website/Silver Bullet.md +++ b/website/Silver Bullet.md @@ -103,7 +103,7 @@ To run Silver Bullet, create a folder for your pages (it can be empty, or be an silverbullet ``` -By default, Silver Bullet will bind to port `3000`, to use a different port use the the `--port` flag. By default Silver Bullet is unauthenticated, to password-protect it, specify a password with the `--password` flag. +By default, Silver Bullet will bind to port `3000`, to use a different port use the the `--port` flag. By default Silver Bullet is unauthenticated, to password-protect it, specify a username and password with the `--user` flag (e.g. `--user pete:1234`). Once downloaded and booted, Silver Bullet will print out a URL to open SB in your browser (by default this will be http://localhost:3000 ).