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