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;
}
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(
permissions: PermissionObject,
type: PermissionType | "admin",
@ -48,6 +61,18 @@ export default class PermissionHelper {
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(
requiredPermissions: PermissionType | "admin",
section: PermissionSection,
@ -60,11 +85,29 @@ export default class PermissionHelper {
if (isOwner || this.can(permissions, requiredPermissions, section, module)) {
next();
} else {
throw new ForbiddenRequestException(
`missing permission for ${section}.${module}.${
Array.isArray(requiredPermissions) ? requiredPermissions.join("|") : requiredPermissions
}`
);
throw new ForbiddenRequestException(`missing permission for ${section}.${module}.${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)) {
next();
} else {
throw new ForbiddenRequestException(
`missing permission for ${section}.${module}.${
Array.isArray(requiredPermissions) ? requiredPermissions.join("|") : requiredPermissions
}`
);
throw new ForbiddenRequestException(`missing permission for ${section}.${module}.${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 });
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(
"/communicationtype",
PermissionHelper.passCheckMiddleware("read", "settings", "communication_type"),
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "communication_type" },
{ requiredPermissions: "read", section: "club", module: "member" },
]),
communicationType
);
router.use(
"/executiveposition",
PermissionHelper.passCheckMiddleware("read", "settings", "executive_position"),
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "executive_position" },
{ requiredPermissions: "read", section: "club", module: "member" },
]),
executivePosition
);
router.use(
"/membershipstatus",
PermissionHelper.passCheckMiddleware("read", "settings", "membership_status"),
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "membership_status" },
{ requiredPermissions: "read", section: "club", module: "member" },
]),
membershipStatus
);
router.use("/qualification", PermissionHelper.passCheckMiddleware("read", "settings", "qualification"), qualification);
router.use("/salutation", PermissionHelper.passCheckMiddleware("read", "settings", "salutation"), salutation);
router.use("/calendartype", PermissionHelper.passCheckMiddleware("read", "settings", "calendar_type"), calendarType);
router.use(
"/qualification",
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("/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(
"/newsletterconfig",
PermissionHelper.passCheckMiddleware("read", "settings", "newsletter_config"),
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermissions: "read", section: "settings", module: "newsletter_config" },
{ requiredPermissions: "read", section: "settings", module: "communication_type" },
]),
newsletterConfig
);
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("/querybuilder", PermissionHelper.passCheckMiddleware("read", "club", "query"), queryBuilder);
router.use("/newsletter", PermissionHelper.passCheckMiddleware("read", "club", "newsletter"), newsletter);
router.use(
"/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("/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("/webapi", preventWebapiAccess, PermissionHelper.passCheckMiddleware("read", "user", "webapi"), api);