mirror of
https://github.com/bknd-io/bknd/
synced 2026-08-04 00:56:01 +00:00
refactor: restructure permission handling and enhance Guard functionality
- Introduced a new `createGuard` function to streamline the creation of Guard instances with permissions and roles. - Updated tests in `authorize.spec.ts` to reflect changes in permission checks, ensuring they now return undefined for denied permissions. - Added new `Permission` and `Policy` classes to improve type safety and flexibility in permission management. - Refactored middleware and controller files to utilize the updated permission structure, including context handling for permissions. - Created a new `SystemController.spec.ts` file to test the integration of the new permission system within the SystemController. - Removed legacy permission handling from core security files, consolidating permission logic within the new structure.
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import { $console, patternMatch } from "bknd/utils";
|
||||
import type { Context } from "hono";
|
||||
import { createMiddleware } from "hono/factory";
|
||||
import type { ServerEnv } from "modules/Controller";
|
||||
|
||||
function getPath(reqOrCtx: Request | Context) {
|
||||
const req = reqOrCtx instanceof Request ? reqOrCtx : reqOrCtx.req.raw;
|
||||
return new URL(req.url).pathname;
|
||||
}
|
||||
|
||||
export function shouldSkip(c: Context<ServerEnv>, skip?: (string | RegExp)[]) {
|
||||
const authCtx = c.get("auth");
|
||||
if (!authCtx) {
|
||||
throw new Error("auth ctx not found");
|
||||
}
|
||||
|
||||
if (authCtx.skip) return true;
|
||||
|
||||
const req = c.req.raw;
|
||||
if (!skip) return false;
|
||||
|
||||
const path = getPath(req);
|
||||
const result = skip.some((s) => patternMatch(path, s));
|
||||
|
||||
authCtx.skip = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
export const auth = (options?: {
|
||||
skip?: (string | RegExp)[];
|
||||
}) =>
|
||||
createMiddleware<ServerEnv>(async (c, next) => {
|
||||
if (!c.get("auth")) {
|
||||
c.set("auth", {
|
||||
registered: false,
|
||||
resolved: false,
|
||||
skip: false,
|
||||
user: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
const app = c.get("app");
|
||||
const authCtx = c.get("auth")!;
|
||||
const authenticator = app?.module.auth.authenticator;
|
||||
|
||||
let skipped = shouldSkip(c, options?.skip) || !app?.module.auth.enabled;
|
||||
|
||||
// make sure to only register once
|
||||
if (authCtx.registered) {
|
||||
skipped = true;
|
||||
$console.debug(`auth middleware already registered for ${getPath(c)}`);
|
||||
} else {
|
||||
authCtx.registered = true;
|
||||
|
||||
if (!skipped && !authCtx.resolved && app?.module.auth.enabled) {
|
||||
authCtx.user = await authenticator?.resolveAuthFromRequest(c);
|
||||
authCtx.resolved = true;
|
||||
}
|
||||
}
|
||||
|
||||
await next();
|
||||
// @todo: potentially add cookie refresh if content-type html and about to expire
|
||||
|
||||
// release
|
||||
authCtx.skip = false;
|
||||
authCtx.resolved = false;
|
||||
authCtx.user = undefined;
|
||||
});
|
||||
Reference in New Issue
Block a user