mirror of
https://github.com/KevinMidboe/immich.git
synced 2025-10-29 17:40:28 +00:00
feat(server): move authentication to tokens stored in the database (#1381)
* chore: add typeorm commands to npm and set default database config values * feat: move to server side authentication tokens * fix: websocket should emit error and disconnect on error thrown by the server * refactor: rename cookie-auth-strategy to user-auth-strategy * feat: user tokens and API keys now use SHA256 hash for performance improvements * test: album e2e test remove unneeded module import * infra: truncate api key table as old keys will no longer work with new hash algorithm * fix(server): e2e tests (#1435) * fix: root module paths * chore: linting * chore: rename user-auth to strategy.ts and make validate return AuthUserDto * fix: we should always send HttpOnly for our auth cookies * chore: remove now unused crypto functions and jwt dependencies * fix: return the extra fields for AuthUserDto in auth service validate --------- Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
@@ -10,14 +10,14 @@ import {
|
||||
import { hash } from 'bcrypt';
|
||||
import { constants, createReadStream, ReadStream } from 'fs';
|
||||
import fs from 'fs/promises';
|
||||
import { AuthUserDto } from '../auth';
|
||||
import { AuthUserDto, ICryptoRepository } from '../auth';
|
||||
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) {}
|
||||
constructor(private userRepository: IUserRepository, private cryptoRepository: ICryptoRepository) {}
|
||||
|
||||
async updateUser(authUser: AuthUserDto, id: string, dto: Partial<UserEntity>): Promise<UserEntity> {
|
||||
if (!(authUser.isAdmin || authUser.id === id)) {
|
||||
@@ -37,7 +37,7 @@ export class UserCore {
|
||||
|
||||
try {
|
||||
if (dto.password) {
|
||||
dto.password = await hash(dto.password, SALT_ROUNDS);
|
||||
dto.password = await this.cryptoRepository.hashBcrypt(dto.password, SALT_ROUNDS);
|
||||
}
|
||||
|
||||
return this.userRepository.update(id, dto);
|
||||
|
||||
@@ -2,8 +2,8 @@ import { IUserRepository } from './user.repository';
|
||||
import { UserEntity } from '@app/infra/db/entities';
|
||||
import { BadRequestException, ForbiddenException, NotFoundException } from '@nestjs/common';
|
||||
import { when } from 'jest-when';
|
||||
import { newUserRepositoryMock } from '../../test';
|
||||
import { AuthUserDto } from '../auth';
|
||||
import { newCryptoRepositoryMock, newUserRepositoryMock } from '../../test';
|
||||
import { AuthUserDto, ICryptoRepository } from '../auth';
|
||||
import { UpdateUserDto } from './dto/update-user.dto';
|
||||
import { UserService } from './user.service';
|
||||
|
||||
@@ -77,10 +77,12 @@ const adminUserResponse = Object.freeze({
|
||||
describe(UserService.name, () => {
|
||||
let sut: UserService;
|
||||
let userRepositoryMock: jest.Mocked<IUserRepository>;
|
||||
let cryptoRepositoryMock: jest.Mocked<ICryptoRepository>;
|
||||
|
||||
beforeEach(async () => {
|
||||
userRepositoryMock = newUserRepositoryMock();
|
||||
sut = new UserService(userRepositoryMock);
|
||||
cryptoRepositoryMock = newCryptoRepositoryMock();
|
||||
sut = new UserService(userRepositoryMock, cryptoRepositoryMock);
|
||||
|
||||
when(userRepositoryMock.get).calledWith(adminUser.id).mockResolvedValue(adminUser);
|
||||
when(userRepositoryMock.get).calledWith(adminUser.id, undefined).mockResolvedValue(adminUser);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { BadRequestException, Inject, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { randomBytes } from 'crypto';
|
||||
import { ReadStream } from 'fs';
|
||||
import { AuthUserDto } from '../auth';
|
||||
import { AuthUserDto, ICryptoRepository } from '../auth';
|
||||
import { IUserRepository } from '../user';
|
||||
import { CreateUserDto } from './dto/create-user.dto';
|
||||
import { UpdateUserDto } from './dto/update-user.dto';
|
||||
@@ -17,8 +17,11 @@ import { UserCore } from './user.core';
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
private userCore: UserCore;
|
||||
constructor(@Inject(IUserRepository) userRepository: IUserRepository) {
|
||||
this.userCore = new UserCore(userRepository);
|
||||
constructor(
|
||||
@Inject(IUserRepository) userRepository: IUserRepository,
|
||||
@Inject(ICryptoRepository) cryptoRepository: ICryptoRepository,
|
||||
) {
|
||||
this.userCore = new UserCore(userRepository, cryptoRepository);
|
||||
}
|
||||
|
||||
async getAllUsers(authUser: AuthUserDto, isAll: boolean): Promise<UserResponseDto[]> {
|
||||
|
||||
Reference in New Issue
Block a user