auth.service.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { BadRequestException, Injectable, InternalServerErrorException, Logger } from '@nestjs/common';
  2. import { InjectRepository } from '@nestjs/typeorm';
  3. import { Repository } from 'typeorm';
  4. import { UserEntity } from '../user/entities/user.entity';
  5. import { LoginCredentialDto } from './dto/login-credential.dto';
  6. import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service';
  7. import { JwtPayloadDto } from './dto/jwt-payload.dto';
  8. import { SignUpDto } from './dto/sign-up.dto';
  9. import * as bcrypt from 'bcrypt';
  10. import { mapUser, User } from '../user/response-dto/user';
  11. @Injectable()
  12. export class AuthService {
  13. constructor(
  14. @InjectRepository(UserEntity)
  15. private userRepository: Repository<UserEntity>,
  16. private immichJwtService: ImmichJwtService,
  17. ) {}
  18. private async validateUser(loginCredential: LoginCredentialDto): Promise<UserEntity> {
  19. const user = await this.userRepository.findOne(
  20. { email: loginCredential.email },
  21. {
  22. select: [
  23. 'id',
  24. 'email',
  25. 'password',
  26. 'salt',
  27. 'firstName',
  28. 'lastName',
  29. 'isAdmin',
  30. 'profileImagePath',
  31. 'isFirstLoggedIn',
  32. ],
  33. },
  34. );
  35. const isAuthenticated = await this.validatePassword(user.password, loginCredential.password, user.salt);
  36. if (user && isAuthenticated) {
  37. return user;
  38. }
  39. return null;
  40. }
  41. public async login(loginCredential: LoginCredentialDto) {
  42. const validatedUser = await this.validateUser(loginCredential);
  43. if (!validatedUser) {
  44. throw new BadRequestException('Incorrect email or password');
  45. }
  46. const payload = new JwtPayloadDto(validatedUser.id, validatedUser.email);
  47. return {
  48. accessToken: await this.immichJwtService.generateToken(payload),
  49. userId: validatedUser.id,
  50. userEmail: validatedUser.email,
  51. firstName: validatedUser.firstName,
  52. lastName: validatedUser.lastName,
  53. isAdmin: validatedUser.isAdmin,
  54. profileImagePath: validatedUser.profileImagePath,
  55. isFirstLogin: validatedUser.isFirstLoggedIn,
  56. };
  57. }
  58. public async adminSignUp(signUpCredential: SignUpDto): Promise<User> {
  59. const adminUser = await this.userRepository.findOne({ where: { isAdmin: true } });
  60. if (adminUser) {
  61. throw new BadRequestException('The server already has an admin');
  62. }
  63. const newAdminUser = new UserEntity();
  64. newAdminUser.email = signUpCredential.email;
  65. newAdminUser.salt = await bcrypt.genSalt();
  66. newAdminUser.password = await this.hashPassword(signUpCredential.password, newAdminUser.salt);
  67. newAdminUser.firstName = signUpCredential.firstName;
  68. newAdminUser.lastName = signUpCredential.lastName;
  69. newAdminUser.isAdmin = true;
  70. try {
  71. const savedNewAdminUserUser = await this.userRepository.save(newAdminUser);
  72. return mapUser(savedNewAdminUserUser);
  73. } catch (e) {
  74. Logger.error('e', 'signUp');
  75. throw new InternalServerErrorException('Failed to register new admin user');
  76. }
  77. }
  78. private async hashPassword(password: string, salt: string): Promise<string> {
  79. return bcrypt.hash(password, salt);
  80. }
  81. private async validatePassword(hasedPassword: string, inputPassword: string, salt: string): Promise<boolean> {
  82. const hash = await bcrypt.hash(inputPassword, salt);
  83. return hash === hasedPassword;
  84. }
  85. }