role and permission handling in auth module

- Updated the `Role` class to change the `create` method signature for improved clarity and flexibility.
- Refactored the `guardRoleSchema` to utilize the new `roleSchema` for better consistency.
- Introduced a new `TPermission` type to enhance type safety in permission handling across the application.
- Updated various components and forms to accommodate the new permission structure, ensuring backward compatibility.
- Enhanced the `AuthRolesEdit` and `AuthRolesList` components to improve role management and permissions display.
- Added new API endpoints for fetching permissions, improving the overall functionality of the auth module.
This commit is contained in:
dswbx
2025-10-14 16:36:42 +02:00
parent 6624927286
commit 1b8ce41837
12 changed files with 254 additions and 52 deletions

View File

@@ -61,7 +61,7 @@ export class AppAuth extends Module<AppAuthSchema> {
// register roles
const roles = transformObject(this.config.roles ?? {}, (role, name) => {
return Role.create({ name, ...role });
return Role.create(name, role);
});
this.ctx.guard.setRoles(Object.values(roles));
this.ctx.guard.setConfig(this.config.guard ?? {});
@@ -210,10 +210,13 @@ export class AppAuth extends Module<AppAuthSchema> {
}
const strategies = this.authenticator.getStrategies();
const roles = Object.fromEntries(this.ctx.guard.getRoles().map((r) => [r.name, r.toJSON()]));
console.log("roles", roles);
return {
...this.config,
...this.authenticator.toJSON(secrets),
roles: secrets ? roles : undefined,
strategies: transformObject(strategies, (strategy) => ({
enabled: this.isStrategyEnabled(strategy),
...strategy.toJSON(secrets),

View File

@@ -1,6 +1,7 @@
import { cookieConfig, jwtConfig } from "auth/authenticate/Authenticator";
import { CustomOAuthStrategy, OAuthStrategy, PasswordStrategy } from "auth/authenticate/strategies";
import { objectTransform, s } from "bknd/utils";
import { roleSchema } from "auth/authorize/Role";
import { objectTransform, omitKeys, pick, s } from "bknd/utils";
import { $object, $record } from "modules/mcp";
export const Strategies = {
@@ -40,11 +41,8 @@ export type AppAuthCustomOAuthStrategy = s.Static<typeof STRATEGIES.custom_oauth
const guardConfigSchema = s.object({
enabled: s.boolean({ default: false }).optional(),
});
export const guardRoleSchema = s.strictObject({
permissions: s.array(s.string()).optional(),
is_default: s.boolean().optional(),
implicit_allow: s.boolean().optional(),
});
export const guardRoleSchema = roleSchema;
export const authConfigSchema = $object(
"config_auth",

View File

@@ -7,6 +7,13 @@ export const permissionOptionsSchema = s
})
.partial();
export type TPermission = {
name: string;
description?: string;
filterable?: boolean;
context?: any;
};
export type PermissionOptions = s.Static<typeof permissionOptionsSchema>;
export type PermissionContext<P extends Permission<any, any, any, any>> = P extends Permission<
any,

View File

@@ -13,7 +13,7 @@ export const rolePermissionSchema = s.strictObject({
export type RolePermissionSchema = s.Static<typeof rolePermissionSchema>;
export const roleSchema = s.strictObject({
name: s.string(),
// @todo: remove anyOf, add migration
permissions: s.anyOf([s.array(s.string()), s.array(rolePermissionSchema)]).optional(),
is_default: s.boolean().optional(),
implicit_allow: s.boolean().optional(),
@@ -44,7 +44,7 @@ export class Role {
public implicit_allow: boolean = false,
) {}
static create(config: RoleSchema) {
static create(name: string, config: RoleSchema) {
const permissions =
config.permissions?.map((p: string | RolePermissionSchema) => {
if (typeof p === "string") {
@@ -53,12 +53,11 @@ export class Role {
const policies = p.policies?.map((policy) => new Policy(policy));
return new RolePermission(new Permission(p.permission), policies, p.effect);
}) ?? [];
return new Role(config.name, permissions, config.is_default, config.implicit_allow);
return new Role(name, permissions, config.is_default, config.implicit_allow);
}
toJSON() {
return {
name: this.name,
permissions: this.permissions.map((p) => p.toJSON()),
is_default: this.is_default,
implicit_allow: this.implicit_allow,