fix(server): Error when loading album with deleted owner (#4086)

* soft delete albums when user gets soft deleted

* fix wrong intl openapi version

* fix tests

* ability to restore albums, automatically restore when user restored

* (e2e) tests for shared albums via link and with user

* (e2e) test deletion of users and linked albums

* (e2e) fix share album with owner test

* fix: deletedAt

* chore: fix restore order

* fix: use timezone date column

* chore: cleanup e2e tests

* (e2e) fix user delete test

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
Daniel Dietzler 2023-09-18 17:56:50 +02:00 committed by GitHub
parent 7d07aaeba3
commit f1c98ac9e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 149 additions and 21 deletions

View file

@ -1,17 +1,21 @@
import { LoginResponseDto } from '@app/domain';
import { LoginResponseDto, UserResponseDto, UserService } from '@app/domain';
import { AppModule, UserController } from '@app/immich';
import { UserEntity } from '@app/infra/entities';
import { INestApplication } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { api } from '@test/api';
import { db } from '@test/db';
import { errorStub, userSignupStub, userStub } from '@test/fixtures';
import request from 'supertest';
import { Repository } from 'typeorm';
describe(`${UserController.name}`, () => {
let app: INestApplication;
let server: any;
let loginResponse: LoginResponseDto;
let accessToken: string;
let userService: UserService;
let userRepository: Repository<UserEntity>;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
@ -19,6 +23,7 @@ describe(`${UserController.name}`, () => {
}).compile();
app = await moduleFixture.createNestApplication().init();
userRepository = moduleFixture.get('UserEntityRepository');
server = app.getHttpServer();
});
@ -27,6 +32,8 @@ describe(`${UserController.name}`, () => {
await api.authApi.adminSignUp(server);
loginResponse = await api.authApi.adminLogin(server);
accessToken = loginResponse.accessToken;
userService = app.get<UserService>(UserService);
});
afterAll(async () => {
@ -173,6 +180,50 @@ describe(`${UserController.name}`, () => {
});
});
describe('DELETE /user/:id', () => {
let userToDelete: UserResponseDto;
beforeEach(async () => {
userToDelete = await api.userApi.create(server, accessToken, {
email: userStub.user1.email,
firstName: userStub.user1.firstName,
lastName: userStub.user1.lastName,
password: 'superSecurePassword',
});
});
it('should require authentication', async () => {
const { status, body } = await request(server).delete(`/user/${userToDelete.id}`);
expect(status).toBe(401);
expect(body).toEqual(errorStub.unauthorized);
});
it('should delete user', async () => {
const deleteRequest = await request(server)
.delete(`/user/${userToDelete.id}`)
.set('Authorization', `Bearer ${accessToken}`);
expect(deleteRequest.status).toBe(200);
expect(deleteRequest.body).toEqual({
...userToDelete,
updatedAt: expect.any(String),
deletedAt: expect.any(String),
});
await userRepository.save({ id: deleteRequest.body.id, deletedAt: new Date('1970-01-01').toISOString() });
await userService.handleUserDelete({ id: userToDelete.id });
const { status, body } = await request(server)
.get('/user')
.query({ isAll: false })
.set('Authorization', `Bearer ${accessToken}`);
expect(status).toBe(200);
expect(body).toHaveLength(1);
});
});
describe('PUT /user', () => {
it('should require authentication', async () => {
const { status, body } = await request(server).put(`/user`);
@ -237,9 +288,9 @@ describe(`${UserController.name}`, () => {
lastName: 'Last Name',
});
expect(after).toMatchObject({
expect(after).toEqual({
...before,
updatedAt: expect.anything(),
updatedAt: expect.any(String),
firstName: 'First Name',
lastName: 'Last Name',
});