Compare commits

..

No commits in common. "ba03b6f097b7d0b8ef98dfa83d0cd648cb99c7eb" and "69134b210a9157385c65a290892ca0aeac0df9b8" have entirely different histories.

45 changed files with 147 additions and 145 deletions

View file

@ -10,7 +10,6 @@ SERVER_PORT = portnumber
JWT_SECRET = ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 JWT_SECRET = ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
JWT_EXPIRATION = [0-9]*(y|d|h|m|s) JWT_EXPIRATION = [0-9]*(y|d|h|m|s)
REFRESH_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)
MAIL_USERNAME = mail_username MAIL_USERNAME = mail_username
MAIL_PASSWORD = mail_password MAIL_PASSWORD = mail_password

View file

@ -25,21 +25,20 @@ services:
container_name: ff_member_administration_server container_name: ff_member_administration_server
restart: unless-stopped restart: unless-stopped
environment: environment:
- DB_TYPE=<mysql|sqlite> # default ist auf mysql gesetzt - DB_TYPE=mysql
- DB_HOST=ffm-db - DB_HOST=ffm-db
- DB_PORT=<number> # default ist auf 3306 gesetzt - DB_PORT=<number> # fallback ist auf 3306 gesetzt
- DB_NAME=ffadmin - DB_NAME=ffadmin
- DB_USERNAME=administration_backend - DB_USERNAME=administration_backend
- DB_PASSWORD=<dbuserpasswd> - DB_PASSWORD=<dbuserpasswd>
- JWT_SECRET=<tobemodified> - JWT_SECRET=<tobemodified>
- JWT_EXPIRATION=<number[m|d] - bsp.:15m> # default ist auf 15m gesetzt - JWT_EXPIRATION=<number[m|d] - bsp.:15m>
- REFRESH_EXPIRATION=<number[m|d] - bsp.:1d> # default ist auf 1d gesetzt - REFRESH_EXPIRATION=<number[m|d] - bsp.:1d>
- PWA_REFRESH_EXPIRATION=<number[m|d] - bsp.:5d> # default ist auf 5d gesetzt
- MAIL_USERNAME=<mailadress|username> - MAIL_USERNAME=<mailadress|username>
- MAIL_PASSWORD=<password> - MAIL_PASSWORD=<password>
- MAIL_HOST=<url> - MAIL_HOST=<url>
- MAIL_PORT=<port> # default ist auf 578 gesetzt - MAIL_PORT=<port>
- MAIL_SECURE=<boolean> # default ist auf false gesetzt - MAIL_SECURE=<boolean>
- CLUB_NAME=<tobemodified> - CLUB_NAME=<tobemodified>
- CLUB_WEBSITE=<tobemodified> - CLUB_WEBSITE=<tobemodified>
volumes: volumes:

View file

@ -43,6 +43,7 @@ export default abstract class MemberCommandHandler {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
static async update(updateMember: UpdateMemberCommand): Promise<void> { static async update(updateMember: UpdateMemberCommand): Promise<void> {
console.log(updateMember);
return await dataSource return await dataSource
.createQueryBuilder() .createQueryBuilder()
.update(member) .update(member)

View file

@ -31,7 +31,7 @@ export default abstract class MembershipCommandHandler {
.createQueryBuilder() .createQueryBuilder()
.update(membership) .update(membership)
.set({ .set({
end: new Date(new Date(createMembership.start).setDate(new Date(createMembership.start).getDate() - 1)), end: new Date(createMembership.start).setDate(new Date(createMembership.start).getDate() - 1),
terminationReason: "beendet durch neuen Eintrag.", terminationReason: "beendet durch neuen Eintrag.",
}) })
.where("end IS NULL") .where("end IS NULL")

View file

@ -1,6 +1,5 @@
export interface CreateRefreshCommand { export interface CreateRefreshCommand {
userId: number; userId: number;
isFromPwa?: boolean;
} }
export interface DeleteRefreshCommand { export interface DeleteRefreshCommand {

View file

@ -1,9 +1,11 @@
import { dataSource } from "../data-source"; import { dataSource } from "../data-source";
import { refresh } from "../entity/refresh"; import { refresh } from "../entity/refresh";
import { PWA_REFRESH_EXPIRATION, REFRESH_EXPIRATION } from "../env.defaults"; import { REFRESH_EXPIRATION } from "../env.defaults";
import InternalException from "../exceptions/internalException"; import InternalException from "../exceptions/internalException";
import { JWTHelper } from "../helpers/jwtHelper";
import { StringHelper } from "../helpers/stringHelper"; import { StringHelper } from "../helpers/stringHelper";
import UserService from "../service/user/userService"; import UserService from "../service/user/userService";
import { JWTRefresh } from "../type/jwtTypes";
import { CreateRefreshCommand, DeleteRefreshCommand } from "./refreshCommand"; import { CreateRefreshCommand, DeleteRefreshCommand } from "./refreshCommand";
import ms from "ms"; import ms from "ms";
@ -14,6 +16,10 @@ export default abstract class RefreshCommandHandler {
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
static async create(createRefresh: CreateRefreshCommand): Promise<string> { static async create(createRefresh: CreateRefreshCommand): Promise<string> {
// let createRefreshToken: JWTRefresh = {
// userId: createRefresh.userId,
// };
// const refreshToken = await JWTHelper.create(createRefreshToken);
const refreshToken = StringHelper.random(32); const refreshToken = StringHelper.random(32);
return await dataSource return await dataSource
@ -23,9 +29,7 @@ export default abstract class RefreshCommandHandler {
.values({ .values({
token: refreshToken, token: refreshToken,
user: await UserService.getById(createRefresh.userId), user: await UserService.getById(createRefresh.userId),
expiry: createRefresh.isFromPwa expiry: new Date(Date.now() + ms(REFRESH_EXPIRATION)),
? new Date(Date.now() + ms(PWA_REFRESH_EXPIRATION))
: new Date(Date.now() + ms(REFRESH_EXPIRATION)),
}) })
.execute() .execute()
.then((result) => { .then((result) => {

View file

@ -60,10 +60,7 @@ export default abstract class AwardCommandHandler {
.execute() .execute()
.then(() => {}) .then(() => {})
.catch((err) => { .catch((err) => {
throw new InternalException( throw new InternalException("Failed deleting award", err);
`Failed deleting award ${err.code.includes("ER_ROW_IS_REFERENCED") ? " due to referenced data" : ""}`,
err
);
}); });
} }
} }

View file

@ -66,10 +66,7 @@ export default abstract class CalendarTypeCommandHandler {
.execute() .execute()
.then(() => {}) .then(() => {})
.catch((err) => { .catch((err) => {
throw new InternalException( throw new InternalException("Failed deleting calendarType", err);
`Failed deleting calendarType${err.code.includes("ER_ROW_IS_REFERENCED") ? " due to referenced data" : ""}`,
err
);
}); });
} }
} }

View file

@ -66,12 +66,7 @@ export default abstract class CommunicationTypeCommandHandler {
.execute() .execute()
.then(() => {}) .then(() => {})
.catch((err) => { .catch((err) => {
throw new InternalException( throw new InternalException("Failed deleting communicationType", err);
`Failed deleting communicationType${
err.code.includes("ER_ROW_IS_REFERENCED") ? " due to referenced data" : ""
}`,
err
);
}); });
} }
} }

View file

@ -64,12 +64,7 @@ export default abstract class ExecutivePositionCommandHandler {
.execute() .execute()
.then(() => {}) .then(() => {})
.catch((err) => { .catch((err) => {
throw new InternalException( throw new InternalException("Failed deleting executivePosition", err);
`Failed deleting executivePosition${
err.code.includes("ER_ROW_IS_REFERENCED") ? " due to referenced data" : ""
}`,
err
);
}); });
} }
} }

View file

@ -64,12 +64,7 @@ export default abstract class MembershipStatusCommandHandler {
.execute() .execute()
.then(() => {}) .then(() => {})
.catch((err) => { .catch((err) => {
throw new InternalException( throw new InternalException("Failed deleting membershipStatus", err);
`Failed deleting membershipStatus${
err.code.includes("ER_ROW_IS_REFERENCED") ? " due to referenced data" : ""
}`,
err
);
}); });
} }
} }

View file

@ -4,3 +4,7 @@ export interface SetNewsletterConfigCommand {
comTypeId: number; comTypeId: number;
config: NewsletterConfigType; config: NewsletterConfigType;
} }
export interface DeleteNewsletterConfigCommand {
comTypeId: number;
}

View file

