change: allow read to related data from allowed modules

This commit is contained in:
Julian Krauser 2025-01-31 11:07:58 +01:00
parent 668d8448da
commit e17eb30aed
2 changed files with 158 additions and 23 deletions

View file

@ -32,6 +32,19 @@ export default class PermissionHelper {
return false; return false;
} }
static canSome(
permissions: PermissionObject,
checks: Array<{
requiredPermissions: PermissionType | "admin";
section: PermissionSection;
module?: PermissionModule;
}>
) {
checks.reduce<boolean>((prev, curr) => {
return prev || this.can(permissions, curr.requiredPermissions, curr.section, curr.module);
}, false);
}
static canSection( static canSection(
permissions: PermissionObject, permissions: PermissionObject,
type: PermissionType | "admin", type: PermissionType | "admin",
@ -48,6 +61,18 @@ export default class PermissionHelper {
return false; return false;
} }
static canSomeSection(
permissions: PermissionObject,
checks: Array<{
requiredPermissions: PermissionType | "admin";
section: PermissionSection;
}>
): boolean {
return checks.reduce<boolean>((prev, curr) => {
return prev || this.can(permissions, curr.requiredPermissions, curr.section);
}, false);
}
static passCheckMiddleware( static passCheckMiddleware(
requiredPermissions: PermissionType | "admin", requiredPermissions: PermissionType | "admin",
section: PermissionSection, section: PermissionSection,
@ -60,11 +85,29 @@ export default class PermissionHelper {
if (isOwner || this.can(permissions, requiredPermissions, section, module)) { if (isOwner || this.can(permissions, requiredPermissions, section, module)) {
next(); next();
} else { } else {
throw new ForbiddenRequestException( throw new ForbiddenRequestException(`missing permission for ${section}.${module}.${requiredPermissions}`);
`missing permission for ${section}.${module}.${ }
Array.isArray(requiredPermissions) ? requiredPermissions.join("|") : requiredPermissions };
}` }
);
static passCheckSomeMiddleware(
checks: Array<{
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.canSome(permissions, checks)) {
next();
} else {
let permissionsToPass = checks.reduce<string>((prev, curr) => {
return prev + (prev != " or " ? "" : "") + `${curr.section}.${curr.module}.${curr.requiredPermissions}`;
}, "");
throw new ForbiddenRequestException(`missing permission for ${permissionsToPass}`);
} }
}; };
} }
@ -80,11 +123,25 @@ export default class PermissionHelper {
if (isOwner || this.canSection(permissions, requiredPermissions, section)) { if (isOwner || this.canSection(permissions, requiredPermissions, section)) {
next(); next();
} else { } else {
throw new ForbiddenRequestException( throw new ForbiddenRequestException(`missing permission for ${section}.${module}.${requiredPermissions}`);
`missing permission for ${section}.${module}.${ }
Array.isArray(requiredPermissions) ? requiredPermissions.join("|") : requiredPermissions };
}` }
);
static sectionPassCheckSomeMiddleware(
checks: Array<{ 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.canSomeSection(permissions, checks)) {
next();
} else {
let permissionsToPass = checks.reduce<string>((prev, curr) => {
return prev + (prev != " or " ? "" : "") + `${curr.section}.${curr.requiredPermissions}`;
}, "");
throw new ForbiddenRequestException(`missing permission for ${permissionsToPass}`);
} }
}; };
} }

View file

