import { Request, Response } from "express"; import { PermissionModule, permissionModules, PermissionObject, PermissionSection, PermissionString, PermissionType, permissionTypes, } from "../type/permissionTypes"; import ForbiddenRequestException from "../exceptions/forbiddenRequestException"; export default class PermissionHelper { static can( permissions: PermissionObject, type: PermissionType | "admin", section: PermissionSection, module?: PermissionModule ) { if (type == "admin") return permissions?.admin ?? false; if (permissions?.admin) return true; if ( (!module && permissions[section] != undefined && (permissions[section]?.all == "*" || permissions[section]?.all?.includes(type))) || permissions[section]?.all == "*" || permissions[section]?.all?.includes(type) ) return true; if (module && (permissions[section]?.[module] == "*" || permissions[section]?.[module]?.includes(type))) return true; return false; } static canSection( permissions: PermissionObject, type: PermissionType | "admin", section: PermissionSection ): boolean { if (type == "admin") return permissions?.admin ?? false; if (permissions?.admin) return true; if ( permissions[section]?.all == "*" || permissions[section]?.all?.includes(type) || permissions[section] != undefined ) return true; return false; } static passCheckMiddleware( requiredPermissions: PermissionType | "admin", section: PermissionSection, module?: PermissionModule ): (req: Request, res: Response, next: Function) => void { return (req: Request, res: Response, next: Function) => { const permissions = req.permissions; const isOwner = req.isOwner; if (isOwner || this.can(permissions, requiredPermissions, section, module)) { next(); } else { throw new ForbiddenRequestException( `missing permission for ${section}.${module}.${ Array.isArray(requiredPermissions) ? requiredPermissions.join("|") : requiredPermissions }` ); } }; } static sectionPassCheckMiddleware( requiredPermissions: PermissionType | "admin", section: PermissionSection ): (req: Request, res: Response, next: Function) => void { return (req: Request, res: Response, next: Function) => { const permissions = req.permissions; const isOwner = req.isOwner; if (isOwner || this.canSection(permissions, requiredPermissions, section)) { next(); } else { throw new ForbiddenRequestException( `missing permission for ${section}.${module}.${ Array.isArray(requiredPermissions) ? requiredPermissions.join("|") : requiredPermissions }` ); } }; } static convertToObject(permissions: Array): PermissionObject { if (permissions.includes("*")) { return { admin: true, }; } let output: PermissionObject = {}; let splitPermissions = permissions.map((e) => e.split(".")) as Array< [PermissionSection, PermissionModule | PermissionType | "*", PermissionType | "*"] >; for (let split of splitPermissions) { if (!output[split[0]]) { output[split[0]] = {}; } if (split[1] == "*" || output[split[0]].all == "*") { output[split[0]] = { all: "*" }; } else if (permissionTypes.includes(split[1] as PermissionType)) { if (!output[split[0]].all || !Array.isArray(output[split[0]].all)) { output[split[0]].all = []; } const permissionIndex = permissionTypes.indexOf(split[1] as PermissionType); const appliedPermissions = permissionTypes.slice(0, permissionIndex + 1); if (output[split[0]].all != "*") { output[split[0]].all = [ ...new Set([...output[split[0]].all, ...appliedPermissions]), ] as Array; } } else { if (split[2] == "*" || output[split[0]][split[1] as PermissionModule] == "*") { output[split[0]][split[1] as PermissionModule] = "*"; } else { if ( !output[split[0]][split[1] as PermissionModule] || !Array.isArray(output[split[0]][split[1] as PermissionModule]) ) { output[split[0]][split[1] as PermissionModule] = []; } const permissionIndex = permissionTypes.indexOf(split[2] as PermissionType); const appliedPermissions = permissionTypes.slice(0, permissionIndex + 1); output[split[0]][split[1] as PermissionModule] = appliedPermissions; if (output[split[0]][split[1] as PermissionModule] != "*") { output[split[0]][split[1] as PermissionModule] = [ ...new Set([...output[split[0]][split[1] as PermissionModule], ...appliedPermissions]), ] as Array; } } } } return output; } static convertToStringArray(permissions: PermissionObject): Array { if (permissions?.admin) { return ["*"]; } let output: Array = []; let sections = Object.keys(permissions) as Array; for (let section of sections) { if (permissions[section].all) { let types = permissions[section].all; if (types == "*" || types.length == permissionTypes.length) { output.push(`${section}.*`); } else { for (let type of types) { output.push(`${section}.${type}`); } } } let modules = Object.keys(permissions[section]).filter((m: PermissionModule) => permissionModules.includes(m) ) as Array; for (let module of modules) { let types = permissions[section][module]; if (types == "*" || types.length == permissionTypes.length) { output.push(`${section}.${module}.*`); } else { for (let type of types) { output.push(`${section}.${module}.${type}`); } } } } return output; } static getWhatToAdd(before: Array, after: Array): Array { return after.filter((permission) => !before.includes(permission)); } static getWhatToRemove(before: Array, after: Array): Array { return before.filter((permission) => !after.includes(permission)); } }