diff --git a/server/apps/cli/src/commands/reset-admin-password.command.ts b/server/apps/cli/src/commands/reset-admin-password.command.ts index 28c639bcac..2a01dd05a3 100644 --- a/server/apps/cli/src/commands/reset-admin-password.command.ts +++ b/server/apps/cli/src/commands/reset-admin-password.command.ts @@ -21,8 +21,7 @@ export class ResetAdminPasswordCommand extends CommandRunner { let { password } = await this.inquirer.ask<{ password: string }>('prompt-password', undefined); password = password || randomBytes(24).toString('base64').replace(/\W/g, ''); - const salt = await bcrypt.genSalt(); - const hashedPassword = await bcrypt.hash(password, salt); + const hashedPassword = await bcrypt.hash(password, 10); const user = await this.userRepository.findOne({ where: { isAdmin: true } }); if (!user) { @@ -30,7 +29,6 @@ export class ResetAdminPasswordCommand extends CommandRunner { return; } - user.salt = salt; user.password = hashedPassword; user.shouldChangePassword = true; diff --git a/server/apps/immich/src/api-v1/user/user.core.ts b/server/apps/immich/src/api-v1/user/user.core.ts index 27aa3339e2..788c218897 100644 --- a/server/apps/immich/src/api-v1/user/user.core.ts +++ b/server/apps/immich/src/api-v1/user/user.core.ts @@ -7,24 +7,18 @@ import { NotFoundException, UnauthorizedException, } from '@nestjs/common'; -import { genSalt, hash } from 'bcrypt'; +import { hash } from 'bcrypt'; import { createReadStream, constants, ReadStream } from 'fs'; import fs from 'fs/promises'; import { AuthUserDto } from '../../decorators/auth-user.decorator'; import { CreateAdminDto, CreateUserDto, CreateUserOAuthDto } from './dto/create-user.dto'; import { IUserRepository, UserListFilter } from './user-repository'; +const SALT_ROUNDS = 10; + export class UserCore { constructor(private userRepository: IUserRepository) {} - private async generateSalt(): Promise { - return genSalt(); - } - - private async hashPassword(password: string, salt: string): Promise { - return hash(password, salt); - } - async updateUser(authUser: AuthUserDto, id: string, dto: Partial): Promise { if (!(authUser.isAdmin || authUser.id === id)) { throw new ForbiddenException('You are not allowed to update this user'); @@ -36,9 +30,7 @@ export class UserCore { try { if (dto.password) { - const salt = await this.generateSalt(); - dto.salt = salt; - dto.password = await this.hashPassword(dto.password, salt); + dto.password = await hash(dto.password, SALT_ROUNDS); } return this.userRepository.update(id, dto); } catch (e) { @@ -63,9 +55,7 @@ export class UserCore { try { const payload: Partial = { ...createUserDto }; if (payload.password) { - const salt = await this.generateSalt(); - payload.salt = salt; - payload.password = await this.hashPassword(payload.password, salt); + payload.password = await hash(payload.password, SALT_ROUNDS); } return this.userRepository.create(payload); } catch (e) { diff --git a/server/apps/immich/src/api-v1/user/user.service.spec.ts b/server/apps/immich/src/api-v1/user/user.service.spec.ts index f50febdf9f..0db9c9f5ea 100644 --- a/server/apps/immich/src/api-v1/user/user.service.spec.ts +++ b/server/apps/immich/src/api-v1/user/user.service.spec.ts @@ -27,7 +27,6 @@ describe('UserService', () => { id: adminUserAuth.id, email: 'admin@test.com', password: 'admin_password', - salt: 'admin_salt', firstName: 'admin_first_name', lastName: 'admin_last_name', isAdmin: true, @@ -42,7 +41,6 @@ describe('UserService', () => { id: immichUserAuth.id, email: 'immich@test.com', password: 'immich_password', - salt: 'immich_salt', firstName: 'immich_first_name', lastName: 'immich_last_name', isAdmin: false, @@ -57,7 +55,6 @@ describe('UserService', () => { id: immichUserAuth.id, email: 'immich@test.com', password: 'immich_password', - salt: 'immich_salt', firstName: 'updated_immich_first_name', lastName: 'updated_immich_last_name', isAdmin: false, diff --git a/server/apps/immich/src/modules/immich-jwt/immich-jwt.service.spec.ts b/server/apps/immich/src/modules/immich-jwt/immich-jwt.service.spec.ts index 7edf313997..904e1baf52 100644 --- a/server/apps/immich/src/modules/immich-jwt/immich-jwt.service.spec.ts +++ b/server/apps/immich/src/modules/immich-jwt/immich-jwt.service.spec.ts @@ -51,7 +51,6 @@ describe('ImmichJwtService', () => { isAdmin: false, email: 'test@immich.com', password: 'changeme', - salt: '123', oauthId: '', profileImagePath: '', shouldChangePassword: false, diff --git a/server/libs/database/src/entities/user.entity.ts b/server/libs/database/src/entities/user.entity.ts index 024d6ccda0..325c36db81 100644 --- a/server/libs/database/src/entities/user.entity.ts +++ b/server/libs/database/src/entities/user.entity.ts @@ -21,9 +21,6 @@ export class UserEntity { @Column({ default: '', select: false }) password?: string; - @Column({ default: '', select: false }) - salt?: string; - @Column({ default: '' }) oauthId!: string; diff --git a/server/libs/database/src/migrations/1672109862870-DropSaltColumn.ts b/server/libs/database/src/migrations/1672109862870-DropSaltColumn.ts new file mode 100644 index 0000000000..91ca5ade11 --- /dev/null +++ b/server/libs/database/src/migrations/1672109862870-DropSaltColumn.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class DropSaltColumn1672109862870 implements MigrationInterface { + name = 'DropSaltColumn1672109862870' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "salt"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "users" ADD "salt" character varying NOT NULL DEFAULT ''`); + } + +}