parent
b24c2996be
commit
e780a838b6
|
@ -82,7 +82,7 @@ silverbullet <pages-path>
|
||||||
|
|
||||||
By default, SB will bind to port `3000`, to use a different port use the
|
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
|
`--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
|
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 ).
|
(spoiler alert: by default this will be http://localhost:3000 ).
|
||||||
|
|
|
@ -21,7 +21,7 @@ export function serveCommand(options: any, folder: string) {
|
||||||
pagesPath: pagesPath,
|
pagesPath: pagesPath,
|
||||||
dbPath: path.join(pagesPath, options.db),
|
dbPath: path.join(pagesPath, options.db),
|
||||||
assetBundle: new AssetBundle(assetBundle as AssetJson),
|
assetBundle: new AssetBundle(assetBundle as AssetJson),
|
||||||
password: options.password,
|
user: options.user,
|
||||||
});
|
});
|
||||||
httpServer.start().catch((e) => {
|
httpServer.start().catch((e) => {
|
||||||
console.error("HTTP Server error", e);
|
console.error("HTTP Server error", e);
|
||||||
|
|
|
@ -10,22 +10,16 @@ import { mime } from "../../plugos/deps.ts";
|
||||||
export class HttpSpacePrimitives implements SpacePrimitives {
|
export class HttpSpacePrimitives implements SpacePrimitives {
|
||||||
fsUrl: string;
|
fsUrl: string;
|
||||||
private plugUrl: string;
|
private plugUrl: string;
|
||||||
token?: string;
|
|
||||||
|
|
||||||
constructor(url: string, token?: string) {
|
constructor(url: string) {
|
||||||
this.fsUrl = url + "/fs";
|
this.fsUrl = url + "/fs";
|
||||||
this.plugUrl = url + "/plug";
|
this.plugUrl = url + "/plug";
|
||||||
this.token = token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async authenticatedFetch(
|
private async authenticatedFetch(
|
||||||
url: string,
|
url: string,
|
||||||
options: any,
|
options: any,
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
if (this.token) {
|
|
||||||
options.headers = options.headers || {};
|
|
||||||
options.headers["Authorization"] = `Bearer ${this.token}`;
|
|
||||||
}
|
|
||||||
const result = await fetch(url, options);
|
const result = await fetch(url, options);
|
||||||
if (result.status === 401) {
|
if (result.status === 401) {
|
||||||
throw Error("Unauthorized");
|
throw Error("Unauthorized");
|
||||||
|
|
|
@ -11,7 +11,8 @@ export type ServerOptions = {
|
||||||
pagesPath: string;
|
pagesPath: string;
|
||||||
dbPath: string;
|
dbPath: string;
|
||||||
assetBundle: AssetBundle;
|
assetBundle: AssetBundle;
|
||||||
password?: string;
|
user?: string;
|
||||||
|
pass?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const staticLastModified = new Date().toUTCString();
|
const staticLastModified = new Date().toUTCString();
|
||||||
|
@ -20,14 +21,14 @@ export class HttpServer {
|
||||||
app: Application;
|
app: Application;
|
||||||
systemBoot: SpaceSystem;
|
systemBoot: SpaceSystem;
|
||||||
private port: number;
|
private port: number;
|
||||||
password?: string;
|
user?: string;
|
||||||
settings: { [key: string]: any } = {};
|
settings: { [key: string]: any } = {};
|
||||||
abortController?: AbortController;
|
abortController?: AbortController;
|
||||||
|
|
||||||
constructor(options: ServerOptions) {
|
constructor(options: ServerOptions) {
|
||||||
this.port = options.port;
|
this.port = options.port;
|
||||||
this.app = new Application(); //{ serverConstructor: FlashServer });
|
this.app = new Application(); //{ serverConstructor: FlashServer });
|
||||||
this.password = options.password;
|
this.user = options.user;
|
||||||
this.systemBoot = new SpaceSystem(
|
this.systemBoot = new SpaceSystem(
|
||||||
options.assetBundle,
|
options.assetBundle,
|
||||||
options.pagesPath,
|
options.pagesPath,
|
||||||
|
@ -63,6 +64,7 @@ export class HttpServer {
|
||||||
await this.systemBoot.start();
|
await this.systemBoot.start();
|
||||||
await this.systemBoot.ensureSpaceIndex();
|
await this.systemBoot.ensureSpaceIndex();
|
||||||
await this.ensureAndLoadSettings();
|
await this.ensureAndLoadSettings();
|
||||||
|
|
||||||
// Serve static files (javascript, css, html)
|
// Serve static files (javascript, css, html)
|
||||||
this.app.use(async ({ request, response }, next) => {
|
this.app.use(async ({ request, response }, next) => {
|
||||||
if (request.url.pathname === "/") {
|
if (request.url.pathname === "/") {
|
||||||
|
@ -106,6 +108,8 @@ export class HttpServer {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.addPasswordAuth(this.app);
|
||||||
|
|
||||||
// Pages API
|
// Pages API
|
||||||
const fsRouter = this.buildFsRouter(this.systemBoot.spacePrimitives);
|
const fsRouter = this.buildFsRouter(this.systemBoot.spacePrimitives);
|
||||||
this.app.use(fsRouter.routes());
|
this.app.use(fsRouter.routes());
|
||||||
|
@ -163,15 +167,20 @@ export class HttpServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private addPasswordAuth(r: Router) {
|
private addPasswordAuth(app: Application) {
|
||||||
if (this.password) {
|
if (this.user) {
|
||||||
r.use(async ({ request, response }, next) => {
|
app.use(async ({ request, response }, next) => {
|
||||||
if (
|
if (
|
||||||
request.headers.get("Authorization") === `Bearer ${this.password}`
|
request.headers.get("Authorization") ===
|
||||||
|
`Basic ${btoa(this.user!)}`
|
||||||
) {
|
) {
|
||||||
await next();
|
await next();
|
||||||
} else {
|
} else {
|
||||||
response.status = 401;
|
response.status = 401;
|
||||||
|
response.headers.set(
|
||||||
|
"WWW-Authenticate",
|
||||||
|
`Basic realm="Please enter your username and password"`,
|
||||||
|
);
|
||||||
response.body = "Unauthorized";
|
response.body = "Unauthorized";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -180,7 +189,6 @@ export class HttpServer {
|
||||||
|
|
||||||
private buildFsRouter(spacePrimitives: SpacePrimitives): Router {
|
private buildFsRouter(spacePrimitives: SpacePrimitives): Router {
|
||||||
const fsRouter = new Router();
|
const fsRouter = new Router();
|
||||||
this.addPasswordAuth(fsRouter);
|
|
||||||
// File list
|
// File list
|
||||||
fsRouter.get("/", async ({ response }) => {
|
fsRouter.get("/", async ({ response }) => {
|
||||||
response.headers.set("Content-type", "application/json");
|
response.headers.set("Content-type", "application/json");
|
||||||
|
@ -276,7 +284,7 @@ export class HttpServer {
|
||||||
|
|
||||||
private buildPlugRouter(): Router {
|
private buildPlugRouter(): Router {
|
||||||
const plugRouter = new Router();
|
const plugRouter = new Router();
|
||||||
this.addPasswordAuth(plugRouter);
|
// this.addPasswordAuth(plugRouter);
|
||||||
const system = this.systemBoot.system;
|
const system = this.systemBoot.system;
|
||||||
|
|
||||||
plugRouter.post(
|
plugRouter.post(
|
||||||
|
|
|
@ -23,7 +23,10 @@ await new Command()
|
||||||
.option("--db <dbfile:string>", "Filename for the database", {
|
.option("--db <dbfile:string>", "Filename for the database", {
|
||||||
default: "data.db",
|
default: "data.db",
|
||||||
})
|
})
|
||||||
.option("--password <password:string>", "Password for basic authentication")
|
.option(
|
||||||
|
"--user <user:string>",
|
||||||
|
"'username:password' combo for BasicAuth authentication",
|
||||||
|
)
|
||||||
.action(serveCommand)
|
.action(serveCommand)
|
||||||
// fix
|
// fix
|
||||||
.command("fix", "Fix a broken space")
|
.command("fix", "Fix a broken space")
|
||||||
|
|
28
web/boot.ts
28
web/boot.ts
|
@ -8,28 +8,14 @@ import { SilverBulletHooks } from "../common/manifest.ts";
|
||||||
import { System } from "../plugos/system.ts";
|
import { System } from "../plugos/system.ts";
|
||||||
|
|
||||||
safeRun(async () => {
|
safeRun(async () => {
|
||||||
let password: string | undefined = localStorage.getItem("password") ||
|
const httpPrimitives = new HttpSpacePrimitives("");
|
||||||
undefined;
|
|
||||||
|
|
||||||
let httpPrimitives = new HttpSpacePrimitives("", password);
|
|
||||||
let settingsPageText = "";
|
let settingsPageText = "";
|
||||||
while (true) {
|
try {
|
||||||
try {
|
settingsPageText = (
|
||||||
settingsPageText = (
|
await httpPrimitives.readFile("SETTINGS.md", "string")
|
||||||
await httpPrimitives.readFile("SETTINGS.md", "string")
|
).data as string;
|
||||||
).data as string;
|
} catch (e: any) {
|
||||||
break;
|
console.error("No settings page found", e.message);
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instantiate a PlugOS system for the client
|
// Instantiate a PlugOS system for the client
|
||||||
|
|
|
@ -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
|
## 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]}`
|
* 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]}`
|
||||||
|
|
|
@ -103,7 +103,7 @@ To run Silver Bullet, create a folder for your pages (it can be empty, or be an
|
||||||
silverbullet <pages-path>
|
silverbullet <pages-path>
|
||||||
```
|
```
|
||||||
|
|
||||||
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 ).
|
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 ).
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue