Compare commits
No commits in common. "main" and "v1.1.0" have entirely different histories.
70 changed files with 444 additions and 2264 deletions
|
@ -18,5 +18,5 @@ MAIL_HOST = mail_hoststring
|
|||
MAIL_PORT = mail_portnumber
|
||||
MAIL_SECURE (true|false) // true for port 465, fals for other ports
|
||||
|
||||
CLUB_NAME = clubname #default FF Admin
|
||||
CLUB_NAME = clubname
|
||||
CLUB_WEBSITE = https://my-club-website-url
|
|
@ -20,13 +20,13 @@ Um den Container hochzufahren, erstellen Sie eine `docker-compose.yml` Datei mit
|
|||
version: "3"
|
||||
|
||||
services:
|
||||
ff-admin-server:
|
||||
ff-ff-admin-server:
|
||||
image: docker.registry.jk-effects.cloud/ehrenamt/ff-admin/server:latest
|
||||
container_name: ff_member_administration_server
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- DB_TYPE=<mysql|sqlite> # default ist auf mysql gesetzt
|
||||
- DB_HOST=ff-db
|
||||
- DB_HOST=ffm-db
|
||||
- DB_PORT=<number> # default ist auf 3306 gesetzt
|
||||
- DB_NAME=ffadmin
|
||||
- DB_USERNAME=administration_backend
|
||||
|
@ -40,7 +40,7 @@ services:
|
|||
- MAIL_HOST=<url>
|
||||
- MAIL_PORT=<port> # default ist auf 578 gesetzt
|
||||
- MAIL_SECURE=<boolean> # default ist auf false gesetzt
|
||||
- CLUB_NAME=<tobemodified> # default ist auf FF Admin gesetzt
|
||||
- CLUB_NAME=<tobemodified>
|
||||
- CLUB_WEBSITE=<tobemodified>
|
||||
volumes:
|
||||
- <volume|local path>:/app/files
|
||||
|
|
52
package-lock.json
generated
52
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "ff-admin-server",
|
||||
"version": "1.2.2",
|
||||
"version": "1.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ff-admin-server",
|
||||
"version": "1.2.2",
|
||||
"version": "1.1.0",
|
||||
"license": "GPL-3.0-only",
|
||||
"dependencies": {
|
||||
"cors": "^2.8.5",
|
||||
|
@ -24,7 +24,6 @@
|
|||
"puppeteer": "^23.11.1",
|
||||
"qrcode": "^1.5.4",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rss-parser": "^3.13.0",
|
||||
"socket.io": "^4.7.5",
|
||||
"speakeasy": "^2.0.0",
|
||||
"typeorm": "^0.3.20",
|
||||
|
@ -1497,15 +1496,6 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||
"license": "BSD-2-Clause",
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/env-paths": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
||||
|
@ -3162,16 +3152,6 @@
|
|||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/rss-parser": {
|
||||
"version": "3.13.0",
|
||||
"resolved": "https://registry.npmjs.org/rss-parser/-/rss-parser-3.13.0.tgz",
|
||||
"integrity": "sha512-7jWUBV5yGN3rqMMj7CZufl/291QAhvrrGpDNE4k/02ZchL0npisiYYqULF71jCEKoIiHvK/Q2e6IkDwPziT7+w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"entities": "^2.0.3",
|
||||
"xml2js": "^0.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/runes2": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/runes2/-/runes2-1.1.4.tgz",
|
||||
|
@ -3202,12 +3182,6 @@
|
|||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
|
||||
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
|
@ -4279,28 +4253,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xml2js": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
|
||||
"integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sax": ">=0.6.0",
|
||||
"xmlbuilder": "~11.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/y18n": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "ff-admin-server",
|
||||
"version": "1.2.2",
|
||||
"version": "1.1.0",
|
||||
"description": "Feuerwehr/Verein Mitgliederverwaltung Server",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
|
@ -39,7 +39,6 @@
|
|||
"puppeteer": "^23.11.1",
|
||||
"qrcode": "^1.5.4",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rss-parser": "^3.13.0",
|
||||
"socket.io": "^4.7.5",
|
||||
"speakeasy": "^2.0.0",
|
||||
"typeorm": "^0.3.20",
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
export interface CreateCommunicationCommand {
|
||||
preferred: boolean;
|
||||
isSMSAlarming: boolean;
|
||||
isSendNewsletter: boolean;
|
||||
mobile: string;
|
||||
email: string;
|
||||
postalCode: string;
|
||||
|
@ -17,7 +16,6 @@ export interface UpdateCommunicationCommand {
|
|||
id: number;
|
||||
preferred: boolean;
|
||||
isSMSAlarming: boolean;
|
||||
isSendNewsletter: boolean;
|
||||
mobile: string;
|
||||
email: string;
|
||||
postalCode: string;
|
||||
|
|
|
@ -14,44 +14,26 @@ export default abstract class CommunicationCommandHandler {
|
|||
* @returns {Promise<number>}
|
||||
*/
|
||||
static async create(createCommunication: CreateCommunicationCommand): Promise<number> {
|
||||
let insertId = -1;
|
||||
return await dataSource
|
||||
.transaction(async (manager) => {
|
||||
await manager
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(communication)
|
||||
.values({
|
||||
preferred: createCommunication.preferred,
|
||||
isSMSAlarming: createCommunication.isSMSAlarming,
|
||||
isSendNewsletter: createCommunication.isSendNewsletter,
|
||||
mobile: createCommunication.mobile,
|
||||
email: createCommunication.email,
|
||||
postalCode: createCommunication.postalCode,
|
||||
city: createCommunication.city,
|
||||
street: createCommunication.street,
|
||||
streetNumber: createCommunication.streetNumber,
|
||||
streetNumberAddition: createCommunication.streetNumberAddition,
|
||||
memberId: createCommunication.memberId,
|
||||
typeId: createCommunication.typeId,
|
||||
})
|
||||
.execute()
|
||||
.then((result) => {
|
||||
insertId = result.identifiers[0].id;
|
||||
});
|
||||
|
||||
await manager
|
||||
.createQueryBuilder()
|
||||
.update(communication)
|
||||
.set({
|
||||
isSendNewsletter: false,
|
||||
})
|
||||
.where("memberId = :memberId", { memberId: createCommunication.memberId })
|
||||
.andWhere("id <> :id", { id: insertId })
|
||||
.execute();
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(communication)
|
||||
.values({
|
||||
preferred: createCommunication.preferred,
|
||||
isSMSAlarming: createCommunication.isSMSAlarming,
|
||||
mobile: createCommunication.mobile,
|
||||
email: createCommunication.email,
|
||||
postalCode: createCommunication.postalCode,
|
||||
city: createCommunication.city,
|
||||
street: createCommunication.street,
|
||||
streetNumber: createCommunication.streetNumber,
|
||||
streetNumberAddition: createCommunication.streetNumberAddition,
|
||||
memberId: createCommunication.memberId,
|
||||
typeId: createCommunication.typeId,
|
||||
})
|
||||
.then(() => {
|
||||
return insertId;
|
||||
.execute()
|
||||
.then((result) => {
|
||||
return result.identifiers[0].id;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("Failed creating communication", err);
|
||||
|
@ -65,36 +47,22 @@ export default abstract class CommunicationCommandHandler {
|
|||
*/
|
||||
static async update(updateCommunication: UpdateCommunicationCommand): Promise<void> {
|
||||
return await dataSource
|
||||
.transaction(async (manager) => {
|
||||
await manager
|
||||
.createQueryBuilder()
|
||||
.update(communication)
|
||||
.set({
|
||||
preferred: updateCommunication.preferred,
|
||||
isSMSAlarming: updateCommunication.isSMSAlarming,
|
||||
isSendNewsletter: updateCommunication.isSendNewsletter,
|
||||
mobile: updateCommunication.mobile,
|
||||
email: updateCommunication.email,
|
||||
postalCode: updateCommunication.postalCode,
|
||||
city: updateCommunication.city,
|
||||
street: updateCommunication.street,
|
||||
streetNumber: updateCommunication.streetNumber,
|
||||
streetNumberAddition: updateCommunication.streetNumberAddition,
|
||||
})
|
||||
.where("id = :id", { id: updateCommunication.id })
|
||||
.andWhere("memberId = :memberId", { memberId: updateCommunication.memberId })
|
||||
.execute();
|
||||
|
||||
await manager
|
||||
.createQueryBuilder()
|
||||
.update(communication)
|
||||
.set({
|
||||
isSendNewsletter: false,
|
||||
})
|
||||
.where("memberId = :memberId", { memberId: updateCommunication.memberId })
|
||||
.andWhere("id <> :id", { id: updateCommunication.id })
|
||||
.execute();
|
||||
.createQueryBuilder()
|
||||
.update(communication)
|
||||
.set({
|
||||
preferred: updateCommunication.preferred,
|
||||
isSMSAlarming: updateCommunication.isSMSAlarming,
|
||||
mobile: updateCommunication.mobile,
|
||||
email: updateCommunication.email,
|
||||
postalCode: updateCommunication.postalCode,
|
||||
city: updateCommunication.city,
|
||||
street: updateCommunication.street,
|
||||
streetNumber: updateCommunication.streetNumber,
|
||||
streetNumberAddition: updateCommunication.streetNumberAddition,
|
||||
})
|
||||
.where("id = :id", { id: updateCommunication.id })
|
||||
.andWhere("memberId = :memberId", { memberId: updateCommunication.memberId })
|
||||
.execute()
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw new InternalException("Failed updating communication", err);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { Salutation } from "../../../enums/salutation";
|
||||
|
||||
export interface CreateMemberCommand {
|
||||
salutationId: number;
|
||||
salutation: Salutation;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
nameaffix: string;
|
||||
|
@ -9,7 +11,7 @@ export interface CreateMemberCommand {
|
|||
|
||||
export interface UpdateMemberCommand {
|
||||
id: number;
|
||||
salutationId: number;
|
||||
salutation: Salutation;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
nameaffix: string;
|
||||
|
@ -17,6 +19,11 @@ export interface UpdateMemberCommand {
|
|||
internalId?: string;
|
||||
}
|
||||
|
||||
export interface UpdateMemberNewsletterCommand {
|
||||
id: number;
|
||||
communicationId: number;
|
||||
}
|
||||
|
||||
export interface DeleteMemberCommand {
|
||||
id: number;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,12 @@ import { dataSource } from "../../../data-source";
|
|||
import { communication } from "../../../entity/club/member/communication";
|
||||
import { member } from "../../../entity/club/member/member";
|
||||
import InternalException from "../../../exceptions/internalException";
|
||||
import { CreateMemberCommand, DeleteMemberCommand, UpdateMemberCommand } from "./memberCommand";
|
||||
import {
|
||||
CreateMemberCommand,
|
||||
DeleteMemberCommand,
|
||||
UpdateMemberCommand,
|
||||
UpdateMemberNewsletterCommand,
|
||||
} from "./memberCommand";
|
||||
|
||||
export default abstract class MemberCommandHandler {
|
||||
/**
|
||||
|
@ -16,7 +21,7 @@ export default abstract class MemberCommandHandler {
|
|||
.insert()
|
||||
.into(member)
|
||||
.values({
|
||||
salutationId: createMember.salutationId,
|
||||
salutation: createMember.salutation,
|
||||
firstname: createMember.firstname,
|
||||
lastname: createMember.lastname,
|
||||
nameaffix: createMember.nameaffix,
|
||||
|
@ -28,10 +33,7 @@ export default abstract class MemberCommandHandler {
|
|||
return result.identifiers[0].id;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException(
|
||||
`Failed creating member${err.code.includes("ER_DUP_ENTRY") ? " due to duplicate entry for column" : ""}`,
|
||||
err
|
||||
);
|
||||
throw new InternalException("Failed creating member", err);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -45,7 +47,7 @@ export default abstract class MemberCommandHandler {
|
|||
.createQueryBuilder()
|
||||
.update(member)
|
||||
.set({
|
||||
salutationId: updateMember.salutationId,
|
||||
salutation: updateMember.salutation,
|
||||
firstname: updateMember.firstname,
|
||||
lastname: updateMember.lastname,
|
||||
nameaffix: updateMember.nameaffix,
|
||||
|
@ -56,10 +58,52 @@ export default abstract class MemberCommandHandler {
|
|||
.execute()
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw new InternalException(
|
||||
`Failed updating member${err.code.includes("ER_DUP_ENTRY") ? " due to duplicate entry for column" : ""}`,
|
||||
err
|
||||
);
|
||||
throw new InternalException("Failed updating member", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description update member newsletter
|
||||
* @param {UpdateMemberCommand} updateMember
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async updateNewsletter(updateMember: UpdateMemberNewsletterCommand): Promise<void> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.update(member)
|
||||
.set({
|
||||
sendNewsletter: await dataSource
|
||||
.getRepository(communication)
|
||||
.createQueryBuilder("communication")
|
||||
.where("id = :id", { id: updateMember.communicationId })
|
||||
.andWhere("memberId = :memberId", { memberId: updateMember.id })
|
||||
.getOneOrFail(),
|
||||
})
|
||||
.where("id = :id", { id: updateMember.id })
|
||||
.execute()
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw new InternalException("Failed updating member", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description update member newsletter to unset
|
||||
* @param {number} memberId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async unsetNewsletter(memberId: number): Promise<void> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.update(member)
|
||||
.set({
|
||||
sendNewsletter: null,
|
||||
})
|
||||
.where("id = :id", { id: memberId })
|
||||
.execute()
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw new InternalException("Failed updating member", err);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
export interface CreateSalutationCommand {
|
||||
salutation: string;
|
||||
}
|
||||
|
||||
export interface UpdateSalutationCommand {
|
||||
id: number;
|
||||
salutation: string;
|
||||
}
|
||||
|
||||
export interface DeleteSalutationCommand {
|
||||
id: number;
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
import { dataSource } from "../../../data-source";
|
||||
import { salutation } from "../../../entity/settings/salutation";
|
||||
import InternalException from "../../../exceptions/internalException";
|
||||
import { CreateSalutationCommand, DeleteSalutationCommand, UpdateSalutationCommand } from "./salutationCommand";
|
||||
|
||||
export default abstract class SalutationCommandHandler {
|
||||
/**
|
||||
* @description create salutation
|
||||
* @param {CreateSalutationCommand} createSalutation
|
||||
* @returns {Promise<number>}
|
||||
*/
|
||||
static async create(createSalutation: CreateSalutationCommand): Promise<number> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(salutation)
|
||||
.values({
|
||||
salutation: createSalutation.salutation,
|
||||
})
|
||||
.execute()
|
||||
.then((result) => {
|
||||
return result.identifiers[0].id;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("Failed creating salutation", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description update salutation
|
||||
* @param {UpdateSalutationCommand} updateSalutation
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async update(updateSalutation: UpdateSalutationCommand): Promise<void> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.update(salutation)
|
||||
.set({
|
||||
salutation: updateSalutation.salutation,
|
||||
})
|
||||
.where("id = :id", { id: updateSalutation.id })
|
||||
.execute()
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw new InternalException("Failed updating salutation", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description delete salutation
|
||||
* @param {DeleteSalutationCommand} deleteSalutation
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async delete(deleteSalutation: DeleteSalutationCommand): Promise<void> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(salutation)
|
||||
.where("id = :id", { id: deleteSalutation.id })
|
||||
.execute()
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw new InternalException(
|
||||
`Failed deleting salutation ${err.code.includes("ER_ROW_IS_REFERENCED") ? " due to referenced data" : ""}`,
|
||||
err
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
export interface CreateWebapiCommand {
|
||||
title: string;
|
||||
token: string;
|
||||
expiry?: Date;
|
||||
}
|
||||
|
||||
export interface UpdateWebapiCommand {
|
||||
id: number;
|
||||
title: string;
|
||||
expiry?: Date;
|
||||
}
|
||||
|
||||
export interface UpdateLastUsageWebapiCommand {
|
||||
id: number;
|
||||
}
|
||||
|
||||
export interface DeleteWebapiCommand {
|
||||
id: number;
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
import { dataSource } from "../../../data-source";
|
||||
import { webapi } from "../../../entity/user/webapi";
|
||||
import InternalException from "../../../exceptions/internalException";
|
||||
import {
|
||||
CreateWebapiCommand,
|
||||
DeleteWebapiCommand,
|
||||
UpdateLastUsageWebapiCommand,
|
||||
UpdateWebapiCommand,
|
||||
} from "./webapiCommand";
|
||||
|
||||
export default abstract class WebapiCommandHandler {
|
||||
/**
|
||||
* @description create api
|
||||
* @param {CreateWebapiCommand} createWebapi
|
||||
* @returns {Promise<number>}
|
||||
*/
|
||||
static async create(createWebapi: CreateWebapiCommand): Promise<number> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(webapi)
|
||||
.values({
|
||||
token: createWebapi.token,
|
||||
title: createWebapi.title,
|
||||
expiry: createWebapi.expiry,
|
||||
})
|
||||
.execute()
|
||||
.then((result) => {
|
||||
return result.identifiers[0].token;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException(
|
||||
`Failed creating api${err.code.includes("ER_DUP_ENTRY") ? " due to duplicate entry for column" : ""}`,
|
||||
err
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description update api
|
||||
* @param {UpdateWebapiCommand} updateWebapi
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async update(updateWebapi: UpdateWebapiCommand): Promise<void> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.update(webapi)
|
||||
.set({
|
||||
title: updateWebapi.title,
|
||||
expiry: updateWebapi.expiry,
|
||||
})
|
||||
.where("id = :id", { id: updateWebapi.id })
|
||||
.execute()
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw new InternalException(
|
||||
`Failed updating api${err.code.includes("ER_DUP_ENTRY") ? " due to duplicate entry for column" : ""}`,
|
||||
err
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description update api usage
|
||||
* @param {UpdateLastUsageWebapiCommand} updateWebapi
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async updateUsage(updateWebapi: UpdateLastUsageWebapiCommand): Promise<void> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.update(webapi)
|
||||
.set({
|
||||
lastUsage: new Date(),
|
||||
})
|
||||
.where("id = :id", { id: updateWebapi.id })
|
||||
.execute()
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw new InternalException(`Failed updating api last usage`, err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description delete api
|
||||
* @param {DeleteWebapiCommand} deleteWebapi
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async delete(deleteWebapi: DeleteWebapiCommand): Promise<void> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(webapi)
|
||||
.where("id = :id", { id: deleteWebapi.id })
|
||||
.execute()
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw new InternalException("Failed deleting api", err);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { PermissionString } from "../../../type/permissionTypes";
|
||||
|
||||
export interface CreateWebapiPermissionCommand {
|
||||
permission: PermissionString;
|
||||
webapiId: number;
|
||||
}
|
||||
|
||||
export interface DeleteWebapiPermissionCommand {
|
||||
permission: PermissionString;
|
||||
webapiId: number;
|
||||
}
|
||||
|
||||
export interface UpdateWebapiPermissionsCommand {
|
||||
webapiId: number;
|
||||
permissions: Array<PermissionString>;
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
import { DeleteResult, EntityManager, InsertResult } from "typeorm";
|
||||
import { dataSource } from "../../../data-source";
|
||||
import { webapiPermission } from "../../../entity/user/webapi_permission";
|
||||
import InternalException from "../../../exceptions/internalException";
|
||||
import WebapiService from "../../../service/user/webapiService";
|
||||
import {
|
||||
CreateWebapiPermissionCommand,
|
||||
DeleteWebapiPermissionCommand,
|
||||
UpdateWebapiPermissionsCommand,
|
||||
} from "./webapiPermissionCommand";
|
||||
import PermissionHelper from "../../../helpers/permissionHelper";
|
||||
import WebapiPermissionService from "../../../service/user/webapiPermissionService";
|
||||
import { PermissionString } from "../../../type/permissionTypes";
|
||||
|
||||
export default abstract class WebapiPermissionCommandHandler {
|
||||
/**
|
||||
* @description update api permissions
|
||||
* @param {UpdateWebapiPermissionsCommand} updateWebapiPermissions
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async updatePermissions(updateWebapiPermissions: UpdateWebapiPermissionsCommand): Promise<void> {
|
||||
let currentPermissions = (await WebapiPermissionService.getByApi(updateWebapiPermissions.webapiId)).map(
|
||||
(r) => r.permission
|
||||
);
|
||||
return await dataSource.manager
|
||||
.transaction(async (manager) => {
|
||||
let newPermissions = PermissionHelper.getWhatToAdd(currentPermissions, updateWebapiPermissions.permissions);
|
||||
let removePermissions = PermissionHelper.getWhatToRemove(
|
||||
currentPermissions,
|
||||
updateWebapiPermissions.permissions
|
||||
);
|
||||
if (newPermissions.length != 0) {
|
||||
await this.updatePermissionsAdd(manager, updateWebapiPermissions.webapiId, newPermissions);
|
||||
}
|
||||
if (removePermissions.length != 0) {
|
||||
await this.updatePermissionsRemove(manager, updateWebapiPermissions.webapiId, removePermissions);
|
||||
}
|
||||
})
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw new InternalException("Failed saving api permissions", err);
|
||||
});
|
||||
}
|
||||
|
||||
private static async updatePermissionsAdd(
|
||||
manager: EntityManager,
|
||||
webapiId: number,
|
||||
permissions: Array<PermissionString>
|
||||
): Promise<InsertResult> {
|
||||
return await manager
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(webapiPermission)
|
||||
.values(
|
||||
permissions.map((p) => ({
|
||||
permission: p,
|
||||
webapiId: webapiId,
|
||||
}))
|
||||
)
|
||||
.orIgnore()
|
||||
.execute();
|
||||
}
|
||||
|
||||
private static async updatePermissionsRemove(
|
||||
manager: EntityManager,
|
||||
webapiId: number,
|
||||
permissions: Array<PermissionString>
|
||||
): Promise<DeleteResult> {
|
||||
return await manager
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(webapiPermission)
|
||||
.where("webapiId = :id", { id: webapiId })
|
||||
.andWhere("permission IN (:...permission)", { permission: permissions })
|
||||
.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description grant permission to user
|
||||
* @param {CreateWebapiPermissionCommand} createPermission
|
||||
* @returns {Promise<number>}
|
||||
*/
|
||||
static async create(createPermission: CreateWebapiPermissionCommand): Promise<number> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(webapiPermission)
|
||||
.values({
|
||||
permission: createPermission.permission,
|
||||
webapiId: createPermission.webapiId,
|
||||
})
|
||||
.execute()
|
||||
.then((result) => {
|
||||
return result.identifiers[0].id;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("Failed saving api permission", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description remove permission from api
|
||||
* @param {DeleteWebapiPermissionCommand} deletePermission
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
static async delete(deletePermission: DeleteWebapiPermissionCommand): Promise<any> {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(webapiPermission)
|
||||
.where("webapiId = :id", { id: deletePermission.webapiId })
|
||||
.andWhere("permission = :permission", { permission: deletePermission.permission })
|
||||
.execute()
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw new InternalException("failed api permission removal", err);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ import {
|
|||
CreateMemberCommand,
|
||||
DeleteMemberCommand,
|
||||
UpdateMemberCommand,
|
||||
UpdateMemberNewsletterCommand,
|
||||
} from "../../../command/club/member/memberCommand";
|
||||
import MemberCommandHandler from "../../../command/club/member/memberCommandHandler";
|
||||
import {
|
||||
|
@ -60,13 +61,8 @@ export async function getAllMembers(req: Request, res: Response): Promise<any> {
|
|||
let offset = parseInt((req.query.offset as string) ?? "0");
|
||||
let count = parseInt((req.query.count as string) ?? "25");
|
||||
let search = (req.query.search as string) ?? "";
|
||||
let noLimit = req.query.noLimit === "true";
|
||||
let ids = ((req.query.ids ?? "") as string)
|
||||
.split(",")
|
||||
.filter((i) => i)
|
||||
.map((i) => parseInt(i));
|
||||
|
||||
let [members, total] = await MemberService.getAll({ offset, count, search, noLimit, ids });
|
||||
let [members, total] = await MemberService.getAll(offset, count, search);
|
||||
|
||||
res.json({
|
||||
members: MemberFactory.mapToBase(members),
|
||||
|
@ -89,19 +85,6 @@ export async function getMemberById(req: Request, res: Response): Promise<any> {
|
|||
res.json(MemberFactory.mapToSingle(member));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get member statistics by id
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getMemberStatisticsById(req: Request, res: Response): Promise<any> {
|
||||
const memberId = parseInt(req.params.id);
|
||||
let member = await MemberService.getStatisticsById(memberId);
|
||||
|
||||
res.json(MemberFactory.mapToMemberStatistic(member));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get memberships by member
|
||||
* @param req {Request} Express req object
|
||||
|
@ -115,19 +98,6 @@ export async function getMembershipsByMember(req: Request, res: Response): Promi
|
|||
res.json(MembershipFactory.mapToBase(memberships));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get member statistics by id
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getMembershipStatisticsById(req: Request, res: Response): Promise<any> {
|
||||
const memberId = parseInt(req.params.memberId);
|
||||
let member = await MembershipService.getStatisticsById(memberId);
|
||||
|
||||
res.json(MembershipFactory.mapToBaseStatistics(member));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get membership by member and record
|
||||
* @param req {Request} Express req object
|
||||
|
@ -284,7 +254,7 @@ export async function createMemberPrintoutList(req: Request, res: Response): Pro
|
|||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function createMember(req: Request, res: Response): Promise<any> {
|
||||
const salutationId = parseInt(req.body.salutationId);
|
||||
const salutation = req.body.salutation;
|
||||
const firstname = req.body.firstname;
|
||||
const lastname = req.body.lastname;
|
||||
const nameaffix = req.body.nameaffix;
|
||||
|
@ -292,7 +262,7 @@ export async function createMember(req: Request, res: Response): Promise<any> {
|
|||
const internalId = req.body.internalId;
|
||||
|
||||
let createMember: CreateMemberCommand = {
|
||||
salutationId,
|
||||
salutation,
|
||||
firstname,
|
||||
lastname,
|
||||
nameaffix,
|
||||
|
@ -408,7 +378,6 @@ export async function addCommunicationToMember(req: Request, res: Response): Pro
|
|||
const memberId = parseInt(req.params.memberId);
|
||||
const preferred = req.body.preferred;
|
||||
const isSMSAlarming = req.body.isSMSAlarming;
|
||||
const isSendNewsletter = req.body.isNewsletterMain;
|
||||
const mobile = req.body.mobile;
|
||||
const email = req.body.email;
|
||||
const postalCode = req.body.postalCode;
|
||||
|
@ -417,11 +386,11 @@ export async function addCommunicationToMember(req: Request, res: Response): Pro
|
|||
const streetNumber = req.body.streetNumber;
|
||||
const streetNumberAddition = req.body.streetNumberAddition;
|
||||
const typeId = req.body.typeId;
|
||||
const isNewsletterMain = req.body.isNewsletterMain;
|
||||
|
||||
let createCommunication: CreateCommunicationCommand = {
|
||||
preferred,
|
||||
isSMSAlarming,
|
||||
isSendNewsletter,
|
||||
mobile,
|
||||
email,
|
||||
postalCode,
|
||||
|
@ -434,6 +403,14 @@ export async function addCommunicationToMember(req: Request, res: Response): Pro
|
|||
};
|
||||
let id = await CommunicationCommandHandler.create(createCommunication);
|
||||
|
||||
if (isNewsletterMain) {
|
||||
let updateNewsletter: UpdateMemberNewsletterCommand = {
|
||||
id: memberId,
|
||||
communicationId: id,
|
||||
};
|
||||
await MemberCommandHandler.updateNewsletter(updateNewsletter);
|
||||
}
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
|
@ -445,7 +422,7 @@ export async function addCommunicationToMember(req: Request, res: Response): Pro
|
|||
*/
|
||||
export async function updateMemberById(req: Request, res: Response): Promise<any> {
|
||||
const memberId = parseInt(req.params.id);
|
||||
const salutationId = parseInt(req.body.salutationId);
|
||||
const salutation = req.body.salutation;
|
||||
const firstname = req.body.firstname;
|
||||
const lastname = req.body.lastname;
|
||||
const nameaffix = req.body.nameaffix;
|
||||
|
@ -454,7 +431,7 @@ export async function updateMemberById(req: Request, res: Response): Promise<any
|
|||
|
||||
let updateMember: UpdateMemberCommand = {
|
||||
id: memberId,
|
||||
salutationId,
|
||||
salutation,
|
||||
firstname,
|
||||
lastname,
|
||||
nameaffix,
|
||||
|
@ -587,7 +564,6 @@ export async function updateCommunicationOfMember(req: Request, res: Response):
|
|||
const recordId = parseInt(req.params.recordId);
|
||||
const preferred = req.body.preferred;
|
||||
const isSMSAlarming = req.body.isSMSAlarming;
|
||||
const isSendNewsletter = req.body.isNewsletterMain;
|
||||
const mobile = req.body.mobile;
|
||||
const email = req.body.email;
|
||||
const postalCode = req.body.postalCode;
|
||||
|
@ -595,12 +571,12 @@ export async function updateCommunicationOfMember(req: Request, res: Response):
|
|||
const street = req.body.street;
|
||||
const streetNumber = req.body.streetNumber;
|
||||
const streetNumberAddition = req.body.streetNumberAddition;
|
||||
const isNewsletterMain = req.body.isNewsletterMain;
|
||||
|
||||
let updateCommunication: UpdateCommunicationCommand = {
|
||||
id: recordId,
|
||||
preferred,
|
||||
isSMSAlarming,
|
||||
isSendNewsletter,
|
||||
mobile,
|
||||
email,
|
||||
postalCode,
|
||||
|
@ -612,6 +588,18 @@ export async function updateCommunicationOfMember(req: Request, res: Response):
|
|||
};
|
||||
await CommunicationCommandHandler.update(updateCommunication);
|
||||
|
||||
let currentUserNewsletterMain = await MemberService.getNewsletterById(memberId);
|
||||
|
||||
if (isNewsletterMain) {
|
||||
let updateNewsletter: UpdateMemberNewsletterCommand = {
|
||||
id: memberId,
|
||||
communicationId: recordId,
|
||||
};
|
||||
await MemberCommandHandler.updateNewsletter(updateNewsletter);
|
||||
} else if (currentUserNewsletterMain.sendNewsletter?.id == recordId) {
|
||||
await MemberCommandHandler.unsetNewsletter(memberId);
|
||||
}
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import UserService from "../../../service/user/userService";
|
|||
import { TemplateHelper } from "../../../helpers/templateHelper";
|
||||
import MailHelper from "../../../helpers/mailHelper";
|
||||
import { NewsletterEventType, NewsletterHelper } from "../../../helpers/newsletterHelper";
|
||||
import { Salutation } from "../../../enums/salutation";
|
||||
|
||||
/**
|
||||
* @description get all newsletters
|
||||
|
@ -141,7 +142,7 @@ export async function createNewsletterPrintoutPreviewById(req: Request, res: Res
|
|||
data.recipient = {
|
||||
firstname: recipient.firstname,
|
||||
lastname: recipient.lastname,
|
||||
salutation: "Anrede",
|
||||
salutation: Salutation.none,
|
||||
nameaffix: "",
|
||||
street: "Straße",
|
||||
streetNumber: "Hausnummer",
|
||||
|
@ -247,7 +248,7 @@ export async function createNewsletterMailPreviewById(req: Request, res: Respons
|
|||
data.recipient = {
|
||||
firstname: recipient.firstname,
|
||||
lastname: recipient.lastname,
|
||||
salutation: "Anrede",
|
||||
salutation: Salutation.none,
|
||||
nameaffix: "",
|
||||
street: "Straße",
|
||||
streetNumber: "Hausnummer",
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
import { Request, Response } from "express";
|
||||
import SalutationService from "../../../service/settings/salutationService";
|
||||
import SalutationFactory from "../../../factory/admin/settings/salutation";
|
||||
import {
|
||||
CreateSalutationCommand,
|
||||
DeleteSalutationCommand,
|
||||
UpdateSalutationCommand,
|
||||
} from "../../../command/settings/salutation/salutationCommand";
|
||||
import SalutationCommandHandler from "../../../command/settings/salutation/salutationCommandHandler";
|
||||
|
||||
/**
|
||||
* @description get all salutations
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getAllSalutations(req: Request, res: Response): Promise<any> {
|
||||
let salutations = await SalutationService.getAll();
|
||||
|
||||
res.json(SalutationFactory.mapToBase(salutations));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get salutation by id
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getSalutationById(req: Request, res: Response): Promise<any> {
|
||||
const id = parseInt(req.params.id);
|
||||
let salutation = await SalutationService.getById(id);
|
||||
|
||||
res.json(SalutationFactory.mapToSingle(salutation));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description create new salutation
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function createSalutation(req: Request, res: Response): Promise<any> {
|
||||
const salutation = req.body.salutation;
|
||||
|
||||
let createSalutation: CreateSalutationCommand = {
|
||||
salutation: salutation,
|
||||
};
|
||||
await SalutationCommandHandler.create(createSalutation);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description update salutation
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function updateSalutation(req: Request, res: Response): Promise<any> {
|
||||
const id = parseInt(req.params.id);
|
||||
const salutation = req.body.salutation;
|
||||
|
||||
let updateSalutation: UpdateSalutationCommand = {
|
||||
id: id,
|
||||
salutation: salutation,
|
||||
};
|
||||
await SalutationCommandHandler.update(updateSalutation);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description delete salutation
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function deleteSalutation(req: Request, res: Response): Promise<any> {
|
||||
const id = parseInt(req.params.id);
|
||||
|
||||
let deleteSalutation: DeleteSalutationCommand = {
|
||||
id: id,
|
||||
};
|
||||
await SalutationCommandHandler.delete(deleteSalutation);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
|
@ -10,7 +10,6 @@ import MailHelper from "../../../helpers/mailHelper";
|
|||
import { CLUB_NAME } from "../../../env.defaults";
|
||||
import { UpdateUserPermissionsCommand } from "../../../command/user/user/userPermissionCommand";
|
||||
import UserPermissionCommandHandler from "../../../command/user/user/userPermissionCommandHandler";
|
||||
import BadRequestException from "../../../exceptions/badRequestException";
|
||||
|
||||
/**
|
||||
* @description get All users
|
||||
|
@ -138,11 +137,7 @@ export async function updateUserRoles(req: Request, res: Response): Promise<any>
|
|||
export async function deleteUser(req: Request, res: Response): Promise<any> {
|
||||
const id = parseInt(req.params.id);
|
||||
|
||||
let { mail, isOwner } = await UserService.getById(id);
|
||||
|
||||
if (isOwner) {
|
||||
throw new BadRequestException("Owner cannot be deleted");
|
||||
}
|
||||
let user = await UserService.getById(id);
|
||||
|
||||
let deleteUser: DeleteUserCommand = {
|
||||
id: id,
|
||||
|
@ -152,7 +147,7 @@ export async function deleteUser(req: Request, res: Response): Promise<any> {
|
|||
try {
|
||||
// sendmail
|
||||
await MailHelper.sendMail(
|
||||
mail,
|
||||
user.mail,
|
||||
`Email Bestätigung für Mitglieder Admin-Portal von ${CLUB_NAME}`,
|
||||
`Ihr Nutzerkonto des Adminportals wurde erfolgreich gelöscht.`
|
||||
);
|
||||
|
|
|
@ -1,155 +0,0 @@
|
|||
import { Request, Response } from "express";
|
||||
import WebapiService from "../../../service/user/webapiService";
|
||||
import ApiFactory from "../../../factory/admin/user/webapi";
|
||||
import WebapiPermissionService from "../../../service/user/webapiPermissionService";
|
||||
import PermissionHelper from "../../../helpers/permissionHelper";
|
||||
import {
|
||||
CreateWebapiCommand,
|
||||
DeleteWebapiCommand,
|
||||
UpdateWebapiCommand,
|
||||
} from "../../../command/user/webapi/webapiCommand";
|
||||
import WebapiCommandHandler from "../../../command/user/webapi/webapiCommandHandler";
|
||||
import { UpdateWebapiPermissionsCommand } from "../../../command/user/webapi/webapiPermissionCommand";
|
||||
import WebapiPermissionCommandHandler from "../../../command/user/webapi/webapiPermissionCommandHandler";
|
||||
import { JWTHelper } from "../../../helpers/jwtHelper";
|
||||
import { CLUB_NAME } from "../../../env.defaults";
|
||||
import { StringHelper } from "../../../helpers/stringHelper";
|
||||
|
||||
/**
|
||||
* @description get All apis
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getAllWebapis(req: Request, res: Response): Promise<any> {
|
||||
let apis = await WebapiService.getAll();
|
||||
|
||||
res.json(ApiFactory.mapToBase(apis));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get api by id
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getWebapiById(req: Request, res: Response): Promise<any> {
|
||||
const id = parseInt(req.params.id);
|
||||
let api = await WebapiService.getById(id);
|
||||
|
||||
res.json(ApiFactory.mapToSingle(api));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get api token by id
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getWebapiTokenById(req: Request, res: Response): Promise<any> {
|
||||
const id = parseInt(req.params.id);
|
||||
let { token } = await WebapiService.getTokenById(id);
|
||||
|
||||
res.send(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get permissions by api
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getWebapiPermissions(req: Request, res: Response): Promise<any> {
|
||||
const id = parseInt(req.params.id);
|
||||
let permissions = await WebapiPermissionService.getByApi(id);
|
||||
|
||||
res.json(PermissionHelper.convertToObject(permissions.map((p) => p.permission)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description create new api
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function createWebapi(req: Request, res: Response): Promise<any> {
|
||||
let title = req.body.title;
|
||||
let expiry = req.body.expiry || null;
|
||||
|
||||
let token = await JWTHelper.create(
|
||||
{
|
||||
iss: CLUB_NAME,
|
||||
sub: "api_token_retrieve",
|
||||
aud: StringHelper.random(32),
|
||||
},
|
||||
{ useExpiration: false }
|
||||
);
|
||||
|
||||
let createApi: CreateWebapiCommand = {
|
||||
token: token,
|
||||
title: title,
|
||||
expiry: expiry,
|
||||
};
|
||||
await WebapiCommandHandler.create(createApi);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description update api data
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function updateWebapi(req: Request, res: Response): Promise<any> {
|
||||
const id = parseInt(req.params.id);
|
||||
let title = req.body.title;
|
||||
let expiry = req.body.expiry || null;
|
||||
|
||||
let updateApi: UpdateWebapiCommand = {
|
||||
id: id,
|
||||
title: title,
|
||||
expiry: expiry,
|
||||
};
|
||||
await WebapiCommandHandler.update(updateApi);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description update api assigned permission strings
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function updateWebapiPermissions(req: Request, res: Response): Promise<any> {
|
||||
const id = parseInt(req.params.id);
|
||||
let permissions = req.body.permissions;
|
||||
|
||||
let permissionStrings = PermissionHelper.convertToStringArray(permissions);
|
||||
|
||||
let updateApiPermissions: UpdateWebapiPermissionsCommand = {
|
||||
webapiId: id,
|
||||
permissions: permissionStrings,
|
||||
};
|
||||
await WebapiPermissionCommandHandler.updatePermissions(updateApiPermissions);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description delete api by id
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function deleteWebapi(req: Request, res: Response): Promise<any> {
|
||||
const id = parseInt(req.params.id);
|
||||
|
||||
let deleteApi: DeleteWebapiCommand = {
|
||||
id: id,
|
||||
};
|
||||
await WebapiCommandHandler.delete(deleteApi);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
import { Request, Response } from "express";
|
||||
import { JWTHelper } from "../helpers/jwtHelper";
|
||||
import { JWTToken } from "../type/jwtTypes";
|
||||
import InternalException from "../exceptions/internalException";
|
||||
import RefreshCommandHandler from "../command/refreshCommandHandler";
|
||||
import { CreateRefreshCommand, DeleteRefreshCommand } from "../command/refreshCommand";
|
||||
import UserService from "../service/user/userService";
|
||||
import speakeasy from "speakeasy";
|
||||
import UnauthorizedRequestException from "../exceptions/unauthorizedRequestException";
|
||||
import RefreshService from "../service/refreshService";
|
||||
import WebapiService from "../service/user/webapiService";
|
||||
import ForbiddenRequestException from "../exceptions/forbiddenRequestException";
|
||||
import WebapiCommandHandler from "../command/user/webapi/webapiCommandHandler";
|
||||
|
||||
/**
|
||||
* @description Check authentication status by token
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getWebApiAccess(req: Request, res: Response): Promise<any> {
|
||||
const bearer = req.headers.authorization?.split(" ")?.[1] ?? undefined;
|
||||
|
||||
let { id, expiry } = await WebapiService.getByToken(bearer);
|
||||
|
||||
if (expiry != null && new Date() > new Date(expiry)) {
|
||||
throw new ForbiddenRequestException("api token expired");
|
||||
}
|
||||
|
||||
await WebapiCommandHandler.updateUsage({ id });
|
||||
|
||||
let accessToken = await JWTHelper.buildWebapiToken(bearer, expiry);
|
||||
|
||||
res.json({
|
||||
accessToken,
|
||||
});
|
||||
}
|
|
@ -68,13 +68,6 @@ import { Memberlist1736079005086 } from "./migrations/1736079005086-memberlist";
|
|||
import { ExtendViewValues1736084198860 } from "./migrations/1736084198860-extendViewValues";
|
||||
import { FinishInternalIdTransfer1736505324488 } from "./migrations/1736505324488-finishInternalIdTransfer";
|
||||
import { ProtocolPresenceExcuse1737287798828 } from "./migrations/1737287798828-protocolPresenceExcuse";
|
||||
import { webapi } from "./entity/user/webapi";
|
||||
import { webapiPermission } from "./entity/user/webapi_permission";
|
||||
import { AddWebapiTokens1737453096674 } from "./migrations/1737453096674-addwebapiTokens";
|
||||
import { salutation } from "./entity/settings/salutation";
|
||||
import { SalutationAsTable1737796878058 } from "./migrations/1737796878058-salutationAsTable";
|
||||
import { UpdateViews1737800468938 } from "./migrations/1737800468938-updateViews";
|
||||
import { MoveSendNewsletterFlag1737816852011 } from "./migrations/1737816852011-moveSendNewsletterFlag";
|
||||
|
||||
const dataSource = new DataSource({
|
||||
type: DB_TYPE as any,
|
||||
|
@ -100,7 +93,6 @@ const dataSource = new DataSource({
|
|||
executivePosition,
|
||||
membershipStatus,
|
||||
qualification,
|
||||
salutation,
|
||||
member,
|
||||
memberAwards,
|
||||
memberExecutivePositions,
|
||||
|
@ -125,8 +117,6 @@ const dataSource = new DataSource({
|
|||
memberExecutivePositionsView,
|
||||
memberQualificationsView,
|
||||
membershipView,
|
||||
webapi,
|
||||
webapiPermission,
|
||||
],
|
||||
migrations: [
|
||||
Initial1724317398939,
|
||||
|
@ -156,10 +146,6 @@ const dataSource = new DataSource({
|
|||
ExtendViewValues1736084198860,
|
||||
FinishInternalIdTransfer1736505324488,
|
||||
ProtocolPresenceExcuse1737287798828,
|
||||
AddWebapiTokens1737453096674,
|
||||
SalutationAsTable1737796878058,
|
||||
UpdateViews1737800468938,
|
||||
MoveSendNewsletterFlag1737816852011,
|
||||
],
|
||||
migrationsRun: true,
|
||||
migrationsTransactionMode: "each",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { calendar } from "../entity/club/calendar";
|
||||
import { member } from "../entity/club/member/member";
|
||||
import { Salutation } from "../enums/salutation";
|
||||
|
||||
export const newsletterDemoData: {
|
||||
title: string;
|
||||
|
@ -17,9 +18,7 @@ export const newsletterDemoData: {
|
|||
}
|
||||
>
|
||||
>;
|
||||
recipient: Partial<
|
||||
Omit<member, "salutation"> & { salutation: string; street: string; streetNumber: string; streetNumberAdd: string }
|
||||
>;
|
||||
recipient: Partial<member & { street: string; streetNumber: string; streetNumberAdd: string }>;
|
||||
} = {
|
||||
title: "Beispiel Newsletter Daten",
|
||||
description: "Zusammenfassung der Demodaten.",
|
||||
|
@ -64,7 +63,7 @@ export const newsletterDemoData: {
|
|||
recipient: {
|
||||
firstname: "Julian",
|
||||
lastname: "Krauser",
|
||||
salutation: "Herr",
|
||||
salutation: Salutation.sir,
|
||||
nameaffix: "",
|
||||
street: "Straße",
|
||||
streetNumber: "Hausnummer",
|
||||
|
|
|
@ -13,9 +13,6 @@ export class communication {
|
|||
@Column({ type: "boolean", default: false })
|
||||
isSMSAlarming: boolean;
|
||||
|
||||
@Column({ type: "boolean", default: false })
|
||||
isSendNewsletter: boolean;
|
||||
|
||||
@Column({ type: "varchar", length: 255, nullable: true })
|
||||
mobile: string;
|
||||
|
||||
|
|
|
@ -1,16 +1,32 @@
|
|||
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne, PrimaryColumn } from "typeorm";
|
||||
import { Salutation } from "../../../enums/salutation";
|
||||
import { membership } from "./membership";
|
||||
import { memberAwards } from "./memberAwards";
|
||||
import { memberQualifications } from "./memberQualifications";
|
||||
import { memberExecutivePositions } from "./memberExecutivePositions";
|
||||
import { communication } from "./communication";
|
||||
import { salutation } from "../../settings/salutation";
|
||||
import { CommunicationViewModel } from "../../../viewmodel/admin/club/member/communication.models";
|
||||
|
||||
@Entity()
|
||||
export class member {
|
||||
@PrimaryColumn({ generated: "increment", type: "int" })
|
||||
id: number;
|
||||
|
||||
@Column({
|
||||
type: "varchar",
|
||||
length: "255",
|
||||
default: Salutation.none.toString(),
|
||||
transformer: {
|
||||
to(value: Salutation) {
|
||||
return value.toString();
|
||||
},
|
||||
from(value: string) {
|
||||
return Salutation[value as keyof typeof Salutation];
|
||||
},
|
||||
},
|
||||
})
|
||||
salutation: Salutation;
|
||||
|
||||
@Column({ type: "varchar", length: 255 })
|
||||
firstname: string;
|
||||
|
||||
|
@ -26,14 +42,16 @@ export class member {
|
|||
@Column({ type: "varchar", length: 255, unique: true, nullable: true })
|
||||
internalId?: string;
|
||||
|
||||
@Column()
|
||||
salutationId: number;
|
||||
|
||||
@OneToMany(() => communication, (communications) => communications.member)
|
||||
communications: communication[];
|
||||
|
||||
@ManyToOne(() => salutation, (salutation) => salutation.members)
|
||||
salutation: salutation;
|
||||
@OneToOne(() => communication, {
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
onUpdate: "RESTRICT",
|
||||
})
|
||||
@JoinColumn()
|
||||
sendNewsletter?: communication;
|
||||
|
||||
@OneToMany(() => membership, (membership) => membership.member)
|
||||
memberships: membership[];
|
||||
|
@ -51,5 +69,4 @@ export class member {
|
|||
lastMembershipEntry?: membership;
|
||||
preferredCommunication?: Array<communication>;
|
||||
smsAlarming?: Array<communication>;
|
||||
sendNewsletter?: communication;
|
||||
}
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import { Column, Entity, OneToMany, PrimaryColumn } from "typeorm";
|
||||
import { memberAwards } from "../club/member/memberAwards";
|
||||
import { member } from "../club/member/member";
|
||||
|
||||
@Entity()
|
||||
export class salutation {
|
||||
@PrimaryColumn({ generated: "increment", type: "int" })
|
||||
id: number;
|
||||
|
||||
@Column({ type: "varchar", length: 255, unique: true })
|
||||
salutation: string;
|
||||
|
||||
@OneToMany(() => member, (member) => member.salutation)
|
||||
members: member[];
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
import { Column, CreateDateColumn, Entity, OneToMany, PrimaryColumn } from "typeorm";
|
||||
import { webapiPermission } from "./webapi_permission";
|
||||
|
||||
@Entity()
|
||||
export class webapi {
|
||||
@PrimaryColumn({ generated: "increment", type: "int" })
|
||||
id: number;
|
||||
|
||||
@Column({ type: "text", unique: true, select: false })
|
||||
token: string;
|
||||
|
||||
@Column({ type: "varchar", length: 255, unique: true })
|
||||
title: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
@Column({ type: "datetime", nullable: true })
|
||||
lastUsage?: Date;
|
||||
|
||||
@Column({ type: "date", nullable: true })
|
||||
expiry?: Date;
|
||||
|
||||
@OneToMany(() => webapiPermission, (apiPermission) => apiPermission.webapi)
|
||||
permissions: webapiPermission[];
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
import { Column, Entity, ManyToOne, OneToMany, PrimaryColumn } from "typeorm";
|
||||
import { PermissionObject, PermissionString } from "../../type/permissionTypes";
|
||||
import { webapi } from "./webapi";
|
||||
|
||||
@Entity()
|
||||
export class webapiPermission {
|
||||
@PrimaryColumn({ type: "int" })
|
||||
webapiId: number;
|
||||
|
||||
@PrimaryColumn({ type: "varchar", length: 255 })
|
||||
permission: PermissionString;
|
||||
|
||||
@ManyToOne(() => webapi, {
|
||||
nullable: false,
|
||||
onDelete: "CASCADE",
|
||||
onUpdate: "RESTRICT",
|
||||
})
|
||||
webapi: webapi;
|
||||
}
|
6
src/enums/salutation.ts
Normal file
6
src/enums/salutation.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
export enum Salutation {
|
||||
sir = "sir",
|
||||
madam = "madam",
|
||||
other = "other",
|
||||
none = "none",
|
||||
}
|
|
@ -21,7 +21,7 @@ export const MAIL_HOST = process.env.MAIL_HOST ?? "";
|
|||
export const MAIL_PORT = Number(process.env.MAIL_PORT ?? "587");
|
||||
export const MAIL_SECURE = process.env.MAIL_SECURE ?? "false";
|
||||
|
||||
export const CLUB_NAME = process.env.CLUB_NAME ?? "FF Admin";
|
||||
export const CLUB_NAME = process.env.CLUB_NAME ?? "";
|
||||
export const CLUB_WEBSITE = process.env.CLUB_WEBSITE ?? "";
|
||||
|
||||
export function configCheck() {
|
||||
|
|
|
@ -20,7 +20,7 @@ export default abstract class CommunicationFactory {
|
|||
streetNumber: record.streetNumber,
|
||||
streetNumberAddition: record.streetNumberAddition,
|
||||
type: CommunicationTypeFactory.mapToSingle(record.type),
|
||||
isNewsletterMain: record?.isSendNewsletter,
|
||||
isNewsletterMain: isMain ? isMain : record?.member?.sendNewsletter?.id == record.id,
|
||||
isSMSAlarming: record.isSMSAlarming,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import { member } from "../../../../entity/club/member/member";
|
||||
import { MemberStatisticsViewModel, MemberViewModel } from "../../../../viewmodel/admin/club/member/member.models";
|
||||
import { memberView } from "../../../../views/memberView";
|
||||
import SalutationFactory from "../../settings/salutation";
|
||||
import { MemberViewModel } from "../../../../viewmodel/admin/club/member/member.models";
|
||||
import CommunicationFactory from "./communication";
|
||||
import MembershipFactory from "./membership";
|
||||
|
||||
|
@ -14,7 +12,7 @@ export default abstract class MemberFactory {
|
|||
public static mapToSingle(record: member): MemberViewModel {
|
||||
return {
|
||||
id: record?.id,
|
||||
salutation: SalutationFactory.mapToSingle(record?.salutation),
|
||||
salutation: record?.salutation,
|
||||
firstname: record?.firstname,
|
||||
lastname: record?.lastname,
|
||||
nameaffix: record?.nameaffix,
|
||||
|
@ -42,23 +40,4 @@ export default abstract class MemberFactory {
|
|||
public static mapToBase(records: Array<member>): Array<MemberViewModel> {
|
||||
return records.map((r) => this.mapToSingle(r));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description map view record to MemberMembershipStatisticsViewModel
|
||||
* @param {memberView} record
|
||||
* @returns {MemberStatisticsViewModel}
|
||||
*/
|
||||
public static mapToMemberStatistic(record: memberView): MemberStatisticsViewModel {
|
||||
return {
|
||||
id: record.id,
|
||||
salutation: record.salutation,
|
||||
firstname: record.firstname,
|
||||
lastname: record.lastname,
|
||||
nameaffix: record.nameaffix,
|
||||
birthdate: record.birthdate,
|
||||
todayAge: record.todayAge,
|
||||
ageThisYear: record.ageThisYear,
|
||||
exactAge: record.exactAge,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
import { membership } from "../../../../entity/club/member/membership";
|
||||
import {
|
||||
MembershipStatisticsViewModel,
|
||||
MembershipViewModel,
|
||||
} from "../../../../viewmodel/admin/club/member/membership.models";
|
||||
import { membershipView } from "../../../../views/membershipsView";
|
||||
import { MembershipViewModel } from "../../../../viewmodel/admin/club/member/membership.models";
|
||||
|
||||
export default abstract class MembershipFactory {
|
||||
/**
|
||||
|
@ -30,33 +26,4 @@ export default abstract class MembershipFactory {
|
|||
public static mapToBase(records: Array<membership>): Array<MembershipViewModel> {
|
||||
return records.map((r) => this.mapToSingle(r));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description map view record to MembershipStatisticsViewModel
|
||||
* @param {membershipView} record
|
||||
* @returns {MembershipStatisticsViewModel}
|
||||
*/
|
||||
public static mapToSingleStatistic(record: membershipView): MembershipStatisticsViewModel {
|
||||
return {
|
||||
durationInDays: record.durationInDays,
|
||||
durationInYears: record.durationInYears,
|
||||
status: record.status,
|
||||
statusId: record.statusId,
|
||||
memberId: record.memberId,
|
||||
memberSalutation: record.memberSalutation,
|
||||
memberFirstname: record.memberFirstname,
|
||||
memberLastname: record.memberLastname,
|
||||
memberNameaffix: record.memberNameaffix,
|
||||
memberBirthdate: record.memberBirthdate,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description map records to MembershipStatisticsViewModel
|
||||
* @param {Array<membershipView>} records
|
||||
* @returns {Array<MembershipStatisticsViewModel>}
|
||||
*/
|
||||
public static mapToBaseStatistics(records: Array<membershipView>): Array<MembershipStatisticsViewModel> {
|
||||
return records.map((r) => this.mapToSingleStatistic(r));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
import { salutation } from "../../../entity/settings/salutation";
|
||||
import { SalutationViewModel } from "../../../viewmodel/admin/settings/salutation.models";
|
||||
|
||||
export default abstract class SalutationFactory {
|
||||
/**
|
||||
* @description map record to salutation
|
||||
* @param {salutation} record
|
||||
* @returns {SalutationViewModel}
|
||||
*/
|
||||
public static mapToSingle(record: salutation): SalutationViewModel {
|
||||
return {
|
||||
id: record.id,
|
||||
salutation: record.salutation,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description map records to salutation
|
||||
* @param {Array<salutation>} records
|
||||
* @returns {Array<SalutationViewModel>}
|
||||
*/
|
||||
public static mapToBase(records: Array<salutation>): Array<SalutationViewModel> {
|
||||
return records.map((r) => this.mapToSingle(r));
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
import { webapi } from "../../../entity/user/webapi";
|
||||
import PermissionHelper from "../../../helpers/permissionHelper";
|
||||
import { ApiViewModel } from "../../../viewmodel/admin/user/webapi.models";
|
||||
|
||||
export default abstract class ApiFactory {
|
||||
/**
|
||||
* @description map record to api
|
||||
* @param {webapi} record
|
||||
* @returns {apiViewModel}
|
||||
*/
|
||||
public static mapToSingle(record: webapi): ApiViewModel {
|
||||
return {
|
||||
id: record.id,
|
||||
permissions: PermissionHelper.convertToObject(record.permissions.map((e) => e.permission)),
|
||||
title: record.title,
|
||||
expiry: record.expiry,
|
||||
lastUsage: record.lastUsage,
|
||||
createdAt: record.createdAt,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description map records to api
|
||||
* @param {Array<webapi>} records
|
||||
* @returns {Array<apiViewModel>}
|
||||
*/
|
||||
public static mapToBase(records: Array<webapi>): Array<ApiViewModel> {
|
||||
return records.map((r) => this.mapToSingle(r));
|
||||
}
|
||||
}
|
|
@ -11,7 +11,6 @@ export default abstract class DynamicQueryBuilder {
|
|||
"executivePosition",
|
||||
"membershipStatus",
|
||||
"qualification",
|
||||
"salutation",
|
||||
"member",
|
||||
"memberAwards",
|
||||
"memberExecutivePositions",
|
||||
|
|
|
@ -6,9 +6,6 @@ import RolePermissionService from "../service/user/rolePermissionService";
|
|||
import UserPermissionService from "../service/user/userPermissionService";
|
||||
import UserService from "../service/user/userService";
|
||||
import PermissionHelper from "./permissionHelper";
|
||||
import WebapiService from "../service/user/webapiService";
|
||||
import WebapiPermissionService from "../service/user/webapiPermissionService";
|
||||
import ms from "ms";
|
||||
|
||||
export abstract class JWTHelper {
|
||||
static validate(token: string): Promise<string | jwt.JwtPayload> {
|
||||
|
@ -20,16 +17,13 @@ export abstract class JWTHelper {
|
|||
});
|
||||
}
|
||||
|
||||
static create(
|
||||
data: JWTData,
|
||||
{ expOverwrite, useExpiration }: { expOverwrite?: number; useExpiration?: boolean } = { useExpiration: true }
|
||||
): Promise<string> {
|
||||
static create(data: JWTData): Promise<string> {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
jwt.sign(
|
||||
data,
|
||||
JWT_SECRET,
|
||||
{
|
||||
...(useExpiration ?? true ? { expiresIn: expOverwrite ?? JWT_EXPIRATION } : {}),
|
||||
expiresIn: JWT_EXPIRATION,
|
||||
},
|
||||
(err, token) => {
|
||||
if (err) reject(err.message);
|
||||
|
@ -78,35 +72,4 @@ export abstract class JWTHelper {
|
|||
throw new InternalException("Failed accessToken creation", err);
|
||||
});
|
||||
}
|
||||
|
||||
static async buildWebapiToken(token: string, expiration?: Date): Promise<string> {
|
||||
let { id, title } = await WebapiService.getByToken(token);
|
||||
let webapiPermissions = await WebapiPermissionService.getByApi(id);
|
||||
let webapiPermissionStrings = webapiPermissions.map((e) => e.permission);
|
||||
let permissionObject = PermissionHelper.convertToObject(webapiPermissionStrings);
|
||||
|
||||
let jwtData: JWTToken = {
|
||||
userId: id,
|
||||
mail: "",
|
||||
username: title,
|
||||
firstname: "",
|
||||
lastname: "",
|
||||
isOwner: false,
|
||||
permissions: permissionObject,
|
||||
sub: "webapi_access_token",
|
||||
};
|
||||
|
||||
let overwriteExpiration =
|
||||
ms(JWT_EXPIRATION) < new Date().getTime() - new Date(expiration).getTime()
|
||||
? null
|
||||
: Date.now() - new Date(expiration).getTime();
|
||||
|
||||
return await JWTHelper.create(jwtData, { expOverwrite: overwriteExpiration, useExpiration: true })
|
||||
.then((result) => {
|
||||
return result;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("Failed webapi accessToken creation", err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ export abstract class NewsletterHelper {
|
|||
recipient: {
|
||||
firstname: recipient.firstname,
|
||||
lastname: recipient.lastname,
|
||||
salutation: recipient.salutation.salutation,
|
||||
salutation: recipient.salutation,
|
||||
nameaffix: recipient.nameaffix,
|
||||
...(showAdress
|
||||
? {
|
||||
|
@ -141,7 +141,7 @@ export abstract class NewsletterHelper {
|
|||
}
|
||||
}
|
||||
|
||||
let members = await MemberService.getAll({ noLimit: true });
|
||||
let members = await MemberService.getAll(0, 1000);
|
||||
|
||||
return members[0].filter((m) => queryMemberIds.includes(m.id));
|
||||
}
|
||||
|
|
|
@ -89,19 +89,6 @@ export default class PermissionHelper {
|
|||
};
|
||||
}
|
||||
|
||||
static isAdminMiddleware(): (req: Request, res: Response, next: Function) => void {
|
||||
return (req: Request, res: Response, next: Function) => {
|
||||
const permissions = req.permissions;
|
||||
const isOwner = req.isOwner;
|
||||
|
||||
if (isOwner || permissions.admin) {
|
||||
next();
|
||||
} else {
|
||||
throw new ForbiddenRequestException(`missing admin permission`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static convertToObject(permissions: Array<PermissionString>): PermissionObject {
|
||||
if (permissions.includes("*")) {
|
||||
return {
|
||||
|
|
|
@ -13,7 +13,6 @@ declare global {
|
|||
isOwner: boolean;
|
||||
permissions: PermissionObject;
|
||||
isPWA: boolean;
|
||||
isWebApiRequest: boolean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,15 +29,10 @@ export default async function authenticate(req: Request, res: Response, next: Fu
|
|||
throw new InternalException("process failed");
|
||||
}
|
||||
|
||||
if (decoded?.sub == "api_token_retrieve") {
|
||||
throw new BadRequestException("This token is only authorized to get temporary access tokens via GET /api/webapi");
|
||||
}
|
||||
|
||||
req.userId = decoded.userId;
|
||||
req.username = decoded.username;
|
||||
req.isOwner = decoded.isOwner;
|
||||
req.permissions = decoded.permissions;
|
||||
req.isWebApiRequest = decoded?.sub == "webapi_access_token";
|
||||
|
||||
next();
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
import { Request, Response } from "express";
|
||||
import jwt from "jsonwebtoken";
|
||||
import BadRequestException from "../exceptions/badRequestException";
|
||||
import UnauthorizedRequestException from "../exceptions/unauthorizedRequestException";
|
||||
import InternalException from "../exceptions/internalException";
|
||||
import { JWTHelper } from "../helpers/jwtHelper";
|
||||
|
||||
export default async function authenticateAPI(req: Request, res: Response, next: Function) {
|
||||
const bearer = req.headers.authorization?.split(" ")?.[1] ?? undefined;
|
||||
|
||||
if (!bearer) {
|
||||
throw new BadRequestException("Provide valid Authorization Header");
|
||||
}
|
||||
|
||||
let decoded: string | jwt.JwtPayload;
|
||||
await JWTHelper.validate(bearer)
|
||||
.then((result) => {
|
||||
decoded = result;
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err == "jwt expired") {
|
||||
throw new UnauthorizedRequestException("Token expired", err);
|
||||
} else {
|
||||
throw new BadRequestException("Failed Authorization Header decoding", err);
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof decoded == "string" || !decoded) {
|
||||
throw new InternalException("process failed");
|
||||
}
|
||||
|
||||
if (decoded?.sub != "api_token_retrieve") {
|
||||
throw new BadRequestException("This route can only be accessed via a api token");
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
import { Request, Response } from "express";
|
||||
import ForbiddenRequestException from "../exceptions/forbiddenRequestException";
|
||||
|
||||
export default async function preventWebapiAccess(req: Request, res: Response, next: Function) {
|
||||
if (req.isWebApiRequest) {
|
||||
throw new ForbiddenRequestException("This route cannot be accessed via webapi");
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
|
@ -8,105 +8,105 @@ export class MemberDataViews1734520998539 implements MigrationInterface {
|
|||
name = "MemberDataViews1734520998539";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// await queryRunner.createView(
|
||||
// new View({
|
||||
// name: "member_view",
|
||||
// expression: (datasource: DataSource) =>
|
||||
// datasource
|
||||
// .getRepository(member)
|
||||
// .createQueryBuilder("member")
|
||||
// .select("member.id", "id")
|
||||
// .addSelect("member.salutation", "salutation")
|
||||
// .addSelect("member.firstname", "firstname")
|
||||
// .addSelect("member.lastname", "lastname")
|
||||
// .addSelect("member.nameaffix", "nameaffix")
|
||||
// .addSelect("member.birthdate", "birthdate")
|
||||
// .addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||
// .addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear"),
|
||||
// }),
|
||||
// true
|
||||
// );
|
||||
// await queryRunner.createView(
|
||||
// new View({
|
||||
// name: "member_executive_positions_view",
|
||||
// expression: (datasource: DataSource) =>
|
||||
// datasource
|
||||
// .getRepository(memberExecutivePositions)
|
||||
// .createQueryBuilder("memberExecutivePositions")
|
||||
// .select("executivePosition.id", "positionId")
|
||||
// .addSelect("executivePosition.position", "position")
|
||||
// .addSelect("member.id", "memberId")
|
||||
// .addSelect("member.salutation", "memberSalutation")
|
||||
// .addSelect("member.firstname", "memberFirstname")
|
||||
// .addSelect("member.lastname", "memberLastname")
|
||||
// .addSelect("member.nameaffix", "memberNameaffix")
|
||||
// .addSelect("member.birthdate", "memberBirthdate")
|
||||
// .addSelect(
|
||||
// "SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))",
|
||||
// "durationInDays"
|
||||
// )
|
||||
// .leftJoin("memberExecutivePositions.executivePosition", "executivePosition")
|
||||
// .leftJoin("memberExecutivePositions.member", "member")
|
||||
// .groupBy("executivePosition.id"),
|
||||
// }),
|
||||
// true
|
||||
// );
|
||||
// await queryRunner.createView(
|
||||
// new View({
|
||||
// name: "member_qualifications_view",
|
||||
// expression: (datasource: DataSource) =>
|
||||
// datasource
|
||||
// .getRepository(memberQualifications)
|
||||
// .createQueryBuilder("memberQualifications")
|
||||
// .select("qualification.id", "qualificationId")
|
||||
// .addSelect("qualification.qualification", "qualification")
|
||||
// .addSelect("member.id", "memberId")
|
||||
// .addSelect("member.salutation", "memberSalutation")
|
||||
// .addSelect("member.firstname", "memberFirstname")
|
||||
// .addSelect("member.lastname", "memberLastname")
|
||||
// .addSelect("member.nameaffix", "memberNameaffix")
|
||||
// .addSelect("member.birthdate", "memberBirthdate")
|
||||
// .addSelect(
|
||||
// "SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))",
|
||||
// "durationInDays"
|
||||
// )
|
||||
// .leftJoin("memberQualifications.qualification", "qualification")
|
||||
// .leftJoin("memberQualifications.member", "member")
|
||||
// .groupBy("qualification.id"),
|
||||
// }),
|
||||
// true
|
||||
// );
|
||||
// await queryRunner.createView(
|
||||
// new View({
|
||||
// name: "membership_view",
|
||||
// expression: (datasource: DataSource) =>
|
||||
// datasource
|
||||
// .getRepository(membership)
|
||||
// .createQueryBuilder("membership")
|
||||
// .select("status.id", "statusId")
|
||||
// .addSelect("status.status", "status")
|
||||
// .addSelect("member.id", "memberId")
|
||||
// .addSelect("member.salutation", "memberSalutation")
|
||||
// .addSelect("member.firstname", "memberFirstname")
|
||||
// .addSelect("member.lastname", "memberLastname")
|
||||
// .addSelect("member.nameaffix", "memberNameaffix")
|
||||
// .addSelect("member.birthdate", "memberBirthdate")
|
||||
// .addSelect(
|
||||
// "SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||
// "durationInDays"
|
||||
// )
|
||||
// .leftJoin("membership.status", "status")
|
||||
// .leftJoin("membership.member", "member")
|
||||
// .groupBy("status.id"),
|
||||
// }),
|
||||
// true
|
||||
// );
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(member)
|
||||
.createQueryBuilder("member")
|
||||
.select("member.id", "id")
|
||||
.addSelect("member.salutation", "salutation")
|
||||
.addSelect("member.firstname", "firstname")
|
||||
.addSelect("member.lastname", "lastname")
|
||||
.addSelect("member.nameaffix", "nameaffix")
|
||||
.addSelect("member.birthdate", "birthdate")
|
||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_executive_positions_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(memberExecutivePositions)
|
||||
.createQueryBuilder("memberExecutivePositions")
|
||||
.select("executivePosition.id", "positionId")
|
||||
.addSelect("executivePosition.position", "position")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.leftJoin("memberExecutivePositions.executivePosition", "executivePosition")
|
||||
.leftJoin("memberExecutivePositions.member", "member")
|
||||
.groupBy("executivePosition.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_qualifications_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(memberQualifications)
|
||||
.createQueryBuilder("memberQualifications")
|
||||
.select("qualification.id", "qualificationId")
|
||||
.addSelect("qualification.qualification", "qualification")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.leftJoin("memberQualifications.qualification", "qualification")
|
||||
.leftJoin("memberQualifications.member", "member")
|
||||
.groupBy("qualification.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "membership_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(membership)
|
||||
.createQueryBuilder("membership")
|
||||
.select("status.id", "statusId")
|
||||
.addSelect("status.status", "status")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.leftJoin("membership.status", "status")
|
||||
.leftJoin("membership.member", "member")
|
||||
.groupBy("status.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
// await queryRunner.dropView("membership_view");
|
||||
// await queryRunner.dropView("member_qualifications_view");
|
||||
// await queryRunner.dropView("member_executive_positions_view");
|
||||
// await queryRunner.dropView("member_view");
|
||||
await queryRunner.dropView("membership_view");
|
||||
await queryRunner.dropView("member_qualifications_view");
|
||||
await queryRunner.dropView("member_executive_positions_view");
|
||||
await queryRunner.dropView("member_view");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,104 +8,106 @@ export class ExtendViewValues1736084198860 implements MigrationInterface {
|
|||
name = "ExtendViewValues1736084198860";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// await queryRunner.dropView("membership_view");
|
||||
// await queryRunner.dropView("member_view");
|
||||
// await queryRunner.createView(
|
||||
// new View({
|
||||
// name: "member_view",
|
||||
// expression: (datasource: DataSource) =>
|
||||
// datasource
|
||||
// .getRepository(member)
|
||||
// .createQueryBuilder("member")
|
||||
// .select("member.id", "id")
|
||||
// .addSelect("member.salutation", "salutation")
|
||||
// .addSelect("member.firstname", "firstname")
|
||||
// .addSelect("member.lastname", "lastname")
|
||||
// .addSelect("member.nameaffix", "nameaffix")
|
||||
// .addSelect("member.birthdate", "birthdate")
|
||||
// .addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||
// .addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
||||
// .addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge"),
|
||||
// }),
|
||||
// true
|
||||
// );
|
||||
// await queryRunner.createView(
|
||||
// new View({
|
||||
// name: "membership_view",
|
||||
// expression: (datasource: DataSource) =>
|
||||
// datasource
|
||||
// .getRepository(membership)
|
||||
// .createQueryBuilder("membership")
|
||||
// .select("status.id", "statusId")
|
||||
// .addSelect("status.status", "status")
|
||||
// .addSelect("member.id", "memberId")
|
||||
// .addSelect("member.salutation", "memberSalutation")
|
||||
// .addSelect("member.firstname", "memberFirstname")
|
||||
// .addSelect("member.lastname", "memberLastname")
|
||||
// .addSelect("member.nameaffix", "memberNameaffix")
|
||||
// .addSelect("member.birthdate", "memberBirthdate")
|
||||
// .addSelect(
|
||||
// "SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||
// "durationInDays"
|
||||
// )
|
||||
// .addSelect(
|
||||
// "CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
||||
// "durationInYears"
|
||||
// )
|
||||
// .leftJoin("membership.status", "status")
|
||||
// .leftJoin("membership.member", "member")
|
||||
// .groupBy("status.id")
|
||||
// .addGroupBy("member.id"),
|
||||
// }),
|
||||
// true
|
||||
// );
|
||||
await queryRunner.dropView("membership_view");
|
||||
await queryRunner.dropView("member_view");
|
||||
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(member)
|
||||
.createQueryBuilder("member")
|
||||
.select("member.id", "id")
|
||||
.addSelect("member.salutation", "salutation")
|
||||
.addSelect("member.firstname", "firstname")
|
||||
.addSelect("member.lastname", "lastname")
|
||||
.addSelect("member.nameaffix", "nameaffix")
|
||||
.addSelect("member.birthdate", "birthdate")
|
||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
||||
.addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "membership_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(membership)
|
||||
.createQueryBuilder("membership")
|
||||
.select("status.id", "statusId")
|
||||
.addSelect("status.status", "status")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.addSelect(
|
||||
"CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
||||
"durationInYears"
|
||||
)
|
||||
.leftJoin("membership.status", "status")
|
||||
.leftJoin("membership.member", "member")
|
||||
.groupBy("status.id")
|
||||
.addGroupBy("member.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
// await queryRunner.dropView("membership_view");
|
||||
// await queryRunner.dropView("member_view");
|
||||
// await queryRunner.createView(
|
||||
// new View({
|
||||
// name: "member_view",
|
||||
// expression: (datasource: DataSource) =>
|
||||
// datasource
|
||||
// .getRepository(member)
|
||||
// .createQueryBuilder("member")
|
||||
// .select("member.id", "id")
|
||||
// .addSelect("member.salutation", "salutation")
|
||||
// .addSelect("member.firstname", "firstname")
|
||||
// .addSelect("member.lastname", "lastname")
|
||||
// .addSelect("member.nameaffix", "nameaffix")
|
||||
// .addSelect("member.birthdate", "birthdate")
|
||||
// .addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||
// .addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear"),
|
||||
// }),
|
||||
// true
|
||||
// );
|
||||
// await queryRunner.createView(
|
||||
// new View({
|
||||
// name: "membership_view",
|
||||
// expression: (datasource: DataSource) =>
|
||||
// datasource
|
||||
// .getRepository(membership)
|
||||
// .createQueryBuilder("membership")
|
||||
// .select("status.id", "statusId")
|
||||
// .addSelect("status.status", "status")
|
||||
// .addSelect("member.id", "memberId")
|
||||
// .addSelect("member.salutation", "memberSalutation")
|
||||
// .addSelect("member.firstname", "memberFirstname")
|
||||
// .addSelect("member.lastname", "memberLastname")
|
||||
// .addSelect("member.nameaffix", "memberNameaffix")
|
||||
// .addSelect("member.birthdate", "memberBirthdate")
|
||||
// .addSelect(
|
||||
// "SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||
// "durationInDays"
|
||||
// )
|
||||
// .leftJoin("membership.status", "status")
|
||||
// .leftJoin("membership.member", "member")
|
||||
// .groupBy("status.id"),
|
||||
// }),
|
||||
// true
|
||||
// );
|
||||
await queryRunner.dropView("membership_view");
|
||||
await queryRunner.dropView("member_view");
|
||||
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(member)
|
||||
.createQueryBuilder("member")
|
||||
.select("member.id", "id")
|
||||
.addSelect("member.salutation", "salutation")
|
||||
.addSelect("member.firstname", "firstname")
|
||||
.addSelect("member.lastname", "lastname")
|
||||
.addSelect("member.nameaffix", "nameaffix")
|
||||
.addSelect("member.birthdate", "birthdate")
|
||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "membership_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(membership)
|
||||
.createQueryBuilder("membership")
|
||||
.select("status.id", "statusId")
|
||||
.addSelect("status.status", "status")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.leftJoin("membership.status", "status")
|
||||
.leftJoin("membership.member", "member")
|
||||
.groupBy("status.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
import { MigrationInterface, QueryRunner, Table, TableForeignKey } from "typeorm";
|
||||
import { DB_TYPE } from "../env.defaults";
|
||||
|
||||
export class AddWebapiTokens1737453096674 implements MigrationInterface {
|
||||
name = "AddWebApiTokens1737453096674";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
const variableType_int = DB_TYPE == "mysql" ? "int" : "integer";
|
||||
|
||||
await queryRunner.createTable(
|
||||
new Table({
|
||||
name: "webapi",
|
||||
columns: [
|
||||
{ name: "id", type: variableType_int, isPrimary: true, isGenerated: true, generationStrategy: "increment" },
|
||||
{ name: "token", type: "text", isUnique: true, isNullable: false },
|
||||
{ name: "title", type: "varchar", isUnique: true, length: "255", isNullable: false },
|
||||
{ name: "createdAt", type: "datetime", default: "CURRENT_TIMESTAMP(6)", isNullable: false },
|
||||
{ name: "lastUsage", type: "datetime", isNullable: true, default: null },
|
||||
{ name: "expiry", type: "date", isNullable: true, default: null },
|
||||
],
|
||||
}),
|
||||
true
|
||||
);
|
||||
|
||||
await queryRunner.createTable(
|
||||
new Table({
|
||||
name: "webapi_permission",
|
||||
columns: [
|
||||
{ name: "webapiId", type: variableType_int, isPrimary: true, isNullable: false },
|
||||
{ name: "permission", type: "varchar", length: "255", isPrimary: true, isNullable: false },
|
||||
],
|
||||
}),
|
||||
true
|
||||
);
|
||||
|
||||
await queryRunner.createForeignKey(
|
||||
"webapi_permission",
|
||||
new TableForeignKey({
|
||||
columnNames: ["webapiId"],
|
||||
referencedColumnNames: ["id"],
|
||||
referencedTableName: "webapi",
|
||||
onDelete: "CASCADE",
|
||||
onUpdate: "RESTRICT",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
const table = await queryRunner.getTable("webapi_permission");
|
||||
const foreignKey = table.foreignKeys.find((fk) => fk.columnNames.indexOf("webapiId") !== -1);
|
||||
await queryRunner.dropForeignKey("webapi_permission", foreignKey);
|
||||
await queryRunner.dropTable("webapi_permission");
|
||||
await queryRunner.dropTable("webapi");
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
import { MigrationInterface, QueryRunner, Table, TableForeignKey } from "typeorm";
|
||||
import { DB_TYPE } from "../env.defaults";
|
||||
import { member } from "../entity/club/member/member";
|
||||
import { salutation } from "../entity/settings/salutation";
|
||||
|
||||
export class SalutationAsTable1737796878058 implements MigrationInterface {
|
||||
name = "SalutationAsTable1737796878058";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
const variableType_int = DB_TYPE == "mysql" ? "int" : "integer";
|
||||
|
||||
await queryRunner.createTable(
|
||||
new Table({
|
||||
name: "salutation",
|
||||
columns: [
|
||||
{ name: "id", type: variableType_int, isPrimary: true, isGenerated: true, generationStrategy: "increment" },
|
||||
{ name: "salutation", type: "varchar", length: "255", isUnique: true, isNullable: false },
|
||||
],
|
||||
}),
|
||||
true
|
||||
);
|
||||
|
||||
// ! has to be sql. Else the column would be dropped and created - resulting in data loss.
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE \`member\` CHANGE \`salutation\` \`salutationId\` varchar(255) NOT NULL DEFAULT ''`
|
||||
);
|
||||
|
||||
// ! has to be sql. Else no data is returned.
|
||||
const existing_salutations = await queryRunner.query(
|
||||
"SELECT DISTINCT salutationId FROM `member` `member` GROUP BY salutationId"
|
||||
);
|
||||
|
||||
for (let s of existing_salutations.map((s: any) => s.salutationId) as Array<string>) {
|
||||
await queryRunner.manager.getRepository(salutation).save({ salutation: s });
|
||||
}
|
||||
|
||||
const salutations = await queryRunner.manager.getRepository(salutation).find();
|
||||
|
||||
for (let salutation of salutations) {
|
||||
await queryRunner.manager
|
||||
.getRepository(member)
|
||||
.createQueryBuilder("member")
|
||||
.update({ salutationId: salutation.id })
|
||||
.where({ salutationId: salutation.salutation })
|
||||
.execute();
|
||||
}
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE \`member\` CHANGE \`salutationId\` \`salutationId\` ${variableType_int} NOT NULL`
|
||||
);
|
||||
|
||||
await queryRunner.createForeignKey(
|
||||
"member",
|
||||
new TableForeignKey({
|
||||
columnNames: ["salutationId"],
|
||||
referencedColumnNames: ["id"],
|
||||
referencedTableName: "salutation",
|
||||
onDelete: "RESTRICT",
|
||||
onUpdate: "RESTRICT",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
const table = await queryRunner.getTable("member");
|
||||
const foreignKey = table.foreignKeys.find((fk) => fk.columnNames.indexOf("salutationId") !== -1);
|
||||
await queryRunner.dropForeignKey("member", foreignKey);
|
||||
|
||||
// ! has to be sql. Else the column would be dropped and created - resulting in data loss.
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE \`member\` CHANGE \`salutationId\` \`salutationId\` varchar(255) NOT NULL DEFAULT ''`
|
||||
);
|
||||
|
||||
const salutations = await queryRunner.manager.getRepository(salutation).find();
|
||||
|
||||
for (let salutation of salutations) {
|
||||
await queryRunner.manager
|
||||
.getRepository(member)
|
||||
.createQueryBuilder("member")
|
||||
.update({ salutationId: salutation.salutation as unknown as number })
|
||||
.where({ salutationId: salutation.id })
|
||||
.execute();
|
||||
}
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE \`member\` CHANGE \`salutationId\` \`salutation\` varchar(255) NOT NULL DEFAULT 'none'`
|
||||
);
|
||||
|
||||
await queryRunner.dropTable("webapi");
|
||||
}
|
||||
}
|
|
@ -1,233 +0,0 @@
|
|||
import { DataSource, MigrationInterface, QueryRunner, View } from "typeorm";
|
||||
import { member } from "../entity/club/member/member";
|
||||
import { memberExecutivePositions } from "../entity/club/member/memberExecutivePositions";
|
||||
import { memberQualifications } from "../entity/club/member/memberQualifications";
|
||||
import { membership } from "../entity/club/member/membership";
|
||||
|
||||
export class UpdateViews1737800468938 implements MigrationInterface {
|
||||
name = "UpdateViews1737800468938";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// await queryRunner.dropView("membership_view");
|
||||
// await queryRunner.dropView("member_executive_positions_view");
|
||||
// await queryRunner.dropView("member_qualifications_view");
|
||||
// await queryRunner.dropView("member_view");
|
||||
await queryRunner.query(`DROP VIEW IF EXISTS membership_view`);
|
||||
await queryRunner.query(`DROP VIEW IF EXISTS member_executive_positions_view`);
|
||||
await queryRunner.query(`DROP VIEW IF EXISTS member_qualifications_view`);
|
||||
await queryRunner.query(`DROP VIEW IF EXISTS member_view`);
|
||||
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(member)
|
||||
.createQueryBuilder("member")
|
||||
.select("member.id", "id")
|
||||
.addSelect("member.firstname", "firstname")
|
||||
.addSelect("member.lastname", "lastname")
|
||||
.addSelect("member.nameaffix", "nameaffix")
|
||||
.addSelect("member.birthdate", "birthdate")
|
||||
.addSelect("salutation.salutation", "salutation")
|
||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
||||
.addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge")
|
||||
.leftJoin("member.salutation", "salutation"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_executive_positions_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(memberExecutivePositions)
|
||||
.createQueryBuilder("memberExecutivePositions")
|
||||
.select("executivePosition.id", "positionId")
|
||||
.addSelect("executivePosition.position", "position")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect("salutation.salutation", "memberSalutation")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.leftJoin("memberExecutivePositions.executivePosition", "executivePosition")
|
||||
.leftJoin("memberExecutivePositions.member", "member")
|
||||
.leftJoin("member.salutation", "salutation")
|
||||
.groupBy("executivePosition.id")
|
||||
.addGroupBy("member.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_qualifications_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(memberQualifications)
|
||||
.createQueryBuilder("memberQualifications")
|
||||
.select("qualification.id", "qualificationId")
|
||||
.addSelect("qualification.qualification", "qualification")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect("salutation.salutation", "memberSalutation")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.leftJoin("memberQualifications.qualification", "qualification")
|
||||
.leftJoin("memberQualifications.member", "member")
|
||||
.leftJoin("member.salutation", "salutation")
|
||||
.groupBy("qualification.id")
|
||||
.addGroupBy("member.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "membership_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(membership)
|
||||
.createQueryBuilder("membership")
|
||||
.select("status.id", "statusId")
|
||||
.addSelect("status.status", "status")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect("salutation.salutation", "memberSalutation")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.addSelect(
|
||||
"CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
||||
"durationInYears"
|
||||
)
|
||||
.leftJoin("membership.status", "status")
|
||||
.leftJoin("membership.member", "member")
|
||||
.leftJoin("member.salutation", "salutation")
|
||||
.groupBy("status.id")
|
||||
.addGroupBy("member.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropView("membership_view");
|
||||
await queryRunner.dropView("member_executive_positions_view");
|
||||
await queryRunner.dropView("member_qualifications_view");
|
||||
await queryRunner.dropView("member_view");
|
||||
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(member)
|
||||
.createQueryBuilder("member")
|
||||
.select("member.id", "id")
|
||||
.addSelect("member.salutation", "salutation")
|
||||
.addSelect("member.firstname", "firstname")
|
||||
.addSelect("member.lastname", "lastname")
|
||||
.addSelect("member.nameaffix", "nameaffix")
|
||||
.addSelect("member.birthdate", "birthdate")
|
||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
||||
.addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_executive_positions_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(memberExecutivePositions)
|
||||
.createQueryBuilder("memberExecutivePositions")
|
||||
.select("executivePosition.id", "positionId")
|
||||
.addSelect("executivePosition.position", "position")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.leftJoin("memberExecutivePositions.executivePosition", "executivePosition")
|
||||
.leftJoin("memberExecutivePositions.member", "member")
|
||||
.groupBy("executivePosition.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_qualifications_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(memberQualifications)
|
||||
.createQueryBuilder("memberQualifications")
|
||||
.select("qualification.id", "qualificationId")
|
||||
.addSelect("qualification.qualification", "qualification")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.leftJoin("memberQualifications.qualification", "qualification")
|
||||
.leftJoin("memberQualifications.member", "member")
|
||||
.groupBy("qualification.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "membership_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(membership)
|
||||
.createQueryBuilder("membership")
|
||||
.select("status.id", "statusId")
|
||||
.addSelect("status.status", "status")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.addSelect(
|
||||
"CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
||||
"durationInYears"
|
||||
)
|
||||
.leftJoin("membership.status", "status")
|
||||
.leftJoin("membership.member", "member")
|
||||
.groupBy("status.id")
|
||||
.addGroupBy("member.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
import { MigrationInterface, QueryRunner, TableColumn, TableForeignKey, TableIndex } from "typeorm";
|
||||
import { communication } from "../entity/club/member/communication";
|
||||
import { member } from "../entity/club/member/member";
|
||||
|
||||
export class MoveSendNewsletterFlag1737816852011 implements MigrationInterface {
|
||||
name = "MoveSendNewsletterFlag1737816852011";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
const table = await queryRunner.getTable("member");
|
||||
const foreignKey = table.foreignKeys.find((fk) => fk.columnNames.indexOf("sendNewsletterId") !== -1);
|
||||
await queryRunner.dropForeignKey("member", foreignKey);
|
||||
|
||||
await queryRunner.addColumn(
|
||||
"communication",
|
||||
new TableColumn({ name: "isSendNewsletter", type: "tinyint", isNullable: false, default: 0 })
|
||||
);
|
||||
|
||||
// ! has to be sql. Else no data is returned.
|
||||
const member_newsletter_send = await queryRunner.query("SELECT sendNewsletterId, id FROM `member` `member`");
|
||||
|
||||
for (let assigned of member_newsletter_send.map((mns: any) => ({
|
||||
id: mns.id,
|
||||
sendNewsletterId: mns.sendNewsletterId,
|
||||
})) as Array<{ id: number; sendNewsletterId: number }>) {
|
||||
await queryRunner.manager
|
||||
.getRepository(communication)
|
||||
.createQueryBuilder("communication")
|
||||
.update({ isSendNewsletter: true })
|
||||
.where({ memberId: assigned.id, id: assigned.sendNewsletterId })
|
||||
.execute();
|
||||
}
|
||||
|
||||
await queryRunner.dropColumn("member", "sendNewsletterId");
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.addColumn(
|
||||
"member",
|
||||
new TableColumn({ name: "sendNewsletterId", type: "int", isNullable: true, isUnique: true, default: null })
|
||||
);
|
||||
|
||||
const member_newsletter_send = await queryRunner.manager
|
||||
.getRepository(communication)
|
||||
.createQueryBuilder("communication")
|
||||
.where("communication.isSendNewsletter = :isSendNewsletter", { isSendNewsletter: true })
|
||||
.getMany();
|
||||
|
||||
for (let assigned of member_newsletter_send.map((mns: any) => ({
|
||||
id: mns.id,
|
||||
memberId: mns.memberId,
|
||||
})) as Array<{ id: number; memberId: number }>) {
|
||||
await queryRunner.query("UPDATE `member` SET sendNewsletterId = ? WHERE id = ?", [
|
||||
assigned.id,
|
||||
assigned.memberId,
|
||||
]);
|
||||
}
|
||||
|
||||
await queryRunner.createForeignKey(
|
||||
"member",
|
||||
new TableForeignKey({
|
||||
columnNames: ["sendNewsletterId"],
|
||||
referencedColumnNames: ["id"],
|
||||
referencedTableName: "communication",
|
||||
onDelete: "SET NULL",
|
||||
onUpdate: "RESTRICT",
|
||||
})
|
||||
);
|
||||
|
||||
await queryRunner.dropColumn("communication", "isSendNewsletter");
|
||||
}
|
||||
}
|
|
@ -1,38 +1,36 @@
|
|||
import express, { Request, Response } from "express";
|
||||
import {
|
||||
addAwardToMember,
|
||||
addCommunicationToMember,
|
||||
addExecutivePositionToMember,
|
||||
addMembershipToMember,
|
||||
addQualificationToMember,
|
||||
createMember,
|
||||
createMemberPrintoutList,
|
||||
deleteAwardOfMember,
|
||||
deleteCommunicationOfMember,
|
||||
deleteExecutivePositionOfMember,
|
||||
deleteMemberById,
|
||||
deleteMembershipOfMember,
|
||||
deleteQualificationOfMember,
|
||||
getAllMembers,
|
||||
getAwardByMemberAndRecord,
|
||||
getAwardsByMember,
|
||||
getCommunicationByMemberAndRecord,
|
||||
getCommunicationsByMember,
|
||||
getExecutivePositionByMemberAndRecord,
|
||||
getExecutivePositionsByMember,
|
||||
getMemberById,
|
||||
getMembershipByMemberAndRecord,
|
||||
getMembershipsByMember,
|
||||
getMembershipStatisticsById,
|
||||
getMemberStatisticsById,
|
||||
getQualificationByMemberAndRecord,
|
||||
getQualificationsByMember,
|
||||
updateAwardOfMember,
|
||||
updateCommunicationOfMember,
|
||||
updateExecutivePositionOfMember,
|
||||
updateMemberById,
|
||||
updateMembershipOfMember,
|
||||
updateQualificationOfMember,
|
||||
addAwardToMember,
|
||||
addCommunicationToMember,
|
||||
addExecutivePositionToMember,
|
||||
addMembershipToMember,
|
||||
addQualificationToMember,
|
||||
createMember,
|
||||
createMemberPrintoutList,
|
||||
deleteAwardOfMember,
|
||||
deleteCommunicationOfMember,
|
||||
deleteExecutivePositionOfMember,
|
||||
deleteMemberById,
|
||||
deleteMembershipOfMember,
|
||||
deleteQualificationOfMember,
|
||||
getAllMembers,
|
||||
getAwardByMemberAndRecord,
|
||||
getAwardsByMember,
|
||||
getCommunicationByMemberAndRecord,
|
||||
getCommunicationsByMember,
|
||||
getExecutivePositionByMemberAndRecord,
|
||||
getExecutivePositionsByMember,
|
||||
getMemberById,
|
||||
getMembershipByMemberAndRecord,
|
||||
getMembershipsByMember,
|
||||
getQualificationByMemberAndRecord,
|
||||
getQualificationsByMember,
|
||||
updateAwardOfMember,
|
||||
updateCommunicationOfMember,
|
||||
updateExecutivePositionOfMember,
|
||||
updateMemberById,
|
||||
updateMembershipOfMember,
|
||||
updateQualificationOfMember,
|
||||
} from "../../../controller/admin/club/memberController";
|
||||
import PermissionHelper from "../../../helpers/permissionHelper";
|
||||
|
||||
|
@ -46,22 +44,14 @@ router.get("/:id", async (req: Request, res: Response) => {
|
|||
await getMemberById(req, res);
|
||||
});
|
||||
|
||||
router.get("/:id/statistics", async (req: Request, res: Response) => {
|
||||
await getMemberStatisticsById(req, res);
|
||||
});
|
||||
|
||||
router.get("/print/namelist", async (req: Request, res: Response) => {
|
||||
await createMemberPrintoutList(req, res);
|
||||
await createMemberPrintoutList(req, res);
|
||||
});
|
||||
|
||||
router.get("/:memberId/memberships", async (req: Request, res: Response) => {
|
||||
await getMembershipsByMember(req, res);
|
||||
});
|
||||
|
||||
router.get("/:memberId/memberships/statistics", async (req: Request, res: Response) => {
|
||||
await getMembershipStatisticsById(req, res);
|
||||
});
|
||||
|
||||
router.get("/:memberId/membership/:id", async (req: Request, res: Response) => {
|
||||
await getMembershipByMemberAndRecord(req, res);
|
||||
});
|
||||
|
|
|
@ -6,7 +6,6 @@ import communicationType from "./settings/communicationType";
|
|||
import executivePosition from "./settings/executivePosition";
|
||||
import membershipStatus from "./settings/membershipStatus";
|
||||
import qualification from "./settings/qualification";
|
||||
import salutation from "./settings/salutation";
|
||||
import calendarType from "./settings/calendarType";
|
||||
import queryStore from "./settings/queryStore";
|
||||
import template from "./settings/template";
|
||||
|
@ -22,8 +21,6 @@ import newsletter from "./club/newsletter";
|
|||
import role from "./user/role";
|
||||
import user from "./user/user";
|
||||
import invite from "./user/invite";
|
||||
import api from "./user/webapi";
|
||||
import preventWebapiAccess from "../../middleware/preventWebApiAccess";
|
||||
|
||||
var router = express.Router({ mergeParams: true });
|
||||
|
||||
|
@ -44,7 +41,6 @@ router.use(
|
|||
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("/querystore", PermissionHelper.passCheckMiddleware("read", "settings", "query_store"), queryStore);
|
||||
router.use("/template", PermissionHelper.passCheckMiddleware("read", "settings", "template"), template);
|
||||
|
@ -64,6 +60,5 @@ router.use("/newsletter", PermissionHelper.passCheckMiddleware("read", "club", "
|
|||
router.use("/role", PermissionHelper.passCheckMiddleware("read", "user", "role"), role);
|
||||
router.use("/user", PermissionHelper.passCheckMiddleware("read", "user", "user"), user);
|
||||
router.use("/invite", PermissionHelper.passCheckMiddleware("read", "user", "user"), invite);
|
||||
router.use("/webapi", preventWebapiAccess, PermissionHelper.passCheckMiddleware("read", "user", "webapi"), api);
|
||||
|
||||
export default router;
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
import express, { Request, Response } from "express";
|
||||
import {
|
||||
createSalutation,
|
||||
deleteSalutation,
|
||||
getAllSalutations,
|
||||
getSalutationById,
|
||||
updateSalutation,
|
||||
} from "../../../controller/admin/settings/salutationController";
|
||||
import PermissionHelper from "../../../helpers/permissionHelper";
|
||||
|
||||
var router = express.Router({ mergeParams: true });
|
||||
|
||||
router.get("/", async (req: Request, res: Response) => {
|
||||
await getAllSalutations(req, res);
|
||||
});
|
||||
|
||||
router.get("/:id", async (req: Request, res: Response) => {
|
||||
await getSalutationById(req, res);
|
||||
});
|
||||
|
||||
router.post(
|
||||
"/",
|
||||
PermissionHelper.passCheckMiddleware("create", "settings", "salutation"),
|
||||
async (req: Request, res: Response) => {
|
||||
await createSalutation(req, res);
|
||||
}
|
||||
);
|
||||
|
||||
router.patch(
|
||||
"/:id",
|
||||
PermissionHelper.passCheckMiddleware("update", "settings", "salutation"),
|
||||
async (req: Request, res: Response) => {
|
||||
await updateSalutation(req, res);
|
||||
}
|
||||
);
|
||||
|
||||
router.delete(
|
||||
"/:id",
|
||||
PermissionHelper.passCheckMiddleware("delete", "settings", "salutation"),
|
||||
async (req: Request, res: Response) => {
|
||||
await deleteSalutation(req, res);
|
||||
}
|
||||
);
|
||||
|
||||
export default router;
|
|
@ -1,64 +0,0 @@
|
|||
import express, { Request, Response } from "express";
|
||||
import PermissionHelper from "../../../helpers/permissionHelper";
|
||||
import {
|
||||
createWebapi,
|
||||
deleteWebapi,
|
||||
getAllWebapis,
|
||||
getWebapiById,
|
||||
getWebapiPermissions,
|
||||
getWebapiTokenById,
|
||||
updateWebapi,
|
||||
updateWebapiPermissions,
|
||||
} from "../../../controller/admin/user/webapiController";
|
||||
|
||||
var router = express.Router({ mergeParams: true });
|
||||
|
||||
router.get("/", async (req: Request, res: Response) => {
|
||||
await getAllWebapis(req, res);
|
||||
});
|
||||
|
||||
router.get("/:id", async (req: Request, res: Response) => {
|
||||
await getWebapiById(req, res);
|
||||
});
|
||||
|
||||
router.get("/:id/token", async (req: Request, res: Response) => {
|
||||
await getWebapiTokenById(req, res);
|
||||
});
|
||||
|
||||
router.get("/:id/permissions", async (req: Request, res: Response) => {
|
||||
await getWebapiPermissions(req, res);
|
||||
});
|
||||
|
||||
router.post(
|
||||
"/",
|
||||
PermissionHelper.passCheckMiddleware("create", "user", "webapi"),
|
||||
async (req: Request, res: Response) => {
|
||||
await createWebapi(req, res);
|
||||
}
|
||||
);
|
||||
|
||||
router.patch(
|
||||
"/:id",
|
||||
PermissionHelper.passCheckMiddleware("update", "user", "webapi"),
|
||||
async (req: Request, res: Response) => {
|
||||
await updateWebapi(req, res);
|
||||
}
|
||||
);
|
||||
|
||||
router.patch(
|
||||
"/:id/permissions",
|
||||
PermissionHelper.passCheckMiddleware("admin", "user", "webapi"),
|
||||
async (req: Request, res: Response) => {
|
||||
await updateWebapiPermissions(req, res);
|
||||
}
|
||||
);
|
||||
|
||||
router.delete(
|
||||
"/:id",
|
||||
PermissionHelper.passCheckMiddleware("delete", "user", "webapi"),
|
||||
async (req: Request, res: Response) => {
|
||||
await deleteWebapi(req, res);
|
||||
}
|
||||
);
|
||||
|
||||
export default router;
|
|
@ -14,11 +14,6 @@ import auth from "./auth";
|
|||
import admin from "./admin/index";
|
||||
import user from "./user";
|
||||
import detectPWA from "../middleware/detectPWA";
|
||||
import webapi from "./webapi";
|
||||
import authenticateAPI from "../middleware/authenticateAPI";
|
||||
import server from "./server";
|
||||
import PermissionHelper from "../helpers/permissionHelper";
|
||||
import preventWebapiAccess from "../middleware/preventWebApiAccess";
|
||||
|
||||
export default (app: Express) => {
|
||||
app.set("query parser", "extended");
|
||||
|
@ -33,14 +28,12 @@ export default (app: Express) => {
|
|||
|
||||
app.use(detectPWA);
|
||||
app.use("/api/public", publicAvailable);
|
||||
app.use("/api/setup", preventWebapiAccess, allowSetup, setup);
|
||||
app.use("/api/reset", preventWebapiAccess, reset);
|
||||
app.use("/api/invite", preventWebapiAccess, invite);
|
||||
app.use("/api/auth", preventWebapiAccess, auth);
|
||||
app.use("/api/webapi", authenticateAPI, webapi);
|
||||
app.use("/api/setup", allowSetup, setup);
|
||||
app.use("/api/reset", reset);
|
||||
app.use("/api/invite", invite);
|
||||
app.use("/api/auth", auth);
|
||||
app.use(authenticate);
|
||||
app.use("/api/admin", admin);
|
||||
app.use("/api/user", preventWebapiAccess, user);
|
||||
app.use("/api/server", preventWebapiAccess, PermissionHelper.isAdminMiddleware(), server);
|
||||
app.use("/api/user", user);
|
||||
app.use(errorHandler);
|
||||
};
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
import express, { Request, Response } from "express";
|
||||
import { FileSystemHelper } from "../helpers/fileSystemHelper";
|
||||
import Parser from "rss-parser";
|
||||
|
||||
var router = express.Router({ mergeParams: true });
|
||||
|
||||
router.get("/version", async (req: Request, res: Response) => {
|
||||
let serverPackage = FileSystemHelper.readTemplateFile("/package.json");
|
||||
let serverJson = JSON.parse(serverPackage);
|
||||
res.send({
|
||||
name: serverJson.name,
|
||||
description: serverJson.description,
|
||||
version: serverJson.version,
|
||||
author: serverJson.author,
|
||||
license: serverJson.license,
|
||||
});
|
||||
});
|
||||
|
||||
router.get("/settings", async (req: Request, res: Response) => {
|
||||
res.json({});
|
||||
});
|
||||
|
||||
router.get("/serverrss", async (req: Request, res: Response) => {
|
||||
const parser = new Parser();
|
||||
let feed = await parser.parseURL("https://forgejo.jk-effects.cloud/Ehrenamt/ff-admin-server/releases.rss");
|
||||
res.json(feed);
|
||||
});
|
||||
|
||||
router.get("/clientrss", async (req: Request, res: Response) => {
|
||||
const parser = new Parser();
|
||||
let feed = await parser.parseURL("https://forgejo.jk-effects.cloud/Ehrenamt/ff-admin/releases.rss");
|
||||
res.json(feed);
|
||||
});
|
||||
|
||||
export default router;
|
|
@ -1,10 +0,0 @@
|
|||
import express, { Request, Response } from "express";
|
||||
import { getWebApiAccess } from "../controller/webapiController";
|
||||
|
||||
var router = express.Router({ mergeParams: true });
|
||||
|
||||
router.get("/retrieve", async (req: Request, res: Response) => {
|
||||
await getWebApiAccess(req, res);
|
||||
});
|
||||
|
||||
export default router;
|
|
@ -14,6 +14,7 @@ export default abstract class CommunicationService {
|
|||
.createQueryBuilder("communication")
|
||||
.leftJoinAndSelect("communication.type", "communicationType")
|
||||
.leftJoinAndSelect("communication.member", "member")
|
||||
.leftJoinAndSelect("member.sendNewsletter", "sendNewsletter")
|
||||
.where("communication.memberId = :memberId", { memberId: memberId })
|
||||
.orderBy("communicationType.type", "ASC")
|
||||
.getMany()
|
||||
|
@ -37,6 +38,7 @@ export default abstract class CommunicationService {
|
|||
.createQueryBuilder("communication")
|
||||
.leftJoinAndSelect("communication.type", "communicationType")
|
||||
.leftJoinAndSelect("communication.member", "member")
|
||||
.leftJoinAndSelect("member.sendNewsletter", "sendNewsletter")
|
||||
.where("communication.memberId = :memberId", { memberId: memberId })
|
||||
.andWhere("communication.id = :recordId", { recordId: recordId })
|
||||
.getOneOrFail()
|
||||
|
|
|
@ -2,26 +2,13 @@ import { dataSource } from "../../../data-source";
|
|||
import { member } from "../../../entity/club/member/member";
|
||||
import { membership } from "../../../entity/club/member/membership";
|
||||
import InternalException from "../../../exceptions/internalException";
|
||||
import { memberView } from "../../../views/memberView";
|
||||
|
||||
export default abstract class MemberService {
|
||||
/**
|
||||
* @description get all members
|
||||
* @returns {Promise<[Array<member>, number]>}
|
||||
*/
|
||||
static async getAll({
|
||||
offset = 0,
|
||||
count = 25,
|
||||
search = "",
|
||||
noLimit = false,
|
||||
ids = [],
|
||||
}: {
|
||||
offset?: number;
|
||||
count?: number;
|
||||
search?: string;
|
||||
noLimit?: boolean;
|
||||
ids?: Array<number>;
|
||||
}): Promise<[Array<member>, number]> {
|
||||
static async getAll(offset: number = 0, count: number = 25, search: string = ""): Promise<[Array<member>, number]> {
|
||||
let query = dataSource
|
||||
.getRepository(member)
|
||||
.createQueryBuilder("member")
|
||||
|
@ -39,6 +26,8 @@ export default abstract class MemberService {
|
|||
)
|
||||
.leftJoinAndSelect("membership_first.status", "status_first")
|
||||
.leftJoinAndSelect("membership_last.status", "status_last")
|
||||
.leftJoinAndSelect("member.sendNewsletter", "sendNewsletter")
|
||||
.leftJoinAndSelect("sendNewsletter.type", "communicationtype")
|
||||
.leftJoinAndMapMany(
|
||||
"member.preferredCommunication",
|
||||
"member.communications",
|
||||
|
@ -46,16 +35,8 @@ export default abstract class MemberService {
|
|||
"preferredCommunication.preferred = 1"
|
||||
)
|
||||
.leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred")
|
||||
.leftJoinAndMapOne(
|
||||
"member.sendNewsletter",
|
||||
"member.communications",
|
||||
"sendNewsletter",
|
||||
"sendNewsletter.isSendNewsletter = 1"
|
||||
)
|
||||
.leftJoinAndSelect("sendNewsletter.type", "communicationtype")
|
||||
.leftJoinAndMapMany("member.smsAlarming", "member.communications", "smsAlarming", "smsAlarming.isSMSAlarming = 1")
|
||||
.leftJoinAndSelect("smsAlarming.type", "communicationtype_smsAlarming")
|
||||
.leftJoinAndSelect("member.salutation", "salutation");
|
||||
.leftJoinAndSelect("smsAlarming.type", "communicationtype_smsAlarming");
|
||||
|
||||
if (search != "") {
|
||||
search.split(" ").forEach((term, index) => {
|
||||
|
@ -73,15 +54,9 @@ export default abstract class MemberService {
|
|||
});
|
||||
}
|
||||
|
||||
if (ids.length != 0) {
|
||||
query = query.where({ id: ids });
|
||||
}
|
||||
|
||||
if (!noLimit) {
|
||||
query = query.offset(offset).limit(count);
|
||||
}
|
||||
|
||||
return await query
|
||||
.offset(offset)
|
||||
.limit(count)
|
||||
.orderBy("member.lastname")
|
||||
.addOrderBy("member.firstname")
|
||||
.addOrderBy("member.nameaffix")
|
||||
|
@ -117,23 +92,18 @@ export default abstract class MemberService {
|
|||
)
|
||||
.leftJoinAndSelect("membership_first.status", "status_first")
|
||||
.leftJoinAndSelect("membership_last.status", "status_last")
|
||||
.leftJoinAndSelect("member.sendNewsletter", "sendNewsletter")
|
||||
.leftJoinAndSelect("sendNewsletter.type", "communicationtype")
|
||||
.leftJoinAndMapMany(
|
||||
"member.preferredCommunication",
|
||||
"member.communications",
|
||||
"preferredCommunication",
|
||||
"preferredCommunication.preferred = 1"
|
||||
)
|
||||
.leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred")
|
||||
.leftJoinAndMapOne(
|
||||
"member.sendNewsletter",
|
||||
"member.communications",
|
||||
"sendNewsletter",
|
||||
"sendNewsletter.isSendNewsletter = 1"
|
||||
)
|
||||
.leftJoinAndSelect("sendNewsletter.type", "communicationtype")
|
||||
|
||||
.leftJoinAndMapMany("member.smsAlarming", "member.communications", "smsAlarming", "smsAlarming.isSMSAlarming = 1")
|
||||
.leftJoinAndSelect("smsAlarming.type", "communicationtype_smsAlarming")
|
||||
.leftJoinAndSelect("member.salutation", "salutation")
|
||||
.leftJoinAndSelect("preferredCommunication.type", "communicationtype_preferred")
|
||||
.where("member.id = :id", { id: id })
|
||||
.getOneOrFail()
|
||||
.then((res) => {
|
||||
|
@ -144,25 +114,6 @@ export default abstract class MemberService {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get member statistics by id
|
||||
* @param {number} id
|
||||
* @returns {Promise<memberView>}
|
||||
*/
|
||||
static async getStatisticsById(id: number): Promise<memberView> {
|
||||
return await dataSource
|
||||
.getRepository(memberView)
|
||||
.createQueryBuilder("memberView")
|
||||
.where("memberView.id = :id", { id: id })
|
||||
.getOneOrFail()
|
||||
.then((res) => {
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("memberView not found by id", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get members where membership is setz
|
||||
* @returns {Promise<member>}
|
||||
|
@ -194,12 +145,7 @@ export default abstract class MemberService {
|
|||
return await dataSource
|
||||
.getRepository(member)
|
||||
.createQueryBuilder("member")
|
||||
.leftJoinAndMapOne(
|
||||
"member.sendNewsletter",
|
||||
"member.communications",
|
||||
"sendNewsletter",
|
||||
"sendNewsletter.isSendNewsletter = 1"
|
||||
)
|
||||
.leftJoinAndSelect("member.sendNewsletter", "sendNewsletter")
|
||||
.where("member.id = :id", { id: id })
|
||||
.getOneOrFail()
|
||||
.then((res) => {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { dataSource } from "../../../data-source";
|
||||
import { membership } from "../../../entity/club/member/membership";
|
||||
import InternalException from "../../../exceptions/internalException";
|
||||
import { membershipView } from "../../../views/membershipsView";
|
||||
|
||||
export default abstract class MembershipService {
|
||||
/**
|
||||
|
@ -46,23 +45,4 @@ export default abstract class MembershipService {
|
|||
throw new InternalException("member membership not found by id", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get membership statistics by memberId
|
||||
* @param {number} memberId
|
||||
* @returns {Promise<Array<membershipView>>}
|
||||
*/
|
||||
static async getStatisticsById(memberId: number): Promise<Array<membershipView>> {
|
||||
return await dataSource
|
||||
.getRepository(membershipView)
|
||||
.createQueryBuilder("membershipView")
|
||||
.where("membershipView.memberId = :memberId", { memberId: memberId })
|
||||
.getMany()
|
||||
.then((res) => {
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("membershipView not found by id", err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
import { dataSource } from "../../data-source";
|
||||
import { salutation } from "../../entity/settings/salutation";
|
||||
import InternalException from "../../exceptions/internalException";
|
||||
|
||||
export default abstract class SalutationService {
|
||||
/**
|
||||
* @description get all salutations
|
||||
* @returns {Promise<Array<salutation>>}
|
||||
*/
|
||||
static async getAll(): Promise<Array<salutation>> {
|
||||
return await dataSource
|
||||
.getRepository(salutation)
|
||||
.createQueryBuilder("salutation")
|
||||
.orderBy("salutation", "ASC")
|
||||
.getMany()
|
||||
.then((res) => {
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("salutations not found", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get salutation by id
|
||||
* @returns {Promise<salutation>}
|
||||
*/
|
||||
static async getById(id: number): Promise<salutation> {
|
||||
return await dataSource
|
||||
.getRepository(salutation)
|
||||
.createQueryBuilder("salutation")
|
||||
.where("salutation.id = :id", { id: id })
|
||||
.getOneOrFail()
|
||||
.then((res) => {
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("salutation not found by id", err);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import { dataSource } from "../../data-source";
|
||||
import { webapiPermission } from "../../entity/user/webapi_permission";
|
||||
import InternalException from "../../exceptions/internalException";
|
||||
|
||||
export default abstract class WebapiPermissionService {
|
||||
/**
|
||||
* @description get permission by api
|
||||
* @param webapiId number
|
||||
* @returns {Promise<Array<webapiPermission>>}
|
||||
*/
|
||||
static async getByApi(webapiId: number): Promise<Array<webapiPermission>> {
|
||||
return await dataSource
|
||||
.getRepository(webapiPermission)
|
||||
.createQueryBuilder("webapi_permission")
|
||||
.where("webapi_permission.webapiId = :webapiId", { webapiId: webapiId })
|
||||
.getMany()
|
||||
.then((res) => {
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("webapi permissions not found by api", err);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
import { dataSource } from "../../data-source";
|
||||
import { webapi } from "../../entity/user/webapi";
|
||||
import InternalException from "../../exceptions/internalException";
|
||||
|
||||
export default abstract class WebapiService {
|
||||
/**
|
||||
* @description get apis
|
||||
* @returns {Promise<Array<webapi>>}
|
||||
*/
|
||||
static async getAll(): Promise<Array<webapi>> {
|
||||
return await dataSource
|
||||
.getRepository(webapi)
|
||||
.createQueryBuilder("webapi")
|
||||
.leftJoinAndSelect("webapi.permissions", "permissions")
|
||||
.getMany()
|
||||
.then((res) => {
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("webapis not found", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get api by id
|
||||
* @param id number
|
||||
* @returns {Promise<webapi>}
|
||||
*/
|
||||
static async getById(id: number): Promise<webapi> {
|
||||
return await dataSource
|
||||
.getRepository(webapi)
|
||||
.createQueryBuilder("webapi")
|
||||
.leftJoinAndSelect("webapi.permissions", "permissions")
|
||||
.where("webapi.id = :id", { id: id })
|
||||
.getOneOrFail()
|
||||
.then((res) => {
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("webapi not found by id", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get api by token
|
||||
* @param token string
|
||||
* @returns {Promise<webapi>}
|
||||
*/
|
||||
static async getByToken(token: string): Promise<webapi> {
|
||||
return await dataSource
|
||||
.getRepository(webapi)
|
||||
.createQueryBuilder("webapi")
|
||||
.leftJoinAndSelect("webapi.permissions", "permissions")
|
||||
.where("webapi.token = :token", { token: token })
|
||||
.getOneOrFail()
|
||||
.then((res) => {
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("webapi not found by token", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get api by id
|
||||
* @param id number
|
||||
* @returns {Promise<webapi>}
|
||||
*/
|
||||
static async getTokenById(id: number): Promise<webapi> {
|
||||
return await dataSource
|
||||
.getRepository(webapi)
|
||||
.createQueryBuilder("webapi")
|
||||
.select("webapi.token")
|
||||
.where("webapi.id = :id", { id: id })
|
||||
.getOneOrFail()
|
||||
.then((res) => {
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("webapi token not found by id", err);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -11,11 +11,9 @@ export type PermissionModule =
|
|||
| "executive_position"
|
||||
| "communication_type"
|
||||
| "membership_status"
|
||||
| "salutation"
|
||||
| "calendar_type"
|
||||
| "user"
|
||||
| "role"
|
||||
| "webapi"
|
||||
| "query"
|
||||
| "query_store"
|
||||
| "template"
|
||||
|
@ -54,11 +52,9 @@ export const permissionModules: Array<PermissionModule> = [
|
|||
"executive_position",
|
||||
"communication_type",
|
||||
"membership_status",
|
||||
"salutation",
|
||||
"calendar_type",
|
||||
"user",
|
||||
"role",
|
||||
"webapi",
|
||||
"query",
|
||||
"query_store",
|
||||
"template",
|
||||
|
@ -73,12 +69,11 @@ export const sectionsAndModules: SectionsAndModulesObject = {
|
|||
"executive_position",
|
||||
"communication_type",
|
||||
"membership_status",
|
||||
"salutation",
|
||||
"calendar_type",
|
||||
"query_store",
|
||||
"template",
|
||||
"template_usage",
|
||||
"newsletter_config",
|
||||
],
|
||||
user: ["user", "role", "webapi"],
|
||||
user: ["user", "role"],
|
||||
};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { SalutationViewModel } from "../../settings/salutation.models";
|
||||
import { Salutation } from "../../../../enums/salutation";
|
||||
import { CommunicationViewModel } from "./communication.models";
|
||||
import { MembershipViewModel } from "./membership.models";
|
||||
|
||||
export interface MemberViewModel {
|
||||
id: number;
|
||||
salutation: SalutationViewModel;
|
||||
salutation: Salutation;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
nameaffix: string;
|
||||
|
@ -16,15 +16,3 @@ export interface MemberViewModel {
|
|||
smsAlarming?: Array<CommunicationViewModel>;
|
||||
preferredCommunication?: Array<CommunicationViewModel>;
|
||||
}
|
||||
|
||||
export interface MemberStatisticsViewModel {
|
||||
id: number;
|
||||
salutation: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
nameaffix: string;
|
||||
birthdate: Date;
|
||||
todayAge: number;
|
||||
ageThisYear: number;
|
||||
exactAge: string;
|
||||
}
|
||||
|
|
|
@ -6,16 +6,3 @@ export interface MembershipViewModel {
|
|||
status: string;
|
||||
statusId: number;
|
||||
}
|
||||
|
||||
export interface MembershipStatisticsViewModel {
|
||||
durationInDays: number;
|
||||
durationInYears: string;
|
||||
status: string;
|
||||
statusId: number;
|
||||
memberId: number;
|
||||
memberSalutation: string;
|
||||
memberFirstname: string;
|
||||
memberLastname: string;
|
||||
memberNameaffix: string;
|
||||
memberBirthdate: Date;
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
export interface SalutationViewModel {
|
||||
id: number;
|
||||
salutation: string;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
import { PermissionObject } from "../../../type/permissionTypes";
|
||||
|
||||
export interface ApiViewModel {
|
||||
id: number;
|
||||
permissions: PermissionObject;
|
||||
title: string;
|
||||
createdAt: Date;
|
||||
lastUsage?: Date;
|
||||
expiry?: Date;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import { DataSource, ViewColumn, ViewEntity } from "typeorm";
|
||||
import { memberExecutivePositions } from "../entity/club/member/memberExecutivePositions";
|
||||
import { Salutation } from "../enums/salutation";
|
||||
|
||||
@ViewEntity({
|
||||
expression: (datasource: DataSource) =>
|
||||
|
@ -9,20 +10,18 @@ import { memberExecutivePositions } from "../entity/club/member/memberExecutiveP
|
|||
.select("executivePosition.id", "positionId")
|
||||
.addSelect("executivePosition.position", "position")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect("salutation.salutation", "memberSalutation")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, memberExecutivePositions.start, COALESCE(memberExecutivePositions.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.leftJoin("memberExecutivePositions.executivePosition", "executivePosition")
|
||||
.leftJoin("memberExecutivePositions.member", "member")
|
||||
.leftJoin("member.salutation", "salutation")
|
||||
.groupBy("executivePosition.id")
|
||||
.addGroupBy("member.id"),
|
||||
.groupBy("executivePosition.id"),
|
||||
})
|
||||
export class memberExecutivePositionsView {
|
||||
@ViewColumn()
|
||||
|
@ -38,7 +37,7 @@ export class memberExecutivePositionsView {
|
|||
memberId: number;
|
||||
|
||||
@ViewColumn()
|
||||
memberSalutation: string;
|
||||
memberSalutation: Salutation;
|
||||
|
||||
@ViewColumn()
|
||||
memberFirstname: string;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { DataSource, ViewColumn, ViewEntity } from "typeorm";
|
||||
import { memberQualifications } from "../entity/club/member/memberQualifications";
|
||||
import { Salutation } from "../enums/salutation";
|
||||
|
||||
@ViewEntity({
|
||||
expression: (datasource: DataSource) =>
|
||||
|
@ -9,20 +10,18 @@ import { memberQualifications } from "../entity/club/member/memberQualifications
|
|||
.select("qualification.id", "qualificationId")
|
||||
.addSelect("qualification.qualification", "qualification")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect("salutation.salutation", "memberSalutation")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, memberQualifications.start, COALESCE(memberQualifications.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.leftJoin("memberQualifications.qualification", "qualification")
|
||||
.leftJoin("memberQualifications.member", "member")
|
||||
.leftJoin("member.salutation", "salutation")
|
||||
.groupBy("qualification.id")
|
||||
.addGroupBy("member.id"),
|
||||
.groupBy("qualification.id"),
|
||||
})
|
||||
export class memberQualificationsView {
|
||||
@ViewColumn()
|
||||
|
@ -38,7 +37,7 @@ export class memberQualificationsView {
|
|||
memberId: number;
|
||||
|
||||
@ViewColumn()
|
||||
memberSalutation: string;
|
||||
memberSalutation: Salutation;
|
||||
|
||||
@ViewColumn()
|
||||
memberFirstname: string;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { DataSource, ViewColumn, ViewEntity } from "typeorm";
|
||||
import { member } from "../entity/club/member/member";
|
||||
import { Salutation } from "../enums/salutation";
|
||||
|
||||
@ViewEntity({
|
||||
expression: (datasource: DataSource) =>
|
||||
|
@ -7,22 +8,21 @@ import { member } from "../entity/club/member/member";
|
|||
.getRepository(member)
|
||||
.createQueryBuilder("member")
|
||||
.select("member.id", "id")
|
||||
.addSelect("member.salutation", "salutation")
|
||||
.addSelect("member.firstname", "firstname")
|
||||
.addSelect("member.lastname", "lastname")
|
||||
.addSelect("member.nameaffix", "nameaffix")
|
||||
.addSelect("member.birthdate", "birthdate")
|
||||
.addSelect("salutation.salutation", "salutation")
|
||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
||||
.addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge")
|
||||
.leftJoin("member.salutation", "salutation"),
|
||||
.addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge"),
|
||||
})
|
||||
export class memberView {
|
||||
@ViewColumn()
|
||||
id: number;
|
||||
|
||||
@ViewColumn()
|
||||
salutation: string;
|
||||
salutation: Salutation;
|
||||
|
||||
@ViewColumn()
|
||||
firstname: string;
|
||||
|
@ -43,5 +43,5 @@ export class memberView {
|
|||
ageThisYear: number;
|
||||
|
||||
@ViewColumn()
|
||||
exactAge: string;
|
||||
exactAge: Date;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { DataSource, ViewColumn, ViewEntity } from "typeorm";
|
||||
import { membership } from "../entity/club/member/membership";
|
||||
import { Salutation } from "../enums/salutation";
|
||||
|
||||
@ViewEntity({
|
||||
expression: (datasource: DataSource) =>
|
||||
|
@ -9,11 +10,11 @@ import { membership } from "../entity/club/member/membership";
|
|||
.select("status.id", "statusId")
|
||||
.addSelect("status.status", "status")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect("salutation.salutation", "memberSalutation")
|
||||
.addSelect("SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))", "durationInDays")
|
||||
.addSelect(
|
||||
"CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
||||
|
@ -21,7 +22,6 @@ import { membership } from "../entity/club/member/membership";
|
|||
)
|
||||
.leftJoin("membership.status", "status")
|
||||
.leftJoin("membership.member", "member")
|
||||
.leftJoin("member.salutation", "salutation")
|
||||
.groupBy("status.id")
|
||||
.addGroupBy("member.id"),
|
||||
})
|
||||
|
@ -30,7 +30,7 @@ export class membershipView {
|
|||
durationInDays: number;
|
||||
|
||||
@ViewColumn()
|
||||
durationInYears: string;
|
||||
durationInYears: Date;
|
||||
|
||||
@ViewColumn()
|
||||
status: string;
|
||||
|
@ -42,7 +42,7 @@ export class membershipView {
|
|||
memberId: number;
|
||||
|
||||
@ViewColumn()
|
||||
memberSalutation: string;
|
||||
memberSalutation: Salutation;
|
||||
|
||||
@ViewColumn()
|
||||
memberFirstname: string;
|
||||
|
|
Loading…
Reference in a new issue