mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:27:09 -05:00 
			
		
		
		
	refactor(server): partner ids (#10321)
This commit is contained in:
		
							parent
							
								
									c896fe393f
								
							
						
					
					
						commit
						78f600ebce
					
				@ -39,6 +39,7 @@ import { ILoggerRepository } from 'src/interfaces/logger.interface';
 | 
			
		||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
 | 
			
		||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
 | 
			
		||||
import { IUserRepository } from 'src/interfaces/user.interface';
 | 
			
		||||
import { getMyPartnerIds } from 'src/utils/asset.util';
 | 
			
		||||
import { usePagination } from 'src/utils/pagination';
 | 
			
		||||
 | 
			
		||||
export class AssetService {
 | 
			
		||||
@ -62,18 +63,16 @@ export class AssetService {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async getMemoryLane(auth: AuthDto, dto: MemoryLaneDto): Promise<MemoryLaneResponseDto[]> {
 | 
			
		||||
    const currentYear = new Date().getFullYear();
 | 
			
		||||
 | 
			
		||||
    // get partners id
 | 
			
		||||
    const userIds: string[] = [auth.user.id];
 | 
			
		||||
    const partners = await this.partnerRepository.getAll(auth.user.id);
 | 
			
		||||
    const partnersIds = partners
 | 
			
		||||
      .filter((partner) => partner.sharedBy && partner.inTimeline)
 | 
			
		||||
      .map((partner) => partner.sharedById);
 | 
			
		||||
    userIds.push(...partnersIds);
 | 
			
		||||
    const partnerIds = await getMyPartnerIds({
 | 
			
		||||
      userId: auth.user.id,
 | 
			
		||||
      repository: this.partnerRepository,
 | 
			
		||||
      timelineEnabled: true,
 | 
			
		||||
    });
 | 
			
		||||
    const userIds = [auth.user.id, ...partnerIds];
 | 
			
		||||
 | 
			
		||||
    const assets = await this.assetRepository.getByDayOfYear(userIds, dto);
 | 
			
		||||
    const groups: Record<number, AssetEntity[]> = {};
 | 
			
		||||
    const currentYear = new Date().getFullYear();
 | 
			
		||||
    for (const asset of assets) {
 | 
			
		||||
      const yearsAgo = currentYear - asset.localDateTime.getFullYear();
 | 
			
		||||
      if (!groups[yearsAgo]) {
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ import { ILoggerRepository } from 'src/interfaces/logger.interface';
 | 
			
		||||
import { IMapRepository } from 'src/interfaces/map.interface';
 | 
			
		||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
 | 
			
		||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
 | 
			
		||||
import { getMyPartnerIds } from 'src/utils/asset.util';
 | 
			
		||||
 | 
			
		||||
export class MapService {
 | 
			
		||||
  private configCore: SystemConfigCore;
 | 
			
		||||
@ -23,14 +24,10 @@ export class MapService {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async getMapMarkers(auth: AuthDto, options: MapMarkerDto): Promise<MapMarkerResponseDto[]> {
 | 
			
		||||
    const userIds: string[] = [auth.user.id];
 | 
			
		||||
    // TODO convert to SQL join
 | 
			
		||||
    const userIds = [auth.user.id];
 | 
			
		||||
    if (options.withPartners) {
 | 
			
		||||
      const partners = await this.partnerRepository.getAll(auth.user.id);
 | 
			
		||||
      const partnersIds = partners
 | 
			
		||||
        .filter((partner) => partner.sharedBy && partner.sharedWith && partner.sharedById != auth.user.id)
 | 
			
		||||
        .map((partner) => partner.sharedById);
 | 
			
		||||
      userIds.push(...partnersIds);
 | 
			
		||||
      const partnerIds = await getMyPartnerIds({ userId: auth.user.id, repository: this.partnerRepository });
 | 
			
		||||
      userIds.push(...partnerIds);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO convert to SQL join
 | 
			
		||||
 | 
			
		||||
@ -24,6 +24,7 @@ import { IPartnerRepository } from 'src/interfaces/partner.interface';
 | 
			
		||||
import { IPersonRepository } from 'src/interfaces/person.interface';
 | 
			
		||||
import { ISearchRepository, SearchExploreItem } from 'src/interfaces/search.interface';
 | 
			
		||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
 | 
			
		||||
import { getMyPartnerIds } from 'src/utils/asset.util';
 | 
			
		||||
import { isSmartSearchEnabled } from 'src/utils/misc';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
@ -140,13 +141,12 @@ export class SearchService {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async getUserIdsToSearch(auth: AuthDto): Promise<string[]> {
 | 
			
		||||
    const userIds: string[] = [auth.user.id];
 | 
			
		||||
    const partners = await this.partnerRepository.getAll(auth.user.id);
 | 
			
		||||
    const partnersIds = partners
 | 
			
		||||
      .filter((partner) => partner.sharedBy && partner.inTimeline)
 | 
			
		||||
      .map((partner) => partner.sharedById);
 | 
			
		||||
    userIds.push(...partnersIds);
 | 
			
		||||
    return userIds;
 | 
			
		||||
    const partnerIds = await getMyPartnerIds({
 | 
			
		||||
      userId: auth.user.id,
 | 
			
		||||
      repository: this.partnerRepository,
 | 
			
		||||
      timelineEnabled: true,
 | 
			
		||||
    });
 | 
			
		||||
    return [auth.user.id, ...partnerIds];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private mapResponse(assets: AssetEntity[], nextPage: string | null): SearchResponseDto {
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,7 @@ import { IAccessRepository } from 'src/interfaces/access.interface';
 | 
			
		||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
 | 
			
		||||
import { IAuditRepository } from 'src/interfaces/audit.interface';
 | 
			
		||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
 | 
			
		||||
import { getMyPartnerIds } from 'src/utils/asset.util';
 | 
			
		||||
import { setIsEqual } from 'src/utils/set';
 | 
			
		||||
 | 
			
		||||
const FULL_SYNC = { needsFullSync: true, deleted: [], upserted: [] };
 | 
			
		||||
@ -46,11 +47,9 @@ export class SyncService {
 | 
			
		||||
      return FULL_SYNC;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const authUserId = auth.user.id;
 | 
			
		||||
 | 
			
		||||
    // app does not have the correct partners synced
 | 
			
		||||
    const partner = await this.partnerRepository.getAll(authUserId);
 | 
			
		||||
    const userIds = [authUserId, ...partner.filter((p) => p.sharedWithId == auth.user.id).map((p) => p.sharedById)];
 | 
			
		||||
    const partnerIds = await getMyPartnerIds({ userId: auth.user.id, repository: this.partnerRepository });
 | 
			
		||||
    const userIds = [auth.user.id, ...partnerIds];
 | 
			
		||||
    if (!setIsEqual(new Set(userIds), new Set(dto.userIds))) {
 | 
			
		||||
      return FULL_SYNC;
 | 
			
		||||
    }
 | 
			
		||||
@ -81,7 +80,7 @@ export class SyncService {
 | 
			
		||||
            auth,
 | 
			
		||||
            stripMetadata: false,
 | 
			
		||||
            // ignore stacks for non partner users
 | 
			
		||||
            withStack: a.ownerId === authUserId,
 | 
			
		||||
            withStack: a.ownerId === auth.user.id,
 | 
			
		||||
          }),
 | 
			
		||||
        ),
 | 
			
		||||
      deleted,
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,7 @@ import { TimeBucketAssetDto, TimeBucketDto, TimeBucketResponseDto } from 'src/dt
 | 
			
		||||
import { IAccessRepository } from 'src/interfaces/access.interface';
 | 
			
		||||
import { IAssetRepository, TimeBucketOptions } from 'src/interfaces/asset.interface';
 | 
			
		||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
 | 
			
		||||
import { getMyPartnerIds } from 'src/utils/asset.util';
 | 
			
		||||
 | 
			
		||||
export class TimelineService {
 | 
			
		||||
  private accessCore: AccessCore;
 | 
			
		||||
@ -43,14 +44,9 @@ export class TimelineService {
 | 
			
		||||
 | 
			
		||||
    if (userId) {
 | 
			
		||||
      userIds = [userId];
 | 
			
		||||
 | 
			
		||||
      if (dto.withPartners) {
 | 
			
		||||
        const partners = await this.partnerRepository.getAll(auth.user.id);
 | 
			
		||||
        const partnersIds = partners
 | 
			
		||||
          .filter((partner) => partner.sharedBy && partner.sharedWith && partner.inTimeline)
 | 
			
		||||
          .map((partner) => partner.sharedById);
 | 
			
		||||
 | 
			
		||||
        userIds.push(...partnersIds);
 | 
			
		||||
        const partnerIds = await getMyPartnerIds({ userId: auth.user.id, repository: this.partnerRepository });
 | 
			
		||||
        userIds.push(...partnerIds);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@ import { AccessCore, Permission } from 'src/cores/access.core';
 | 
			
		||||
import { BulkIdErrorReason, BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto';
 | 
			
		||||
import { AuthDto } from 'src/dtos/auth.dto';
 | 
			
		||||
import { IAccessRepository } from 'src/interfaces/access.interface';
 | 
			
		||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
 | 
			
		||||
import { setDifference, setUnion } from 'src/utils/set';
 | 
			
		||||
 | 
			
		||||
export interface IBulkAsset {
 | 
			
		||||
@ -91,3 +92,33 @@ export const removeAssets = async (
 | 
			
		||||
 | 
			
		||||
  return results;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type PartnerIdOptions = {
 | 
			
		||||
  userId: string;
 | 
			
		||||
  repository: IPartnerRepository;
 | 
			
		||||
  /** only include partners with `inTimeline: true` */
 | 
			
		||||
  timelineEnabled?: boolean;
 | 
			
		||||
};
 | 
			
		||||
export const getMyPartnerIds = async ({ userId, repository, timelineEnabled }: PartnerIdOptions) => {
 | 
			
		||||
  const partnerIds = new Set<string>();
 | 
			
		||||
  const partners = await repository.getAll(userId);
 | 
			
		||||
  for (const partner of partners) {
 | 
			
		||||
    // ignore deleted users
 | 
			
		||||
    if (!partner.sharedBy || !partner.sharedWith) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // wrong direction
 | 
			
		||||
    if (partner.sharedWithId !== userId) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (timelineEnabled && !partner.inTimeline) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    partnerIds.add(partner.sharedById);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return [...partnerIds];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user