mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
Refactor asset handling and authentication logic (for node)
Updated asset path configuration and server-side logic to standardize asset serving. Introduced `shouldSkipAuth` to bypass authentication for asset requests. Added test coverage for the new asset path handling logic.
This commit is contained in:
9
app/__test__/auth/middleware.spec.ts
Normal file
9
app/__test__/auth/middleware.spec.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { describe, expect, it } from "bun:test";
|
||||
import { shouldSkipAuth } from "../../src/auth/middlewares";
|
||||
|
||||
describe("auth middleware", () => {
|
||||
it("should skip auth on asset paths", () => {
|
||||
expect(shouldSkipAuth({ req: new Request("http://localhost/assets/test.js") })).toBe(true);
|
||||
expect(shouldSkipAuth({ req: new Request("http://localhost/") })).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -58,7 +58,7 @@ const result = await esbuild.build({
|
||||
sourcemap,
|
||||
entryPoints: ["src/ui/main.tsx"],
|
||||
entryNames: "[dir]/[name]-[hash]",
|
||||
outdir: "dist/static",
|
||||
outdir: "dist/static/assets",
|
||||
platform: "browser",
|
||||
bundle: true,
|
||||
splitting: true,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { IncomingMessage } from "node:http";
|
||||
import { App, type CreateAppConfig, registries } from "bknd";
|
||||
import { config as $config } from "core";
|
||||
import type { MiddlewareHandler } from "hono";
|
||||
import { StorageLocalAdapter } from "media/storage/adapters/StorageLocalAdapter";
|
||||
import type { AdminControllerOptions } from "modules/server/AdminController";
|
||||
@@ -106,12 +107,10 @@ export async function createRuntimeApp<Env = any>(
|
||||
App.Events.AppBuiltEvent,
|
||||
async () => {
|
||||
if (serveStatic) {
|
||||
if (Array.isArray(serveStatic)) {
|
||||
const [path, handler] = serveStatic;
|
||||
const [path, handler] = Array.isArray(serveStatic)
|
||||
? serveStatic
|
||||
: [$config.server.assets_path + "*", serveStatic];
|
||||
app.modules.server.get(path, handler);
|
||||
} else {
|
||||
app.modules.server.get("/*", serveStatic);
|
||||
}
|
||||
}
|
||||
|
||||
await config.onBuilt?.(app);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Permission } from "core";
|
||||
import { type Permission, config } from "core";
|
||||
import type { Context } from "hono";
|
||||
import { createMiddleware } from "hono/factory";
|
||||
import type { ServerEnv } from "modules/Module";
|
||||
@@ -21,18 +21,27 @@ async function resolveAuth(app: ServerEnv["Variables"]["app"], c: Context<Server
|
||||
authenticator.requestCookieRefresh(c);
|
||||
}
|
||||
|
||||
export function shouldSkipAuth(c: { req: Request }) {
|
||||
return new URL(c.req.url).pathname.startsWith(config.server.assets_path);
|
||||
}
|
||||
|
||||
export const auth = createMiddleware<ServerEnv>(async (c, next) => {
|
||||
if (!shouldSkipAuth) {
|
||||
// make sure to only register once
|
||||
if (c.get("auth_registered")) {
|
||||
return;
|
||||
}
|
||||
|
||||
await resolveAuth(c.get("app"), c);
|
||||
c.set("auth_registered", true);
|
||||
}
|
||||
|
||||
await next();
|
||||
});
|
||||
|
||||
export const permission = (...permissions: Permission[]) =>
|
||||
createMiddleware<ServerEnv>(async (c, next) => {
|
||||
if (!shouldSkipAuth) {
|
||||
const app = c.get("app");
|
||||
if (app) {
|
||||
const p = Array.isArray(permissions) ? permissions : [permissions];
|
||||
@@ -43,6 +52,7 @@ export const permission = (...permissions: Permission[]) =>
|
||||
} else {
|
||||
console.warn("app not in context, skip permission check");
|
||||
}
|
||||
}
|
||||
|
||||
await next();
|
||||
});
|
||||
|
||||
@@ -10,7 +10,8 @@ export interface DB {}
|
||||
|
||||
export const config = {
|
||||
server: {
|
||||
default_port: 1337
|
||||
default_port: 1337,
|
||||
assets_path: "/assets/"
|
||||
},
|
||||
data: {
|
||||
default_primary_field: "id"
|
||||
|
||||
@@ -10,7 +10,9 @@ import type { Hono } from "hono";
|
||||
export type ServerEnv = {
|
||||
Variables: {
|
||||
app: App;
|
||||
// to prevent resolving auth multiple times
|
||||
auth_resolved: boolean;
|
||||
// to only register once
|
||||
auth_registered: boolean;
|
||||
html?: string;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/** @jsxImportSource hono/jsx */
|
||||
|
||||
import type { App } from "App";
|
||||
import { isDebug } from "core";
|
||||
import { config, isDebug } from "core";
|
||||
import { addFlashMessage } from "core/server/flash";
|
||||
import { html } from "hono/html";
|
||||
import { Fragment } from "hono/jsx";
|
||||
@@ -13,6 +13,7 @@ const htmlBkndContextReplace = "<!-- BKND_CONTEXT -->";
|
||||
// @todo: add migration to remove admin path from config
|
||||
export type AdminControllerOptions = {
|
||||
basepath?: string;
|
||||
assets_path?: string;
|
||||
html?: string;
|
||||
forceDev?: boolean | { mainPath: string };
|
||||
};
|
||||
@@ -20,7 +21,7 @@ export type AdminControllerOptions = {
|
||||
export class AdminController extends Controller {
|
||||
constructor(
|
||||
private readonly app: App,
|
||||
private options: AdminControllerOptions = {}
|
||||
private _options: AdminControllerOptions = {}
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -29,6 +30,14 @@ export class AdminController extends Controller {
|
||||
return this.app.modules.ctx();
|
||||
}
|
||||
|
||||
get options() {
|
||||
return {
|
||||
...this._options,
|
||||
basepath: this._options.basepath ?? "/",
|
||||
assets_path: this._options.assets_path ?? config.server.assets_path
|
||||
};
|
||||
}
|
||||
|
||||
get basepath() {
|
||||
return this.options.basepath ?? "/";
|
||||
}
|
||||
@@ -156,8 +165,16 @@ export class AdminController extends Controller {
|
||||
<title>BKND</title>
|
||||
{isProd ? (
|
||||
<Fragment>
|
||||
<script type="module" CrossOrigin src={"/" + assets?.js} />
|
||||
<link rel="stylesheet" crossOrigin href={"/" + assets?.css} />
|
||||
<script
|
||||
type="module"
|
||||
CrossOrigin
|
||||
src={this.options.assets_path + assets?.js}
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
crossOrigin
|
||||
href={this.options.assets_path + assets?.css}
|
||||
/>
|
||||
</Fragment>
|
||||
) : (
|
||||
<Fragment>
|
||||
|
||||
Reference in New Issue
Block a user