forked from Cutlery/immich
		
	chore(server): Use ChunkedSet in Access repository (#6943)
This change simplifies the Access repository methods, by using the `ChunkedSet` decorator. As the methods expect sets, the `chunks` util needed to be fixed, so it returns chunks of the same type it received. Now `chunks` is overloaded, to have proper typing based on the input parameter.
This commit is contained in:
		
							parent
							
								
									61768ce89e
								
							
						
					
					
						commit
						4164bcfd0d
					
				@ -178,23 +178,25 @@ export function Optional({ nullable, ...validationOptions }: OptionalOptions = {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Chunks an array or set into smaller arrays of the specified size.
 | 
					 * Chunks an array or set into smaller collections of the same type and specified size.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param collection The collection to chunk.
 | 
					 * @param collection The collection to chunk.
 | 
				
			||||||
 * @param size The size of each chunk.
 | 
					 * @param size The size of each chunk.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function chunks<T>(collection: Array<T> | Set<T>, size: number): T[][] {
 | 
					export function chunks<T>(collection: Array<T>, size: number): Array<Array<T>>;
 | 
				
			||||||
 | 
					export function chunks<T>(collection: Set<T>, size: number): Array<Set<T>>;
 | 
				
			||||||
 | 
					export function chunks<T>(collection: Array<T> | Set<T>, size: number): Array<Array<T>> | Array<Set<T>> {
 | 
				
			||||||
  if (collection instanceof Set) {
 | 
					  if (collection instanceof Set) {
 | 
				
			||||||
    const result = [];
 | 
					    const result = [];
 | 
				
			||||||
    let chunk = [];
 | 
					    let chunk = new Set<T>();
 | 
				
			||||||
    for (const element of collection) {
 | 
					    for (const element of collection) {
 | 
				
			||||||
      chunk.push(element);
 | 
					      chunk.add(element);
 | 
				
			||||||
      if (chunk.length === size) {
 | 
					      if (chunk.size === size) {
 | 
				
			||||||
        result.push(chunk);
 | 
					        result.push(chunk);
 | 
				
			||||||
        chunk = [];
 | 
					        chunk = new Set<T>();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (chunk.length > 0) {
 | 
					    if (chunk.size > 0) {
 | 
				
			||||||
      result.push(chunk);
 | 
					      result.push(chunk);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import { IAccessRepository, chunks, setUnion } from '@app/domain';
 | 
					import { IAccessRepository } from '@app/domain';
 | 
				
			||||||
import { InjectRepository } from '@nestjs/typeorm';
 | 
					import { InjectRepository } from '@nestjs/typeorm';
 | 
				
			||||||
import { Brackets, In, Repository } from 'typeorm';
 | 
					import { Brackets, In, Repository } from 'typeorm';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
@ -12,7 +12,8 @@ import {
 | 
				
			|||||||
  SharedLinkEntity,
 | 
					  SharedLinkEntity,
 | 
				
			||||||
  UserTokenEntity,
 | 
					  UserTokenEntity,
 | 
				
			||||||
} from '../entities';
 | 
					} from '../entities';
 | 
				
			||||||
import { DATABASE_PARAMETER_CHUNK_SIZE, DummyValue, GenerateSql } from '../infra.util';
 | 
					import { DummyValue, GenerateSql } from '../infra.util';
 | 
				
			||||||
 | 
					import { ChunkedSet } from '../infra.utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type IActivityAccess = IAccessRepository['activity'];
 | 
					type IActivityAccess = IAccessRepository['activity'];
 | 
				
			||||||
type IAlbumAccess = IAccessRepository['album'];
 | 
					type IAlbumAccess = IAccessRepository['album'];
 | 
				
			||||||
@ -30,62 +31,55 @@ class ActivityAccess implements IActivityAccess {
 | 
				
			|||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkOwnerAccess(userId: string, activityIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkOwnerAccess(userId: string, activityIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (activityIds.size === 0) {
 | 
					    if (activityIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.activityRepository
 | 
				
			||||||
      chunks(activityIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.activityRepository
 | 
					 | 
				
			||||||
      .find({
 | 
					      .find({
 | 
				
			||||||
        select: { id: true },
 | 
					        select: { id: true },
 | 
				
			||||||
        where: {
 | 
					        where: {
 | 
				
			||||||
              id: In(idChunk),
 | 
					          id: In([...activityIds]),
 | 
				
			||||||
          userId,
 | 
					          userId,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
          .then((activities) => new Set(activities.map((activity) => activity.id))),
 | 
					      .then((activities) => new Set(activities.map((activity) => activity.id)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkAlbumOwnerAccess(userId: string, activityIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkAlbumOwnerAccess(userId: string, activityIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (activityIds.size === 0) {
 | 
					    if (activityIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.activityRepository
 | 
				
			||||||
      chunks(activityIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.activityRepository
 | 
					 | 
				
			||||||
      .find({
 | 
					      .find({
 | 
				
			||||||
        select: { id: true },
 | 
					        select: { id: true },
 | 
				
			||||||
        where: {
 | 
					        where: {
 | 
				
			||||||
              id: In(idChunk),
 | 
					          id: In([...activityIds]),
 | 
				
			||||||
          album: {
 | 
					          album: {
 | 
				
			||||||
            ownerId: userId,
 | 
					            ownerId: userId,
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
          .then((activities) => new Set(activities.map((activity) => activity.id))),
 | 
					      .then((activities) => new Set(activities.map((activity) => activity.id)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkCreateAccess(userId: string, albumIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkCreateAccess(userId: string, albumIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (albumIds.size === 0) {
 | 
					    if (albumIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.albumRepository
 | 
				
			||||||
      chunks(albumIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.albumRepository
 | 
					 | 
				
			||||||
      .createQueryBuilder('album')
 | 
					      .createQueryBuilder('album')
 | 
				
			||||||
      .select('album.id')
 | 
					      .select('album.id')
 | 
				
			||||||
      .leftJoin('album.sharedUsers', 'sharedUsers')
 | 
					      .leftJoin('album.sharedUsers', 'sharedUsers')
 | 
				
			||||||
          .where('album.id IN (:...albumIds)', { albumIds: idChunk })
 | 
					      .where('album.id IN (:...albumIds)', { albumIds: [...albumIds] })
 | 
				
			||||||
      .andWhere('album.isActivityEnabled = true')
 | 
					      .andWhere('album.isActivityEnabled = true')
 | 
				
			||||||
      .andWhere(
 | 
					      .andWhere(
 | 
				
			||||||
        new Brackets((qb) => {
 | 
					        new Brackets((qb) => {
 | 
				
			||||||
@ -93,9 +87,7 @@ class ActivityAccess implements IActivityAccess {
 | 
				
			|||||||
        }),
 | 
					        }),
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
      .getMany()
 | 
					      .getMany()
 | 
				
			||||||
          .then((albums) => new Set(albums.map((album) => album.id))),
 | 
					      .then((albums) => new Set(albums.map((album) => album.id)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -106,71 +98,61 @@ class AlbumAccess implements IAlbumAccess {
 | 
				
			|||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkOwnerAccess(userId: string, albumIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkOwnerAccess(userId: string, albumIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (albumIds.size === 0) {
 | 
					    if (albumIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.albumRepository
 | 
				
			||||||
      chunks(albumIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.albumRepository
 | 
					 | 
				
			||||||
      .find({
 | 
					      .find({
 | 
				
			||||||
        select: { id: true },
 | 
					        select: { id: true },
 | 
				
			||||||
        where: {
 | 
					        where: {
 | 
				
			||||||
              id: In(idChunk),
 | 
					          id: In([...albumIds]),
 | 
				
			||||||
          ownerId: userId,
 | 
					          ownerId: userId,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
          .then((albums) => new Set(albums.map((album) => album.id))),
 | 
					      .then((albums) => new Set(albums.map((album) => album.id)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkSharedAlbumAccess(userId: string, albumIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkSharedAlbumAccess(userId: string, albumIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (albumIds.size === 0) {
 | 
					    if (albumIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.albumRepository
 | 
				
			||||||
      chunks(albumIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.albumRepository
 | 
					 | 
				
			||||||
      .find({
 | 
					      .find({
 | 
				
			||||||
        select: { id: true },
 | 
					        select: { id: true },
 | 
				
			||||||
        where: {
 | 
					        where: {
 | 
				
			||||||
              id: In(idChunk),
 | 
					          id: In([...albumIds]),
 | 
				
			||||||
          sharedUsers: {
 | 
					          sharedUsers: {
 | 
				
			||||||
            id: userId,
 | 
					            id: userId,
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
          .then((albums) => new Set(albums.map((album) => album.id))),
 | 
					      .then((albums) => new Set(albums.map((album) => album.id)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkSharedLinkAccess(sharedLinkId: string, albumIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkSharedLinkAccess(sharedLinkId: string, albumIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (albumIds.size === 0) {
 | 
					    if (albumIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.sharedLinkRepository
 | 
				
			||||||
      chunks(albumIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.sharedLinkRepository
 | 
					 | 
				
			||||||
      .find({
 | 
					      .find({
 | 
				
			||||||
        select: { albumId: true },
 | 
					        select: { albumId: true },
 | 
				
			||||||
        where: {
 | 
					        where: {
 | 
				
			||||||
          id: sharedLinkId,
 | 
					          id: sharedLinkId,
 | 
				
			||||||
              albumId: In(idChunk),
 | 
					          albumId: In([...albumIds]),
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      .then(
 | 
					      .then(
 | 
				
			||||||
            (sharedLinks) =>
 | 
					        (sharedLinks) => new Set(sharedLinks.flatMap((sharedLink) => (sharedLink.albumId ? [sharedLink.albumId] : []))),
 | 
				
			||||||
              new Set(sharedLinks.flatMap((sharedLink) => (sharedLink.albumId ? [sharedLink.albumId] : []))),
 | 
					      );
 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -183,21 +165,20 @@ class AssetAccess implements IAssetAccess {
 | 
				
			|||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkAlbumAccess(userId: string, assetIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkAlbumAccess(userId: string, assetIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (assetIds.size === 0) {
 | 
					    if (assetIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.albumRepository
 | 
				
			||||||
      chunks(assetIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.albumRepository
 | 
					 | 
				
			||||||
      .createQueryBuilder('album')
 | 
					      .createQueryBuilder('album')
 | 
				
			||||||
      .innerJoin('album.assets', 'asset')
 | 
					      .innerJoin('album.assets', 'asset')
 | 
				
			||||||
      .leftJoin('album.sharedUsers', 'sharedUsers')
 | 
					      .leftJoin('album.sharedUsers', 'sharedUsers')
 | 
				
			||||||
      .select('asset.id', 'assetId')
 | 
					      .select('asset.id', 'assetId')
 | 
				
			||||||
      .addSelect('asset.livePhotoVideoId', 'livePhotoVideoId')
 | 
					      .addSelect('asset.livePhotoVideoId', 'livePhotoVideoId')
 | 
				
			||||||
      .where('array["asset"."id", "asset"."livePhotoVideoId"] && array[:...assetIds]::uuid[]', {
 | 
					      .where('array["asset"."id", "asset"."livePhotoVideoId"] && array[:...assetIds]::uuid[]', {
 | 
				
			||||||
            assetIds: idChunk,
 | 
					        assetIds: [...assetIds],
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      .andWhere(
 | 
					      .andWhere(
 | 
				
			||||||
        new Brackets((qb) => {
 | 
					        new Brackets((qb) => {
 | 
				
			||||||
@ -216,63 +197,54 @@ class AssetAccess implements IAssetAccess {
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return allowedIds;
 | 
					        return allowedIds;
 | 
				
			||||||
          }),
 | 
					      });
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkOwnerAccess(userId: string, assetIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkOwnerAccess(userId: string, assetIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (assetIds.size === 0) {
 | 
					    if (assetIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.assetRepository
 | 
				
			||||||
      chunks(assetIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.assetRepository
 | 
					 | 
				
			||||||
      .find({
 | 
					      .find({
 | 
				
			||||||
        select: { id: true },
 | 
					        select: { id: true },
 | 
				
			||||||
        where: {
 | 
					        where: {
 | 
				
			||||||
              id: In(idChunk),
 | 
					          id: In([...assetIds]),
 | 
				
			||||||
          ownerId: userId,
 | 
					          ownerId: userId,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        withDeleted: true,
 | 
					        withDeleted: true,
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
          .then((assets) => new Set(assets.map((asset) => asset.id))),
 | 
					      .then((assets) => new Set(assets.map((asset) => asset.id)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkPartnerAccess(userId: string, assetIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkPartnerAccess(userId: string, assetIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (assetIds.size === 0) {
 | 
					    if (assetIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.partnerRepository
 | 
				
			||||||
      chunks(assetIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.partnerRepository
 | 
					 | 
				
			||||||
      .createQueryBuilder('partner')
 | 
					      .createQueryBuilder('partner')
 | 
				
			||||||
      .innerJoin('partner.sharedBy', 'sharedBy')
 | 
					      .innerJoin('partner.sharedBy', 'sharedBy')
 | 
				
			||||||
      .innerJoin('sharedBy.assets', 'asset')
 | 
					      .innerJoin('sharedBy.assets', 'asset')
 | 
				
			||||||
      .select('asset.id', 'assetId')
 | 
					      .select('asset.id', 'assetId')
 | 
				
			||||||
      .where('partner.sharedWithId = :userId', { userId })
 | 
					      .where('partner.sharedWithId = :userId', { userId })
 | 
				
			||||||
          .andWhere('asset.id IN (:...assetIds)', { assetIds: idChunk })
 | 
					      .andWhere('asset.id IN (:...assetIds)', { assetIds: [...assetIds] })
 | 
				
			||||||
      .getRawMany()
 | 
					      .getRawMany()
 | 
				
			||||||
          .then((rows) => new Set(rows.map((row) => row.assetId))),
 | 
					      .then((rows) => new Set(rows.map((row) => row.assetId)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkSharedLinkAccess(sharedLinkId: string, assetIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkSharedLinkAccess(sharedLinkId: string, assetIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (assetIds.size === 0) {
 | 
					    if (assetIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.sharedLinkRepository
 | 
				
			||||||
      chunks(assetIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.sharedLinkRepository
 | 
					 | 
				
			||||||
      .createQueryBuilder('sharedLink')
 | 
					      .createQueryBuilder('sharedLink')
 | 
				
			||||||
      .leftJoin('sharedLink.album', 'album')
 | 
					      .leftJoin('sharedLink.album', 'album')
 | 
				
			||||||
      .leftJoin('sharedLink.assets', 'assets')
 | 
					      .leftJoin('sharedLink.assets', 'assets')
 | 
				
			||||||
@ -285,7 +257,7 @@ class AssetAccess implements IAssetAccess {
 | 
				
			|||||||
      .andWhere(
 | 
					      .andWhere(
 | 
				
			||||||
        'array["assets"."id", "assets"."livePhotoVideoId", "albumAssets"."id", "albumAssets"."livePhotoVideoId"] && array[:...assetIds]::uuid[]',
 | 
					        'array["assets"."id", "assets"."livePhotoVideoId", "albumAssets"."id", "albumAssets"."livePhotoVideoId"] && array[:...assetIds]::uuid[]',
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
              assetIds: idChunk,
 | 
					          assetIds: [...assetIds],
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
      .getRawMany()
 | 
					      .getRawMany()
 | 
				
			||||||
@ -306,9 +278,7 @@ class AssetAccess implements IAssetAccess {
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return allowedIds;
 | 
					        return allowedIds;
 | 
				
			||||||
          }),
 | 
					      });
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -316,24 +286,21 @@ class AuthDeviceAccess implements IAuthDeviceAccess {
 | 
				
			|||||||
  constructor(private tokenRepository: Repository<UserTokenEntity>) {}
 | 
					  constructor(private tokenRepository: Repository<UserTokenEntity>) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkOwnerAccess(userId: string, deviceIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkOwnerAccess(userId: string, deviceIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (deviceIds.size === 0) {
 | 
					    if (deviceIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.tokenRepository
 | 
				
			||||||
      chunks(deviceIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.tokenRepository
 | 
					 | 
				
			||||||
      .find({
 | 
					      .find({
 | 
				
			||||||
        select: { id: true },
 | 
					        select: { id: true },
 | 
				
			||||||
        where: {
 | 
					        where: {
 | 
				
			||||||
          userId,
 | 
					          userId,
 | 
				
			||||||
              id: In(idChunk),
 | 
					          id: In([...deviceIds]),
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
          .then((tokens) => new Set(tokens.map((token) => token.id))),
 | 
					      .then((tokens) => new Set(tokens.map((token) => token.id)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -344,43 +311,37 @@ class LibraryAccess implements ILibraryAccess {
 | 
				
			|||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkOwnerAccess(userId: string, libraryIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkOwnerAccess(userId: string, libraryIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (libraryIds.size === 0) {
 | 
					    if (libraryIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.libraryRepository
 | 
				
			||||||
      chunks(libraryIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.libraryRepository
 | 
					 | 
				
			||||||
      .find({
 | 
					      .find({
 | 
				
			||||||
        select: { id: true },
 | 
					        select: { id: true },
 | 
				
			||||||
        where: {
 | 
					        where: {
 | 
				
			||||||
              id: In(idChunk),
 | 
					          id: In([...libraryIds]),
 | 
				
			||||||
          ownerId: userId,
 | 
					          ownerId: userId,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
          .then((libraries) => new Set(libraries.map((library) => library.id))),
 | 
					      .then((libraries) => new Set(libraries.map((library) => library.id)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkPartnerAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkPartnerAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (partnerIds.size === 0) {
 | 
					    if (partnerIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.partnerRepository
 | 
				
			||||||
      chunks(partnerIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.partnerRepository
 | 
					 | 
				
			||||||
      .createQueryBuilder('partner')
 | 
					      .createQueryBuilder('partner')
 | 
				
			||||||
      .select('partner.sharedById')
 | 
					      .select('partner.sharedById')
 | 
				
			||||||
          .where('partner.sharedById IN (:...partnerIds)', { partnerIds: idChunk })
 | 
					      .where('partner.sharedById IN (:...partnerIds)', { partnerIds: [...partnerIds] })
 | 
				
			||||||
      .andWhere('partner.sharedWithId = :userId', { userId })
 | 
					      .andWhere('partner.sharedWithId = :userId', { userId })
 | 
				
			||||||
      .getMany()
 | 
					      .getMany()
 | 
				
			||||||
          .then((partners) => new Set(partners.map((partner) => partner.sharedById))),
 | 
					      .then((partners) => new Set(partners.map((partner) => partner.sharedById)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -388,22 +349,19 @@ class TimelineAccess implements ITimelineAccess {
 | 
				
			|||||||
  constructor(private partnerRepository: Repository<PartnerEntity>) {}
 | 
					  constructor(private partnerRepository: Repository<PartnerEntity>) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkPartnerAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkPartnerAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (partnerIds.size === 0) {
 | 
					    if (partnerIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.partnerRepository
 | 
				
			||||||
      chunks(partnerIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.partnerRepository
 | 
					 | 
				
			||||||
      .createQueryBuilder('partner')
 | 
					      .createQueryBuilder('partner')
 | 
				
			||||||
      .select('partner.sharedById')
 | 
					      .select('partner.sharedById')
 | 
				
			||||||
          .where('partner.sharedById IN (:...partnerIds)', { partnerIds: idChunk })
 | 
					      .where('partner.sharedById IN (:...partnerIds)', { partnerIds: [...partnerIds] })
 | 
				
			||||||
      .andWhere('partner.sharedWithId = :userId', { userId })
 | 
					      .andWhere('partner.sharedWithId = :userId', { userId })
 | 
				
			||||||
      .getMany()
 | 
					      .getMany()
 | 
				
			||||||
          .then((partners) => new Set(partners.map((partner) => partner.sharedById))),
 | 
					      .then((partners) => new Set(partners.map((partner) => partner.sharedById)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -414,47 +372,41 @@ class PersonAccess implements IPersonAccess {
 | 
				
			|||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkOwnerAccess(userId: string, personIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkOwnerAccess(userId: string, personIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (personIds.size === 0) {
 | 
					    if (personIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.personRepository
 | 
				
			||||||
      chunks(personIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.personRepository
 | 
					 | 
				
			||||||
      .find({
 | 
					      .find({
 | 
				
			||||||
        select: { id: true },
 | 
					        select: { id: true },
 | 
				
			||||||
        where: {
 | 
					        where: {
 | 
				
			||||||
              id: In(idChunk),
 | 
					          id: In([...personIds]),
 | 
				
			||||||
          ownerId: userId,
 | 
					          ownerId: userId,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
          .then((persons) => new Set(persons.map((person) => person.id))),
 | 
					      .then((persons) => new Set(persons.map((person) => person.id)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkFaceOwnerAccess(userId: string, assetFaceIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkFaceOwnerAccess(userId: string, assetFaceIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (assetFaceIds.size === 0) {
 | 
					    if (assetFaceIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.assetFaceRepository
 | 
				
			||||||
      chunks(assetFaceIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.assetFaceRepository
 | 
					 | 
				
			||||||
      .find({
 | 
					      .find({
 | 
				
			||||||
        select: { id: true },
 | 
					        select: { id: true },
 | 
				
			||||||
        where: {
 | 
					        where: {
 | 
				
			||||||
              id: In(idChunk),
 | 
					          id: In([...assetFaceIds]),
 | 
				
			||||||
          asset: {
 | 
					          asset: {
 | 
				
			||||||
            ownerId: userId,
 | 
					            ownerId: userId,
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
          .then((faces) => new Set(faces.map((face) => face.id))),
 | 
					      .then((faces) => new Set(faces.map((face) => face.id)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -462,22 +414,19 @@ class PartnerAccess implements IPartnerAccess {
 | 
				
			|||||||
  constructor(private partnerRepository: Repository<PartnerEntity>) {}
 | 
					  constructor(private partnerRepository: Repository<PartnerEntity>) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
					  @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
 | 
				
			||||||
 | 
					  @ChunkedSet({ paramIndex: 1 })
 | 
				
			||||||
  async checkUpdateAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>> {
 | 
					  async checkUpdateAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>> {
 | 
				
			||||||
    if (partnerIds.size === 0) {
 | 
					    if (partnerIds.size === 0) {
 | 
				
			||||||
      return new Set();
 | 
					      return new Set();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Promise.all(
 | 
					    return this.partnerRepository
 | 
				
			||||||
      chunks(partnerIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
 | 
					 | 
				
			||||||
        this.partnerRepository
 | 
					 | 
				
			||||||
      .createQueryBuilder('partner')
 | 
					      .createQueryBuilder('partner')
 | 
				
			||||||
      .select('partner.sharedById')
 | 
					      .select('partner.sharedById')
 | 
				
			||||||
          .where('partner.sharedById IN (:...partnerIds)', { partnerIds: idChunk })
 | 
					      .where('partner.sharedById IN (:...partnerIds)', { partnerIds: [...partnerIds] })
 | 
				
			||||||
      .andWhere('partner.sharedWithId = :userId', { userId })
 | 
					      .andWhere('partner.sharedWithId = :userId', { userId })
 | 
				
			||||||
      .getMany()
 | 
					      .getMany()
 | 
				
			||||||
          .then((partners) => new Set(partners.map((partner) => partner.sharedById))),
 | 
					      .then((partners) => new Set(partners.map((partner) => partner.sharedById)));
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    ).then((results) => setUnion(...results));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user