import { BadRequestException, Injectable, InternalServerErrorException, Logger, StreamableFile } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Not, Repository } from 'typeorm'; import { AuthUserDto } from '../../decorators/auth-user.decorator'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; import { UserEntity } from './entities/user.entity'; import * as bcrypt from 'bcrypt'; import sharp from 'sharp'; import { createReadStream, unlink, unlinkSync } from 'fs'; import { Response as Res } from 'express'; @Injectable() export class UserService { constructor( @InjectRepository(UserEntity) private userRepository: Repository, ) { } async getAllUsers(authUser: AuthUserDto, isAll: boolean) { if (isAll) { return await this.userRepository.find(); } return await this.userRepository.find({ where: { id: Not(authUser.id) }, order: { createdAt: 'DESC' } }); } async getUserCount(isAdmin: boolean) { let users; if (isAdmin) { users = await this.userRepository.find({ where: { isAdmin: true } }); } else { users = await this.userRepository.find(); } return { userCount: users.length } } async createUser(createUserDto: CreateUserDto) { const user = await this.userRepository.findOne({ where: { email: createUserDto.email } }); if (user) { throw new BadRequestException('User exists'); } const newUser = new UserEntity(); newUser.email = createUserDto.email; newUser.salt = await bcrypt.genSalt(); newUser.password = await this.hashPassword(createUserDto.password, newUser.salt); newUser.firstName = createUserDto.firstName; newUser.lastName = createUserDto.lastName; newUser.isAdmin = false; try { const savedUser = await this.userRepository.save(newUser); return { id: savedUser.id, email: savedUser.email, firstName: savedUser.firstName, lastName: savedUser.lastName, createdAt: savedUser.createdAt, }; } catch (e) { Logger.error(e, 'Create new user'); throw new InternalServerErrorException('Failed to register new user'); } } private async hashPassword(password: string, salt: string): Promise { return bcrypt.hash(password, salt); } async updateUser(updateUserDto: UpdateUserDto) { const user = await this.userRepository.findOne(updateUserDto.id); user.lastName = updateUserDto.lastName || user.lastName; user.firstName = updateUserDto.firstName || user.firstName; user.profileImagePath = updateUserDto.profileImagePath || user.profileImagePath; user.isFirstLoggedIn = updateUserDto.isFirstLoggedIn || user.isFirstLoggedIn; // If payload includes password - Create new password for user if (updateUserDto.password) { user.salt = await bcrypt.genSalt(); user.password = await this.hashPassword(updateUserDto.password, user.salt); } if (updateUserDto.isAdmin) { const adminUser = await this.userRepository.findOne({ where: { isAdmin: true } }) if (adminUser) { throw new BadRequestException("Admin user exists") } user.isAdmin = true; } try { const updatedUser = await this.userRepository.save(user); return { id: updatedUser.id, email: updatedUser.email, firstName: updatedUser.firstName, lastName: updatedUser.lastName, isAdmin: updatedUser.isAdmin, profileImagePath: updatedUser.profileImagePath, }; } catch (e) { Logger.error(e, 'Create new user'); throw new InternalServerErrorException('Failed to register new user'); } } async createProfileImage(authUser: AuthUserDto, fileInfo: Express.Multer.File) { try { await this.userRepository.update(authUser.id, { profileImagePath: fileInfo.path }) return { userId: authUser.id, profileImagePath: fileInfo.path }; } catch (e) { Logger.error(e, 'Create User Profile Image'); throw new InternalServerErrorException('Failed to create new user profile image'); } } async getUserProfileImage(userId: string, res: Res) { try { const user = await this.userRepository.findOne({ id: userId }) if (!user.profileImagePath) { console.log("empty return") throw new BadRequestException('User does not have a profile image'); } res.set({ 'Content-Type': 'image/jpeg', }); const fileStream = createReadStream(user.profileImagePath) return new StreamableFile(fileStream); } catch (e) { console.log("error getting user profile") } } }