2024-11-20 09:32:43 +01:00
|
|
|
import { Request, Response } from "express";
|
|
|
|
import speakeasy from "speakeasy";
|
|
|
|
import QRCode from "qrcode";
|
|
|
|
import InternalException from "../exceptions/internalException";
|
2025-02-15 10:59:54 +01:00
|
|
|
import UserService from "../service/management/userService";
|
|
|
|
import UserFactory from "../factory/admin/management/user";
|
2025-05-05 17:43:57 +02:00
|
|
|
import {
|
|
|
|
TransferUserOwnerCommand,
|
|
|
|
UpdateUserCommand,
|
|
|
|
UpdateUserSecretCommand,
|
|
|
|
} from "../command/management/user/userCommand";
|
2025-02-15 10:59:54 +01:00
|
|
|
import UserCommandHandler from "../command/management/user/userCommandHandler";
|
2024-11-21 15:58:47 +01:00
|
|
|
import ForbiddenRequestException from "../exceptions/forbiddenRequestException";
|
2025-04-19 16:51:37 +02:00
|
|
|
import SettingHelper from "../helpers/settingsHelper";
|
2025-05-05 17:43:57 +02:00
|
|
|
import { LoginRoutineEnum } from "../enums/loginRoutineEnum";
|
2024-11-20 09:32:43 +01:00
|
|
|
|
|
|
|
/**
|
2024-11-20 10:02:34 +01:00
|
|
|
* @description get my by id
|
2024-11-20 09:32:43 +01:00
|
|
|
* @param req {Request} Express req object
|
|
|
|
* @param res {Response} Express res object
|
|
|
|
* @returns {Promise<*>}
|
|
|
|
*/
|
2024-11-20 10:02:34 +01:00
|
|
|
export async function getMeById(req: Request, res: Response): Promise<any> {
|
2025-01-29 08:53:49 +01:00
|
|
|
const id = req.userId;
|
2024-11-20 10:02:34 +01:00
|
|
|
let user = await UserService.getById(id);
|
|
|
|
|
|
|
|
res.json(UserFactory.mapToSingle(user));
|
|
|
|
}
|
|
|
|
|
2025-05-05 17:43:57 +02:00
|
|
|
/**
|
|
|
|
* @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,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-11-20 10:02:34 +01:00
|
|
|
/**
|
|
|
|
* @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> {
|
2025-01-29 08:53:49 +01:00
|
|
|
const userId = req.userId;
|
2024-11-20 09:32:43 +01:00
|
|
|
|
2025-05-04 19:01:06 +02:00
|
|
|
let { secret, routine } = await UserService.getUserSecretAndRoutine(userId);
|
|
|
|
|
2025-04-19 16:51:37 +02:00
|
|
|
const url = `otpauth://totp/FF Admin ${SettingHelper.getSetting("club.name")}?secret=${secret}`;
|
2024-11-20 09:32:43 +01:00
|
|
|
|
|
|
|
QRCode.toDataURL(url)
|
|
|
|
.then((result) => {
|
|
|
|
res.json({
|
|
|
|
dataUrl: result,
|
|
|
|
otp: secret,
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
throw new InternalException("QRCode not created", err);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-11-20 10:02:34 +01:00
|
|
|
* @description verify my totp
|
2024-11-20 09:32:43 +01:00
|
|
|
* @param req {Request} Express req object
|
|
|
|
* @param res {Response} Express res object
|
|
|
|
* @returns {Promise<*>}
|
|
|
|
*/
|
2024-11-20 10:02:34 +01:00
|
|
|
export async function verifyMyTotp(req: Request, res: Response): Promise<any> {
|
2025-01-29 08:53:49 +01:00
|
|
|
const userId = req.userId;
|
2024-11-20 09:32:43 +01:00
|
|
|
let totp = req.body.totp;
|
|
|
|
|
2025-05-04 19:01:06 +02:00
|
|
|
let { secret, routine } = await UserService.getUserSecretAndRoutine(userId);
|
2025-05-05 17:43:57 +02:00
|
|
|
|
|
|
|
if (routine != LoginRoutineEnum.totp) {
|
|
|
|
throw new ForbiddenRequestException("only allowed for totp login");
|
|
|
|
}
|
|
|
|
|
2024-11-20 09:32:43 +01:00
|
|
|
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);
|
|
|
|
}
|
2024-11-20 10:02:34 +01:00
|
|
|
|
2025-05-05 17:43:57 +02:00
|
|
|
/**
|
|
|
|
* @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);
|
|
|
|
}
|
|
|
|
|
2024-11-21 15:58:47 +01:00
|
|
|
/**
|
|
|
|
* @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> {
|
2025-01-29 08:53:49 +01:00
|
|
|
const userId = req.userId;
|
2024-11-21 15:58:47 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2024-11-20 10:02:34 +01:00
|
|
|
/**
|
|
|
|
* @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> {
|
2025-01-29 08:53:49 +01:00
|
|
|
const id = req.userId;
|
2024-11-20 10:02:34 +01:00
|
|
|
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);
|
|
|
|
}
|