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

176 lines
5.6 KiB
TypeScript
Raw Normal View History

2024-08-25 13:36:19 +02:00
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";
2025-02-15 10:59:54 +01:00
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";
2024-08-25 13:36:19 +02:00
import MailHelper from "../helpers/mailHelper";
2025-02-15 10:59:54 +01:00
import InviteService from "../service/management/inviteService";
import UserService from "../service/management/userService";
2024-08-25 13:36:19 +02:00
import CustomRequestException from "../exceptions/customRequestException";
import { CLUB_NAME } from "../env.defaults";
2025-02-15 10:59:54 +01:00
import { CreateUserPermissionCommand } from "../command/management/user/userPermissionCommand";
import UserPermissionCommandHandler from "../command/management/user/userPermissionCommandHandler";
import InviteFactory from "../factory/admin/management/invite";
2024-08-25 13:36:19 +02:00
2024-11-23 14:25:31 +01:00
/**
* @description get all invites
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
2024-11-24 12:36:12 +01:00
export async function getInvites(req: Request, res: Response): Promise<any> {
let invites = await InviteService.getAll();
res.json(InviteFactory.mapToBase(invites));
}
2024-11-23 14:25:31 +01:00
2024-08-25 13:36:19 +02:00
/**
* @description start first user
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
2024-09-01 14:55:05 +02:00
export async function inviteUser(req: Request, res: Response, isInvite: boolean = true): Promise<any> {
2024-08-25 13:36:19 +02:00
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}` });
2024-08-25 13:36:19 +02:00
let createInvite: CreateInviteCommand = {
username: username,
mail: mail,
firstname: firstname,
lastname: lastname,
secret: secret.base32,
};
let token = await InviteCommandHandler.create(createInvite);
// sendmail
2024-12-28 18:03:33 +01:00
await MailHelper.sendMail(
2024-08-25 13:36:19 +02:00
mail,
`Email Bestätigung für Mitglieder Admin-Portal von ${CLUB_NAME}`,
2024-09-01 14:55:05 +02:00
`Öffne folgenden Link: ${origin}/${isInvite ? "invite" : "setup"}/verify?mail=${mail}&token=${token}`
2024-08-25 13:36:19 +02:00
);
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<any> {
let mail = req.body.mail;
let token = req.body.token;
2024-11-23 14:25:31 +01:00
let { secret, username } = await InviteService.getByMailAndToken(mail, token);
2024-08-25 13:36:19 +02:00
const url = `otpauth://totp/Mitgliederverwaltung ${CLUB_NAME}?secret=${secret}`;
2024-08-25 13:36:19 +02:00
QRCode.toDataURL(url)
.then((result) => {
res.json({
dataUrl: result,
otp: secret,
2024-11-23 14:25:31 +01:00
username,
});
2024-08-25 13:36:19 +02:00
})
.catch((err) => {
2024-09-06 10:08:19 +02:00
throw new InternalException("QRCode not created", err);
2024-08-25 13:36:19 +02:00
});
}
/**
* @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<any> {
2024-08-25 13:36:19 +02:00
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,
2024-10-07 18:09:27 +02:00
isOwner: grantAdmin,
2024-08-25 13:36:19 +02:00
};
let id = await UserCommandHandler.create(createUser);
2024-11-23 12:11:19 +01:00
let accessToken = await JWTHelper.buildToken(id);
2024-08-25 13:36:19 +02:00
let refreshCommand: CreateRefreshCommand = {
userId: id,
};
2024-11-23 12:11:19 +01:00
let refreshToken = await RefreshCommandHandler.create(refreshCommand);
2024-08-25 13:36:19 +02:00
let deleteInvite: DeleteInviteCommand = {
mail: mail,
token: token,
};
await InviteCommandHandler.deleteByTokenAndMail(deleteInvite);
res.json({
accessToken,
refreshToken,
});
}
2024-11-23 14:25:31 +01:00
/**
2024-11-24 12:36:12 +01:00
* @description delete invite by mail
2024-11-23 14:25:31 +01:00
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
2024-11-24 12:36:12 +01:00
export async function deleteInvite(req: Request, res: Response): Promise<any> {
const mail = req.params.mail;
await InviteCommandHandler.deleteByMail(mail);
res.sendStatus(204);
2024-11-23 14:25:31 +01:00
}