2023-11-14 04:10:35 +01:00
|
|
|
import { UserAvatarColor } from '@app/infra/entities';
|
2023-05-15 19:30:53 +02:00
|
|
|
import { BadRequestException } from '@nestjs/common';
|
2023-06-08 17:01:07 +02:00
|
|
|
import { authStub, newPartnerRepositoryMock, partnerStub } from '@test';
|
2023-11-11 22:06:19 +01:00
|
|
|
import { IAccessRepository, IPartnerRepository, PartnerDirection } from '../repositories';
|
|
|
|
import { PartnerResponseDto } from './partner.dto';
|
2023-05-15 19:30:53 +02:00
|
|
|
import { PartnerService } from './partner.service';
|
|
|
|
|
|
|
|
const responseDto = {
|
2023-11-11 22:06:19 +01:00
|
|
|
admin: <PartnerResponseDto>{
|
2023-05-15 19:30:53 +02:00
|
|
|
email: 'admin@test.com',
|
2023-11-12 02:03:32 +01:00
|
|
|
name: 'admin_name',
|
2023-05-15 19:30:53 +02:00
|
|
|
id: 'admin_id',
|
|
|
|
isAdmin: true,
|
|
|
|
oauthId: '',
|
|
|
|
profileImagePath: '',
|
|
|
|
shouldChangePassword: false,
|
2023-05-22 05:18:10 +02:00
|
|
|
storageLabel: 'admin',
|
2023-05-30 15:15:56 +02:00
|
|
|
createdAt: new Date('2021-01-01'),
|
|
|
|
deletedAt: null,
|
|
|
|
updatedAt: new Date('2021-01-01'),
|
feat(server): support for read-only assets and importing existing items in the filesystem (#2715)
* Added read-only flag for assets, endpoint to trigger file import vs upload
* updated fixtures with new property
* if upload is 'read-only', ensure there is no existing asset at the designated originalPath
* added test for file import as well as detecting existing image at read-only destination location
* Added storage service test for a case where it should not move read-only assets
* upload doesn't need the read-only flag available, just importing
* default isReadOnly on import endpoint to true
* formatting fixes
* create-asset dto needs isReadOnly, so set it to false by default on create, updated api generation
* updated code to reflect changes in MR
* fixed read stream promise return type
* new index for originalPath, check for existing path on import, reglardless of user, to prevent duplicates
* refactor: import asset
* chore: open api
* chore: tests
* Added externalPath support for individual users, updated UI to allow this to be set by admin
* added missing var for externalPath in ui
* chore: open api
* fix: compilation issues
* fix: server test
* built api, fixed user-response dto to include externalPath
* reverted accidental commit
* bad commit of duplicate externalPath in user response dto
* fixed tests to include externalPath on expected result
* fix: unit tests
* centralized supported filetypes, perform file type checking of asset and sidecar during file import process
* centralized supported filetype check method to keep regex DRY
* fixed typo
* combined migrations into one
* update api
* Removed externalPath from shared-link code, added column to admin user page whether external paths / import is enabled or not
* update mimetype
* Fixed detect correct mimetype
* revert asset-upload config
* reverted domain.constant
* refactor
* fix mime-type issue
* fix format
---------
Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2023-06-22 04:33:20 +02:00
|
|
|
externalPath: null,
|
2023-08-10 04:01:16 +02:00
|
|
|
memoriesEnabled: true,
|
2023-11-14 04:10:35 +01:00
|
|
|
avatarColor: UserAvatarColor.PRIMARY,
|
2023-11-11 22:06:19 +01:00
|
|
|
inTimeline: true,
|
2023-05-15 19:30:53 +02:00
|
|
|
},
|
2023-11-11 22:06:19 +01:00
|
|
|
user1: <PartnerResponseDto>{
|
2023-05-15 19:30:53 +02:00
|
|
|
email: 'immich@test.com',
|
2023-11-12 02:03:32 +01:00
|
|
|
name: 'immich_name',
|
2023-05-22 05:18:10 +02:00
|
|
|
id: 'user-id',
|
2023-05-15 19:30:53 +02:00
|
|
|
isAdmin: false,
|
|
|
|
oauthId: '',
|
|
|
|
profileImagePath: '',
|
|
|
|
shouldChangePassword: false,
|
2023-05-22 05:18:10 +02:00
|
|
|
storageLabel: null,
|
2023-05-30 15:15:56 +02:00
|
|
|
createdAt: new Date('2021-01-01'),
|
|
|
|
deletedAt: null,
|
|
|
|
updatedAt: new Date('2021-01-01'),
|
feat(server): support for read-only assets and importing existing items in the filesystem (#2715)
* Added read-only flag for assets, endpoint to trigger file import vs upload
* updated fixtures with new property
* if upload is 'read-only', ensure there is no existing asset at the designated originalPath
* added test for file import as well as detecting existing image at read-only destination location
* Added storage service test for a case where it should not move read-only assets
* upload doesn't need the read-only flag available, just importing
* default isReadOnly on import endpoint to true
* formatting fixes
* create-asset dto needs isReadOnly, so set it to false by default on create, updated api generation
* updated code to reflect changes in MR
* fixed read stream promise return type
* new index for originalPath, check for existing path on import, reglardless of user, to prevent duplicates
* refactor: import asset
* chore: open api
* chore: tests
* Added externalPath support for individual users, updated UI to allow this to be set by admin
* added missing var for externalPath in ui
* chore: open api
* fix: compilation issues
* fix: server test
* built api, fixed user-response dto to include externalPath
* reverted accidental commit
* bad commit of duplicate externalPath in user response dto
* fixed tests to include externalPath on expected result
* fix: unit tests
* centralized supported filetypes, perform file type checking of asset and sidecar during file import process
* centralized supported filetype check method to keep regex DRY
* fixed typo
* combined migrations into one
* update api
* Removed externalPath from shared-link code, added column to admin user page whether external paths / import is enabled or not
* update mimetype
* Fixed detect correct mimetype
* revert asset-upload config
* reverted domain.constant
* refactor
* fix mime-type issue
* fix format
---------
Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2023-06-22 04:33:20 +02:00
|
|
|
externalPath: null,
|
2023-08-10 04:01:16 +02:00
|
|
|
memoriesEnabled: true,
|
2023-11-14 04:10:35 +01:00
|
|
|
avatarColor: UserAvatarColor.PRIMARY,
|
2023-11-11 22:06:19 +01:00
|
|
|
inTimeline: true,
|
2023-05-15 19:30:53 +02:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
describe(PartnerService.name, () => {
|
|
|
|
let sut: PartnerService;
|
|
|
|
let partnerMock: jest.Mocked<IPartnerRepository>;
|
2023-11-11 22:06:19 +01:00
|
|
|
let accessMock: jest.Mocked<IAccessRepository>;
|
2023-05-15 19:30:53 +02:00
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
partnerMock = newPartnerRepositoryMock();
|
2023-11-11 22:06:19 +01:00
|
|
|
sut = new PartnerService(partnerMock, accessMock);
|
2023-05-15 19:30:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should work', () => {
|
|
|
|
expect(sut).toBeDefined();
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('getAll', () => {
|
|
|
|
it("should return a list of partners with whom I've shared my library", async () => {
|
|
|
|
partnerMock.getAll.mockResolvedValue([partnerStub.adminToUser1, partnerStub.user1ToAdmin1]);
|
|
|
|
await expect(sut.getAll(authStub.user1, PartnerDirection.SharedBy)).resolves.toEqual([responseDto.admin]);
|
|
|
|
expect(partnerMock.getAll).toHaveBeenCalledWith(authStub.user1.id);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return a list of partners who have shared their libraries with me', async () => {
|
|
|
|
partnerMock.getAll.mockResolvedValue([partnerStub.adminToUser1, partnerStub.user1ToAdmin1]);
|
|
|
|
await expect(sut.getAll(authStub.user1, PartnerDirection.SharedWith)).resolves.toEqual([responseDto.admin]);
|
|
|
|
expect(partnerMock.getAll).toHaveBeenCalledWith(authStub.user1.id);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('create', () => {
|
|
|
|
it('should create a new partner', async () => {
|
|
|
|
partnerMock.get.mockResolvedValue(null);
|
|
|
|
partnerMock.create.mockResolvedValue(partnerStub.adminToUser1);
|
|
|
|
|
|
|
|
await expect(sut.create(authStub.admin, authStub.user1.id)).resolves.toEqual(responseDto.user1);
|
|
|
|
|
|
|
|
expect(partnerMock.create).toHaveBeenCalledWith({
|
|
|
|
sharedById: authStub.admin.id,
|
|
|
|
sharedWithId: authStub.user1.id,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw an error when the partner already exists', async () => {
|
|
|
|
partnerMock.get.mockResolvedValue(partnerStub.adminToUser1);
|
|
|
|
|
|
|
|
await expect(sut.create(authStub.admin, authStub.user1.id)).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
|
|
|
|
expect(partnerMock.create).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('remove', () => {
|
|
|
|
it('should remove a partner', async () => {
|
|
|
|
partnerMock.get.mockResolvedValue(partnerStub.adminToUser1);
|
|
|
|
|
|
|
|
await sut.remove(authStub.admin, authStub.user1.id);
|
|
|
|
|
|
|
|
expect(partnerMock.remove).toHaveBeenCalledWith(partnerStub.adminToUser1);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw an error when the partner does not exist', async () => {
|
|
|
|
partnerMock.get.mockResolvedValue(null);
|
|
|
|
|
|
|
|
await expect(sut.remove(authStub.admin, authStub.user1.id)).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
|
|
|
|
expect(partnerMock.remove).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|