From d1cf9f4c6628c3ef5b37f298a0af88e43b605cd6 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 23 Nov 2024 14:25:31 +0100 Subject: [PATCH 1/2] invite base operations --- src/controller/inviteController.ts | 21 ++++++++++++++++- src/routes/admin/index.ts | 2 ++ src/routes/admin/invite.ts | 37 ++++++++++++++++++++++++++++++ src/routes/admin/user.ts | 8 ------- src/routes/index.ts | 2 ++ src/routes/invite.ts | 16 +++++++++++++ 6 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 src/routes/admin/invite.ts create mode 100644 src/routes/invite.ts diff --git a/src/controller/inviteController.ts b/src/controller/inviteController.ts index a6ff7eb..f169110 100644 --- a/src/controller/inviteController.ts +++ b/src/controller/inviteController.ts @@ -19,6 +19,14 @@ import { CLUB_NAME } from "../env.defaults"; import { CreateUserPermissionCommand } from "../command/userPermissionCommand"; import UserPermissionCommandHandler from "../command/userPermissionCommandHandler"; +/** + * @description get all invites + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function getInvites(req: Request, res: Response): Promise {} + /** * @description start first user * @param req {Request} Express req object @@ -78,7 +86,7 @@ export async function verifyInvite(req: Request, res: Response): Promise { let mail = req.body.mail; let token = req.body.token; - let { secret } = await InviteService.getByMailAndToken(mail, token); + let { secret, username } = await InviteService.getByMailAndToken(mail, token); const url = `otpauth://totp/Mitgliederverwaltung ${CLUB_NAME}?secret=${secret}`; @@ -87,6 +95,7 @@ export async function verifyInvite(req: Request, res: Response): Promise { res.json({ dataUrl: result, otp: secret, + username, }); }) .catch((err) => { @@ -146,3 +155,13 @@ export async function finishInvite(req: Request, res: Response, grantAdmin: bool refreshToken, }); } + +/** + * @description delete invites + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function deleteInvites(req: Request, res: Response): Promise { + const id = parseInt(req.params.id); +} diff --git a/src/routes/admin/index.ts b/src/routes/admin/index.ts index cdafa5e..3df08e7 100644 --- a/src/routes/admin/index.ts +++ b/src/routes/admin/index.ts @@ -14,6 +14,7 @@ import calendar from "./calendar"; import role from "./role"; import user from "./user"; +import invite from "./invite"; var router = express.Router({ mergeParams: true }); @@ -42,5 +43,6 @@ router.use("/calendar", PermissionHelper.passCheckMiddleware("read", "club", "ca 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); export default router; diff --git a/src/routes/admin/invite.ts b/src/routes/admin/invite.ts new file mode 100644 index 0000000..f1e5136 --- /dev/null +++ b/src/routes/admin/invite.ts @@ -0,0 +1,37 @@ +import express, { Request, Response } from "express"; +import PermissionHelper from "../../helpers/permissionHelper"; +import { + deleteUser, + getAllUsers, + getUserById, + getUserPermissions, + getUserRoles, + updateUser, + updateUserPermissions, + updateUserRoles, +} from "../../controller/admin/userController"; +import { inviteUser } from "../../controller/inviteController"; + +var router = express.Router({ mergeParams: true }); + +router.get("/", async (req: Request, res: Response) => { + await getAllUsers(req, res); +}); + +router.post( + "/invite", + PermissionHelper.passCheckMiddleware("create", "user", "user"), + async (req: Request, res: Response) => { + await inviteUser(req, res); + } +); + +router.delete( + "/:id", + PermissionHelper.passCheckMiddleware("delete", "user", "user"), + async (req: Request, res: Response) => { + //await deleteUser(req, res); + } +); + +export default router; diff --git a/src/routes/admin/user.ts b/src/routes/admin/user.ts index 7ce7046..8bfd44b 100644 --- a/src/routes/admin/user.ts +++ b/src/routes/admin/user.ts @@ -30,14 +30,6 @@ router.get("/:id/roles", async (req: Request, res: Response) => { await getUserRoles(req, res); }); -router.post( - "/invite", - PermissionHelper.passCheckMiddleware("create", "user", "user"), - async (req: Request, res: Response) => { - await inviteUser(req, res); - } -); - router.patch( "/:id", PermissionHelper.passCheckMiddleware("update", "user", "user"), diff --git a/src/routes/index.ts b/src/routes/index.ts index 5025c17..eee3e7d 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -8,6 +8,7 @@ import errorHandler from "../middleware/errorHandler"; import publicAvailable from "./public"; import setup from "./setup"; +import invite from "./invite"; import reset from "./reset"; import auth from "./auth"; import admin from "./admin/index"; @@ -27,6 +28,7 @@ export default (app: Express) => { app.use("/public", publicAvailable); app.use("/setup", allowSetup, setup); app.use("/reset", reset); + app.use("/invite", invite); app.use("/auth", auth); app.use(authenticate); app.use("/admin", admin); diff --git a/src/routes/invite.ts b/src/routes/invite.ts new file mode 100644 index 0000000..783ecef --- /dev/null +++ b/src/routes/invite.ts @@ -0,0 +1,16 @@ +import express from "express"; +import { isSetup } from "../controller/setupController"; +import { finishInvite, inviteUser, verifyInvite } from "../controller/inviteController"; +import ParamaterPassCheckHelper from "../helpers/parameterPassCheckHelper"; + +var router = express.Router({ mergeParams: true }); + +router.post("/verify", ParamaterPassCheckHelper.requiredIncludedMiddleware(["mail", "token"]), async (req, res) => { + await verifyInvite(req, res); +}); + +router.put("/", ParamaterPassCheckHelper.requiredIncludedMiddleware(["mail", "token", "totp"]), async (req, res) => { + await finishInvite(req, res); +}); + +export default router; From c66c847ec1b7636823ec9b3cb7ee2d8b340da68e Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sun, 24 Nov 2024 12:36:12 +0100 Subject: [PATCH 2/2] invite management --- src/command/inviteCommandHandler.ts | 20 +++++++++++++++++++- src/controller/inviteController.ts | 17 +++++++++++++---- src/factory/admin/invite.ts | 27 +++++++++++++++++++++++++++ src/routes/admin/invite.ts | 20 +++++--------------- src/service/inviteService.ts | 17 +++++++++++++++++ src/viewmodel/admin/invite.models.ts | 6 ++++++ 6 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 src/factory/admin/invite.ts create mode 100644 src/viewmodel/admin/invite.models.ts diff --git a/src/command/inviteCommandHandler.ts b/src/command/inviteCommandHandler.ts index 23a5939..468247b 100644 --- a/src/command/inviteCommandHandler.ts +++ b/src/command/inviteCommandHandler.ts @@ -37,7 +37,7 @@ export default abstract class InviteCommandHandler { /** * @description delete invite by mail and token - * @param DeleteRefreshCommand + * @param DeleteInviteCommand * @returns {Promise} */ static async deleteByTokenAndMail(deleteInvite: DeleteInviteCommand): Promise { @@ -53,4 +53,22 @@ export default abstract class InviteCommandHandler { throw new InternalException("failed invite removal", err); }); } + + /** + * @description delete invite by mail + * @param DeleteByMailInviteCommand + * @returns {Promise} + */ + static async deleteByMail(mail: string): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(invite) + .where("invite.mail = :mail", { mail }) + .execute() + .then((res) => {}) + .catch((err) => { + throw new InternalException("failed invite removal", err); + }); + } } diff --git a/src/controller/inviteController.ts b/src/controller/inviteController.ts index f169110..8fa2f34 100644 --- a/src/controller/inviteController.ts +++ b/src/controller/inviteController.ts @@ -18,6 +18,7 @@ import CustomRequestException from "../exceptions/customRequestException"; import { CLUB_NAME } from "../env.defaults"; import { CreateUserPermissionCommand } from "../command/userPermissionCommand"; import UserPermissionCommandHandler from "../command/userPermissionCommandHandler"; +import InviteFactory from "../factory/admin/invite"; /** * @description get all invites @@ -25,7 +26,11 @@ import UserPermissionCommandHandler from "../command/userPermissionCommandHandle * @param res {Response} Express res object * @returns {Promise<*>} */ -export async function getInvites(req: Request, res: Response): Promise {} +export async function getInvites(req: Request, res: Response): Promise { + let invites = await InviteService.getAll(); + + res.json(InviteFactory.mapToBase(invites)); +} /** * @description start first user @@ -157,11 +162,15 @@ export async function finishInvite(req: Request, res: Response, grantAdmin: bool } /** - * @description delete invites + * @description delete invite by mail * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ -export async function deleteInvites(req: Request, res: Response): Promise { - const id = parseInt(req.params.id); +export async function deleteInvite(req: Request, res: Response): Promise { + const mail = req.params.mail; + + await InviteCommandHandler.deleteByMail(mail); + + res.sendStatus(204); } diff --git a/src/factory/admin/invite.ts b/src/factory/admin/invite.ts new file mode 100644 index 0000000..a1ac7a7 --- /dev/null +++ b/src/factory/admin/invite.ts @@ -0,0 +1,27 @@ +import { invite } from "../../entity/invite"; +import { InviteViewModel } from "../../viewmodel/admin/invite.models"; + +export default abstract class InviteFactory { + /** + * @description map record to invite + * @param {invite} record + * @returns {InviteViewModel} + */ + public static mapToSingle(record: invite): InviteViewModel { + return { + mail: record.mail, + username: record.username, + firstname: record.firstname, + lastname: record.lastname, + }; + } + + /** + * @description map records to invite + * @param {Array} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/routes/admin/invite.ts b/src/routes/admin/invite.ts index f1e5136..0eb5070 100644 --- a/src/routes/admin/invite.ts +++ b/src/routes/admin/invite.ts @@ -1,25 +1,15 @@ import express, { Request, Response } from "express"; import PermissionHelper from "../../helpers/permissionHelper"; -import { - deleteUser, - getAllUsers, - getUserById, - getUserPermissions, - getUserRoles, - updateUser, - updateUserPermissions, - updateUserRoles, -} from "../../controller/admin/userController"; -import { inviteUser } from "../../controller/inviteController"; +import { deleteInvite, getInvites, inviteUser } from "../../controller/inviteController"; var router = express.Router({ mergeParams: true }); router.get("/", async (req: Request, res: Response) => { - await getAllUsers(req, res); + await getInvites(req, res); }); router.post( - "/invite", + "/", PermissionHelper.passCheckMiddleware("create", "user", "user"), async (req: Request, res: Response) => { await inviteUser(req, res); @@ -27,10 +17,10 @@ router.post( ); router.delete( - "/:id", + "/:mail", PermissionHelper.passCheckMiddleware("delete", "user", "user"), async (req: Request, res: Response) => { - //await deleteUser(req, res); + await deleteInvite(req, res); } ); diff --git a/src/service/inviteService.ts b/src/service/inviteService.ts index 8af16ec..f6e6a7c 100644 --- a/src/service/inviteService.ts +++ b/src/service/inviteService.ts @@ -3,6 +3,23 @@ import { invite } from "../entity/invite"; import InternalException from "../exceptions/internalException"; export default abstract class InviteService { + /** + * @description get all invites + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(invite) + .createQueryBuilder("invite") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new InternalException("invites not found", err); + }); + } + /** * @description get invite by id * @param mail string diff --git a/src/viewmodel/admin/invite.models.ts b/src/viewmodel/admin/invite.models.ts new file mode 100644 index 0000000..6f886df --- /dev/null +++ b/src/viewmodel/admin/invite.models.ts @@ -0,0 +1,6 @@ +export interface InviteViewModel { + mail: string; + username: string; + firstname: string; + lastname: string; +}