refactor(server): new password repo method (#8208)

This commit is contained in:
Jason Rasmussen 2024-03-23 14:33:25 -04:00 committed by GitHub
parent 604b8ff17c
commit 787eebcf1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 15 additions and 10 deletions

View File

@ -3,6 +3,8 @@ import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { Version } from 'src/utils/version';
export const SALT_ROUNDS = 10;
const { version } = JSON.parse(readFileSync('./package.json', 'utf8'));
export const serverVersion = Version.fromString(version);

View File

@ -1,5 +1,6 @@
import { BadRequestException, ForbiddenException } from '@nestjs/common';
import sanitize from 'sanitize-filename';
import { SALT_ROUNDS } from 'src/constants';
import { UserResponseDto } from 'src/dtos/user.dto';
import { LibraryType } from 'src/entities/library.entity';
import { UserEntity } from 'src/entities/user.entity';
@ -7,8 +8,6 @@ import { ICryptoRepository } from 'src/interfaces/crypto.interface';
import { ILibraryRepository } from 'src/interfaces/library.interface';
import { IUserRepository } from 'src/interfaces/user.interface';
const SALT_ROUNDS = 10;
let instance: UserCore | null;
export class UserCore {

View File

@ -8,4 +8,5 @@ export interface ICryptoRepository {
hashSha1(data: string | Buffer): Buffer;
hashBcrypt(data: string | Buffer, saltOrRounds: string | number): Promise<string>;
compareBcrypt(data: string | Buffer, encrypted: string): boolean;
newPassword(bytes: number): string;
}

View File

@ -41,4 +41,8 @@ export class CryptoRepository implements ICryptoRepository {
stream.on('end', () => resolve(hash.digest()));
});
}
newPassword(bytes: number) {
return randomBytes(bytes).toString('base64').replaceAll(/\W/g, '');
}
}

View File

@ -27,7 +27,7 @@ describe(APIKeyService.name, () => {
name: 'Test Key',
userId: authStub.admin.user.id,
});
expect(cryptoMock.randomBytes).toHaveBeenCalled();
expect(cryptoMock.newPassword).toHaveBeenCalled();
expect(cryptoMock.hashSha256).toHaveBeenCalled();
});
@ -41,7 +41,7 @@ describe(APIKeyService.name, () => {
name: 'API Key',
userId: authStub.admin.user.id,
});
expect(cryptoMock.randomBytes).toHaveBeenCalled();
expect(cryptoMock.newPassword).toHaveBeenCalled();
expect(cryptoMock.hashSha256).toHaveBeenCalled();
});
});

View File

@ -13,7 +13,7 @@ export class APIKeyService {
) {}
async create(auth: AuthDto, dto: APIKeyCreateDto): Promise<APIKeyCreateResponseDto> {
const secret = this.crypto.randomBytes(32).toString('base64').replaceAll(/\W/g, '');
const secret = this.crypto.newPassword(32);
const entity = await this.repository.create({
key: this.crypto.hashSha256(secret),
name: dto.name || 'API Key',

View File

@ -146,7 +146,6 @@ export class AuthService {
async adminSignUp(dto: SignUpDto): Promise<UserResponseDto> {
const adminUser = await this.userRepository.getAdmin();
if (adminUser) {
throw new BadRequestException('The server already has an admin');
}
@ -427,7 +426,7 @@ export class AuthService {
}
private async createLoginResponse(user: UserEntity, authType: AuthType, loginDetails: LoginDetails) {
const key = this.cryptoRepository.randomBytes(32).toString('base64').replaceAll(/\W/g, '');
const key = this.cryptoRepository.newPassword(32);
const token = this.cryptoRepository.hashSha256(key);
await this.userTokenRepository.create({

View File

@ -1,6 +1,5 @@
import { BadRequestException, ForbiddenException, Inject, Injectable, NotFoundException } from '@nestjs/common';
import { DateTime } from 'luxon';
import { randomBytes } from 'node:crypto';
import { StorageCore, StorageFolder } from 'src/cores/storage.core';
import { SystemConfigCore } from 'src/cores/system-config.core';
import { UserCore } from 'src/cores/user.core';
@ -26,7 +25,7 @@ export class UserService {
constructor(
@Inject(IAlbumRepository) private albumRepository: IAlbumRepository,
@Inject(ICryptoRepository) cryptoRepository: ICryptoRepository,
@Inject(ICryptoRepository) private cryptoRepository: ICryptoRepository,
@Inject(IJobRepository) private jobRepository: IJobRepository,
@Inject(ILibraryRepository) libraryRepository: ILibraryRepository,
@Inject(IStorageRepository) private storageRepository: IStorageRepository,
@ -132,7 +131,7 @@ export class UserService {
}
const providedPassword = await ask(mapUser(admin));
const password = providedPassword || randomBytes(24).toString('base64').replaceAll(/\W/g, '');
const password = providedPassword || this.cryptoRepository.newPassword(24);
await this.userCore.updateUser(admin, admin.id, { password });

View File

@ -9,5 +9,6 @@ export const newCryptoRepositoryMock = (): jest.Mocked<ICryptoRepository> => {
hashSha256: jest.fn().mockImplementation((input) => `${input} (hashed)`),
hashSha1: jest.fn().mockImplementation((input) => Buffer.from(`${input.toString()} (hashed)`)),
hashFile: jest.fn().mockImplementation((input) => `${input} (file-hashed)`),
newPassword: jest.fn().mockReturnValue(Buffer.from('random-bytes').toString('base64')),
};
};