import { Request, Response } from "express"; import speakeasy from "speakeasy"; import QRCode from "qrcode"; import InternalException from "../exceptions/internalException"; import UserService from "../service/management/userService"; import UserFactory from "../factory/admin/management/user"; import { TransferUserOwnerCommand, UpdateUserCommand, UpdateUserSecretCommand, } from "../command/management/user/userCommand"; import UserCommandHandler from "../command/management/user/userCommandHandler"; import ForbiddenRequestException from "../exceptions/forbiddenRequestException"; import SettingHelper from "../helpers/settingsHelper"; import { LoginRoutineEnum } from "../enums/loginRoutineEnum"; /** * @description get my by id * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function getMeById(req: Request, res: Response): Promise<any> { const id = req.userId; let user = await UserService.getById(id); res.json(UserFactory.mapToSingle(user)); } /** * @description get my routine by id * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function getMyRoutine(req: Request, res: Response): Promise<any> { const id = req.userId; let user = await UserService.getById(id); res.json({ routine: user.routine, }); } /** * @description get my totp * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function getMyTotp(req: Request, res: Response): Promise<any> { const userId = req.userId; let { secret, routine } = await UserService.getUserSecretAndRoutine(userId); const url = `otpauth://totp/FF Admin ${SettingHelper.getSetting("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 verify my totp * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function verifyMyTotp(req: Request, res: Response): Promise<any> { const userId = req.userId; let totp = req.body.totp; let { secret, routine } = await UserService.getUserSecretAndRoutine(userId); if (routine != LoginRoutineEnum.totp) { throw new ForbiddenRequestException("only allowed for totp login"); } let valid = speakeasy.totp.verify({ secret: secret, encoding: "base32", token: totp, window: 2, }); if (!valid) { throw new InternalException("Token not valid or expired"); } res.sendStatus(204); } /** * @description change my password * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function changeMyPassword(req: Request, res: Response): Promise<any> { const userId = req.userId; let current = req.body.current; let newpassword = req.body.newpassword; let { secret, routine } = await UserService.getUserSecretAndRoutine(userId); if (routine == LoginRoutineEnum.password && current != secret) { throw new ForbiddenRequestException("passwords do not match"); } let updateUser: UpdateUserSecretCommand = { id: userId, secret: newpassword, routine: LoginRoutineEnum.password, }; await UserCommandHandler.updateSecret(updateUser); res.sendStatus(204); } /** * @description get change to totp * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function getChangeToTOTP(req: Request, res: Response): Promise<any> { var secret = speakeasy.generateSecret({ length: 20, name: `FF Admin ${SettingHelper.getSetting("club.name")}` }); QRCode.toDataURL(secret.otpauth_url) .then((result) => { res.json({ dataUrl: result, otp: secret.base32, }); }) .catch((err) => { throw new InternalException("QRCode not created", err); }); } /** * @description change to totp * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function changeToTOTP(req: Request, res: Response): Promise<any> { const userId = req.userId; let otp = req.body.otp; let totp = req.body.totp; let valid = speakeasy.totp.verify({ secret: otp, encoding: "base32", token: totp, window: 2, }); if (!valid) { throw new InternalException("Token not valid or expired"); } let updateUser: UpdateUserSecretCommand = { id: userId, secret: otp, routine: LoginRoutineEnum.totp, }; await UserCommandHandler.updateSecret(updateUser); res.sendStatus(204); } /** * @description change to password * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function changeToPW(req: Request, res: Response): Promise<any> { const userId = req.userId; let newpassword = req.body.newpassword; let updateUser: UpdateUserSecretCommand = { id: userId, secret: newpassword, routine: LoginRoutineEnum.password, }; await UserCommandHandler.updateSecret(updateUser); res.sendStatus(204); } /** * @description transferOwnership * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function transferOwnership(req: Request, res: Response): Promise<any> { const userId = req.userId; let toId = req.body.toId; let { isOwner } = await UserService.getById(userId); if (!isOwner) { throw new ForbiddenRequestException("Action only allowed to owner."); } let transfer: TransferUserOwnerCommand = { toId: toId, fromId: userId, }; await UserCommandHandler.transferOwnership(transfer); res.sendStatus(204); } /** * @description update my data * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function updateMe(req: Request, res: Response): Promise<any> { const id = req.userId; let mail = req.body.mail; let firstname = req.body.firstname; let lastname = req.body.lastname; let username = req.body.username; let updateUser: UpdateUserCommand = { id: id, mail: mail, firstname: firstname, lastname: lastname, username: username, }; await UserCommandHandler.update(updateUser); res.sendStatus(204); }