@ -1,7 +1,7 @@
import { dataSource } from "../../../data-source"; import { dataSource } from "../../../data-source";
import { newsletterConfig } from "../../../entity/settings/newsletterConfig"; import { newsletterConfig } from "../../../entity/settings/newsletterConfig";
import InternalException from "../../../exceptions/internalException"; import InternalException from "../../../exceptions/internalException";
import { SetNewsletterConfigCommand } from "./newsletterConfigCommand"; import { DeleteNewsletterConfigCommand, SetNewsletterConfigCommand } from "./newsletterConfigCommand";
export default abstract class NewsletterConfigCommandHandler { export default abstract class NewsletterConfigCommandHandler {
/** /**
@ -27,4 +27,21 @@ export default abstract class NewsletterConfigCommandHandler {
throw new InternalException("Failed setting newsletterConfig", err); throw new InternalException("Failed setting 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);
});
}
} }

View file

@ -66,10 +66,7 @@ export default abstract class QualificationCommandHandler {
.execute() .execute()
.then(() => {}) .then(() => {})
.catch((err) => { .catch((err) => {
throw new InternalException( throw new InternalException("Failed deleting qualification", err);
`Failed deleting qualification${err.code.includes("ER_ROW_IS_REFERENCED") ? " due to referenced data" : ""}`,
err
);
}); });
} }
} }

View file

@ -63,10 +63,7 @@ export default abstract class QueryStoreCommandHandler {
.execute() .execute()
.then(() => {}) .then(() => {})
.catch((err) => { .catch((err) => {
throw new InternalException( throw new InternalException("Failed deleting queryStore", err);
`Failed deleting queryStore${err.code.includes("ER_ROW_IS_REFERENCED") ? " due to referenced data" : ""}`,
err
);
}); });
} }
} }

View file

@ -64,10 +64,7 @@ export default abstract class TemplateCommandHandler {
.execute() .execute()
.then(() => {}) .then(() => {})
.catch((err) => { .catch((err) => {
throw new InternalException( throw new InternalException("Failed deleting template", err);
`Failed deleting template${err.code.includes("ER_ROW_IS_REFERENCED") ? " due to referenced data" : ""}`,
err
);
}); });
} }
} }

View file

@ -6,10 +6,7 @@ import NewsletterDatesFactory from "../../../factory/admin/club/newsletter/newsl
import NewsletterRecipientsService from "../../../service/club/newsletter/newsletterRecipientsService"; import NewsletterRecipientsService from "../../../service/club/newsletter/newsletterRecipientsService";
import NewsletterRecipientsFactory from "../../../factory/admin/club/newsletter/newsletterRecipients"; import NewsletterRecipientsFactory from "../../../factory/admin/club/newsletter/newsletterRecipients";
import { FileSystemHelper } from "../../../helpers/fileSystemHelper"; import { FileSystemHelper } from "../../../helpers/fileSystemHelper";
import { import { CreateNewsletterCommand, SynchronizeNewsletterCommand } from "../../../command/club/newsletter/newsletterCommand";
CreateNewsletterCommand,
SynchronizeNewsletterCommand,
} from "../../../command/club/newsletter/newsletterCommand";
import NewsletterCommandHandler from "../../../command/club/newsletter/newsletterCommandHandler"; import NewsletterCommandHandler from "../../../command/club/newsletter/newsletterCommandHandler";
import { SynchronizeNewsletterDatesCommand } from "../../../command/club/newsletter/newsletterDatesCommand"; import { SynchronizeNewsletterDatesCommand } from "../../../command/club/newsletter/newsletterDatesCommand";
import NewsletterDatesCommandHandler from "../../../command/club/newsletter/newsletterDatesCommandHandler"; import NewsletterDatesCommandHandler from "../../../command/club/newsletter/newsletterDatesCommandHandler";
@ -191,14 +188,15 @@ export async function createNewsletter(req: Request, res: Response): Promise<any
export async function getNewsletterPrintoutProgressById(req: Request, res: Response): Promise<any> { export async function getNewsletterPrintoutProgressById(req: Request, res: Response): Promise<any> {
let newsletterId = parseInt(req.params.newsletterId); let newsletterId = parseInt(req.params.newsletterId);
res.writeHead(200, { res.setHeader("Content-Type", "text/event-stream");
"Content-Type": "text/plain", res.setHeader("Cache-Control", "no-cache");
"Transfer-Encoding": "chunked", res.setHeader("Connection", "keep-alive");
});
res.flushHeaders();
const progressHandler = (data: NewsletterEventType) => { const progressHandler = (data: NewsletterEventType) => {
if (data.newsletterId == newsletterId && data.kind == "pdf") { if (data.newsletterId == newsletterId && data.kind == "pdf") {
res.write(JSON.stringify(data) + "//"); res.write(JSON.stringify(data));
} }
}; };
@ -289,14 +287,15 @@ export async function sendNewsletterById(req: Request, res: Response): Promise<a
export async function getNewsletterSendingProgressById(req: Request, res: Response): Promise<any> { export async function getNewsletterSendingProgressById(req: Request, res: Response): Promise<any> {
let newsletterId = parseInt(req.params.newsletterId); let newsletterId = parseInt(req.params.newsletterId);
res.writeHead(200, { res.setHeader("Content-Type", "text/event-stream");
"Content-Type": "text/plain", res.setHeader("Cache-Control", "no-cache");
"Transfer-Encoding": "chunked", res.setHeader("Connection", "keep-alive");
});
res.flushHeaders();
const progressHandler = (data: NewsletterEventType) => { const progressHandler = (data: NewsletterEventType) => {
if (data.newsletterId == newsletterId && data.kind == "mail") { if (data.newsletterId == newsletterId && data.kind == "mail") {
res.write(JSON.stringify(data) + "//"); res.write(JSON.stringify(data));
} }
}; };

View file

@ -2,7 +2,7 @@ import { Request, Response } from "express";
import NewsletterConfigService from "../../../service/settings/newsletterConfigService"; import NewsletterConfigService from "../../../service/settings/newsletterConfigService";
import NewsletterConfigFactory from "../../../factory/admin/settings/newsletterConfig"; import NewsletterConfigFactory from "../../../factory/admin/settings/newsletterConfig";
import NewsletterConfigCommandHandler from "../../../command/settings/newsletterConfig/newsletterConfigCommandHandler"; 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 * @description get all newsletterConfigs
@ -47,3 +47,20 @@ export async function setNewsletterConfig(req: Request, res: Response): Promise<
res.send(id); res.send(id);
} }
/**
* @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);
}

View file

@ -8,6 +8,9 @@ import UserService from "../service/user/userService";
import speakeasy from "speakeasy"; import speakeasy from "speakeasy";
import UnauthorizedRequestException from "../exceptions/unauthorizedRequestException"; import UnauthorizedRequestException from "../exceptions/unauthorizedRequestException";
import RefreshService from "../service/refreshService"; import RefreshService from "../service/refreshService";
import UserPermissionService from "../service/user/userPermissionService";
import PermissionHelper from "../helpers/permissionHelper";
import RolePermissionService from "../service/user/rolePermissionService";
/** /**
* @description Check authentication status by token * @description Check authentication status by token
@ -36,7 +39,6 @@ export async function login(req: Request, res: Response): Promise<any> {
let refreshCommand: CreateRefreshCommand = { let refreshCommand: CreateRefreshCommand = {
userId: id, userId: id,
isFromPwa: req.isPWA,
}; };
let refreshToken = await RefreshCommandHandler.create(refreshCommand); let refreshToken = await RefreshCommandHandler.create(refreshCommand);
@ -81,7 +83,6 @@ export async function refresh(req: Request, res: Response): Promise<any> {
let refreshCommand: CreateRefreshCommand = { let refreshCommand: CreateRefreshCommand = {
userId: tokenUserId, userId: tokenUserId,
isFromPwa: req.isPWA,
}; };
let refreshToken = await RefreshCommandHandler.create(refreshCommand); let refreshToken = await RefreshCommandHandler.create(refreshCommand);

View file

@ -40,17 +40,17 @@ export class communication {
@Column() @Column()
typeId: number; typeId: number;
@ManyToOne(() => member, (member) => member.awards, {
nullable: false,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
member: member;
@ManyToOne(() => communicationType, (communicationType) => communicationType.communications, { @ManyToOne(() => communicationType, (communicationType) => communicationType.communications, {
nullable: false, nullable: false,
onDelete: "RESTRICT", onDelete: "RESTRICT",
onUpdate: "RESTRICT", onUpdate: "RESTRICT",
}) })
type: communicationType; type: communicationType;
@ManyToOne(() => member, (member) => member.awards, {
nullable: false,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
member: member;
} }

View file

@ -9,7 +9,7 @@ export class protocolPrintout {
@Column({ type: "varchar", length: 255 }) @Column({ type: "varchar", length: 255 })
title: string; title: string;
@Column({ type: "int", default: "1" }) @Column({ type: "int" })
iteration: number; iteration: number;
@Column({ type: "varchar", length: 255 }) @Column({ type: "varchar", length: 255 })

View file

@ -13,7 +13,6 @@ export const SERVER_PORT = Number(process.env.SERVER_PORT ?? 5000);
export const JWT_SECRET = process.env.JWT_SECRET ?? "my_jwt_secret_string_ilughfnadiuhgq§$IUZGFVRweiouarbt1oub3h5q4a"; export const JWT_SECRET = process.env.JWT_SECRET ?? "my_jwt_secret_string_ilughfnadiuhgq§$IUZGFVRweiouarbt1oub3h5q4a";
export const JWT_EXPIRATION = process.env.JWT_EXPIRATION ?? "15m"; export const JWT_EXPIRATION = process.env.JWT_EXPIRATION ?? "15m";
export const REFRESH_EXPIRATION = process.env.REFRESH_EXPIRATION ?? "1d"; export const REFRESH_EXPIRATION = process.env.REFRESH_EXPIRATION ?? "1d";
export const PWA_REFRESH_EXPIRATION = process.env.PWA_REFRESH_EXPIRATION ?? "5d";
export const MAIL_USERNAME = process.env.MAIL_USERNAME ?? ""; export const MAIL_USERNAME = process.env.MAIL_USERNAME ?? "";
export const MAIL_PASSWORD = process.env.MAIL_PASSWORD ?? ""; export const MAIL_PASSWORD = process.env.MAIL_PASSWORD ?? "";
@ -36,7 +35,6 @@ export function configCheck() {
if (JWT_SECRET == "" || typeof JWT_SECRET != "string") throw new Error("set valid value to JWT_SECRET"); if (JWT_SECRET == "" || typeof JWT_SECRET != "string") throw new Error("set valid value to JWT_SECRET");
checkMS(JWT_EXPIRATION, "JWT_EXPIRATION"); checkMS(JWT_EXPIRATION, "JWT_EXPIRATION");
checkMS(REFRESH_EXPIRATION, "REFRESH_EXPIRATION"); checkMS(REFRESH_EXPIRATION, "REFRESH_EXPIRATION");
checkMS(PWA_REFRESH_EXPIRATION, "PWA_REFRESH_EXPIRATION");
if (MAIL_USERNAME == "" || typeof MAIL_USERNAME != "string") throw new Error("set valid value to MAIL_USERNAME"); if (MAIL_USERNAME == "" || typeof MAIL_USERNAME != "string") throw new Error("set valid value to MAIL_USERNAME");
if (MAIL_PASSWORD == "" || typeof MAIL_PASSWORD != "string") throw new Error("set valid value to MAIL_PASSWORD"); if (MAIL_PASSWORD == "" || typeof MAIL_PASSWORD != "string") throw new Error("set valid value to MAIL_PASSWORD");
@ -44,6 +42,7 @@ export function configCheck() {
if (typeof MAIL_PORT != "number") throw new Error("set valid numeric value to MAIL_PORT"); if (typeof MAIL_PORT != "number") throw new Error("set valid numeric value to MAIL_PORT");
if (MAIL_SECURE != "true" && MAIL_SECURE != "false") throw new Error("set 'true' or 'false' to MAIL_SECURE"); if (MAIL_SECURE != "true" && MAIL_SECURE != "false") throw new Error("set 'true' or 'false' to MAIL_SECURE");
console.log(CLUB_WEBSITE);
if ( if (
CLUB_WEBSITE != "" && CLUB_WEBSITE != "" &&
!/^(http(s):\/\/.)[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/.test(CLUB_WEBSITE) !/^(http(s):\/\/.)[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/.test(CLUB_WEBSITE)

View file

@ -33,21 +33,12 @@ export abstract class NewsletterHelper {
private static formatJobEmit( private static formatJobEmit(
event: "progress" | "complete", event: "progress" | "complete",
kind: "pdf" | "mail", kind: "pdf" | "mail",
factor: "success" | "failed" | "info",
newsletterId: number, newsletterId: number,
total: number, total: number,
iteration: number, iteration: number,
msg: string msg: string
) { ) {
this.jobStatus.emit<NewsletterEventType>(event, { this.jobStatus.emit<NewsletterEventType>(event, { kind, newsletterId, total, iteration, msg, date: new Date() });
kind,
newsletterId,
factor,
total,
iteration,
msg,
date: new Date(),
});
} }
public static buildData( public static buildData(
@ -141,6 +132,8 @@ export abstract class NewsletterHelper {
} }
} }
console.log(queryMemberIds);
let members = await MemberService.getAll(0, 1000); let members = await MemberService.getAll(0, 1000);
return members[0].filter((m) => queryMemberIds.includes(m.id)); return members[0].filter((m) => queryMemberIds.includes(m.id));
@ -178,9 +171,18 @@ export abstract class NewsletterHelper {
allowedForMail.includes(m.sendNewsletter?.type?.id) allowedForMail.includes(m.sendNewsletter?.type?.id)
); );
this.formatJobEmit("progress", "mail", "info", newsletterId, mailRecipients.length, 0, "starting sending"); this.formatJobEmit("progress", "mail", newsletterId, mailRecipients.length, 0, "starting sending");
for (const [index, rec] of mailRecipients.entries()) { for (const [index, rec] of mailRecipients.entries()) {
this.formatJobEmit(
"progress",
"mail",
newsletterId,
mailRecipients.length,
index,
`start sending to ${rec.sendNewsletter.email}`
);
let data = this.buildData(newsletter, dates, rec); let data = this.buildData(newsletter, dates, rec);
const { body } = await TemplateHelper.renderFileForModule({ const { body } = await TemplateHelper.renderFileForModule({
@ -195,10 +197,9 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"progress", "progress",
"mail", "mail",
"success",
newsletterId, newsletterId,
mailRecipients.length, mailRecipients.length,
index + 1, index,
`successfully sent to ${rec.sendNewsletter.email}` `successfully sent to ${rec.sendNewsletter.email}`
); );
}) })
@ -206,19 +207,18 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"progress", "progress",
"mail", "mail",
"failed",
newsletterId, newsletterId,
mailRecipients.length, mailRecipients.length,
index + 1, index,
`failed to send to ${rec.sendNewsletter.email}` `failed to send to ${rec.sendNewsletter.email}`
); );
console.log("mail send", err);
}); });
} }
this.formatJobEmit( this.formatJobEmit(
"complete", "complete",
"mail", "mail",
"info",
newsletterId, newsletterId,
mailRecipients.length, mailRecipients.length,
mailRecipients.length, mailRecipients.length,
@ -249,12 +249,21 @@ export abstract class NewsletterHelper {
(m) => !notAllowedForPdf.includes(m.sendNewsletter?.type?.id) || m.sendNewsletter == null (m) => !notAllowedForPdf.includes(m.sendNewsletter?.type?.id) || m.sendNewsletter == null
); );
this.formatJobEmit("progress", "pdf", "info", newsletterId, pdfRecipients.length + 1, 0, "starting sending"); this.formatJobEmit("progress", "pdf", newsletterId, pdfRecipients.length, 0, "starting sending");
for (const [index, rec] of [ for (const [index, rec] of [
...pdfRecipients, ...pdfRecipients,
{ id: 0, firstname: "Alle Mitglieder", lastname: CLUB_NAME } as member, { id: 0, firstname: "Alle Mitglieder", lastname: CLUB_NAME } as member,
].entries()) { ].entries()) {
this.formatJobEmit(
"progress",
"pdf",
newsletterId,
pdfRecipients.length,
index,
`start print for ${rec.lastname}, ${rec.firstname}`
);
let data = this.buildData(newsletter, dates, rec, printWithAdress.includes(rec.sendNewsletter?.type?.id)); let data = this.buildData(newsletter, dates, rec, printWithAdress.includes(rec.sendNewsletter?.type?.id));
await PdfExport.renderFile({ await PdfExport.renderFile({
@ -268,10 +277,9 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"progress", "progress",
"pdf", "pdf",
"success",
newsletterId, newsletterId,
pdfRecipients.length + 1, pdfRecipients.length,
index + 1, index,
`successfully printed for ${rec.lastname}, ${rec.firstname}` `successfully printed for ${rec.lastname}, ${rec.firstname}`
); );
}) })
@ -279,15 +287,24 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"progress", "progress",
"pdf", "pdf",
"failed",
newsletterId, newsletterId,
pdfRecipients.length + 1, pdfRecipients.length,
index + 1, index,
`failed print for ${rec.lastname}, ${rec.firstname}` `failed print for ${rec.lastname}, ${rec.firstname}`
); );
console.log("pdf print", err);
}); });
} }
this.formatJobEmit(
"progress",
"pdf",
newsletterId,
pdfRecipients.length,
pdfRecipients.length,
"starting pdf combine"
);
await PdfExport.sqashToSingleFile( await PdfExport.sqashToSingleFile(
`newsletter/${newsletter.id}_${newsletter.title.replace(" ", "")}`, `newsletter/${newsletter.id}_${newsletter.title.replace(" ", "")}`,
"allPdfsTogether", "allPdfsTogether",
@ -297,10 +314,9 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"progress", "progress",
"pdf", "pdf",
"success",
newsletterId, newsletterId,
pdfRecipients.length + 1, pdfRecipients.length,
pdfRecipients.length + 1, pdfRecipients.length,
"sucessfully combined pdf" "sucessfully combined pdf"
); );
}) })
@ -308,21 +324,20 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"progress", "progress",
"pdf", "pdf",
"failed",
newsletterId, newsletterId,
pdfRecipients.length + 1, pdfRecipients.length,
pdfRecipients.length + 1, pdfRecipients.length,
"failed combining pdf" "failed combining pdf"
); );
console.log("pdf squash", err);
}); });
this.formatJobEmit( this.formatJobEmit(
"complete", "complete",
"pdf", "pdf",
"info",
newsletterId, newsletterId,
pdfRecipients.length + 1, pdfRecipients.length,
pdfRecipients.length + 1, pdfRecipients.length,
`completed printing process` `completed printing process`
); );
} }

View file

@ -12,7 +12,6 @@ declare global {
username: string; username: string;
isOwner: boolean; isOwner: boolean;
permissions: PermissionObject; permissions: PermissionObject;
isPWA: boolean;
} }
} }
} }

View file

@ -1,11 +0,0 @@
import { Request, Response } from "express";
export default async function detectPWA(req: Request, res: Response, next: Function) {
const userAgent = req.headers["user-agent"] || "";
if ((userAgent.includes("Mobile") && userAgent.includes("Standalone")) || req.headers["x-pwa-client"] === "true") {
req.isPWA = true;
} else {
req.isPWA = false;
}
next();
}

View file

@ -19,6 +19,7 @@ export class InternalId1735822722235 implements MigrationInterface {
); );
// let memberships = await queryRunner.manager.getRepository(membership).find(); // let memberships = await queryRunner.manager.getRepository(membership).find();
// console.log(memberships);
// let internalIds = memberships.reduce<{ [key: number]: Array<string> }>((acc, cur) => { // let internalIds = memberships.reduce<{ [key: number]: Array<string> }>((acc, cur) => {
// let memberId = cur.memberId; // let memberId = cur.memberId;
// let setIds = acc[memberId] ?? []; // let setIds = acc[memberId] ?? [];
@ -29,6 +30,7 @@ export class InternalId1735822722235 implements MigrationInterface {
// return acc; // return acc;
// }, {}); // }, {});
// console.log(internalIds);
// for (const [id, value] of Object.entries(internalIds)) { // for (const [id, value] of Object.entries(internalIds)) {
// const ids = value.filter((v) => v != null).join(", "); // const ids = value.filter((v) => v != null).join(", ");
// if (ids) { // if (ids) {

View file

@ -1,5 +1,6 @@
import express, { Request, Response } from "express"; import express, { Request, Response } from "express";
import { import {
deleteNewsletterConfig,
getAllNewsletterConfigs, getAllNewsletterConfigs,
getNewsletterConfigById, getNewsletterConfigById,
setNewsletterConfig, 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; export default router;

View file

@ -13,7 +13,6 @@ import reset from "./reset";
import auth from "./auth"; import auth from "./auth";
import admin from "./admin/index"; import admin from "./admin/index";
import user from "./user"; import user from "./user";
import detectPWA from "../middleware/detectPWA";
export default (app: Express) => { export default (app: Express) => {
app.set("query parser", "extended"); app.set("query parser", "extended");
@ -26,7 +25,6 @@ export default (app: Express) => {
app.use(cors()); app.use(cors());
app.options("*", cors()); app.options("*", cors());
app.use(detectPWA);
app.use("/api/public", publicAvailable); app.use("/api/public", publicAvailable);
app.use("/api/setup", allowSetup, setup); app.use("/api/setup", allowSetup, setup);
app.use("/api/reset", reset); app.use("/api/reset", reset);

View file

@ -12,7 +12,6 @@ export default abstract class CalendarService {
.getRepository(calendar) .getRepository(calendar)
.createQueryBuilder("calendar") .createQueryBuilder("calendar")
.leftJoinAndSelect("calendar.type", "type") .leftJoinAndSelect("calendar.type", "type")
.orderBy("starttime", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -16,7 +16,6 @@ export default abstract class CommunicationService {
.leftJoinAndSelect("communication.member", "member") .leftJoinAndSelect("communication.member", "member")
.leftJoinAndSelect("member.sendNewsletter", "sendNewsletter") .leftJoinAndSelect("member.sendNewsletter", "sendNewsletter")
.where("communication.memberId = :memberId", { memberId: memberId }) .where("communication.memberId = :memberId", { memberId: memberId })
.orderBy("communicationType.type", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -14,7 +14,6 @@ export default abstract class MemberAwardService {
.createQueryBuilder("memberAwards") .createQueryBuilder("memberAwards")
.leftJoinAndSelect("memberAwards.award", "award") .leftJoinAndSelect("memberAwards.award", "award")
.where("memberAwards.memberId = :memberId", { memberId: memberId }) .where("memberAwards.memberId = :memberId", { memberId: memberId })
.orderBy("award.award", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -14,8 +14,6 @@ export default abstract class MemberExecutivePositionService {
.createQueryBuilder("memberExecutivePositions") .createQueryBuilder("memberExecutivePositions")
.leftJoinAndSelect("memberExecutivePositions.executivePosition", "executivePosition") .leftJoinAndSelect("memberExecutivePositions.executivePosition", "executivePosition")
.where("memberExecutivePositions.memberId = :memberId", { memberId: memberId }) .where("memberExecutivePositions.memberId = :memberId", { memberId: memberId })
.orderBy("executivePosition.position", "ASC")
.addOrderBy("memberExecutivePositions.start", "DESC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -14,7 +14,6 @@ export default abstract class MemberQualificationService {
.createQueryBuilder("memberQualifications") .createQueryBuilder("memberQualifications")
.leftJoinAndSelect("memberQualifications.qualification", "qualification") .leftJoinAndSelect("memberQualifications.qualification", "qualification")
.where("memberQualifications.memberId = :memberId", { memberId: memberId }) .where("memberQualifications.memberId = :memberId", { memberId: memberId })
.orderBy("qualification.qualification", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -12,7 +12,6 @@ export default abstract class AwardService {
return await dataSource return await dataSource
.getRepository(award) .getRepository(award)
.createQueryBuilder("award") .createQueryBuilder("award")
.orderBy("award", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -11,7 +11,6 @@ export default abstract class CalendarTypeService {
return await dataSource return await dataSource
.getRepository(calendarType) .getRepository(calendarType)
.createQueryBuilder("calendarType") .createQueryBuilder("calendarType")
.orderBy("type", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -11,7 +11,6 @@ export default abstract class CommunicationTypeService {
return await dataSource return await dataSource
.getRepository(communicationType) .getRepository(communicationType)
.createQueryBuilder("communicationType") .createQueryBuilder("communicationType")
.orderBy("type", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -12,7 +12,6 @@ export default abstract class ExecutivePositionService {
return await dataSource return await dataSource
.getRepository(executivePosition) .getRepository(executivePosition)
.createQueryBuilder("executivePosition") .createQueryBuilder("executivePosition")
.orderBy("position", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -12,7 +12,6 @@ export default abstract class MembershipStatusService {
return await dataSource return await dataSource
.getRepository(membershipStatus) .getRepository(membershipStatus)
.createQueryBuilder("membershipStatus") .createQueryBuilder("membershipStatus")
.orderBy("status", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -13,7 +13,6 @@ export default abstract class NewsletterConfigService {
.getRepository(newsletterConfig) .getRepository(newsletterConfig)
.createQueryBuilder("newsletterConfig") .createQueryBuilder("newsletterConfig")
.leftJoinAndSelect("newsletterConfig.comType", "comType") .leftJoinAndSelect("newsletterConfig.comType", "comType")
.orderBy("comType.type", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -13,7 +13,6 @@ export default abstract class QualificationService {
return await dataSource return await dataSource
.getRepository(qualification) .getRepository(qualification)
.createQueryBuilder("qualification") .createQueryBuilder("qualification")
.orderBy("qualification", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -11,7 +11,6 @@ export default abstract class QueryStoreService {
return await dataSource return await dataSource
.getRepository(query) .getRepository(query)
.createQueryBuilder("queryStore") .createQueryBuilder("queryStore")
.orderBy("title", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -12,7 +12,6 @@ export default abstract class TemplateService {
return await dataSource return await dataSource
.getRepository(template) .getRepository(template)
.createQueryBuilder("template") .createQueryBuilder("template")
.orderBy("template", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -14,7 +14,6 @@ export default abstract class TemplateUsageService {
.leftJoinAndSelect("templateUsage.header", "headerTemplate") .leftJoinAndSelect("templateUsage.header", "headerTemplate")
.leftJoinAndSelect("templateUsage.body", "bodyTemplate") .leftJoinAndSelect("templateUsage.body", "bodyTemplate")
.leftJoinAndSelect("templateUsage.footer", "footerTemplate") .leftJoinAndSelect("templateUsage.footer", "footerTemplate")
.orderBy("scope", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -12,7 +12,6 @@ export default abstract class RoleService {
.getRepository(role) .getRepository(role)
.createQueryBuilder("role") .createQueryBuilder("role")
.leftJoinAndSelect("role.permissions", "role_permissions") .leftJoinAndSelect("role.permissions", "role_permissions")
.orderBy("role", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;

View file

@ -15,8 +15,6 @@ export default abstract class UserService {
.leftJoinAndSelect("user.roles", "roles") .leftJoinAndSelect("user.roles", "roles")
.leftJoinAndSelect("user.permissions", "permissions") .leftJoinAndSelect("user.permissions", "permissions")
.leftJoinAndSelect("roles.permissions", "role_permissions") .leftJoinAndSelect("roles.permissions", "role_permissions")
.orderBy("firstname", "ASC")
.addOrderBy("lastname", "ASC")
.getMany() .getMany()
.then((res) => { .then((res) => {
return res; return res;