mirror of
https://github.com/immich-app/immich.git
synced 2026-04-16 23:51:55 -04:00
* feat(web): lighter timeline buckets * GalleryViewer * weird ssr * Remove generics from AssetInteraction * ensure keys on getAssetInfo, alt-text * empty - trigger ci * re-add alt-text * test fix * update tests * tests * missing import * feat(server): lighter buckets * fix: flappy e2e test * lint * revert settings * unneeded cast * fix after merge * Adapt web client to consume new server response format * test * missing import * lint * Use nulls, make-sql * openapi battle * date->string * tests * tests * lint/tests * lint * test * push aggregation to query * openapi * stack as tuple * openapi * update references to description * update alt text tests * update sql * update sql * update timeline tests * linting, fix expected response * string tuple * fix spec * fix * silly generator * rename patch * minimize sorting * review * lint * lint * sql * test * avoid abbreviations * review comment - type safety in test * merge conflicts * lint * lint/abbreviations * remove unncessary code * review comments * sql * re-add package-lock * use booleans, fix visibility in openapi spec, less cursed controller * update sql * no need to use sql template * array access actually doesn't seem to matter * remove redundant code * re-add sql decorator * unused type * remove null assertions * bad merge * Fix test * shave * extra clean shave * use decorator for content type * redundant types * redundant comment * update comment * unnecessary res --------- Co-authored-by: mertalev <101130780+mertalev@users.noreply.github.com> Co-authored-by: Alex <alex.tran1502@gmail.com>
77 lines
2.9 KiB
TypeScript
77 lines
2.9 KiB
TypeScript
import { BadRequestException, Injectable } from '@nestjs/common';
|
|
import { AuthDto } from 'src/dtos/auth.dto';
|
|
import { TimeBucketAssetDto, TimeBucketDto, TimeBucketsResponseDto } from 'src/dtos/time-bucket.dto';
|
|
import { AssetVisibility, Permission } from 'src/enum';
|
|
import { TimeBucketOptions } from 'src/repositories/asset.repository';
|
|
import { BaseService } from 'src/services/base.service';
|
|
import { getMyPartnerIds } from 'src/utils/asset.util';
|
|
|
|
@Injectable()
|
|
export class TimelineService extends BaseService {
|
|
async getTimeBuckets(auth: AuthDto, dto: TimeBucketDto): Promise<TimeBucketsResponseDto[]> {
|
|
await this.timeBucketChecks(auth, dto);
|
|
const timeBucketOptions = await this.buildTimeBucketOptions(auth, dto);
|
|
return await this.assetRepository.getTimeBuckets(timeBucketOptions);
|
|
}
|
|
|
|
// pre-jsonified response
|
|
async getTimeBucket(auth: AuthDto, dto: TimeBucketAssetDto): Promise<string> {
|
|
await this.timeBucketChecks(auth, dto);
|
|
const timeBucketOptions = await this.buildTimeBucketOptions(auth, { ...dto });
|
|
|
|
// TODO: use id cursor for pagination
|
|
const bucket = await this.assetRepository.getTimeBucket(dto.timeBucket, timeBucketOptions);
|
|
return bucket.assets;
|
|
}
|
|
|
|
private async buildTimeBucketOptions(auth: AuthDto, dto: TimeBucketDto): Promise<TimeBucketOptions> {
|
|
const { userId, ...options } = dto;
|
|
let userIds: string[] | undefined = undefined;
|
|
|
|
if (userId) {
|
|
userIds = [userId];
|
|
if (dto.withPartners) {
|
|
const partnerIds = await getMyPartnerIds({
|
|
userId: auth.user.id,
|
|
repository: this.partnerRepository,
|
|
timelineEnabled: true,
|
|
});
|
|
userIds.push(...partnerIds);
|
|
}
|
|
}
|
|
|
|
return { ...options, userIds };
|
|
}
|
|
|
|
private async timeBucketChecks(auth: AuthDto, dto: TimeBucketDto) {
|
|
if (dto.albumId) {
|
|
await this.requireAccess({ auth, permission: Permission.ALBUM_READ, ids: [dto.albumId] });
|
|
} else {
|
|
dto.userId = dto.userId || auth.user.id;
|
|
}
|
|
|
|
if (dto.userId) {
|
|
await this.requireAccess({ auth, permission: Permission.TIMELINE_READ, ids: [dto.userId] });
|
|
if (dto.visibility === AssetVisibility.ARCHIVE) {
|
|
await this.requireAccess({ auth, permission: Permission.ARCHIVE_READ, ids: [dto.userId] });
|
|
}
|
|
}
|
|
|
|
if (dto.tagId) {
|
|
await this.requireAccess({ auth, permission: Permission.TAG_READ, ids: [dto.tagId] });
|
|
}
|
|
|
|
if (dto.withPartners) {
|
|
const requestedArchived = dto.visibility === AssetVisibility.ARCHIVE || dto.visibility === undefined;
|
|
const requestedFavorite = dto.isFavorite === true || dto.isFavorite === false;
|
|
const requestedTrash = dto.isTrashed === true;
|
|
|
|
if (requestedArchived || requestedFavorite || requestedTrash) {
|
|
throw new BadRequestException(
|
|
'withPartners is only supported for non-archived, non-trashed, non-favorited assets',
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|