mirror of
https://github.com/immich-app/immich.git
synced 2025-01-06 03:46:47 +01:00
refactor(server): drop salt column (#1185)
This commit is contained in:
parent
0c896d9e59
commit
4e860b024b
6 changed files with 20 additions and 25 deletions
|
@ -21,8 +21,7 @@ export class ResetAdminPasswordCommand extends CommandRunner {
|
||||||
let { password } = await this.inquirer.ask<{ password: string }>('prompt-password', undefined);
|
let { password } = await this.inquirer.ask<{ password: string }>('prompt-password', undefined);
|
||||||
password = password || randomBytes(24).toString('base64').replace(/\W/g, '');
|
password = password || randomBytes(24).toString('base64').replace(/\W/g, '');
|
||||||
|
|
||||||
const salt = await bcrypt.genSalt();
|
const hashedPassword = await bcrypt.hash(password, 10);
|
||||||
const hashedPassword = await bcrypt.hash(password, salt);
|
|
||||||
|
|
||||||
const user = await this.userRepository.findOne({ where: { isAdmin: true } });
|
const user = await this.userRepository.findOne({ where: { isAdmin: true } });
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
@ -30,7 +29,6 @@ export class ResetAdminPasswordCommand extends CommandRunner {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
user.salt = salt;
|
|
||||||
user.password = hashedPassword;
|
user.password = hashedPassword;
|
||||||
user.shouldChangePassword = true;
|
user.shouldChangePassword = true;
|
||||||
|
|
||||||
|
|
|
@ -7,24 +7,18 @@ import {
|
||||||
NotFoundException,
|
NotFoundException,
|
||||||
UnauthorizedException,
|
UnauthorizedException,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { genSalt, hash } from 'bcrypt';
|
import { hash } from 'bcrypt';
|
||||||
import { createReadStream, constants, ReadStream } from 'fs';
|
import { createReadStream, constants, ReadStream } from 'fs';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import { AuthUserDto } from '../../decorators/auth-user.decorator';
|
import { AuthUserDto } from '../../decorators/auth-user.decorator';
|
||||||
import { CreateAdminDto, CreateUserDto, CreateUserOAuthDto } from './dto/create-user.dto';
|
import { CreateAdminDto, CreateUserDto, CreateUserOAuthDto } from './dto/create-user.dto';
|
||||||
import { IUserRepository, UserListFilter } from './user-repository';
|
import { IUserRepository, UserListFilter } from './user-repository';
|
||||||
|
|
||||||
|
const SALT_ROUNDS = 10;
|
||||||
|
|
||||||
export class UserCore {
|
export class UserCore {
|
||||||
constructor(private userRepository: IUserRepository) {}
|
constructor(private userRepository: IUserRepository) {}
|
||||||
|
|
||||||
private async generateSalt(): Promise<string> {
|
|
||||||
return genSalt();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async hashPassword(password: string, salt: string): Promise<string> {
|
|
||||||
return hash(password, salt);
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateUser(authUser: AuthUserDto, id: string, dto: Partial<UserEntity>): Promise<UserEntity> {
|
async updateUser(authUser: AuthUserDto, id: string, dto: Partial<UserEntity>): Promise<UserEntity> {
|
||||||
if (!(authUser.isAdmin || authUser.id === id)) {
|
if (!(authUser.isAdmin || authUser.id === id)) {
|
||||||
throw new ForbiddenException('You are not allowed to update this user');
|
throw new ForbiddenException('You are not allowed to update this user');
|
||||||
|
@ -36,9 +30,7 @@ export class UserCore {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (dto.password) {
|
if (dto.password) {
|
||||||
const salt = await this.generateSalt();
|
dto.password = await hash(dto.password, SALT_ROUNDS);
|
||||||
dto.salt = salt;
|
|
||||||
dto.password = await this.hashPassword(dto.password, salt);
|
|
||||||
}
|
}
|
||||||
return this.userRepository.update(id, dto);
|
return this.userRepository.update(id, dto);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -63,9 +55,7 @@ export class UserCore {
|
||||||
try {
|
try {
|
||||||
const payload: Partial<UserEntity> = { ...createUserDto };
|
const payload: Partial<UserEntity> = { ...createUserDto };
|
||||||
if (payload.password) {
|
if (payload.password) {
|
||||||
const salt = await this.generateSalt();
|
payload.password = await hash(payload.password, SALT_ROUNDS);
|
||||||
payload.salt = salt;
|
|
||||||
payload.password = await this.hashPassword(payload.password, salt);
|
|
||||||
}
|
}
|
||||||
return this.userRepository.create(payload);
|
return this.userRepository.create(payload);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -27,7 +27,6 @@ describe('UserService', () => {
|
||||||
id: adminUserAuth.id,
|
id: adminUserAuth.id,
|
||||||
email: 'admin@test.com',
|
email: 'admin@test.com',
|
||||||
password: 'admin_password',
|
password: 'admin_password',
|
||||||
salt: 'admin_salt',
|
|
||||||
firstName: 'admin_first_name',
|
firstName: 'admin_first_name',
|
||||||
lastName: 'admin_last_name',
|
lastName: 'admin_last_name',
|
||||||
isAdmin: true,
|
isAdmin: true,
|
||||||
|
@ -42,7 +41,6 @@ describe('UserService', () => {
|
||||||
id: immichUserAuth.id,
|
id: immichUserAuth.id,
|
||||||
email: 'immich@test.com',
|
email: 'immich@test.com',
|
||||||
password: 'immich_password',
|
password: 'immich_password',
|
||||||
salt: 'immich_salt',
|
|
||||||
firstName: 'immich_first_name',
|
firstName: 'immich_first_name',
|
||||||
lastName: 'immich_last_name',
|
lastName: 'immich_last_name',
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
|
@ -57,7 +55,6 @@ describe('UserService', () => {
|
||||||
id: immichUserAuth.id,
|
id: immichUserAuth.id,
|
||||||
email: 'immich@test.com',
|
email: 'immich@test.com',
|
||||||
password: 'immich_password',
|
password: 'immich_password',
|
||||||
salt: 'immich_salt',
|
|
||||||
firstName: 'updated_immich_first_name',
|
firstName: 'updated_immich_first_name',
|
||||||
lastName: 'updated_immich_last_name',
|
lastName: 'updated_immich_last_name',
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
|
|
|
@ -51,7 +51,6 @@ describe('ImmichJwtService', () => {
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
email: 'test@immich.com',
|
email: 'test@immich.com',
|
||||||
password: 'changeme',
|
password: 'changeme',
|
||||||
salt: '123',
|
|
||||||
oauthId: '',
|
oauthId: '',
|
||||||
profileImagePath: '',
|
profileImagePath: '',
|
||||||
shouldChangePassword: false,
|
shouldChangePassword: false,
|
||||||
|
|
|
@ -21,9 +21,6 @@ export class UserEntity {
|
||||||
@Column({ default: '', select: false })
|
@Column({ default: '', select: false })
|
||||||
password?: string;
|
password?: string;
|
||||||
|
|
||||||
@Column({ default: '', select: false })
|
|
||||||
salt?: string;
|
|
||||||
|
|
||||||
@Column({ default: '' })
|
@Column({ default: '' })
|
||||||
oauthId!: string;
|
oauthId!: string;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class DropSaltColumn1672109862870 implements MigrationInterface {
|
||||||
|
name = 'DropSaltColumn1672109862870'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "salt"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" ADD "salt" character varying NOT NULL DEFAULT ''`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue