diff --git a/app/__test__/modules/AppAuth.spec.ts b/app/__test__/modules/AppAuth.spec.ts index 14640f0..d8866c7 100644 --- a/app/__test__/modules/AppAuth.spec.ts +++ b/app/__test__/modules/AppAuth.spec.ts @@ -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 { AppAuth, type ModuleBuildContext } from "../../src/modules"; import { disableConsoleLog, enableConsoleLog } from "../helper"; @@ -76,4 +77,29 @@ describe("AppAuth", () => { 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); + }); }); diff --git a/app/src/App.ts b/app/src/App.ts index 9faa1d4..cc8af11 100644 --- a/app/src/App.ts +++ b/app/src/App.ts @@ -74,7 +74,7 @@ export class App { server.use(async (c, next) => { c.set("app", this); await next(); - }) + }); } }); this.modules.ctx().emgr.registerEvents(AppEvents); @@ -108,7 +108,6 @@ export class App { //console.log("emitting built", options); await this.emgr.emit(new AppBuiltEvent({ app: this })); - server.all("/api/*", async (c) => c.notFound()); if (options?.save) { @@ -130,6 +129,10 @@ export class App { return this.modules.server; } + get em() { + return this.modules.ctx().em; + } + get fetch(): any { return this.server.fetch; } @@ -194,4 +197,4 @@ export function createApp(config: CreateAppConfig = {}) { } return new App(connection, config.initialConfig, config.plugins, config.options); -} \ No newline at end of file +} diff --git a/app/src/auth/AppAuth.ts b/app/src/auth/AppAuth.ts index c8557da..a65b251 100644 --- a/app/src/auth/AppAuth.ts +++ b/app/src/auth/AppAuth.ts @@ -1,9 +1,11 @@ import { type AuthAction, Authenticator, type ProfileExchange, Role, type Strategy } from "auth"; import type { PasswordStrategy } from "auth/authenticate/strategies"; +import { auth } from "auth/middlewares"; import { type DB, Exception, type PrimaryFieldType } from "core"; import { type Static, secureRandomString, transformObject } from "core/utils"; import { type Entity, EntityIndex, type EntityManager } from "data"; import { type FieldSchema, entity, enumm, make, text } from "data/prototype"; +import type { Hono } from "hono"; import { pick } from "lodash-es"; import { Module } from "modules/Module"; import { AuthController } from "./api/AuthController"; @@ -89,6 +91,10 @@ export class AppAuth extends Module { return this._controller; } + override onServerInit(hono: Hono) { + hono.use(auth); + } + getSchema() { return authConfigSchema; } diff --git a/app/src/auth/authenticate/Authenticator.ts b/app/src/auth/authenticate/Authenticator.ts index 46fa586..01355b5 100644 --- a/app/src/auth/authenticate/Authenticator.ts +++ b/app/src/auth/authenticate/Authenticator.ts @@ -243,7 +243,6 @@ export class Authenticator = Record< if (this.config.cookie.renew) { const token = await this.getAuthCookie(c); if (token) { - console.log("renewing cookie", c.req.url); await this.setAuthCookie(c, token); } } diff --git a/app/src/auth/middlewares.ts b/app/src/auth/middlewares.ts index d378dc4..6f00ee0 100644 --- a/app/src/auth/middlewares.ts +++ b/app/src/auth/middlewares.ts @@ -16,17 +16,24 @@ async function resolveAuth(app: ServerEnv["Variables"]["app"], c: Context(async (c, next) => { + // 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(async (c, next) => { const app = c.get("app"); - await resolveAuth(app, c); const p = Array.isArray(permissions) ? permissions : [permissions]; const guard = app.modules.ctx().guard; diff --git a/app/src/modules/Controller.ts b/app/src/modules/Controller.ts index ebd31c0..99aace5 100644 --- a/app/src/modules/Controller.ts +++ b/app/src/modules/Controller.ts @@ -6,14 +6,10 @@ export class Controller { protected middlewares = { auth, permission - } + }; - protected create({ auth }: { auth?: boolean } = {}): Hono { - const server = Controller.createServer(); - if (auth !== false) { - server.use(this.middlewares.auth); - } - return server; + protected create(): Hono { + return Controller.createServer(); } static createServer(): Hono { @@ -23,4 +19,4 @@ export class Controller { getController(): Hono { return this.create(); } -} \ No newline at end of file +} diff --git a/app/src/modules/Module.ts b/app/src/modules/Module.ts index 6a86d3e..e9e2933 100644 --- a/app/src/modules/Module.ts +++ b/app/src/modules/Module.ts @@ -10,6 +10,7 @@ export type ServerEnv = { Variables: { app: App; auth_resolved: boolean; + auth_registered: boolean; html?: string; }; }; @@ -87,9 +88,9 @@ export abstract class Module) {} get ctx() { if (!this._ctx) { diff --git a/app/src/modules/ModuleManager.ts b/app/src/modules/ModuleManager.ts index dcbfb34..558b3d8 100644 --- a/app/src/modules/ModuleManager.ts +++ b/app/src/modules/ModuleManager.ts @@ -212,14 +212,9 @@ export class ModuleManager { 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) => { - if ("getMiddleware" in module) { - const middleware = module.getMiddleware(); - if (middleware) { - this.server.use(middleware); - } - } + module.onServerInit(this.server); }); } @@ -550,4 +545,4 @@ export function getDefaultConfig(): ModuleConfigs { }); return config as any; -} \ No newline at end of file +} diff --git a/app/src/modules/server/AdminController.tsx b/app/src/modules/server/AdminController.tsx index 1da3dee..e7e60fe 100644 --- a/app/src/modules/server/AdminController.tsx +++ b/app/src/modules/server/AdminController.tsx @@ -65,8 +65,6 @@ export class AdminController extends Controller { } c.set("html", html); - // refresh cookie if needed - await auth.authenticator?.requestCookieRefresh(c); await next(); });