@ -27,42 +27,120 @@ import preventWebapiAccess from "../../middleware/preventWebApiAccess";
var router = express.Router({ mergeParams: true }); var router = express.Router({ mergeParams: true });
router.use("/award", PermissionHelper.passCheckMiddleware("read", "settings", "award"), award); router.use(
"/award",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "award" },
{ requiredPermissions: "read", section: "club", module: "member" },
]),
award
);
router.use( router.use(
"/communicationtype", "/communicationtype",
PermissionHelper.passCheckMiddleware("read", "settings", "communication_type"), PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "communication_type" },
{ requiredPermissions: "read", section: "club", module: "member" },
]),
communicationType communicationType
); );
router.use( router.use(
"/executiveposition", "/executiveposition",
PermissionHelper.passCheckMiddleware("read", "settings", "executive_position"), PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "executive_position" },
{ requiredPermissions: "read", section: "club", module: "member" },
]),
executivePosition executivePosition
); );
router.use( router.use(
"/membershipstatus", "/membershipstatus",
PermissionHelper.passCheckMiddleware("read", "settings", "membership_status"), PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "membership_status" },
{ requiredPermissions: "read", section: "club", module: "member" },
]),
membershipStatus membershipStatus
); );
router.use("/qualification", PermissionHelper.passCheckMiddleware("read", "settings", "qualification"), qualification); router.use(
router.use("/salutation", PermissionHelper.passCheckMiddleware("read", "settings", "salutation"), salutation); "/qualification",
router.use("/calendartype", PermissionHelper.passCheckMiddleware("read", "settings", "calendar_type"), calendarType); PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "qualification" },
{ requiredPermissions: "read", section: "club", module: "member" },
]),
qualification
);
router.use(
"/salutation",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "salutation" },
{ requiredPermissions: "read", section: "club", module: "member" },
]),
salutation
);
router.use(
"/calendartype",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "calendar_type" },
{ requiredPermissions: "read", section: "club", module: "calendar" },
]),
calendarType
);
router.use("/querystore", PermissionHelper.passCheckMiddleware("read", "settings", "query_store"), queryStore); router.use("/querystore", PermissionHelper.passCheckMiddleware("read", "settings", "query_store"), queryStore);
router.use("/template", PermissionHelper.passCheckMiddleware("read", "settings", "template"), template); router.use("/template", PermissionHelper.passCheckMiddleware("read", "settings", "template"), template);
router.use("/templateusage", PermissionHelper.passCheckMiddleware("read", "settings", "template_usage"), templateUsage); router.use(
"/templateusage",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "template_usage" },
{ requiredPermissions: "read", section: "settings", module: "template" },
]),
templateUsage
);
router.use( router.use(
"/newsletterconfig", "/newsletterconfig",
PermissionHelper.passCheckMiddleware("read", "settings", "newsletter_config"), PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "newsletter_config" },
{ requiredPermissions: "read", section: "settings", module: "communication_type" },
]),
newsletterConfig newsletterConfig
); );
router.use("/member", PermissionHelper.passCheckMiddleware("read", "club", "member"), member); router.use("/member", PermissionHelper.passCheckMiddleware("read", "club", "member"), member);
router.use("/protocol", PermissionHelper.passCheckMiddleware("read", "club", "protocol"), protocol); router.use(
"/protocol",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "club", module: "protocol" },
{ requiredPermissions: "read", section: "club", module: "member" },
]),
protocol
);
router.use("/calendar", PermissionHelper.passCheckMiddleware("read", "club", "calendar"), calendar); router.use("/calendar", PermissionHelper.passCheckMiddleware("read", "club", "calendar"), calendar);
router.use("/querybuilder", PermissionHelper.passCheckMiddleware("read", "club", "query"), queryBuilder); router.use(
router.use("/newsletter", PermissionHelper.passCheckMiddleware("read", "club", "newsletter"), newsletter); "/querybuilder",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "club", module: "query" },
{ requiredPermissions: "read", section: "settings", 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: "settings", module: "query_store" },
]),
newsletter
);
router.use("/role", PermissionHelper.passCheckMiddleware("read", "user", "role"), role); router.use("/role", PermissionHelper.passCheckMiddleware("read", "user", "role"), role);
router.use("/user", PermissionHelper.passCheckMiddleware("read", "user", "user"), user); router.use(
"/user",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "user", module: "user" },
{ requiredPermissions: "read", section: "user", module: "role" },
]),
user
);
router.use("/invite", PermissionHelper.passCheckMiddleware("read", "user", "user"), invite); router.use("/invite", PermissionHelper.passCheckMiddleware("read", "user", "user"), invite);
router.use("/webapi", preventWebapiAccess, PermissionHelper.passCheckMiddleware("read", "user", "webapi"), api); router.use("/webapi", preventWebapiAccess, PermissionHelper.passCheckMiddleware("read", "user", "webapi"), api);