ff-admin-server/src/controller/resetController.ts

128 lines
3.8 KiB
TypeScript

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<any> {
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
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<any> {
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<any> {
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,
});
}