mirror of
https://github.com/immich-app/immich.git
synced 2025-06-14 11:07:49 -04:00
* WIP fix user e2e tests The e2e tests still don't seem to work due to migrations not running. Changes: - update user.e2e tests to use new `userService.createUser` method - fix server `typeorm` command to use ORM config - update make test-e2e to re-create database volume every time - add User DTO - update auth.service and user.service to use User DTO - update CreateUserDto making optional properties that are optional * Fix migrations - add missing `.ts` extension to migrations path - update user e2e test for the new returned User resource
102 lines
3.3 KiB
TypeScript
102 lines
3.3 KiB
TypeScript
import { BadRequestException, Injectable, InternalServerErrorException, Logger } from '@nestjs/common';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { Repository } from 'typeorm';
|
|
import { UserEntity } from '../user/entities/user.entity';
|
|
import { LoginCredentialDto } from './dto/login-credential.dto';
|
|
import { ImmichJwtService } from '../../modules/immich-jwt/immich-jwt.service';
|
|
import { JwtPayloadDto } from './dto/jwt-payload.dto';
|
|
import { SignUpDto } from './dto/sign-up.dto';
|
|
import * as bcrypt from 'bcrypt';
|
|
import { mapUser, User } from '../user/response-dto/user';
|
|
|
|
@Injectable()
|
|
export class AuthService {
|
|
constructor(
|
|
@InjectRepository(UserEntity)
|
|
private userRepository: Repository<UserEntity>,
|
|
private immichJwtService: ImmichJwtService,
|
|
) {}
|
|
|
|
private async validateUser(loginCredential: LoginCredentialDto): Promise<UserEntity> {
|
|
const user = await this.userRepository.findOne(
|
|
{ email: loginCredential.email },
|
|
{
|
|
select: [
|
|
'id',
|
|
'email',
|
|
'password',
|
|
'salt',
|
|
'firstName',
|
|
'lastName',
|
|
'isAdmin',
|
|
'profileImagePath',
|
|
'isFirstLoggedIn',
|
|
],
|
|
},
|
|
);
|
|
|
|
const isAuthenticated = await this.validatePassword(user.password, loginCredential.password, user.salt);
|
|
|
|
if (user && isAuthenticated) {
|
|
return user;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public async login(loginCredential: LoginCredentialDto) {
|
|
const validatedUser = await this.validateUser(loginCredential);
|
|
|
|
if (!validatedUser) {
|
|
throw new BadRequestException('Incorrect email or password');
|
|
}
|
|
|
|
const payload = new JwtPayloadDto(validatedUser.id, validatedUser.email);
|
|
|
|
return {
|
|
accessToken: await this.immichJwtService.generateToken(payload),
|
|
userId: validatedUser.id,
|
|
userEmail: validatedUser.email,
|
|
firstName: validatedUser.firstName,
|
|
lastName: validatedUser.lastName,
|
|
isAdmin: validatedUser.isAdmin,
|
|
profileImagePath: validatedUser.profileImagePath,
|
|
isFirstLogin: validatedUser.isFirstLoggedIn,
|
|
};
|
|
}
|
|
|
|
public async adminSignUp(signUpCredential: SignUpDto): Promise<User> {
|
|
const adminUser = await this.userRepository.findOne({ where: { isAdmin: true } });
|
|
|
|
if (adminUser) {
|
|
throw new BadRequestException('The server already has an admin');
|
|
}
|
|
|
|
const newAdminUser = new UserEntity();
|
|
newAdminUser.email = signUpCredential.email;
|
|
newAdminUser.salt = await bcrypt.genSalt();
|
|
newAdminUser.password = await this.hashPassword(signUpCredential.password, newAdminUser.salt);
|
|
newAdminUser.firstName = signUpCredential.firstName;
|
|
newAdminUser.lastName = signUpCredential.lastName;
|
|
newAdminUser.isAdmin = true;
|
|
|
|
try {
|
|
const savedNewAdminUserUser = await this.userRepository.save(newAdminUser);
|
|
|
|
return mapUser(savedNewAdminUserUser);
|
|
} catch (e) {
|
|
Logger.error('e', 'signUp');
|
|
throw new InternalServerErrorException('Failed to register new admin user');
|
|
}
|
|
}
|
|
|
|
private async hashPassword(password: string, salt: string): Promise<string> {
|
|
return bcrypt.hash(password, salt);
|
|
}
|
|
|
|
private async validatePassword(hasedPassword: string, inputPassword: string, salt: string): Promise<boolean> {
|
|
const hash = await bcrypt.hash(inputPassword, salt);
|
|
return hash === hasedPassword;
|
|
}
|
|
}
|