patches v1.3.1 #59
12 changed files with 114 additions and 37 deletions
20
.env.example
20
.env.example
|
@ -1,4 +1,4 @@
|
|||
DB_TYPE = (mysql|sqlite|postgres)
|
||||
DB_TYPE = (mysql|sqlite|postgres) # default ist mysql
|
||||
|
||||
## BSP für mysql
|
||||
DB_PORT = 3306
|
||||
|
@ -19,20 +19,20 @@ DB_HOST = filename.db
|
|||
|
||||
SERVER_PORT = portnumber
|
||||
|
||||
JWT_SECRET = ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
|
||||
JWT_EXPIRATION = [0-9]*(y|d|h|m|s)
|
||||
REFRESH_EXPIRATION = [0-9]*(y|d|h|m|s)
|
||||
PWA_REFRESH_EXPIRATION = [0-9]*(y|d|h|m|s)
|
||||
JWT_SECRET = ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 # besitzt default
|
||||
JWT_EXPIRATION = [0-9]*(y|d|h|m|s) # default ist 15m
|
||||
REFRESH_EXPIRATION = [0-9]*(y|d|h|m|s) # default ist 1d
|
||||
PWA_REFRESH_EXPIRATION = [0-9]*(y|d|h|m|s) # default ist 5d
|
||||
|
||||
MAIL_USERNAME = mail_username
|
||||
MAIL_PASSWORD = mail_password
|
||||
MAIL_HOST = mail_hoststring
|
||||
MAIL_PORT = mail_portnumber
|
||||
MAIL_SECURE = (true|false) // true for port 465, fals for other ports
|
||||
MAIL_PORT = mail_portnumber # default ist 587
|
||||
MAIL_SECURE = (true|false) # true für port 465, false für anders gewählten port
|
||||
|
||||
CLUB_NAME = clubname #default FF Admin
|
||||
CLUB_WEBSITE = https://my-club-website-url
|
||||
CLUB_WEBSITE = https://my-club-website-url #optional, muss aber mit http:// oder https:// beginnen
|
||||
|
||||
BACKUP_INTERVAL = number of days (min 1)
|
||||
BACKUP_COPIES = number of parallel copies
|
||||
BACKUP_INTERVAL = number of days (min 1) # default 1
|
||||
BACKUP_COPIES = number of parallel copies #default 7
|
||||
BACKUP_AUTO_RESTORE = (true|false) # default false
|
|
@ -32,7 +32,7 @@ RUN apk add --no-cache \
|
|||
|
||||
WORKDIR /app
|
||||
|
||||
RUN mkdir -p /app/export
|
||||
RUN mkdir -p /app/files
|
||||
|
||||
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ services:
|
|||
- MAIL_USERNAME=<mailadress|username>
|
||||
- MAIL_PASSWORD=<password>
|
||||
- MAIL_HOST=<url>
|
||||
- MAIL_PORT=<port> # default ist auf 578 gesetzt
|
||||
- MAIL_PORT=<port> # default ist auf 587 gesetzt
|
||||
- MAIL_SECURE=<boolean> # default ist auf false gesetzt
|
||||
- CLUB_NAME=<tobemodified> # default ist auf FF Admin gesetzt
|
||||
- CLUB_WEBSITE=<tobemodified>
|
||||
|
|
|
@ -4,3 +4,7 @@ export interface SetNewsletterConfigCommand {
|
|||
comTypeId: number;
|
||||
config: NewsletterConfigType;
|
||||
}
|
||||
|
||||
export interface DeleteNewsletterConfigCommand {
|
||||
comTypeId: number;
|
||||
}
|
||||
|
|
|
@ -2,15 +2,15 @@ import { dataSource } from "../../../data-source";
|
|||
import { newsletterConfig } from "../../../entity/settings/newsletterConfig";
|
||||
import DatabaseActionException from "../../../exceptions/databaseActionException";
|
||||
import InternalException from "../../../exceptions/internalException";
|
||||
import { SetNewsletterConfigCommand } from "./newsletterConfigCommand";
|
||||
import { DeleteNewsletterConfigCommand, SetNewsletterConfigCommand } from "./newsletterConfigCommand";
|
||||
|
||||
export default abstract class NewsletterConfigCommandHandler {
|
||||
/**
|
||||
* @description set newsletterConfig
|
||||
* @param {SetNewsletterConfigCommand} setNewsletterConfig
|
||||
* @returns {Promise<number>}
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async set(setNewsletterConfig: SetNewsletterConfigCommand): Promise<number> {
|
||||
static async set(setNewsletterConfig: SetNewsletterConfigCommand): Promise<void> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
|
@ -21,11 +21,27 @@ export default abstract class NewsletterConfigCommandHandler {
|
|||
})
|
||||
.orUpdate(["config"], "comTypeId")
|
||||
.execute()
|
||||
.then((result) => {
|
||||
return result.identifiers[0].id;
|
||||
})
|
||||
.then((result) => {})
|
||||
.catch((err) => {
|
||||
throw new DatabaseActionException("SET", "newsletterConfig", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description delete newsletterConfig
|
||||
* @param {DeleteNewsletterConfigCommand} deleteNewsletterConfig
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async delete(deleteNewsletterConfig: DeleteNewsletterConfigCommand): Promise<void> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(newsletterConfig)
|
||||
.where("comTypeId = :comTypeId", { comTypeId: deleteNewsletterConfig.comTypeId })
|
||||
.execute()
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw new InternalException("Failed setting newsletterConfig", err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,10 @@ import { Request, Response } from "express";
|
|||
import NewsletterConfigService from "../../../service/settings/newsletterConfigService";
|
||||
import NewsletterConfigFactory from "../../../factory/admin/settings/newsletterConfig";
|
||||
import NewsletterConfigCommandHandler from "../../../command/settings/newsletterConfig/newsletterConfigCommandHandler";
|
||||
import { SetNewsletterConfigCommand } from "../../../command/settings/newsletterConfig/newsletterConfigCommand";
|
||||
import {
|
||||
DeleteNewsletterConfigCommand,
|
||||
SetNewsletterConfigCommand,
|
||||
} from "../../../command/settings/newsletterConfig/newsletterConfigCommand";
|
||||
|
||||
/**
|
||||
* @description get all newsletterConfigs
|
||||
|
@ -43,7 +46,24 @@ export async function setNewsletterConfig(req: Request, res: Response): Promise<
|
|||
comTypeId,
|
||||
config,
|
||||
};
|
||||
let id = await NewsletterConfigCommandHandler.set(createNewsletterConfig);
|
||||
await NewsletterConfigCommandHandler.set(createNewsletterConfig);
|
||||
|
||||
res.send(id);
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description delete award
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function deleteNewsletterConfig(req: Request, res: Response): Promise<any> {
|
||||
const comTypeId = parseInt(req.params.comTypeId);
|
||||
|
||||
let deleteNewsletterConfig: DeleteNewsletterConfigCommand = {
|
||||
comTypeId: comTypeId,
|
||||
};
|
||||
await NewsletterConfigCommandHandler.delete(deleteNewsletterConfig);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ export const MAIL_SECURE = process.env.MAIL_SECURE ?? "false";
|
|||
export const CLUB_NAME = process.env.CLUB_NAME ?? "FF Admin";
|
||||
export const CLUB_WEBSITE = process.env.CLUB_WEBSITE ?? "";
|
||||
|
||||
export const BACKUP_INTERVAL = Number(process.env.BACKUP_INTERVAL ?? "0");
|
||||
export const BACKUP_COPIES = Number(process.env.BACKUP_COPIES ?? "0");
|
||||
export const BACKUP_INTERVAL = Number(process.env.BACKUP_INTERVAL ?? "1");
|
||||
export const BACKUP_COPIES = Number(process.env.BACKUP_COPIES ?? "7");
|
||||
export const BACKUP_AUTO_RESTORE = process.env.BACKUP_AUTO_RESTORE ?? "true";
|
||||
|
||||
export function configCheck() {
|
||||
|
@ -60,6 +60,8 @@ export function configCheck() {
|
|||
|
||||
if (BACKUP_AUTO_RESTORE != "true" && BACKUP_AUTO_RESTORE != "false")
|
||||
throw new Error("set 'true' or 'false' to BACKUP_AUTO_RESTORE");
|
||||
if (BACKUP_INTERVAL < 1) throw new Error("BACKUP_INTERVAL has to be at least 1");
|
||||
if (BACKUP_COPIES < 1) throw new Error("BACKUP_COPIES has to be at least 1");
|
||||
}
|
||||
|
||||
function checkMS(input: string, origin: string) {
|
||||
|
|
|
@ -168,8 +168,9 @@ export default abstract class BackupHelper {
|
|||
this.transactionManager = undefined;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
this.transactionManager = undefined;
|
||||
throw new DatabaseActionException("BACKUP RESTORE", include.join(", "), err);
|
||||
throw new DatabaseActionException("BACKUP RESTORE", include.join(", ") || "FULL", err);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -331,6 +332,7 @@ export default abstract class BackupHelper {
|
|||
"newsletter.isSent",
|
||||
])
|
||||
.addSelect(["dates.calendarId", "dates.diffTitle", "dates.diffDescription"])
|
||||
.addSelect(["recipients.memberId"])
|
||||
.addSelect([
|
||||
...(collectIds ? ["member.id"] : []),
|
||||
"member.firstname",
|
||||
|
@ -340,7 +342,13 @@ export default abstract class BackupHelper {
|
|||
"member.internalId",
|
||||
])
|
||||
.addSelect(["recipientsByQuery.title", "recipientsByQuery.query"])
|
||||
.getMany();
|
||||
.getMany()
|
||||
.then((res: any) =>
|
||||
res.map((n: any) => ({
|
||||
...n,
|
||||
recipients: n.recipients.map((r: any) => ({ ...r, ...(false ? {} : { memberId: undefined }) })),
|
||||
}))
|
||||
);
|
||||
}
|
||||
private static async getNewsletterConfig(): Promise<Array<any>> {
|
||||
return await dataSource
|
||||
|
@ -630,7 +638,10 @@ export default abstract class BackupHelper {
|
|||
private static async setNewsletter(data: Array<any>, collectedIds: boolean): Promise<void> {
|
||||
await this.setQueryStore(
|
||||
uniqBy(
|
||||
data.map((d) => d.recipientsByQueryId).map((d) => ({ ...d, id: undefined })),
|
||||
data
|
||||
.map((d) => d.recipientsByQuery)
|
||||
.filter((q) => q != null)
|
||||
.map((d) => ({ ...d, id: undefined })),
|
||||
"query"
|
||||
)
|
||||
);
|
||||
|
@ -639,10 +650,14 @@ export default abstract class BackupHelper {
|
|||
let members = await this.transactionManager.getRepository("member").find();
|
||||
let dataWithMappedIds = data.map((d) => ({
|
||||
...d,
|
||||
recipientsByQueryId: {
|
||||
...d.recipientsByQueryId,
|
||||
id: queries.find((s) => s.query == d.recipientsByQueryId.query)?.id ?? undefined,
|
||||
},
|
||||
...(d.recipientsByQuery != null
|
||||
? {
|
||||
recipientsByQuery: {
|
||||
...d.recipientsByQuery,
|
||||
id: queries.find((s) => s.title == d.recipientsByQuery.title)?.id ?? undefined,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
...(!collectedIds
|
||||
? {
|
||||
recipients: d.recipients.map((r: any) => ({
|
||||
|
@ -687,7 +702,7 @@ export default abstract class BackupHelper {
|
|||
await this.transactionManager
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into("award")
|
||||
.into("calendar_type")
|
||||
.values(uniqBy([...(data?.["calendar_type"] ?? []), ...usedTypes], "type"))
|
||||
.orIgnore()
|
||||
.execute();
|
||||
|
|
|
@ -23,7 +23,7 @@ import BackupHelper from "./helpers/backupHelper";
|
|||
dataSource.initialize().then(async () => {
|
||||
if ((BACKUP_AUTO_RESTORE as "true" | "false") == "true" && (await dataSource.createQueryRunner().hasTable("user"))) {
|
||||
await BackupHelper.autoRestoreBackup().catch((err) => {
|
||||
console.log(`${new Date().toISOString()}: failed auto-restoring database`);
|
||||
console.log(`${new Date().toISOString()}: failed auto-restoring database`, err);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import express, { Request, Response } from "express";
|
||||
import {
|
||||
deleteNewsletterConfig,
|
||||
getAllNewsletterConfigs,
|
||||
getNewsletterConfigById,
|
||||
setNewsletterConfig,
|
||||
|
@ -24,4 +25,12 @@ router.put(
|
|||
}
|
||||
);
|
||||
|
||||
router.delete(
|
||||
"/:comTypeId",
|
||||
PermissionHelper.passCheckMiddleware("create", "settings", "newsletter_config"),
|
||||
async (req: Request, res: Response) => {
|
||||
await deleteNewsletterConfig(req, res);
|
||||
}
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
|
|
@ -5,6 +5,7 @@ import { membership } from "../../../entity/club/member/membership";
|
|||
import DatabaseActionException from "../../../exceptions/databaseActionException";
|
||||
import InternalException from "../../../exceptions/internalException";
|
||||
import { memberView } from "../../../views/memberView";
|
||||
import { DB_TYPE } from "../../../env.defaults";
|
||||
|
||||
export default abstract class MemberService {
|
||||
/**
|
||||
|
@ -158,13 +159,17 @@ export default abstract class MemberService {
|
|||
"member.firstMembershipEntry",
|
||||
"member.memberships",
|
||||
"membership_first",
|
||||
"membership_first.memberId = member.id AND membership_first.start = (SELECT MIN(m.start) FROM membership m WHERE m.memberId = member.id)"
|
||||
DB_TYPE == "postgres"
|
||||
? 'membership_first.memberId = member.id AND membership_first.start = (SELECT MIN("m_first"."start") FROM "membership" "m_first" WHERE "m_first"."memberId" = "member"."id")'
|
||||
: "membership_first.memberId = member.id AND membership_first.start = (SELECT MIN(m_first.start) FROM membership m_first WHERE m_first.memberId = member.id)"
|
||||
)
|
||||
.leftJoinAndMapOne(
|
||||
"member.lastMembershipEntry",
|
||||
"member.memberships",
|
||||
"membership_last",
|
||||
"membership_last.memberId = member.id AND membership_last.start = (SELECT MAX(m.start) FROM membership m WHERE m.memberId = member.id)"
|
||||
DB_TYPE == "postgres"
|
||||
? 'membership_last.memberId = member.id AND membership_last.start = (SELECT MAX("m_last"."start") FROM "membership" "m_last" WHERE "m_last"."memberId" = "member"."id")'
|
||||
: "membership_last.memberId = member.id AND membership_last.start = (SELECT MAX(m_last.start) FROM membership m_last WHERE m_last.memberId = member.id)"
|
||||
)
|
||||
.leftJoinAndSelect("membership_first.status", "status_first")
|
||||
.leftJoinAndSelect("membership_last.status", "status_last")
|
||||
|
@ -172,17 +177,22 @@ export default abstract class MemberService {
|
|||
"member.preferredCommunication",
|
||||
"member.communications",
|
||||
"preferredCommunication",
|
||||
"preferredCommunication.preferred = 1"
|
||||
"preferredCommunication.preferred = true"
|
||||
)
|
||||
.leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred")
|
||||
.leftJoinAndMapOne(
|
||||
"member.sendNewsletter",
|
||||
"member.communications",
|
||||
"sendNewsletter",
|
||||
"sendNewsletter.isSendNewsletter = 1"
|
||||
"sendNewsletter.isSendNewsletter = true"
|
||||
)
|
||||
.leftJoinAndSelect("sendNewsletter.type", "communicationtype")
|
||||
.leftJoinAndMapMany("member.smsAlarming", "member.communications", "smsAlarming", "smsAlarming.isSMSAlarming = 1")
|
||||
.leftJoinAndMapMany(
|
||||
"member.smsAlarming",
|
||||
"member.communications",
|
||||
"smsAlarming",
|
||||
"smsAlarming.isSMSAlarming = true"
|
||||
)
|
||||
.leftJoinAndSelect("smsAlarming.type", "communicationtype_smsAlarming")
|
||||
.leftJoinAndSelect("member.salutation", "salutation");
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ export default abstract class NewsletterRecipientsService {
|
|||
"sendNewsletter",
|
||||
"sendNewsletter.isSendNewsletter = 1"
|
||||
)
|
||||
.leftJoinAndSelect("member.salutation", "salutation")
|
||||
.leftJoinAndSelect("sendNewsletter.type", "communicationtype")
|
||||
.leftJoinAndSelect("newsletterRecipients.newsletter", "newsletter")
|
||||
.where("newsletterRecipients.newsletterId = :id", { id: newsletterId })
|
||||
|
|
Loading…
Add table
Reference in a new issue