2023-10-29 02:35:38 +01:00
|
|
|
import { BadRequestException, ForbiddenException, UnauthorizedException } from '@nestjs/common';
|
2023-06-21 03:08:43 +02:00
|
|
|
import _ from 'lodash';
|
2024-03-20 23:53:07 +01:00
|
|
|
import { AssetIdErrorReason } from 'src/dtos/asset-ids.response.dto';
|
2024-03-20 22:02:51 +01:00
|
|
|
import { SharedLinkType } from 'src/entities/shared-link.entity';
|
2024-03-21 12:59:49 +01:00
|
|
|
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
|
|
|
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
2024-03-21 00:07:30 +01:00
|
|
|
import { SharedLinkService } from 'src/services/shared-link.service';
|
2024-03-20 19:32:04 +01:00
|
|
|
import { albumStub } from 'test/fixtures/album.stub';
|
|
|
|
import { assetStub } from 'test/fixtures/asset.stub';
|
|
|
|
import { authStub } from 'test/fixtures/auth.stub';
|
|
|
|
import { sharedLinkResponseStub, sharedLinkStub } from 'test/fixtures/shared-link.stub';
|
|
|
|
import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock';
|
|
|
|
import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock';
|
|
|
|
import { newSharedLinkRepositoryMock } from 'test/repositories/shared-link.repository.mock';
|
2024-04-16 16:44:45 +02:00
|
|
|
import { Mocked } from 'vitest';
|
2023-06-02 04:09:57 +02:00
|
|
|
|
|
|
|
describe(SharedLinkService.name, () => {
|
|
|
|
let sut: SharedLinkService;
|
2023-06-28 15:56:24 +02:00
|
|
|
let accessMock: IAccessRepositoryMock;
|
2024-04-16 16:44:45 +02:00
|
|
|
let cryptoMock: Mocked<ICryptoRepository>;
|
|
|
|
let shareMock: Mocked<ISharedLinkRepository>;
|
2023-06-02 04:09:57 +02:00
|
|
|
|
2024-03-05 23:23:06 +01:00
|
|
|
beforeEach(() => {
|
2023-06-21 03:08:43 +02:00
|
|
|
accessMock = newAccessRepositoryMock();
|
|
|
|
cryptoMock = newCryptoRepositoryMock();
|
2023-06-02 04:09:57 +02:00
|
|
|
shareMock = newSharedLinkRepositoryMock();
|
|
|
|
|
2023-06-21 03:08:43 +02:00
|
|
|
sut = new SharedLinkService(accessMock, cryptoMock, shareMock);
|
2023-06-02 04:09:57 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should work', () => {
|
|
|
|
expect(sut).toBeDefined();
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('getAll', () => {
|
|
|
|
it('should return all shared links for a user', async () => {
|
|
|
|
shareMock.getAll.mockResolvedValue([sharedLinkStub.expired, sharedLinkStub.valid]);
|
|
|
|
await expect(sut.getAll(authStub.user1)).resolves.toEqual([
|
|
|
|
sharedLinkResponseStub.expired,
|
|
|
|
sharedLinkResponseStub.valid,
|
|
|
|
]);
|
2023-12-10 05:34:12 +01:00
|
|
|
expect(shareMock.getAll).toHaveBeenCalledWith(authStub.user1.user.id);
|
2023-06-02 04:09:57 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('getMine', () => {
|
|
|
|
it('should only work for a public user', async () => {
|
2023-10-29 02:35:38 +01:00
|
|
|
await expect(sut.getMine(authStub.admin, {})).rejects.toBeInstanceOf(ForbiddenException);
|
2023-06-02 04:09:57 +02:00
|
|
|
expect(shareMock.get).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return the shared link for the public user', async () => {
|
|
|
|
const authDto = authStub.adminSharedLink;
|
|
|
|
shareMock.get.mockResolvedValue(sharedLinkStub.valid);
|
2023-10-29 02:35:38 +01:00
|
|
|
await expect(sut.getMine(authDto, {})).resolves.toEqual(sharedLinkResponseStub.valid);
|
2023-12-10 05:34:12 +01:00
|
|
|
expect(shareMock.get).toHaveBeenCalledWith(authDto.user.id, authDto.sharedLink?.id);
|
2023-06-02 04:09:57 +02:00
|
|
|
});
|
|
|
|
|
2023-10-14 03:46:30 +02:00
|
|
|
it('should not return metadata', async () => {
|
2023-06-02 04:09:57 +02:00
|
|
|
const authDto = authStub.adminSharedLinkNoExif;
|
|
|
|
shareMock.get.mockResolvedValue(sharedLinkStub.readonlyNoExif);
|
2023-10-29 02:35:38 +01:00
|
|
|
await expect(sut.getMine(authDto, {})).resolves.toEqual(sharedLinkResponseStub.readonlyNoMetadata);
|
2023-12-10 05:34:12 +01:00
|
|
|
expect(shareMock.get).toHaveBeenCalledWith(authDto.user.id, authDto.sharedLink?.id);
|
2023-10-29 02:35:38 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw an error for an password protected shared link', async () => {
|
|
|
|
const authDto = authStub.adminSharedLink;
|
|
|
|
shareMock.get.mockResolvedValue(sharedLinkStub.passwordRequired);
|
|
|
|
await expect(sut.getMine(authDto, {})).rejects.toBeInstanceOf(UnauthorizedException);
|
2023-12-10 05:34:12 +01:00
|
|
|
expect(shareMock.get).toHaveBeenCalledWith(authDto.user.id, authDto.sharedLink?.id);
|
2023-06-02 04:09:57 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('get', () => {
|
|
|
|
it('should throw an error for an invalid shared link', async () => {
|
|
|
|
shareMock.get.mockResolvedValue(null);
|
|
|
|
await expect(sut.get(authStub.user1, 'missing-id')).rejects.toBeInstanceOf(BadRequestException);
|
2023-12-10 05:34:12 +01:00
|
|
|
expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.user.id, 'missing-id');
|
2023-06-02 04:09:57 +02:00
|
|
|
expect(shareMock.update).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should get a shared link by id', async () => {
|
|
|
|
shareMock.get.mockResolvedValue(sharedLinkStub.valid);
|
|
|
|
await expect(sut.get(authStub.user1, sharedLinkStub.valid.id)).resolves.toEqual(sharedLinkResponseStub.valid);
|
2023-12-10 05:34:12 +01:00
|
|
|
expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.user.id, sharedLinkStub.valid.id);
|
2023-06-02 04:09:57 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2023-06-21 03:08:43 +02:00
|
|
|
describe('create', () => {
|
|
|
|
it('should not allow an album shared link without an albumId', async () => {
|
|
|
|
await expect(sut.create(authStub.admin, { type: SharedLinkType.ALBUM, assetIds: [] })).rejects.toBeInstanceOf(
|
|
|
|
BadRequestException,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not allow non-owners to create album shared links', async () => {
|
|
|
|
await expect(
|
|
|
|
sut.create(authStub.admin, { type: SharedLinkType.ALBUM, assetIds: [], albumId: 'album-1' }),
|
|
|
|
).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not allow individual shared links with no assets', async () => {
|
|
|
|
await expect(
|
|
|
|
sut.create(authStub.admin, { type: SharedLinkType.INDIVIDUAL, assetIds: [] }),
|
|
|
|
).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should require asset ownership to make an individual shared link', async () => {
|
|
|
|
await expect(
|
|
|
|
sut.create(authStub.admin, { type: SharedLinkType.INDIVIDUAL, assetIds: ['asset-1'] }),
|
|
|
|
).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should create an album shared link', async () => {
|
2023-11-25 23:56:23 +01:00
|
|
|
accessMock.album.checkOwnerAccess.mockResolvedValue(new Set([albumStub.oneAsset.id]));
|
2023-06-21 03:08:43 +02:00
|
|
|
shareMock.create.mockResolvedValue(sharedLinkStub.valid);
|
|
|
|
|
|
|
|
await sut.create(authStub.admin, { type: SharedLinkType.ALBUM, albumId: albumStub.oneAsset.id });
|
|
|
|
|
2023-11-25 23:56:23 +01:00
|
|
|
expect(accessMock.album.checkOwnerAccess).toHaveBeenCalledWith(
|
2023-12-10 05:34:12 +01:00
|
|
|
authStub.admin.user.id,
|
2023-11-25 23:56:23 +01:00
|
|
|
new Set([albumStub.oneAsset.id]),
|
|
|
|
);
|
2023-06-21 03:08:43 +02:00
|
|
|
expect(shareMock.create).toHaveBeenCalledWith({
|
|
|
|
type: SharedLinkType.ALBUM,
|
2023-12-10 05:34:12 +01:00
|
|
|
userId: authStub.admin.user.id,
|
2023-06-21 03:08:43 +02:00
|
|
|
albumId: albumStub.oneAsset.id,
|
|
|
|
allowDownload: true,
|
|
|
|
allowUpload: true,
|
|
|
|
assets: [],
|
|
|
|
description: null,
|
|
|
|
expiresAt: null,
|
|
|
|
showExif: true,
|
|
|
|
key: Buffer.from('random-bytes', 'utf8'),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should create an individual shared link', async () => {
|
chore(server): Check asset permissions in bulk (#5329)
Modify Access repository, to evaluate `asset` permissions in bulk.
Queries have been validated to match what they currently generate for single ids.
Queries:
* `asset` album access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "albums" "AlbumEntity"
LEFT JOIN "albums_assets_assets" "AlbumEntity_AlbumEntity__AlbumEntity_assets"
ON "AlbumEntity_AlbumEntity__AlbumEntity_assets"."albumsId"="AlbumEntity"."id"
LEFT JOIN "assets" "AlbumEntity__AlbumEntity_assets"
ON "AlbumEntity__AlbumEntity_assets"."id"="AlbumEntity_AlbumEntity__AlbumEntity_assets"."assetsId"
AND "AlbumEntity__AlbumEntity_assets"."deletedAt" IS NULL
LEFT JOIN "albums_shared_users_users" "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"
ON "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."albumsId"="AlbumEntity"."id"
LEFT JOIN "users" "AlbumEntity__AlbumEntity_sharedUsers"
ON "AlbumEntity__AlbumEntity_sharedUsers"."id"="AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."usersId"
AND "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" IS NULL
WHERE
(
("AlbumEntity"."ownerId" = $1 AND "AlbumEntity__AlbumEntity_assets"."id" = $2)
OR ("AlbumEntity__AlbumEntity_sharedUsers"."id" = $3 AND "AlbumEntity__AlbumEntity_assets"."id" = $4)
OR ("AlbumEntity"."ownerId" = $5 AND "AlbumEntity__AlbumEntity_assets"."livePhotoVideoId" = $6)
OR ("AlbumEntity__AlbumEntity_sharedUsers"."id" = $7 AND "AlbumEntity__AlbumEntity_assets"."livePhotoVideoId" = $8)
)
AND "AlbumEntity"."deletedAt" IS NULL
)
LIMIT 1
-- After
SELECT
"asset"."id" AS "assetId",
"asset"."livePhotoVideoId" AS "livePhotoVideoId"
FROM "albums" "album"
INNER JOIN "albums_assets_assets" "album_asset"
ON "album_asset"."albumsId"="album"."id"
INNER JOIN "assets" "asset"
ON "asset"."id"="album_asset"."assetsId"
AND "asset"."deletedAt" IS NULL
LEFT JOIN "albums_shared_users_users" "album_sharedUsers"
ON "album_sharedUsers"."albumsId"="album"."id"
LEFT JOIN "users" "sharedUsers"
ON "sharedUsers"."id"="album_sharedUsers"."usersId"
AND "sharedUsers"."deletedAt" IS NULL
WHERE
(
"album"."ownerId" = $1
OR "sharedUsers"."id" = $2
)
AND (
"asset"."id" IN ($3, $4)
OR "asset"."livePhotoVideoId" IN ($5, $6)
)
AND "album"."deletedAt" IS NULL
```
* `asset` owner access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "assets" "AssetEntity"
WHERE
"AssetEntity"."id" = $1
AND "AssetEntity"."ownerId" = $2
)
LIMIT 1
-- After
SELECT
"AssetEntity"."id" AS "AssetEntity_id"
FROM "assets" "AssetEntity"
WHERE
"AssetEntity"."id" IN ($1, $2)
AND "AssetEntity"."ownerId" = $3
```
* `asset` partner access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "partners" "PartnerEntity"
LEFT JOIN "users" "PartnerEntity__PartnerEntity_sharedWith"
ON "PartnerEntity__PartnerEntity_sharedWith"."id"="PartnerEntity"."sharedWithId"
AND "PartnerEntity__PartnerEntity_sharedWith"."deletedAt" IS NULL
LEFT JOIN "users" "PartnerEntity__PartnerEntity_sharedBy"
ON "PartnerEntity__PartnerEntity_sharedBy"."id"="PartnerEntity"."sharedById"
AND "PartnerEntity__PartnerEntity_sharedBy"."deletedAt" IS NULL
LEFT JOIN "assets" "0aabe9f4a62b794e2c24a074297e534f51a4ac6c"
ON "0aabe9f4a62b794e2c24a074297e534f51a4ac6c"."ownerId"="PartnerEntity__PartnerEntity_sharedBy"."id"
AND "0aabe9f4a62b794e2c24a074297e534f51a4ac6c"."deletedAt" IS NULL
LEFT JOIN "users" "PartnerEntity__sharedBy"
ON "PartnerEntity__sharedBy"."id"="PartnerEntity"."sharedById"
AND "PartnerEntity__sharedBy"."deletedAt" IS NULL
LEFT JOIN "users" "PartnerEntity__sharedWith"
ON "PartnerEntity__sharedWith"."id"="PartnerEntity"."sharedWithId"
AND "PartnerEntity__sharedWith"."deletedAt" IS NULL
WHERE
"PartnerEntity__PartnerEntity_sharedWith"."id" = $1
AND "0aabe9f4a62b794e2c24a074297e534f51a4ac6c"."id" = $2
)
LIMIT 1
-- After
SELECT
"asset"."id" AS "assetId"
FROM "partners" "partner"
INNER JOIN "users" "sharedBy"
ON "sharedBy"."id"="partner"."sharedById"
AND "sharedBy"."deletedAt" IS NULL
INNER JOIN "assets" "asset"
ON "asset"."ownerId"="sharedBy"."id"
AND "asset"."deletedAt" IS NULL
WHERE
"partner"."sharedWithId" = $1
AND "asset"."id" IN ($2, $3)
```
* `asset` shared link access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "shared_links" "SharedLinkEntity"
LEFT JOIN "albums" "SharedLinkEntity__SharedLinkEntity_album"
ON "SharedLinkEntity__SharedLinkEntity_album"."id"="SharedLinkEntity"."albumId"
AND "SharedLinkEntity__SharedLinkEntity_album"."deletedAt" IS NULL
LEFT JOIN "albums_assets_assets" "760f12c00d97bdcec1ce224d1e3bf449859942b6"
ON "760f12c00d97bdcec1ce224d1e3bf449859942b6"."albumsId"="SharedLinkEntity__SharedLinkEntity_album"."id"
LEFT JOIN "assets" "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"
ON "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."id"="760f12c00d97bdcec1ce224d1e3bf449859942b6"."assetsId"
AND "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."deletedAt" IS NULL
LEFT JOIN "shared_link__asset" "SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"
ON "SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"."sharedLinksId"="SharedLinkEntity"."id"
LEFT JOIN "assets" "SharedLinkEntity__SharedLinkEntity_assets"
ON "SharedLinkEntity__SharedLinkEntity_assets"."id"="SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"."assetsId"
AND "SharedLinkEntity__SharedLinkEntity_assets"."deletedAt" IS NULL
WHERE (
("SharedLinkEntity"."id" = $1 AND "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."id" = $2)
OR ("SharedLinkEntity"."id" = $3 AND "SharedLinkEntity__SharedLinkEntity_assets"."id" = $4)
OR ("SharedLinkEntity"."id" = $5 AND "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."livePhotoVideoId" = $6)
OR ("SharedLinkEntity"."id" = $7 AND "SharedLinkEntity__SharedLinkEntity_assets"."livePhotoVideoId" = $8)
)
)
LIMIT 1
-- After
SELECT
"assets"."id" AS "assetId",
"assets"."livePhotoVideoId" AS "assetLivePhotoVideoId",
"albumAssets"."id" AS "albumAssetId",
"albumAssets"."livePhotoVideoId" AS "albumAssetLivePhotoVideoId"
FROM "shared_links" "sharedLink"
LEFT JOIN "albums" "album"
ON "album"."id"="sharedLink"."albumId"
AND "album"."deletedAt" IS NULL
LEFT JOIN "shared_link__asset" "assets_sharedLink"
ON "assets_sharedLink"."sharedLinksId"="sharedLink"."id"
LEFT JOIN "assets" "assets"
ON "assets"."id"="assets_sharedLink"."assetsId"
AND "assets"."deletedAt" IS NULL
LEFT JOIN "albums_assets_assets" "album_albumAssets"
ON "album_albumAssets"."albumsId"="album"."id"
LEFT JOIN "assets" "albumAssets"
ON "albumAssets"."id"="album_albumAssets"."assetsId"
AND "albumAssets"."deletedAt" IS NULL
WHERE
"sharedLink"."id" = $1
AND (
"assets"."id" IN ($2, $3)
OR "albumAssets"."id" IN ($4, $5)
OR "assets"."livePhotoVideoId" IN ($6, $7)
OR "albumAssets"."livePhotoVideoId" IN ($8, $9)
)
```
2023-12-02 03:56:41 +01:00
|
|
|
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set([assetStub.image.id]));
|
2023-06-21 03:08:43 +02:00
|
|
|
shareMock.create.mockResolvedValue(sharedLinkStub.individual);
|
|
|
|
|
|
|
|
await sut.create(authStub.admin, {
|
|
|
|
type: SharedLinkType.INDIVIDUAL,
|
2023-08-01 03:28:07 +02:00
|
|
|
assetIds: [assetStub.image.id],
|
2023-10-14 03:46:30 +02:00
|
|
|
showMetadata: true,
|
2023-06-21 03:08:43 +02:00
|
|
|
allowDownload: true,
|
|
|
|
allowUpload: true,
|
|
|
|
});
|
|
|
|
|
2023-12-10 05:34:12 +01:00
|
|
|
expect(accessMock.asset.checkOwnerAccess).toHaveBeenCalledWith(
|
|
|
|
authStub.admin.user.id,
|
|
|
|
new Set([assetStub.image.id]),
|
|
|
|
);
|
2023-06-21 03:08:43 +02:00
|
|
|
expect(shareMock.create).toHaveBeenCalledWith({
|
|
|
|
type: SharedLinkType.INDIVIDUAL,
|
2023-12-10 05:34:12 +01:00
|
|
|
userId: authStub.admin.user.id,
|
2023-06-21 03:08:43 +02:00
|
|
|
albumId: null,
|
|
|
|
allowDownload: true,
|
|
|
|
allowUpload: true,
|
2023-08-01 03:28:07 +02:00
|
|
|
assets: [{ id: assetStub.image.id }],
|
2023-06-21 03:08:43 +02:00
|
|
|
description: null,
|
|
|
|
expiresAt: null,
|
|
|
|
showExif: true,
|
|
|
|
key: Buffer.from('random-bytes', 'utf8'),
|
|
|
|
});
|
|
|
|
});
|
2024-06-13 16:21:47 +02:00
|
|
|
|
|
|
|
it('should create a shared link with allowDownload set to false when showMetadata is false', async () => {
|
|
|
|
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set([assetStub.image.id]));
|
|
|
|
shareMock.create.mockResolvedValue(sharedLinkStub.individual);
|
|
|
|
|
|
|
|
await sut.create(authStub.admin, {
|
|
|
|
type: SharedLinkType.INDIVIDUAL,
|
|
|
|
assetIds: [assetStub.image.id],
|
|
|
|
showMetadata: false,
|
|
|
|
allowDownload: true,
|
|
|
|
allowUpload: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(accessMock.asset.checkOwnerAccess).toHaveBeenCalledWith(
|
|
|
|
authStub.admin.user.id,
|
|
|
|
new Set([assetStub.image.id]),
|
|
|
|
);
|
|
|
|
expect(shareMock.create).toHaveBeenCalledWith({
|
|
|
|
type: SharedLinkType.INDIVIDUAL,
|
|
|
|
userId: authStub.admin.user.id,
|
|
|
|
albumId: null,
|
|
|
|
allowDownload: false,
|
|
|
|
allowUpload: true,
|
|
|
|
assets: [{ id: assetStub.image.id }],
|
|
|
|
description: null,
|
|
|
|
expiresAt: null,
|
|
|
|
showExif: false,
|
|
|
|
key: Buffer.from('random-bytes', 'utf8'),
|
|
|
|
});
|
|
|
|
});
|
2023-06-21 03:08:43 +02:00
|
|
|
});
|
|
|
|
|
2023-06-02 04:09:57 +02:00
|
|
|
describe('update', () => {
|
|
|
|
it('should throw an error for an invalid shared link', async () => {
|
|
|
|
shareMock.get.mockResolvedValue(null);
|
|
|
|
await expect(sut.update(authStub.user1, 'missing-id', {})).rejects.toBeInstanceOf(BadRequestException);
|
2023-12-10 05:34:12 +01:00
|
|
|
expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.user.id, 'missing-id');
|
2023-06-02 04:09:57 +02:00
|
|
|
expect(shareMock.update).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should update a shared link', async () => {
|
|
|
|
shareMock.get.mockResolvedValue(sharedLinkStub.valid);
|
|
|
|
shareMock.update.mockResolvedValue(sharedLinkStub.valid);
|
|
|
|
await sut.update(authStub.user1, sharedLinkStub.valid.id, { allowDownload: false });
|
2023-12-10 05:34:12 +01:00
|
|
|
expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.user.id, sharedLinkStub.valid.id);
|
2023-06-02 04:09:57 +02:00
|
|
|
expect(shareMock.update).toHaveBeenCalledWith({
|
|
|
|
id: sharedLinkStub.valid.id,
|
2023-12-10 05:34:12 +01:00
|
|
|
userId: authStub.user1.user.id,
|
2023-06-02 04:09:57 +02:00
|
|
|
allowDownload: false,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('remove', () => {
|
|
|
|
it('should throw an error for an invalid shared link', async () => {
|
|
|
|
shareMock.get.mockResolvedValue(null);
|
|
|
|
await expect(sut.remove(authStub.user1, 'missing-id')).rejects.toBeInstanceOf(BadRequestException);
|
2023-12-10 05:34:12 +01:00
|
|
|
expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.user.id, 'missing-id');
|
2023-06-02 04:09:57 +02:00
|
|
|
expect(shareMock.update).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should remove a key', async () => {
|
|
|
|
shareMock.get.mockResolvedValue(sharedLinkStub.valid);
|
|
|
|
await sut.remove(authStub.user1, sharedLinkStub.valid.id);
|
2023-12-10 05:34:12 +01:00
|
|
|
expect(shareMock.get).toHaveBeenCalledWith(authStub.user1.user.id, sharedLinkStub.valid.id);
|
2023-06-02 04:09:57 +02:00
|
|
|
expect(shareMock.remove).toHaveBeenCalledWith(sharedLinkStub.valid);
|
|
|
|
});
|
|
|
|
});
|
2023-06-21 03:08:43 +02:00
|
|
|
|
|
|
|
describe('addAssets', () => {
|
|
|
|
it('should not work on album shared links', async () => {
|
|
|
|
shareMock.get.mockResolvedValue(sharedLinkStub.valid);
|
|
|
|
await expect(sut.addAssets(authStub.admin, 'link-1', { assetIds: ['asset-1'] })).rejects.toBeInstanceOf(
|
|
|
|
BadRequestException,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should add assets to a shared link', async () => {
|
|
|
|
shareMock.get.mockResolvedValue(_.cloneDeep(sharedLinkStub.individual));
|
|
|
|
shareMock.create.mockResolvedValue(sharedLinkStub.individual);
|
chore(server): Check asset permissions in bulk (#5329)
Modify Access repository, to evaluate `asset` permissions in bulk.
Queries have been validated to match what they currently generate for single ids.
Queries:
* `asset` album access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "albums" "AlbumEntity"
LEFT JOIN "albums_assets_assets" "AlbumEntity_AlbumEntity__AlbumEntity_assets"
ON "AlbumEntity_AlbumEntity__AlbumEntity_assets"."albumsId"="AlbumEntity"."id"
LEFT JOIN "assets" "AlbumEntity__AlbumEntity_assets"
ON "AlbumEntity__AlbumEntity_assets"."id"="AlbumEntity_AlbumEntity__AlbumEntity_assets"."assetsId"
AND "AlbumEntity__AlbumEntity_assets"."deletedAt" IS NULL
LEFT JOIN "albums_shared_users_users" "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"
ON "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."albumsId"="AlbumEntity"."id"
LEFT JOIN "users" "AlbumEntity__AlbumEntity_sharedUsers"
ON "AlbumEntity__AlbumEntity_sharedUsers"."id"="AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."usersId"
AND "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" IS NULL
WHERE
(
("AlbumEntity"."ownerId" = $1 AND "AlbumEntity__AlbumEntity_assets"."id" = $2)
OR ("AlbumEntity__AlbumEntity_sharedUsers"."id" = $3 AND "AlbumEntity__AlbumEntity_assets"."id" = $4)
OR ("AlbumEntity"."ownerId" = $5 AND "AlbumEntity__AlbumEntity_assets"."livePhotoVideoId" = $6)
OR ("AlbumEntity__AlbumEntity_sharedUsers"."id" = $7 AND "AlbumEntity__AlbumEntity_assets"."livePhotoVideoId" = $8)
)
AND "AlbumEntity"."deletedAt" IS NULL
)
LIMIT 1
-- After
SELECT
"asset"."id" AS "assetId",
"asset"."livePhotoVideoId" AS "livePhotoVideoId"
FROM "albums" "album"
INNER JOIN "albums_assets_assets" "album_asset"
ON "album_asset"."albumsId"="album"."id"
INNER JOIN "assets" "asset"
ON "asset"."id"="album_asset"."assetsId"
AND "asset"."deletedAt" IS NULL
LEFT JOIN "albums_shared_users_users" "album_sharedUsers"
ON "album_sharedUsers"."albumsId"="album"."id"
LEFT JOIN "users" "sharedUsers"
ON "sharedUsers"."id"="album_sharedUsers"."usersId"
AND "sharedUsers"."deletedAt" IS NULL
WHERE
(
"album"."ownerId" = $1
OR "sharedUsers"."id" = $2
)
AND (
"asset"."id" IN ($3, $4)
OR "asset"."livePhotoVideoId" IN ($5, $6)
)
AND "album"."deletedAt" IS NULL
```
* `asset` owner access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "assets" "AssetEntity"
WHERE
"AssetEntity"."id" = $1
AND "AssetEntity"."ownerId" = $2
)
LIMIT 1
-- After
SELECT
"AssetEntity"."id" AS "AssetEntity_id"
FROM "assets" "AssetEntity"
WHERE
"AssetEntity"."id" IN ($1, $2)
AND "AssetEntity"."ownerId" = $3
```
* `asset` partner access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "partners" "PartnerEntity"
LEFT JOIN "users" "PartnerEntity__PartnerEntity_sharedWith"
ON "PartnerEntity__PartnerEntity_sharedWith"."id"="PartnerEntity"."sharedWithId"
AND "PartnerEntity__PartnerEntity_sharedWith"."deletedAt" IS NULL
LEFT JOIN "users" "PartnerEntity__PartnerEntity_sharedBy"
ON "PartnerEntity__PartnerEntity_sharedBy"."id"="PartnerEntity"."sharedById"
AND "PartnerEntity__PartnerEntity_sharedBy"."deletedAt" IS NULL
LEFT JOIN "assets" "0aabe9f4a62b794e2c24a074297e534f51a4ac6c"
ON "0aabe9f4a62b794e2c24a074297e534f51a4ac6c"."ownerId"="PartnerEntity__PartnerEntity_sharedBy"."id"
AND "0aabe9f4a62b794e2c24a074297e534f51a4ac6c"."deletedAt" IS NULL
LEFT JOIN "users" "PartnerEntity__sharedBy"
ON "PartnerEntity__sharedBy"."id"="PartnerEntity"."sharedById"
AND "PartnerEntity__sharedBy"."deletedAt" IS NULL
LEFT JOIN "users" "PartnerEntity__sharedWith"
ON "PartnerEntity__sharedWith"."id"="PartnerEntity"."sharedWithId"
AND "PartnerEntity__sharedWith"."deletedAt" IS NULL
WHERE
"PartnerEntity__PartnerEntity_sharedWith"."id" = $1
AND "0aabe9f4a62b794e2c24a074297e534f51a4ac6c"."id" = $2
)
LIMIT 1
-- After
SELECT
"asset"."id" AS "assetId"
FROM "partners" "partner"
INNER JOIN "users" "sharedBy"
ON "sharedBy"."id"="partner"."sharedById"
AND "sharedBy"."deletedAt" IS NULL
INNER JOIN "assets" "asset"
ON "asset"."ownerId"="sharedBy"."id"
AND "asset"."deletedAt" IS NULL
WHERE
"partner"."sharedWithId" = $1
AND "asset"."id" IN ($2, $3)
```
* `asset` shared link access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "shared_links" "SharedLinkEntity"
LEFT JOIN "albums" "SharedLinkEntity__SharedLinkEntity_album"
ON "SharedLinkEntity__SharedLinkEntity_album"."id"="SharedLinkEntity"."albumId"
AND "SharedLinkEntity__SharedLinkEntity_album"."deletedAt" IS NULL
LEFT JOIN "albums_assets_assets" "760f12c00d97bdcec1ce224d1e3bf449859942b6"
ON "760f12c00d97bdcec1ce224d1e3bf449859942b6"."albumsId"="SharedLinkEntity__SharedLinkEntity_album"."id"
LEFT JOIN "assets" "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"
ON "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."id"="760f12c00d97bdcec1ce224d1e3bf449859942b6"."assetsId"
AND "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."deletedAt" IS NULL
LEFT JOIN "shared_link__asset" "SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"
ON "SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"."sharedLinksId"="SharedLinkEntity"."id"
LEFT JOIN "assets" "SharedLinkEntity__SharedLinkEntity_assets"
ON "SharedLinkEntity__SharedLinkEntity_assets"."id"="SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"."assetsId"
AND "SharedLinkEntity__SharedLinkEntity_assets"."deletedAt" IS NULL
WHERE (
("SharedLinkEntity"."id" = $1 AND "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."id" = $2)
OR ("SharedLinkEntity"."id" = $3 AND "SharedLinkEntity__SharedLinkEntity_assets"."id" = $4)
OR ("SharedLinkEntity"."id" = $5 AND "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."livePhotoVideoId" = $6)
OR ("SharedLinkEntity"."id" = $7 AND "SharedLinkEntity__SharedLinkEntity_assets"."livePhotoVideoId" = $8)
)
)
LIMIT 1
-- After
SELECT
"assets"."id" AS "assetId",
"assets"."livePhotoVideoId" AS "assetLivePhotoVideoId",
"albumAssets"."id" AS "albumAssetId",
"albumAssets"."livePhotoVideoId" AS "albumAssetLivePhotoVideoId"
FROM "shared_links" "sharedLink"
LEFT JOIN "albums" "album"
ON "album"."id"="sharedLink"."albumId"
AND "album"."deletedAt" IS NULL
LEFT JOIN "shared_link__asset" "assets_sharedLink"
ON "assets_sharedLink"."sharedLinksId"="sharedLink"."id"
LEFT JOIN "assets" "assets"
ON "assets"."id"="assets_sharedLink"."assetsId"
AND "assets"."deletedAt" IS NULL
LEFT JOIN "albums_assets_assets" "album_albumAssets"
ON "album_albumAssets"."albumsId"="album"."id"
LEFT JOIN "assets" "albumAssets"
ON "albumAssets"."id"="album_albumAssets"."assetsId"
AND "albumAssets"."deletedAt" IS NULL
WHERE
"sharedLink"."id" = $1
AND (
"assets"."id" IN ($2, $3)
OR "albumAssets"."id" IN ($4, $5)
OR "assets"."livePhotoVideoId" IN ($6, $7)
OR "albumAssets"."livePhotoVideoId" IN ($8, $9)
)
```
2023-12-02 03:56:41 +01:00
|
|
|
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset-3']));
|
2023-06-21 03:08:43 +02:00
|
|
|
|
|
|
|
await expect(
|
2023-08-01 03:28:07 +02:00
|
|
|
sut.addAssets(authStub.admin, 'link-1', { assetIds: [assetStub.image.id, 'asset-2', 'asset-3'] }),
|
2023-06-21 03:08:43 +02:00
|
|
|
).resolves.toEqual([
|
2023-08-01 03:28:07 +02:00
|
|
|
{ assetId: assetStub.image.id, success: false, error: AssetIdErrorReason.DUPLICATE },
|
2023-06-21 03:08:43 +02:00
|
|
|
{ assetId: 'asset-2', success: false, error: AssetIdErrorReason.NO_PERMISSION },
|
|
|
|
{ assetId: 'asset-3', success: true },
|
|
|
|
]);
|
|
|
|
|
chore(server): Check asset permissions in bulk (#5329)
Modify Access repository, to evaluate `asset` permissions in bulk.
Queries have been validated to match what they currently generate for single ids.
Queries:
* `asset` album access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "albums" "AlbumEntity"
LEFT JOIN "albums_assets_assets" "AlbumEntity_AlbumEntity__AlbumEntity_assets"
ON "AlbumEntity_AlbumEntity__AlbumEntity_assets"."albumsId"="AlbumEntity"."id"
LEFT JOIN "assets" "AlbumEntity__AlbumEntity_assets"
ON "AlbumEntity__AlbumEntity_assets"."id"="AlbumEntity_AlbumEntity__AlbumEntity_assets"."assetsId"
AND "AlbumEntity__AlbumEntity_assets"."deletedAt" IS NULL
LEFT JOIN "albums_shared_users_users" "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"
ON "AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."albumsId"="AlbumEntity"."id"
LEFT JOIN "users" "AlbumEntity__AlbumEntity_sharedUsers"
ON "AlbumEntity__AlbumEntity_sharedUsers"."id"="AlbumEntity_AlbumEntity__AlbumEntity_sharedUsers"."usersId"
AND "AlbumEntity__AlbumEntity_sharedUsers"."deletedAt" IS NULL
WHERE
(
("AlbumEntity"."ownerId" = $1 AND "AlbumEntity__AlbumEntity_assets"."id" = $2)
OR ("AlbumEntity__AlbumEntity_sharedUsers"."id" = $3 AND "AlbumEntity__AlbumEntity_assets"."id" = $4)
OR ("AlbumEntity"."ownerId" = $5 AND "AlbumEntity__AlbumEntity_assets"."livePhotoVideoId" = $6)
OR ("AlbumEntity__AlbumEntity_sharedUsers"."id" = $7 AND "AlbumEntity__AlbumEntity_assets"."livePhotoVideoId" = $8)
)
AND "AlbumEntity"."deletedAt" IS NULL
)
LIMIT 1
-- After
SELECT
"asset"."id" AS "assetId",
"asset"."livePhotoVideoId" AS "livePhotoVideoId"
FROM "albums" "album"
INNER JOIN "albums_assets_assets" "album_asset"
ON "album_asset"."albumsId"="album"."id"
INNER JOIN "assets" "asset"
ON "asset"."id"="album_asset"."assetsId"
AND "asset"."deletedAt" IS NULL
LEFT JOIN "albums_shared_users_users" "album_sharedUsers"
ON "album_sharedUsers"."albumsId"="album"."id"
LEFT JOIN "users" "sharedUsers"
ON "sharedUsers"."id"="album_sharedUsers"."usersId"
AND "sharedUsers"."deletedAt" IS NULL
WHERE
(
"album"."ownerId" = $1
OR "sharedUsers"."id" = $2
)
AND (
"asset"."id" IN ($3, $4)
OR "asset"."livePhotoVideoId" IN ($5, $6)
)
AND "album"."deletedAt" IS NULL
```
* `asset` owner access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "assets" "AssetEntity"
WHERE
"AssetEntity"."id" = $1
AND "AssetEntity"."ownerId" = $2
)
LIMIT 1
-- After
SELECT
"AssetEntity"."id" AS "AssetEntity_id"
FROM "assets" "AssetEntity"
WHERE
"AssetEntity"."id" IN ($1, $2)
AND "AssetEntity"."ownerId" = $3
```
* `asset` partner access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "partners" "PartnerEntity"
LEFT JOIN "users" "PartnerEntity__PartnerEntity_sharedWith"
ON "PartnerEntity__PartnerEntity_sharedWith"."id"="PartnerEntity"."sharedWithId"
AND "PartnerEntity__PartnerEntity_sharedWith"."deletedAt" IS NULL
LEFT JOIN "users" "PartnerEntity__PartnerEntity_sharedBy"
ON "PartnerEntity__PartnerEntity_sharedBy"."id"="PartnerEntity"."sharedById"
AND "PartnerEntity__PartnerEntity_sharedBy"."deletedAt" IS NULL
LEFT JOIN "assets" "0aabe9f4a62b794e2c24a074297e534f51a4ac6c"
ON "0aabe9f4a62b794e2c24a074297e534f51a4ac6c"."ownerId"="PartnerEntity__PartnerEntity_sharedBy"."id"
AND "0aabe9f4a62b794e2c24a074297e534f51a4ac6c"."deletedAt" IS NULL
LEFT JOIN "users" "PartnerEntity__sharedBy"
ON "PartnerEntity__sharedBy"."id"="PartnerEntity"."sharedById"
AND "PartnerEntity__sharedBy"."deletedAt" IS NULL
LEFT JOIN "users" "PartnerEntity__sharedWith"
ON "PartnerEntity__sharedWith"."id"="PartnerEntity"."sharedWithId"
AND "PartnerEntity__sharedWith"."deletedAt" IS NULL
WHERE
"PartnerEntity__PartnerEntity_sharedWith"."id" = $1
AND "0aabe9f4a62b794e2c24a074297e534f51a4ac6c"."id" = $2
)
LIMIT 1
-- After
SELECT
"asset"."id" AS "assetId"
FROM "partners" "partner"
INNER JOIN "users" "sharedBy"
ON "sharedBy"."id"="partner"."sharedById"
AND "sharedBy"."deletedAt" IS NULL
INNER JOIN "assets" "asset"
ON "asset"."ownerId"="sharedBy"."id"
AND "asset"."deletedAt" IS NULL
WHERE
"partner"."sharedWithId" = $1
AND "asset"."id" IN ($2, $3)
```
* `asset` shared link access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "shared_links" "SharedLinkEntity"
LEFT JOIN "albums" "SharedLinkEntity__SharedLinkEntity_album"
ON "SharedLinkEntity__SharedLinkEntity_album"."id"="SharedLinkEntity"."albumId"
AND "SharedLinkEntity__SharedLinkEntity_album"."deletedAt" IS NULL
LEFT JOIN "albums_assets_assets" "760f12c00d97bdcec1ce224d1e3bf449859942b6"
ON "760f12c00d97bdcec1ce224d1e3bf449859942b6"."albumsId"="SharedLinkEntity__SharedLinkEntity_album"."id"
LEFT JOIN "assets" "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"
ON "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."id"="760f12c00d97bdcec1ce224d1e3bf449859942b6"."assetsId"
AND "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."deletedAt" IS NULL
LEFT JOIN "shared_link__asset" "SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"
ON "SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"."sharedLinksId"="SharedLinkEntity"."id"
LEFT JOIN "assets" "SharedLinkEntity__SharedLinkEntity_assets"
ON "SharedLinkEntity__SharedLinkEntity_assets"."id"="SharedLinkEntity__SharedLinkEntity_assets_SharedLinkEntity"."assetsId"
AND "SharedLinkEntity__SharedLinkEntity_assets"."deletedAt" IS NULL
WHERE (
("SharedLinkEntity"."id" = $1 AND "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."id" = $2)
OR ("SharedLinkEntity"."id" = $3 AND "SharedLinkEntity__SharedLinkEntity_assets"."id" = $4)
OR ("SharedLinkEntity"."id" = $5 AND "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."livePhotoVideoId" = $6)
OR ("SharedLinkEntity"."id" = $7 AND "SharedLinkEntity__SharedLinkEntity_assets"."livePhotoVideoId" = $8)
)
)
LIMIT 1
-- After
SELECT
"assets"."id" AS "assetId",
"assets"."livePhotoVideoId" AS "assetLivePhotoVideoId",
"albumAssets"."id" AS "albumAssetId",
"albumAssets"."livePhotoVideoId" AS "albumAssetLivePhotoVideoId"
FROM "shared_links" "sharedLink"
LEFT JOIN "albums" "album"
ON "album"."id"="sharedLink"."albumId"
AND "album"."deletedAt" IS NULL
LEFT JOIN "shared_link__asset" "assets_sharedLink"
ON "assets_sharedLink"."sharedLinksId"="sharedLink"."id"
LEFT JOIN "assets" "assets"
ON "assets"."id"="assets_sharedLink"."assetsId"
AND "assets"."deletedAt" IS NULL
LEFT JOIN "albums_assets_assets" "album_albumAssets"
ON "album_albumAssets"."albumsId"="album"."id"
LEFT JOIN "assets" "albumAssets"
ON "albumAssets"."id"="album_albumAssets"."assetsId"
AND "albumAssets"."deletedAt" IS NULL
WHERE
"sharedLink"."id" = $1
AND (
"assets"."id" IN ($2, $3)
OR "albumAssets"."id" IN ($4, $5)
OR "assets"."livePhotoVideoId" IN ($6, $7)
OR "albumAssets"."livePhotoVideoId" IN ($8, $9)
)
```
2023-12-02 03:56:41 +01:00
|
|
|
expect(accessMock.asset.checkOwnerAccess).toHaveBeenCalledTimes(1);
|
2023-06-21 03:08:43 +02:00
|
|
|
expect(shareMock.update).toHaveBeenCalledWith({
|
|
|
|
...sharedLinkStub.individual,
|
2023-08-01 03:28:07 +02:00
|
|
|
assets: [assetStub.image, { id: 'asset-3' }],
|
2023-06-21 03:08:43 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('removeAssets', () => {
|
|
|
|
it('should not work on album shared links', async () => {
|
|
|
|
shareMock.get.mockResolvedValue(sharedLinkStub.valid);
|
|
|
|
await expect(sut.removeAssets(authStub.admin, 'link-1', { assetIds: ['asset-1'] })).rejects.toBeInstanceOf(
|
|
|
|
BadRequestException,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should remove assets from a shared link', async () => {
|
|
|
|
shareMock.get.mockResolvedValue(_.cloneDeep(sharedLinkStub.individual));
|
|
|
|
shareMock.create.mockResolvedValue(sharedLinkStub.individual);
|
|
|
|
|
|
|
|
await expect(
|
2023-08-01 03:28:07 +02:00
|
|
|
sut.removeAssets(authStub.admin, 'link-1', { assetIds: [assetStub.image.id, 'asset-2'] }),
|
2023-06-21 03:08:43 +02:00
|
|
|
).resolves.toEqual([
|
2023-08-01 03:28:07 +02:00
|
|
|
{ assetId: assetStub.image.id, success: true },
|
2023-06-21 03:08:43 +02:00
|
|
|
{ assetId: 'asset-2', success: false, error: AssetIdErrorReason.NOT_FOUND },
|
|
|
|
]);
|
|
|
|
|
|
|
|
expect(shareMock.update).toHaveBeenCalledWith({ ...sharedLinkStub.individual, assets: [] });
|
|
|
|
});
|
|
|
|
});
|
2023-12-11 20:37:47 +01:00
|
|
|
|
|
|
|
describe('getMetadataTags', () => {
|
|
|
|
it('should return null when auth is not a shared link', async () => {
|
|
|
|
await expect(sut.getMetadataTags(authStub.admin)).resolves.toBe(null);
|
|
|
|
expect(shareMock.get).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return null when shared link has a password', async () => {
|
|
|
|
await expect(sut.getMetadataTags(authStub.passwordSharedLink)).resolves.toBe(null);
|
|
|
|
expect(shareMock.get).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return metadata tags', async () => {
|
|
|
|
shareMock.get.mockResolvedValue(sharedLinkStub.individual);
|
|
|
|
await expect(sut.getMetadataTags(authStub.adminSharedLink)).resolves.toEqual({
|
|
|
|
description: '1 shared photos & videos',
|
|
|
|
imageUrl:
|
2024-05-31 19:44:04 +02:00
|
|
|
'/api/assets/asset-id/thumbnail?key=LCtkaJX4R1O_9D-2lq0STzsPryoL1UdAbyb6Sna1xxmQCSuqU2J1ZUsqt6GR-yGm1s0',
|
2023-12-11 20:37:47 +01:00
|
|
|
title: 'Public Share',
|
|
|
|
});
|
|
|
|
expect(shareMock.get).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
2023-06-02 04:09:57 +02:00
|
|
|
});
|