From 56484020d89aff9148ff4b335d99d4f1b425c50e Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 7 May 2025 09:05:36 +0200 Subject: [PATCH] enhance: permission handling --- src/controller/authController.ts | 2 -- src/helpers/permissionHelper.ts | 37 ++++++++----------- src/routes/admin/index.ts | 62 ++++++++++++++++---------------- src/type/permissionTypes.ts | 4 ++- 4 files changed, 49 insertions(+), 56 deletions(-) diff --git a/src/controller/authController.ts b/src/controller/authController.ts index 6302a3c..ce674ab 100644 --- a/src/controller/authController.ts +++ b/src/controller/authController.ts @@ -41,8 +41,6 @@ export async function login(req: Request, res: Response): Promise { let { id } = await UserService.getByUsername(username); let { secret, routine } = await UserService.getUserSecretAndRoutine(id); - console.log(secret, passedSecret); - let valid = false; if (routine == LoginRoutineEnum.totp) { valid = speakeasy.totp.verify({ diff --git a/src/helpers/permissionHelper.ts b/src/helpers/permissionHelper.ts index 6a83f92..fd66663 100644 --- a/src/helpers/permissionHelper.ts +++ b/src/helpers/permissionHelper.ts @@ -17,33 +17,30 @@ export default class PermissionHelper { permissions: PermissionObject, type: PermissionType | "admin", section: PermissionSection, - module?: PermissionModule + module: PermissionModule ) { if (type == "admin") return permissions?.admin ?? permissions?.adminByOwner ?? false; if (permissions?.admin || permissions?.adminByOwner) return true; if ( - (!module && - permissions[section] != undefined && - (permissions[section]?.all == "*" || permissions[section]?.all?.includes(type))) || permissions[section]?.all == "*" || - permissions[section]?.all?.includes(type) + permissions[section]?.all?.includes(type) || + permissions[section]?.[module] == "*" || + permissions[section]?.[module]?.includes(type) ) return true; - if (module && (permissions[section]?.[module] == "*" || permissions[section]?.[module]?.includes(type))) - return true; return false; } static canSome( permissions: PermissionObject, checks: Array<{ - requiredPermissions: PermissionType | "admin"; + requiredPermission: PermissionType | "admin"; section: PermissionSection; - module?: PermissionModule; + module: PermissionModule; }> ) { checks.reduce((prev, curr) => { - return prev || this.can(permissions, curr.requiredPermissions, curr.section, curr.module); + return prev || this.can(permissions, curr.requiredPermission, curr.section, curr.module); }, false); } @@ -66,12 +63,12 @@ export default class PermissionHelper { static canSomeSection( permissions: PermissionObject, checks: Array<{ - requiredPermissions: PermissionType | "admin"; + requiredPermission: PermissionType | "admin"; section: PermissionSection; }> ): boolean { return checks.reduce((prev, curr) => { - return prev || this.can(permissions, curr.requiredPermissions, curr.section); + return prev || this.canSection(permissions, curr.requiredPermission, curr.section); }, false); } @@ -83,7 +80,7 @@ export default class PermissionHelper { static passCheckMiddleware( requiredPermissions: PermissionType | "admin", section: PermissionSection, - module?: PermissionModule + module: PermissionModule ): (req: Request, res: Response, next: Function) => void { return (req: Request, res: Response, next: Function) => { const permissions = req.permissions; @@ -99,9 +96,9 @@ export default class PermissionHelper { static passCheckSomeMiddleware( checks: Array<{ - requiredPermissions: PermissionType | "admin"; + requiredPermission: PermissionType | "admin"; section: PermissionSection; - module?: PermissionModule; + module: PermissionModule; }> ): (req: Request, res: Response, next: Function) => void { return (req: Request, res: Response, next: Function) => { @@ -111,9 +108,7 @@ export default class PermissionHelper { if (isOwner || this.canSome(permissions, checks)) { next(); } else { - let permissionsToPass = checks.reduce((prev, curr) => { - return prev + (prev != " or " ? "" : "") + `${curr.section}.${curr.module}.${curr.requiredPermissions}`; - }, ""); + let permissionsToPass = checks.map((c) => `${c.section}.${c.module}.${c.requiredPermission}`).join(" or "); throw new ForbiddenRequestException(`missing permission for ${permissionsToPass}`); } }; @@ -136,7 +131,7 @@ export default class PermissionHelper { } static sectionPassCheckSomeMiddleware( - checks: Array<{ requiredPermissions: PermissionType | "admin"; section: PermissionSection }> + checks: Array<{ requiredPermission: PermissionType | "admin"; section: PermissionSection }> ): (req: Request, res: Response, next: Function) => void { return (req: Request, res: Response, next: Function) => { const permissions = req.permissions; @@ -145,9 +140,7 @@ export default class PermissionHelper { if (isOwner || this.canSomeSection(permissions, checks)) { next(); } else { - let permissionsToPass = checks.reduce((prev, curr) => { - return prev + (prev != " or " ? "" : "") + `${curr.section}.${curr.requiredPermissions}`; - }, ""); + let permissionsToPass = checks.map((c) => `${c.section}.${c.requiredPermission}`).join(" or "); throw new ForbiddenRequestException(`missing permission for ${permissionsToPass}`); } }; diff --git a/src/routes/admin/index.ts b/src/routes/admin/index.ts index 5c3444b..4e74012 100644 --- a/src/routes/admin/index.ts +++ b/src/routes/admin/index.ts @@ -33,64 +33,64 @@ var router = express.Router({ mergeParams: true }); router.use( "/award", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "configuration", module: "award" }, - { requiredPermissions: "read", section: "club", module: "member" }, + { requiredPermission: "read", section: "configuration", module: "award" }, + { requiredPermission: "read", section: "club", module: "member" }, ]), award ); router.use( "/communicationtype", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "configuration", module: "communication_type" }, - { requiredPermissions: "read", section: "club", module: "member" }, + { requiredPermission: "read", section: "configuration", module: "communication_type" }, + { requiredPermission: "read", section: "club", module: "member" }, ]), communicationType ); router.use( "/executiveposition", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "configuration", module: "executive_position" }, - { requiredPermissions: "read", section: "club", module: "member" }, + { requiredPermission: "read", section: "configuration", module: "executive_position" }, + { requiredPermission: "read", section: "club", module: "member" }, ]), executivePosition ); router.use( "/membershipstatus", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "configuration", module: "membership_status" }, - { requiredPermissions: "read", section: "club", module: "member" }, + { requiredPermission: "read", section: "configuration", module: "membership_status" }, + { requiredPermission: "read", section: "club", module: "member" }, ]), membershipStatus ); router.use( "/qualification", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "configuration", module: "qualification" }, - { requiredPermissions: "read", section: "club", module: "member" }, + { requiredPermission: "read", section: "configuration", module: "qualification" }, + { requiredPermission: "read", section: "club", module: "member" }, ]), qualification ); router.use( "/salutation", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "configuration", module: "salutation" }, - { requiredPermissions: "read", section: "club", module: "member" }, + { requiredPermission: "read", section: "configuration", module: "salutation" }, + { requiredPermission: "read", section: "club", module: "member" }, ]), salutation ); router.use( "/calendartype", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "configuration", module: "calendar_type" }, - { requiredPermissions: "read", section: "club", module: "calendar" }, + { requiredPermission: "read", section: "configuration", module: "calendar_type" }, + { requiredPermission: "read", section: "club", module: "calendar" }, ]), calendarType ); router.use( "/querystore", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "configuration", module: "query_store" }, - { requiredPermissions: "read", section: "club", module: "listprint" }, + { requiredPermission: "read", section: "configuration", module: "query_store" }, + { requiredPermission: "read", section: "club", module: "listprint" }, ]), queryStore ); @@ -98,16 +98,16 @@ router.use("/template", PermissionHelper.passCheckMiddleware("read", "configurat router.use( "/templateusage", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "configuration", module: "template_usage" }, - { requiredPermissions: "read", section: "configuration", module: "template" }, + { requiredPermission: "read", section: "configuration", module: "template_usage" }, + { requiredPermission: "read", section: "configuration", module: "template" }, ]), templateUsage ); router.use( "/newsletterconfig", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "configuration", module: "newsletter_config" }, - { requiredPermissions: "read", section: "configuration", module: "communication_type" }, + { requiredPermission: "read", section: "configuration", module: "newsletter_config" }, + { requiredPermission: "read", section: "configuration", module: "communication_type" }, ]), newsletterConfig ); @@ -116,8 +116,8 @@ router.use("/member", PermissionHelper.passCheckMiddleware("read", "club", "memb router.use( "/protocol", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "club", module: "protocol" }, - { requiredPermissions: "read", section: "club", module: "member" }, + { requiredPermission: "read", section: "club", module: "protocol" }, + { requiredPermission: "read", section: "club", module: "member" }, ]), protocol ); @@ -125,19 +125,19 @@ router.use("/calendar", PermissionHelper.passCheckMiddleware("read", "club", "ca router.use( "/querybuilder", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "club", module: "query" }, - { requiredPermissions: "read", section: "configuration", module: "query_store" }, + { requiredPermission: "read", section: "club", module: "query" }, + { requiredPermission: "read", section: "configuration", module: "query_store" }, ]), queryBuilder ); router.use( "/newsletter", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "club", module: "newsletter" }, - { requiredPermissions: "read", section: "club", module: "member" }, - { requiredPermissions: "read", section: "club", module: "calendar" }, - { requiredPermissions: "read", section: "club", module: "query" }, - { requiredPermissions: "read", section: "configuration", module: "query_store" }, + { requiredPermission: "read", section: "club", module: "newsletter" }, + { requiredPermission: "read", section: "club", module: "member" }, + { requiredPermission: "read", section: "club", module: "calendar" }, + { requiredPermission: "read", section: "club", module: "query" }, + { requiredPermission: "read", section: "configuration", module: "query_store" }, ]), newsletter ); @@ -147,8 +147,8 @@ router.use("/role", PermissionHelper.passCheckMiddleware("read", "management", " router.use( "/user", PermissionHelper.passCheckSomeMiddleware([ - { requiredPermissions: "read", section: "management", module: "user" }, - { requiredPermissions: "read", section: "management", module: "role" }, + { requiredPermission: "read", section: "management", module: "user" }, + { requiredPermission: "read", section: "management", module: "role" }, ]), user ); diff --git a/src/type/permissionTypes.ts b/src/type/permissionTypes.ts index c3babac..eff7fd1 100644 --- a/src/type/permissionTypes.ts +++ b/src/type/permissionTypes.ts @@ -98,5 +98,7 @@ export const sectionsAndModules: SectionsAndModulesObject = { "newsletter_config", ], management: ["user", "role", "webapi", "backup", "setting"], - additional: [], + additional: [ + //{ key: "val", name: "name", type: "number", emptyIfAdmin: true }, + ], };