mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
Refactor module middleware initialization logic.
Replaced `getMiddleware` with `onServerInit` for streamlined middleware registration. Updated `AppAuth` to automatically register its authentication middleware. Added a test case to verify middleware registration. Removed redundant cookie renewal logic from `AdminController` and made related adjustments across modules.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
import { afterAll, beforeAll, beforeEach, describe, expect, spyOn, test } from "bun:test";
|
||||||
|
import { createApp } from "../../src";
|
||||||
import { AuthController } from "../../src/auth/api/AuthController";
|
import { AuthController } from "../../src/auth/api/AuthController";
|
||||||
import { AppAuth, type ModuleBuildContext } from "../../src/modules";
|
import { AppAuth, type ModuleBuildContext } from "../../src/modules";
|
||||||
import { disableConsoleLog, enableConsoleLog } from "../helper";
|
import { disableConsoleLog, enableConsoleLog } from "../helper";
|
||||||
@@ -76,4 +77,29 @@ describe("AppAuth", () => {
|
|||||||
expect(users[0].email).toBe("some@body.com");
|
expect(users[0].email).toBe("some@body.com");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("registers auth middleware automatically", async () => {
|
||||||
|
const app = createApp({
|
||||||
|
initialConfig: {
|
||||||
|
auth: {
|
||||||
|
enabled: true,
|
||||||
|
jwt: {
|
||||||
|
secret: "123456"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await app.build();
|
||||||
|
const spy = spyOn(app.module.auth.authenticator, "requestCookieRefresh");
|
||||||
|
|
||||||
|
// register custom route
|
||||||
|
app.server.get("/test", async (c) => c.text("test"));
|
||||||
|
|
||||||
|
// call a system api and then the custom route
|
||||||
|
await app.server.request("/api/system/ping");
|
||||||
|
await app.server.request("/test");
|
||||||
|
|
||||||
|
expect(spy.mock.calls.length).toBe(2);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export class App {
|
|||||||
server.use(async (c, next) => {
|
server.use(async (c, next) => {
|
||||||
c.set("app", this);
|
c.set("app", this);
|
||||||
await next();
|
await next();
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.modules.ctx().emgr.registerEvents(AppEvents);
|
this.modules.ctx().emgr.registerEvents(AppEvents);
|
||||||
@@ -108,7 +108,6 @@ export class App {
|
|||||||
//console.log("emitting built", options);
|
//console.log("emitting built", options);
|
||||||
await this.emgr.emit(new AppBuiltEvent({ app: this }));
|
await this.emgr.emit(new AppBuiltEvent({ app: this }));
|
||||||
|
|
||||||
|
|
||||||
server.all("/api/*", async (c) => c.notFound());
|
server.all("/api/*", async (c) => c.notFound());
|
||||||
|
|
||||||
if (options?.save) {
|
if (options?.save) {
|
||||||
@@ -130,6 +129,10 @@ export class App {
|
|||||||
return this.modules.server;
|
return this.modules.server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get em() {
|
||||||
|
return this.modules.ctx().em;
|
||||||
|
}
|
||||||
|
|
||||||
get fetch(): any {
|
get fetch(): any {
|
||||||
return this.server.fetch;
|
return this.server.fetch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { type AuthAction, Authenticator, type ProfileExchange, Role, type Strategy } from "auth";
|
import { type AuthAction, Authenticator, type ProfileExchange, Role, type Strategy } from "auth";
|
||||||
import type { PasswordStrategy } from "auth/authenticate/strategies";
|
import type { PasswordStrategy } from "auth/authenticate/strategies";
|
||||||
|
import { auth } from "auth/middlewares";
|
||||||
import { type DB, Exception, type PrimaryFieldType } from "core";
|
import { type DB, Exception, type PrimaryFieldType } from "core";
|
||||||
import { type Static, secureRandomString, transformObject } from "core/utils";
|
import { type Static, secureRandomString, transformObject } from "core/utils";
|
||||||
import { type Entity, EntityIndex, type EntityManager } from "data";
|
import { type Entity, EntityIndex, type EntityManager } from "data";
|
||||||
import { type FieldSchema, entity, enumm, make, text } from "data/prototype";
|
import { type FieldSchema, entity, enumm, make, text } from "data/prototype";
|
||||||
|
import type { Hono } from "hono";
|
||||||
import { pick } from "lodash-es";
|
import { pick } from "lodash-es";
|
||||||
import { Module } from "modules/Module";
|
import { Module } from "modules/Module";
|
||||||
import { AuthController } from "./api/AuthController";
|
import { AuthController } from "./api/AuthController";
|
||||||
@@ -89,6 +91,10 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
|||||||
return this._controller;
|
return this._controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override onServerInit(hono: Hono<any>) {
|
||||||
|
hono.use(auth);
|
||||||
|
}
|
||||||
|
|
||||||
getSchema() {
|
getSchema() {
|
||||||
return authConfigSchema;
|
return authConfigSchema;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -243,7 +243,6 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
|||||||
if (this.config.cookie.renew) {
|
if (this.config.cookie.renew) {
|
||||||
const token = await this.getAuthCookie(c);
|
const token = await this.getAuthCookie(c);
|
||||||
if (token) {
|
if (token) {
|
||||||
console.log("renewing cookie", c.req.url);
|
|
||||||
await this.setAuthCookie(c, token);
|
await this.setAuthCookie(c, token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,17 +16,24 @@ async function resolveAuth(app: ServerEnv["Variables"]["app"], c: Context<Server
|
|||||||
const guard = app.modules.ctx().guard;
|
const guard = app.modules.ctx().guard;
|
||||||
|
|
||||||
guard.setUserContext(await authenticator.resolveAuthFromRequest(c));
|
guard.setUserContext(await authenticator.resolveAuthFromRequest(c));
|
||||||
|
|
||||||
|
// renew cookie if applicable
|
||||||
|
authenticator.requestCookieRefresh(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const auth = createMiddleware<ServerEnv>(async (c, next) => {
|
export const auth = createMiddleware<ServerEnv>(async (c, next) => {
|
||||||
|
// make sure to only register once
|
||||||
|
if (c.get("auth_registered")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
await resolveAuth(c.get("app"), c);
|
await resolveAuth(c.get("app"), c);
|
||||||
|
c.set("auth_registered", true);
|
||||||
await next();
|
await next();
|
||||||
});
|
});
|
||||||
|
|
||||||
export const permission = (...permissions: Permission[]) =>
|
export const permission = (...permissions: Permission[]) =>
|
||||||
createMiddleware<ServerEnv>(async (c, next) => {
|
createMiddleware<ServerEnv>(async (c, next) => {
|
||||||
const app = c.get("app");
|
const app = c.get("app");
|
||||||
await resolveAuth(app, c);
|
|
||||||
|
|
||||||
const p = Array.isArray(permissions) ? permissions : [permissions];
|
const p = Array.isArray(permissions) ? permissions : [permissions];
|
||||||
const guard = app.modules.ctx().guard;
|
const guard = app.modules.ctx().guard;
|
||||||
|
|||||||
@@ -6,14 +6,10 @@ export class Controller {
|
|||||||
protected middlewares = {
|
protected middlewares = {
|
||||||
auth,
|
auth,
|
||||||
permission
|
permission
|
||||||
}
|
};
|
||||||
|
|
||||||
protected create({ auth }: { auth?: boolean } = {}): Hono<ServerEnv> {
|
protected create(): Hono<ServerEnv> {
|
||||||
const server = Controller.createServer();
|
return Controller.createServer();
|
||||||
if (auth !== false) {
|
|
||||||
server.use(this.middlewares.auth);
|
|
||||||
}
|
|
||||||
return server;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static createServer(): Hono<ServerEnv> {
|
static createServer(): Hono<ServerEnv> {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export type ServerEnv = {
|
|||||||
Variables: {
|
Variables: {
|
||||||
app: App;
|
app: App;
|
||||||
auth_resolved: boolean;
|
auth_resolved: boolean;
|
||||||
|
auth_registered: boolean;
|
||||||
html?: string;
|
html?: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -87,9 +88,9 @@ export abstract class Module<Schema extends TSchema = TSchema, ConfigSchema = St
|
|||||||
return this._schema;
|
return this._schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMiddleware() {
|
// action performed when server has been initialized
|
||||||
return undefined;
|
// can be used to assign global middlewares
|
||||||
}
|
onServerInit(hono: Hono<ServerEnv>) {}
|
||||||
|
|
||||||
get ctx() {
|
get ctx() {
|
||||||
if (!this._ctx) {
|
if (!this._ctx) {
|
||||||
|
|||||||
@@ -212,14 +212,9 @@ export class ModuleManager {
|
|||||||
this.options.onServerInit(this.server);
|
this.options.onServerInit(this.server);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo: this is a current workaround, controllers must be reworked
|
// optional method for each module to register global middlewares, etc.
|
||||||
objectEach(this.modules, (module) => {
|
objectEach(this.modules, (module) => {
|
||||||
if ("getMiddleware" in module) {
|
module.onServerInit(this.server);
|
||||||
const middleware = module.getMiddleware();
|
|
||||||
if (middleware) {
|
|
||||||
this.server.use(middleware);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,8 +65,6 @@ export class AdminController extends Controller {
|
|||||||
}
|
}
|
||||||
c.set("html", html);
|
c.set("html", html);
|
||||||
|
|
||||||
// refresh cookie if needed
|
|
||||||
await auth.authenticator?.requestCookieRefresh(c);
|
|
||||||
await next();
|
await next();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user