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 { CreateResetCommand, DeleteResetCommand } from "../command/resetCommand"; import ResetCommandHandler from "../command/resetCommandHandler"; import MailHelper from "../helpers/mailHelper"; import ResetService from "../service/resetService"; import UserService from "../service/userService"; import { CLUB_NAME } from "../env.defaults"; import PermissionHelper from "../helpers/permissionHelper"; import RolePermissionService from "../service/rolePermissionService"; import UserPermissionService from "../service/userPermissionService"; import { UpdateUserSecretCommand } from "../command/userCommand"; import UserCommandHandler from "../command/userCommandHandler"; /** * @description request totp reset * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function startReset(req: Request, res: Response): Promise { let origin = req.headers.origin; let username = req.body.username; let { mail } = await UserService.getByUsername(username); var secret = speakeasy.generateSecret({ length: 20, name: `Mitgliederverwaltung ${CLUB_NAME}` }); let createReset: CreateResetCommand = { username: username, mail: mail, secret: secret.base32, }; let token = await ResetCommandHandler.create(createReset); // sendmail let mailhelper = new MailHelper(); await mailhelper.sendMail( mail, `Email Bestätigung für Mitglieder Admin-Portal von ${CLUB_NAME}`, `Öffne folgenden Link: ${origin}/reset/reset?mail=${mail}&token=${token}` ); res.sendStatus(204); } /** * @description verify reset link * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function verifyReset(req: Request, res: Response): Promise { let mail = req.body.mail; let token = req.body.token; let { secret } = await ResetService.getByMailAndToken(mail, token); const url = `otpauth://totp/Mitgliederverwaltung ${CLUB_NAME}?secret=${secret}`; QRCode.toDataURL(url) .then((result) => { res.json({ dataUrl: result, otp: secret, }); }) .catch((err) => { throw new InternalException("QRCode not created", err); }); } /** * @description finishReset * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function finishReset(req: Request, res: Response): Promise { let mail = req.body.mail; let token = req.body.token; let totp = req.body.totp; let { secret, username } = await ResetService.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 { id } = await UserService.getByUsername(username); let updateUserSecret: UpdateUserSecretCommand = { id, secret, }; await UserCommandHandler.updateSecret(updateUserSecret); let accessToken = await JWTHelper.buildToken(id); let refreshCommand: CreateRefreshCommand = { userId: id, }; let refreshToken = await RefreshCommandHandler.create(refreshCommand); let deleteReset: DeleteResetCommand = { mail: mail, token: token, }; await ResetCommandHandler.deleteByTokenAndMail(deleteReset); res.json({ accessToken, refreshToken, }); }