domino-server/src/server/controllers/UserController.ts
2024-07-06 20:32:41 +02:00

153 lines
4.8 KiB
TypeScript

import { validationResult } from 'express-validator';
import { SecurityManager } from '../managers/SecurityManager';
import { CryptoService } from '../services/CryptoService';
import { TemporalTokenMongoManager } from '../db/mongo/TemporalTokenMongoManager';
import { BaseController } from './BaseController';
import { MailerService } from '../services/mailer/MailerService';
import { NamespacesService } from '../services/NamespacesService';
import { UsersService } from '../services/UsersService';
import { Request, Response } from 'express';
export class UserController extends BaseController {
security = new SecurityManager();
temporalTokenManager = new TemporalTokenMongoManager();
usersService = new UsersService();
mailService = new MailerService();
cryptoService = new CryptoService();
namespacesService = new NamespacesService();
constructor() {
super();
}
async getNamespaces(req: Request, res: Response) {
return await this.namespacesService.getNamespaces();
}
async getUser(req: Request, res: Response) {
try {
const { id } = req.params;
const user = await this.usersService.getById(id);
res.json(user).status(200).end();
} catch (error) {
this.handleError(res, error);
}
}
async createUser(req: Request, res: Response) {
const user = req.body;
try {
const validation = validationResult(req);
if (!validation.isEmpty()) {
res.status(400).json({ errors: validation.array() });
return;
}
await this.usersService.createUser(user);
res.status(201).end();
} catch (error) {
this.handleError(res, error);
}
}
async updateUserNamespace(req: Request, res: Response) {
try {
const { userId, namespaceId } = req.params;
return await this.usersService.updateUserNamespace(userId, namespaceId);
} catch (error) {
this.handleError(res, error);
}
}
async resetUserNamespace(req: Request, res: Response) {
try {
const { userId } = req.params;
const defaultNS = await this.namespacesService.getDefaultNamespace();
if (!defaultNS._id) {
throw new Error('Default namespace not found');
}
return await this.usersService.updateUserNamespace(userId, defaultNS._id.toString());
} catch (error) {
this.handleError(res, error);
}
}
async updateUser(req: Request, res: Response) {
const user = req.body;
try {
const validation = validationResult(req);
if (!validation.isEmpty()) {
res.status(400).json({ errors: validation.array() });
return;
}
const { id } = req.params;
await this.usersService.updateUser(user, id);
res.status(200).end();
} catch (error) {
this.handleError(res, error);
}
}
async deleteUser(req: Request, res: Response) {
try {
const { id } = req.params;
await this.usersService.deleteUser(id);
res.status(200).end();
} catch (error) {
this.handleError(res, error);
}
}
async listUsers(req: Request, res: Response): Promise<void> {
try {
const { available = false } = req.query;
let users = [];
if (available) {
const defaultNamespace = await this.namespacesService.getDefaultNamespace();
users = await this.usersService.listUsers({ not: defaultNamespace._id });
} else {
users = await this.usersService.listUsers();
}
res.json(users).status(200).end();
} catch (error) {
this.handleError(res, error);
}
}
async passwordRecovery(req: Request, res: Response) {
try {
const { username } = req.body;
const user = await this.usersService.getByUsername(username);
if (user === null) {
res.status(404).json({ message: 'User not found', code: 'user-not-found'}).end();
return;
}
if (!user.email) {
res.status(404).json({ message: 'Email not found', code: 'email-not-found'}).end();
return;
}
const { email, firstname, lastname, _id: userId } = user;
const pin = this.cryptoService.generateRandomPin(8);
const token = this.security.getHashedPassword(pin);
const temporalToken = {
userId,
token,
createdAt: new Date().getTime(),
validUntil: new Date().getTime() + 1000 * 60 * 60 * 1,
type: TemporalTokenMongoManager.Types.PASSWORD_RECOVERY,
}
if (!userId) {
throw new Error('User not found');
}
this.temporalTokenManager.deleteAllByUserAndType(userId.toString(), TemporalTokenMongoManager.Types.PASSWORD_RECOVERY);
this.temporalTokenManager.addToken(temporalToken);
await this.mailService.sendRecoveryPasswordEmail(firstname, lastname, email, pin);
res.status(200).end();
} catch (error: any) {
this.handleError(res, error, { code: 'critical', message: error.message });
}
}
}