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 } from "../command/refreshCommand"; import speakeasy from "speakeasy"; import UnauthorizedRequestException from "../exceptions/unauthorizedRequestException"; import QRCode from "qrcode"; import { CreateUserCommand } from "../command/management/user/userCommand"; import UserCommandHandler from "../command/management/user/userCommandHandler"; import { CreateInviteCommand, DeleteInviteCommand } from "../command/management/user/inviteCommand"; import InviteCommandHandler from "../command/management/user/inviteCommandHandler"; import MailHelper from "../helpers/mailHelper"; import InviteService from "../service/management/inviteService"; import UserService from "../service/management/userService"; import CustomRequestException from "../exceptions/customRequestException"; import { CLUB_NAME } from "../env.defaults"; import { CreateUserPermissionCommand } from "../command/management/user/userPermissionCommand"; import UserPermissionCommandHandler from "../command/management/user/userPermissionCommandHandler"; import InviteFactory from "../factory/admin/management/invite"; /** * @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 { let invites = await InviteService.getAll(); res.json(InviteFactory.mapToBase(invites)); } /** * @description start first user * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function inviteUser(req: Request, res: Response, isInvite: boolean = true): Promise { let origin = req.headers.origin; let username = req.body.username; let mail = req.body.mail; let firstname = req.body.firstname; let lastname = req.body.lastname; let users = await UserService.getByMailOrUsername(mail, username); if (users.length == 1) { // username or mail is used if (users[0].username == username && users[0].mail == mail) { throw new CustomRequestException(409, "Username and Mail are already in use"); } else if (users[0].username == username) { throw new CustomRequestException(409, "Username is already in use"); } else { throw new CustomRequestException(409, "Mail is already in use"); } } else if (users.length >= 2) { throw new CustomRequestException(409, "Username and Mail are already in use"); } var secret = speakeasy.generateSecret({ length: 20, name: `Mitgliederverwaltung ${CLUB_NAME}` }); let createInvite: CreateInviteCommand = { username: username, mail: mail, firstname: firstname, lastname: lastname, secret: secret.base32, }; let token = await InviteCommandHandler.create(createInvite); // sendmail await MailHelper.sendMail( mail, `Email Bestätigung für Mitglieder Admin-Portal von ${CLUB_NAME}`, `Öffne folgenden Link: ${origin}/${isInvite ? "invite" : "setup"}/verify?mail=${mail}&token=${token}` ); res.sendStatus(204); } /** * @description Create first user * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function verifyInvite(req: Request, res: Response): Promise { let mail = req.body.mail; let token = req.body.token; let { secret, username } = await InviteService.getByMailAndToken(mail, token); const url = `otpauth://totp/Mitgliederverwaltung ${CLUB_NAME}?secret=${secret}`; QRCode.toDataURL(url) .then((result) => { res.json({ dataUrl: result, otp: secret, username, }); }) .catch((err) => { throw new InternalException("QRCode not created", err); }); } /** * @description Create first user * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function finishInvite(req: Request, res: Response, grantAdmin: boolean = false): Promise { let mail = req.body.mail; let token = req.body.token; let totp = req.body.totp; let { secret, username, firstname, lastname } = await InviteService.getByMailAndToken(mail, token); let valid = speakeasy.totp.verify({ secret: secret, encoding: "base32", token: totp, window: 2, }); if (!valid) { throw new UnauthorizedRequestException("Token not valid or expired"); } let createUser: CreateUserCommand = { username: username, firstname: firstname, lastname: lastname, mail: mail, secret: secret, isOwner: grantAdmin, }; let id = await UserCommandHandler.create(createUser); let accessToken = await JWTHelper.buildToken(id); let refreshCommand: CreateRefreshCommand = { userId: id, }; let refreshToken = await RefreshCommandHandler.create(refreshCommand); let deleteInvite: DeleteInviteCommand = { mail: mail, token: token, }; await InviteCommandHandler.deleteByTokenAndMail(deleteInvite); res.json({ accessToken, refreshToken, }); } /** * @description delete invite by mail * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function deleteInvite(req: Request, res: Response): Promise { const mail = req.params.mail; await InviteCommandHandler.deleteByMail(mail); res.sendStatus(204); }