mirror of
https://github.com/immich-app/immich.git
synced 2025-01-21 00:52:43 -05:00
fix(server): remove shared links during user delete (#7696)
* fix(server): remove shared links during user delete * add delete cascade for shared links
This commit is contained in:
parent
a5a27594b8
commit
dbb6a8dc2a
5 changed files with 21 additions and 21 deletions
4
machine-learning/.gitignore
vendored
4
machine-learning/.gitignore
vendored
|
@ -171,4 +171,6 @@ cython_debug/
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
*.onnx
|
*.onnx
|
||||||
*.zip
|
*.zip
|
||||||
|
|
||||||
|
core
|
|
@ -8,7 +8,6 @@ import {
|
||||||
import {
|
import {
|
||||||
authStub,
|
authStub,
|
||||||
newAlbumRepositoryMock,
|
newAlbumRepositoryMock,
|
||||||
newAssetRepositoryMock,
|
|
||||||
newCryptoRepositoryMock,
|
newCryptoRepositoryMock,
|
||||||
newJobRepositoryMock,
|
newJobRepositoryMock,
|
||||||
newLibraryRepositoryMock,
|
newLibraryRepositoryMock,
|
||||||
|
@ -23,7 +22,6 @@ import { CacheControl, ImmichFileResponse } from '../domain.util';
|
||||||
import { JobName } from '../job';
|
import { JobName } from '../job';
|
||||||
import {
|
import {
|
||||||
IAlbumRepository,
|
IAlbumRepository,
|
||||||
IAssetRepository,
|
|
||||||
ICryptoRepository,
|
ICryptoRepository,
|
||||||
IJobRepository,
|
IJobRepository,
|
||||||
ILibraryRepository,
|
ILibraryRepository,
|
||||||
|
@ -47,7 +45,6 @@ describe(UserService.name, () => {
|
||||||
let cryptoRepositoryMock: jest.Mocked<ICryptoRepository>;
|
let cryptoRepositoryMock: jest.Mocked<ICryptoRepository>;
|
||||||
|
|
||||||
let albumMock: jest.Mocked<IAlbumRepository>;
|
let albumMock: jest.Mocked<IAlbumRepository>;
|
||||||
let assetMock: jest.Mocked<IAssetRepository>;
|
|
||||||
let jobMock: jest.Mocked<IJobRepository>;
|
let jobMock: jest.Mocked<IJobRepository>;
|
||||||
let libraryMock: jest.Mocked<ILibraryRepository>;
|
let libraryMock: jest.Mocked<ILibraryRepository>;
|
||||||
let storageMock: jest.Mocked<IStorageRepository>;
|
let storageMock: jest.Mocked<IStorageRepository>;
|
||||||
|
@ -55,7 +52,6 @@ describe(UserService.name, () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
albumMock = newAlbumRepositoryMock();
|
albumMock = newAlbumRepositoryMock();
|
||||||
assetMock = newAssetRepositoryMock();
|
|
||||||
configMock = newSystemConfigRepositoryMock();
|
configMock = newSystemConfigRepositoryMock();
|
||||||
cryptoRepositoryMock = newCryptoRepositoryMock();
|
cryptoRepositoryMock = newCryptoRepositoryMock();
|
||||||
jobMock = newJobRepositoryMock();
|
jobMock = newJobRepositoryMock();
|
||||||
|
@ -63,16 +59,7 @@ describe(UserService.name, () => {
|
||||||
storageMock = newStorageRepositoryMock();
|
storageMock = newStorageRepositoryMock();
|
||||||
userMock = newUserRepositoryMock();
|
userMock = newUserRepositoryMock();
|
||||||
|
|
||||||
sut = new UserService(
|
sut = new UserService(albumMock, cryptoRepositoryMock, jobMock, libraryMock, storageMock, configMock, userMock);
|
||||||
albumMock,
|
|
||||||
assetMock,
|
|
||||||
cryptoRepositoryMock,
|
|
||||||
jobMock,
|
|
||||||
libraryMock,
|
|
||||||
storageMock,
|
|
||||||
configMock,
|
|
||||||
userMock,
|
|
||||||
);
|
|
||||||
|
|
||||||
when(userMock.get).calledWith(authStub.admin.user.id, {}).mockResolvedValue(userStub.admin);
|
when(userMock.get).calledWith(authStub.admin.user.id, {}).mockResolvedValue(userStub.admin);
|
||||||
when(userMock.get).calledWith(authStub.admin.user.id, { withDeleted: true }).mockResolvedValue(userStub.admin);
|
when(userMock.get).calledWith(authStub.admin.user.id, { withDeleted: true }).mockResolvedValue(userStub.admin);
|
||||||
|
@ -537,7 +524,6 @@ describe(UserService.name, () => {
|
||||||
expect(storageMock.unlinkDir).toHaveBeenCalledWith('upload/thumbs/deleted-user', options);
|
expect(storageMock.unlinkDir).toHaveBeenCalledWith('upload/thumbs/deleted-user', options);
|
||||||
expect(storageMock.unlinkDir).toHaveBeenCalledWith('upload/encoded-video/deleted-user', options);
|
expect(storageMock.unlinkDir).toHaveBeenCalledWith('upload/encoded-video/deleted-user', options);
|
||||||
expect(albumMock.deleteAll).toHaveBeenCalledWith(user.id);
|
expect(albumMock.deleteAll).toHaveBeenCalledWith(user.id);
|
||||||
expect(assetMock.deleteAll).toHaveBeenCalledWith(user.id);
|
|
||||||
expect(userMock.delete).toHaveBeenCalledWith(user, true);
|
expect(userMock.delete).toHaveBeenCalledWith(user, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { CacheControl, ImmichFileResponse } from '../domain.util';
|
||||||
import { IEntityJob, JobName } from '../job';
|
import { IEntityJob, JobName } from '../job';
|
||||||
import {
|
import {
|
||||||
IAlbumRepository,
|
IAlbumRepository,
|
||||||
IAssetRepository,
|
|
||||||
ICryptoRepository,
|
ICryptoRepository,
|
||||||
IJobRepository,
|
IJobRepository,
|
||||||
ILibraryRepository,
|
ILibraryRepository,
|
||||||
|
@ -31,7 +30,6 @@ export class UserService {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(IAlbumRepository) private albumRepository: IAlbumRepository,
|
@Inject(IAlbumRepository) private albumRepository: IAlbumRepository,
|
||||||
@Inject(IAssetRepository) private assetRepository: IAssetRepository,
|
|
||||||
@Inject(ICryptoRepository) cryptoRepository: ICryptoRepository,
|
@Inject(ICryptoRepository) cryptoRepository: ICryptoRepository,
|
||||||
@Inject(IJobRepository) private jobRepository: IJobRepository,
|
@Inject(IJobRepository) private jobRepository: IJobRepository,
|
||||||
@Inject(ILibraryRepository) libraryRepository: ILibraryRepository,
|
@Inject(ILibraryRepository) libraryRepository: ILibraryRepository,
|
||||||
|
@ -185,9 +183,7 @@ export class UserService {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.warn(`Removing user from database: ${user.id}`);
|
this.logger.warn(`Removing user from database: ${user.id}`);
|
||||||
|
|
||||||
await this.albumRepository.deleteAll(user.id);
|
await this.albumRepository.deleteAll(user.id);
|
||||||
await this.assetRepository.deleteAll(user.id);
|
|
||||||
await this.userRepository.delete(user, true);
|
await this.userRepository.delete(user, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -27,7 +27,7 @@ export class SharedLinkEntity {
|
||||||
@Column()
|
@Column()
|
||||||
userId!: string;
|
userId!: string;
|
||||||
|
|
||||||
@ManyToOne(() => UserEntity)
|
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
|
||||||
user!: UserEntity;
|
user!: UserEntity;
|
||||||
|
|
||||||
@Index('IDX_sharedlink_key')
|
@Index('IDX_sharedlink_key')
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class CascadeSharedLinksDelete1709825430031 implements MigrationInterface {
|
||||||
|
name = 'CascadeSharedLinksDelete1709825430031'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "shared_links" DROP CONSTRAINT "FK_66fe3837414c5a9f1c33ca49340"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "shared_links" ADD CONSTRAINT "FK_66fe3837414c5a9f1c33ca49340" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "shared_links" DROP CONSTRAINT "FK_66fe3837414c5a9f1c33ca49340"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "shared_links" ADD CONSTRAINT "FK_66fe3837414c5a9f1c33ca49340" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue