chore(server): Check album permissions in bulk (#5290)
* chore(server): Check album permissions in bulk
Modify Access repository, to evaluate `album` permissions in bulk.
Queries have been validated to match what they currently generate for
single ids.
Queries:
* Owner access:
```sql
-- Before
SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS (
SELECT 1
FROM "albums" "AlbumEntity"
WHERE
"AlbumEntity"."id" = $1
AND "AlbumEntity"."ownerId" = $2
AND "AlbumEntity"."deletedAt" IS NULL
)
LIMIT 1
-- After
SELECT
"AlbumEntity"."id" AS "AlbumEntity_id"
FROM "albums" "AlbumEntity"
WHERE
"AlbumEntity"."id" IN ($1, $2)
AND "AlbumEntity"."ownerId" = $3
AND "AlbumEntity"."deletedAt" IS NULL
```
* 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"
WHERE
"SharedLinkEntity"."id" = $1
AND "SharedLinkEntity"."albumId" = $2
)
LIMIT 1
-- After
SELECT
"SharedLinkEntity"."albumId" AS "SharedLinkEntity_albumId",
"SharedLinkEntity"."id" AS "SharedLinkEntity_id"
FROM "shared_links" "SharedLinkEntity"
WHERE
"SharedLinkEntity"."id" = $1
AND "SharedLinkEntity"."albumId" IN ($2, $3)
```
* Shared 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_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"."id" = $1
AND "AlbumEntity__AlbumEntity_sharedUsers"."id" = $2
AND "AlbumEntity"."deletedAt" IS NULL
)
LIMIT 1
-- After
SELECT
"AlbumEntity"."id" AS "AlbumEntity_id"
FROM "albums" "AlbumEntity"
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"."id" IN ($1, $2)
AND "AlbumEntity__AlbumEntity_sharedUsers"."id" = $3
AND "AlbumEntity"."deletedAt" IS NULL
```
* chore(server): Add set utils, avoid double queries for same ids
* chore(server): Review feedback
This commit is contained in:
committed by
GitHub
parent
698226634e
commit
6d1b325b34
@@ -24,7 +24,7 @@ describe(ActivityService.name, () => {
|
||||
|
||||
describe('getAll', () => {
|
||||
it('should get all', async () => {
|
||||
accessMock.album.hasOwnerAccess.mockResolvedValue(true);
|
||||
accessMock.album.checkOwnerAccess.mockResolvedValue(new Set(['album-id']));
|
||||
activityMock.search.mockResolvedValue([]);
|
||||
|
||||
await expect(sut.getAll(authStub.admin, { assetId: 'asset-id', albumId: 'album-id' })).resolves.toEqual([]);
|
||||
@@ -37,7 +37,7 @@ describe(ActivityService.name, () => {
|
||||
});
|
||||
|
||||
it('should filter by type=like', async () => {
|
||||
accessMock.album.hasOwnerAccess.mockResolvedValue(true);
|
||||
accessMock.album.checkOwnerAccess.mockResolvedValue(new Set(['album-id']));
|
||||
activityMock.search.mockResolvedValue([]);
|
||||
|
||||
await expect(
|
||||
@@ -52,7 +52,7 @@ describe(ActivityService.name, () => {
|
||||
});
|
||||
|
||||
it('should filter by type=comment', async () => {
|
||||
accessMock.album.hasOwnerAccess.mockResolvedValue(true);
|
||||
accessMock.album.checkOwnerAccess.mockResolvedValue(new Set(['album-id']));
|
||||
activityMock.search.mockResolvedValue([]);
|
||||
|
||||
await expect(
|
||||
@@ -70,7 +70,7 @@ describe(ActivityService.name, () => {
|
||||
describe('getStatistics', () => {
|
||||
it('should get the comment count', async () => {
|
||||
activityMock.getStatistics.mockResolvedValue(1);
|
||||
accessMock.album.hasOwnerAccess.mockResolvedValue(true);
|
||||
accessMock.album.checkOwnerAccess.mockResolvedValue(new Set([activityStub.oneComment.albumId]));
|
||||
await expect(
|
||||
sut.getStatistics(authStub.admin, {
|
||||
assetId: 'asset-id',
|
||||
@@ -82,7 +82,6 @@ describe(ActivityService.name, () => {
|
||||
|
||||
describe('addComment', () => {
|
||||
it('should require access to the album', async () => {
|
||||
accessMock.album.hasOwnerAccess.mockResolvedValue(false);
|
||||
await expect(
|
||||
sut.create(authStub.admin, {
|
||||
albumId: 'album-id',
|
||||
@@ -114,7 +113,7 @@ describe(ActivityService.name, () => {
|
||||
});
|
||||
|
||||
it('should fail because activity is disabled for the album', async () => {
|
||||
accessMock.album.hasOwnerAccess.mockResolvedValue(true);
|
||||
accessMock.album.checkOwnerAccess.mockResolvedValue(new Set(['album-id']));
|
||||
accessMock.activity.hasCreateAccess.mockResolvedValue(false);
|
||||
activityMock.create.mockResolvedValue(activityStub.oneComment);
|
||||
|
||||
@@ -148,7 +147,7 @@ describe(ActivityService.name, () => {
|
||||
});
|
||||
|
||||
it('should skip if like exists', async () => {
|
||||
accessMock.album.hasOwnerAccess.mockResolvedValue(true);
|
||||
accessMock.album.checkOwnerAccess.mockResolvedValue(new Set(['album-id']));
|
||||
accessMock.activity.hasCreateAccess.mockResolvedValue(true);
|
||||
activityMock.search.mockResolvedValue([activityStub.liked]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user