mirror of
https://github.com/immich-app/immich.git
synced 2025-01-06 03:46:47 +01:00
c04340c63e
Modify Access repository, to evaluate `authDevice`, `library`, `partner`, `person`, and `timeline` permissions in bulk. Queries have been validated to match what they currently generate for single ids. As an extra performance improvement, we now use a custom QueryBuilder for the Partners queries, to avoid the eager relationships that add unneeded `LEFT JOIN` clauses. We only filter based on the ids present in the `partners` table, so those joins can be avoided. Queries: * `library` owner access: ```sql -- Before SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS ( SELECT 1 FROM "libraries" "LibraryEntity" WHERE "LibraryEntity"."id" = $1 AND "LibraryEntity"."ownerId" = $2 AND "LibraryEntity"."deletedAt" IS NULL ) LIMIT 1 -- After SELECT "LibraryEntity"."id" AS "LibraryEntity_id" FROM "libraries" "LibraryEntity" WHERE "LibraryEntity"."id" IN ($1, $2) AND "LibraryEntity"."ownerId" = $3 AND "LibraryEntity"."deletedAt" IS NULL ``` * `library` 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__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"."sharedWithId" = $1 AND "PartnerEntity"."sharedById" = $2 ) LIMIT 1 -- After SELECT "partner"."sharedById" AS "partner_sharedById", "partner"."sharedWithId" AS "partner_sharedWithId" FROM "partners" "partner" WHERE "partner"."sharedById" IN ($1, $2) AND "partner"."sharedWithId" = $3 ``` * `authDevice` owner access: ```sql -- Before SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS ( SELECT 1 FROM "user_token" "UserTokenEntity" WHERE "UserTokenEntity"."userId" = $1 AND "UserTokenEntity"."id" = $2 ) LIMIT 1 -- After SELECT "UserTokenEntity"."id" AS "UserTokenEntity_id" FROM "user_token" "UserTokenEntity" WHERE "UserTokenEntity"."userId" = $1 AND "UserTokenEntity"."id" IN ($2, $3) ``` * `timeline` 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__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"."sharedWithId" = $1 AND "PartnerEntity"."sharedById" = $2 ) LIMIT 1 -- After SELECT "partner"."sharedById" AS "partner_sharedById", "partner"."sharedWithId" AS "partner_sharedWithId" FROM "partners" "partner" WHERE "partner"."sharedById" IN ($1, $2) AND "partner"."sharedWithId" = $3 ``` * `person` owner access: ```sql -- Before SELECT 1 AS "row_exists" FROM (SELECT 1 AS dummy_column) "dummy_table" WHERE EXISTS ( SELECT 1 FROM "person" "PersonEntity" WHERE "PersonEntity"."id" = $1 AND "PersonEntity"."ownerId" = $2 ) LIMIT 1 -- After SELECT "PersonEntity"."id" AS "PersonEntity_id" FROM "person" "PersonEntity" WHERE "PersonEntity"."id" IN ($1, $2) AND "PersonEntity"."ownerId" = $3 ``` * `partner` update 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__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"."sharedWithId" = $1 AND "PartnerEntity"."sharedById" = $2 ) LIMIT 1 -- After SELECT "partner"."sharedById" AS "partner_sharedById", "partner"."sharedWithId" AS "partner_sharedWithId" FROM "partners" "partner" WHERE "partner"."sharedById" IN ($1, $2) AND "partner"."sharedWithId" = $3 ```
59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
import { AccessCore, IAccessRepository } from '@app/domain';
|
|
|
|
export interface IAccessRepositoryMock {
|
|
activity: jest.Mocked<IAccessRepository['activity']>;
|
|
asset: jest.Mocked<IAccessRepository['asset']>;
|
|
album: jest.Mocked<IAccessRepository['album']>;
|
|
authDevice: jest.Mocked<IAccessRepository['authDevice']>;
|
|
library: jest.Mocked<IAccessRepository['library']>;
|
|
timeline: jest.Mocked<IAccessRepository['timeline']>;
|
|
person: jest.Mocked<IAccessRepository['person']>;
|
|
partner: jest.Mocked<IAccessRepository['partner']>;
|
|
}
|
|
|
|
export const newAccessRepositoryMock = (reset = true): IAccessRepositoryMock => {
|
|
if (reset) {
|
|
AccessCore.reset();
|
|
}
|
|
|
|
return {
|
|
activity: {
|
|
hasOwnerAccess: jest.fn(),
|
|
hasAlbumOwnerAccess: jest.fn(),
|
|
hasCreateAccess: jest.fn(),
|
|
},
|
|
asset: {
|
|
hasOwnerAccess: jest.fn(),
|
|
hasAlbumAccess: jest.fn(),
|
|
hasPartnerAccess: jest.fn(),
|
|
hasSharedLinkAccess: jest.fn(),
|
|
},
|
|
|
|
album: {
|
|
checkOwnerAccess: jest.fn().mockResolvedValue(new Set()),
|
|
checkSharedAlbumAccess: jest.fn().mockResolvedValue(new Set()),
|
|
checkSharedLinkAccess: jest.fn().mockResolvedValue(new Set()),
|
|
},
|
|
|
|
authDevice: {
|
|
checkOwnerAccess: jest.fn().mockResolvedValue(new Set()),
|
|
},
|
|
|
|
library: {
|
|
checkOwnerAccess: jest.fn().mockResolvedValue(new Set()),
|
|
checkPartnerAccess: jest.fn().mockResolvedValue(new Set()),
|
|
},
|
|
|
|
timeline: {
|
|
checkPartnerAccess: jest.fn().mockResolvedValue(new Set()),
|
|
},
|
|
|
|
person: {
|
|
checkOwnerAccess: jest.fn().mockResolvedValue(new Set()),
|
|
},
|
|
|
|
partner: {
|
|
checkUpdateAccess: jest.fn().mockResolvedValue(new Set()),
|
|
},
|
|
};
|
|
};
|