import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Model, Types } from 'mongoose'; import { MailerService } from '../mailer/mailer.service'; import { CreateTempUserDto } from './dto/create-temp-user.dto'; import { TempUser } from './temp-user.schema'; import * as ejs from 'ejs'; import { ITempUser } from './temp-user.interface'; @Injectable() export class TempUserService { constructor( private readonly mailerService: MailerService, @InjectModel(TempUser.name) private tempUserModel: Model<ITempUser> ) {} public async create(createTempUser: CreateTempUserDto, structureName: string): Promise<TempUser> { const userInDb = await this.findOne(createTempUser.email); if (userInDb) { throw new HttpException('User already exists', HttpStatus.BAD_REQUEST); } const createUser = await this.tempUserModel.create(createTempUser); // Send email this.sendUserMail(createUser, structureName); return this.findOne(createTempUser.email); } public async findOne(mail: string): Promise<ITempUser> { return this.tempUserModel.findOne({ email: mail }); } public async findById(id: string): Promise<TempUser> { return this.tempUserModel.findById(Types.ObjectId(id)); } public async delete(mail: string): Promise<TempUser> { const userInDb = await this.findOne(mail); if (!userInDb) { throw new HttpException('User does not exists', HttpStatus.BAD_REQUEST); } await this.tempUserModel.deleteOne({ email: mail }); return userInDb; } public async updateStructureLinked(createTempUser: CreateTempUserDto): Promise<TempUser> { const userInDb = await this.tempUserModel .find({ $and: [ { email: createTempUser.email, }, { pendingStructuresLink: { $in: [createTempUser.pendingStructuresLink[0]] }, }, ], }) .exec(); if (userInDb.length > 0) { throw new HttpException('User already linked', HttpStatus.UNPROCESSABLE_ENTITY); } return this.tempUserModel .updateOne( { email: createTempUser.email }, { $push: { pendingStructuresLink: createTempUser.pendingStructuresLink[0] } } ) .exec(); } /** * Send email in order to tell the user that an account is alreday fill with his structure info. * @param user User */ private async sendUserMail(user: ITempUser, structureName: string): Promise<any> { const config = this.mailerService.config; const ejsPath = this.mailerService.getTemplateLocation(config.templates.tempUserRegistration.ejs); const jsonConfig = this.mailerService.loadJsonConfig(config.templates.tempUserRegistration.json); const html = await ejs.renderFile(ejsPath, { config, id: user._id, name: structureName, }); this.mailerService.send(user.email, jsonConfig.subject, html); } public async getStructureTempUsers(structureId: string): Promise<ITempUser[]> { return this.tempUserModel .find({ pendingStructuresLink: Types.ObjectId(structureId) }) .select('email updatedAt') .exec(); } public async removeFromStructureLinked(userEmail: string, idStructure: string): Promise<Types.ObjectId[]> { const user = await this.findOne(userEmail); if (!user) { throw new HttpException('Invalid temp user', HttpStatus.NOT_FOUND); } if (!user.pendingStructuresLink.includes(Types.ObjectId(idStructure))) { throw new HttpException("Temp user doesn't belong to this structure", HttpStatus.NOT_FOUND); } user.pendingStructuresLink = user.pendingStructuresLink.filter((structureId) => { return !structureId.equals(idStructure); }); await user.save(); return user.pendingStructuresLink; } }