Compare commits

...

4 commits

9 changed files with 188 additions and 30 deletions

View file

@ -43,6 +43,9 @@ export class calendar {
@UpdateDateColumn()
updatedAt: Date;
@Column({ type: "varchar", nullable: true, default: null, unique: true })
webpageId: string;
@ManyToOne(() => calendarType, (t) => t.calendar, {
nullable: false,
onDelete: "RESTRICT",

View file

@ -9,7 +9,7 @@ export class calendarType {
@Column({ type: "varchar", length: 255, unique: true })
type: string;
@Column({ type: "boolean" }) // none specified cal dav request
@Column({ type: "boolean", default: false }) // none specified cal dav request
nscdr: boolean;
@Column({ type: "varchar", length: 255 })
@ -18,6 +18,9 @@ export class calendarType {
@Column({ type: "varchar", length: 255, nullable: true, default: null })
passphrase: string | null;
@Column({ type: "boolean", default: false })
sendToWebpage: boolean;
@OneToMany(() => calendar, (c) => c.type, {
nullable: false,
onDelete: "RESTRICT",

View file

@ -22,6 +22,9 @@ export class user {
@Column({ type: "varchar", length: 255 })
secret: string;
@Column({ type: "boolean", default: false })
static: boolean;
@Column({ type: "boolean", default: false })
isOwner: boolean;

View file

@ -21,8 +21,7 @@ export type BackupSectionRefered = {
};
export type BackupFileContent = { [key in BackupSection]?: BackupFileContentSection } & {
collectIds: boolean;
version: 1;
backup_file_details: { collectIds: boolean; createdAt: Date; version: 1 };
};
export type BackupFileContentSection = Array<any> | { [key: string]: Array<any> };
@ -90,7 +89,7 @@ export default abstract class BackupHelper {
filename = new Date().toISOString().split("T")[0];
}
let json: BackupFileContent = { collectIds, version: 1 };
let json: BackupFileContent = { backup_file_details: { collectIds, createdAt: new Date(), version: 1 } };
for (const section of this.backupSection) {
json[section.type] = await this.getSectionData(section.type, collectIds);
}
@ -131,7 +130,7 @@ export default abstract class BackupHelper {
for (const section of sections
.filter((s) => Object.keys(backup).includes(s.type))
.sort((a, b) => a.orderOnInsert - b.orderOnInsert)) {
await this.setSectionData(section.type, backup[section.type], backup.collectIds ?? false);
await this.setSectionData(section.type, backup[section.type], backup.backup_file_details.collectIds ?? false);
}
this.transactionManager = undefined;

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

@ -59,6 +59,7 @@ export const user_table = new Table({
{ name: "firstname", type: getTypeByORM("varchar"), length: "255", isNullable: false },
{ name: "lastname", type: getTypeByORM("varchar"), length: "255", isNullable: false },
{ name: "secret", type: getTypeByORM("varchar"), length: "255", isNullable: false },
{ name: "static", type: getTypeByORM("boolean"), isNullable: false, default: false },
{ name: "isOwner", type: getTypeByORM("boolean"), isNullable: false, default: false },
],
});

View file

@ -6,9 +6,10 @@ export const calendar_type_table = new Table({
columns: [
{ name: "id", type: getTypeByORM("int"), isPrimary: true, isGenerated: true, generationStrategy: "increment" },
{ name: "type", type: getTypeByORM("varchar"), length: "255", isUnique: true, isNullable: false },
{ name: "nscdr", type: getTypeByORM("boolean"), isNullable: false },
{ name: "nscdr", type: getTypeByORM("boolean"), isNullable: false, default: false },
{ name: "color", type: getTypeByORM("varchar"), length: "255", isNullable: false },
{ name: "passphrase", type: getTypeByORM("varchar"), length: "255", isNullable: true },
{ name: "sendToWebpage", type: getTypeByORM("boolean"), isNullable: false, default: false },
],
});
@ -45,6 +46,14 @@ export const calendar_table = new Table({
default: "CURRENT_TIMESTAMP(6)",
onUpdate: "CURRENT_TIMESTAMP(6)",
},
{
name: "webpageId",
type: getTypeByORM("varchar"),
length: "255",
isNullable: true,
default: null,
isUnique: true,
},
{ name: "typeId", type: getTypeByORM("int"), isNullable: false },
],
foreignKeys: [

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);

View file

@ -14,7 +14,12 @@ export default abstract class NewsletterRecipientsService {
.getRepository(newsletterRecipients)
.createQueryBuilder("newsletterRecipients")
.leftJoinAndSelect("newsletterRecipients.member", "member")
.leftJoinAndSelect("member.sendNewsletter", "sendNewsletter")
.leftJoinAndMapOne(
"member.sendNewsletter",
"member.communications",
"sendNewsletter",
"sendNewsletter.isSendNewsletter = 1"
)
.leftJoinAndSelect("sendNewsletter.type", "communicationtype")
.leftJoinAndSelect("newsletterRecipients.newsletter", "newsletter")
.where("newsletterRecipients.newsletterId = :id", { id: newsletterId })