1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-08 21:06:48 +01:00

Check public albums for asset

This commit is contained in:
Matthias Rupp 2022-11-20 23:57:23 +01:00
parent 0e02bbed85
commit 11407b7e30
3 changed files with 35 additions and 4 deletions

View file

@ -25,6 +25,7 @@ export interface IAlbumRepository {
updateAlbum(album: AlbumEntity, updateAlbumDto: UpdateAlbumDto): Promise<AlbumEntity>; updateAlbum(album: AlbumEntity, updateAlbumDto: UpdateAlbumDto): Promise<AlbumEntity>;
getListByAssetId(userId: string, assetId: string): Promise<AlbumEntity[]>; getListByAssetId(userId: string, assetId: string): Promise<AlbumEntity[]>;
getCountByUserId(userId: string): Promise<AlbumCountResponseDto>; getCountByUserId(userId: string): Promise<AlbumCountResponseDto>;
getSharedAlbumCount(userId: string, assetId: string): Promise<number>;
} }
export const ALBUM_REPOSITORY = 'ALBUM_REPOSITORY'; export const ALBUM_REPOSITORY = 'ALBUM_REPOSITORY';
@ -283,4 +284,17 @@ export class AlbumRepository implements IAlbumRepository {
return this.albumRepository.save(album); return this.albumRepository.save(album);
} }
async getSharedAlbumCount(userId: string, assetId: string): Promise<number> {
const result = await this
.userAlbumRepository
.createQueryBuilder('usa')
.select('count(aa)', 'count')
.innerJoin('asset_album', 'aa', 'aa.albumId = usa.albumId')
.where('aa.assetId = :assetId', { assetId })
.andWhere('usa.sharedUserId = :userId', { userId })
.getRawOne();
return result.count;
}
} }

View file

@ -10,13 +10,18 @@ import { CommunicationModule } from '../communication/communication.module';
import { QueueNameEnum } from '@app/job/constants/queue-name.constant'; import { QueueNameEnum } from '@app/job/constants/queue-name.constant';
import { AssetRepository, ASSET_REPOSITORY } from './asset-repository'; import { AssetRepository, ASSET_REPOSITORY } from './asset-repository';
import { DownloadModule } from '../../modules/download/download.module'; import { DownloadModule } from '../../modules/download/download.module';
import {ALBUM_REPOSITORY, AlbumRepository} from "../album/album-repository";
import {AlbumEntity} from "@app/database/entities/album.entity";
import {UserAlbumEntity} from "@app/database/entities/user-album.entity";
import {UserEntity} from "@app/database/entities/user.entity";
import {AssetAlbumEntity} from "@app/database/entities/asset-album.entity";
@Module({ @Module({
imports: [ imports: [
CommunicationModule, CommunicationModule,
BackgroundTaskModule, BackgroundTaskModule,
DownloadModule, DownloadModule,
TypeOrmModule.forFeature([AssetEntity]), TypeOrmModule.forFeature([AssetEntity, AlbumEntity, UserAlbumEntity, UserEntity, AssetAlbumEntity]),
BullModule.registerQueue({ BullModule.registerQueue({
name: QueueNameEnum.ASSET_UPLOADED, name: QueueNameEnum.ASSET_UPLOADED,
defaultJobOptions: { defaultJobOptions: {
@ -42,6 +47,10 @@ import { DownloadModule } from '../../modules/download/download.module';
provide: ASSET_REPOSITORY, provide: ASSET_REPOSITORY,
useClass: AssetRepository, useClass: AssetRepository,
}, },
{
provide: ALBUM_REPOSITORY,
useClass: AlbumRepository,
},
], ],
exports: [AssetService], exports: [AssetService],
}) })

View file

@ -54,6 +54,7 @@ import { InjectQueue } from '@nestjs/bull';
import { Queue } from 'bull'; import { Queue } from 'bull';
import { DownloadService } from '../../modules/download/download.service'; import { DownloadService } from '../../modules/download/download.service';
import { DownloadDto } from './dto/download-library.dto'; import { DownloadDto } from './dto/download-library.dto';
import { ALBUM_REPOSITORY, IAlbumRepository } from "../album/album-repository";
const fileInfo = promisify(stat); const fileInfo = promisify(stat);
@ -63,6 +64,9 @@ export class AssetService {
@Inject(ASSET_REPOSITORY) @Inject(ASSET_REPOSITORY)
private _assetRepository: IAssetRepository, private _assetRepository: IAssetRepository,
@Inject(ALBUM_REPOSITORY)
private _albumRepository: IAlbumRepository,
@InjectRepository(AssetEntity) @InjectRepository(AssetEntity)
private assetRepository: Repository<AssetEntity>, private assetRepository: Repository<AssetEntity>,
@ -627,8 +631,8 @@ export class AssetService {
return this._assetRepository.getAssetCountByUserId(authUser.id); return this._assetRepository.getAssetCountByUserId(authUser.id);
} }
async checkAssetsAccess(authUser: AuthUserDto, assetIds: string[], mustBeOwner: boolean = false) { async checkAssetsAccess(authUser: AuthUserDto, assetIds: string[], mustBeOwner = false) {
for (let assetId of assetIds) { for (const assetId of assetIds) {
// Step 1: Check if user owns asset // Step 1: Check if user owns asset
if (await this._assetRepository.countByIdAndUser(assetId, authUser.id) == 1) { if (await this._assetRepository.countByIdAndUser(assetId, authUser.id) == 1) {
continue; continue;
@ -636,9 +640,13 @@ export class AssetService {
// Avoid additional checks if ownership is required // Avoid additional checks if ownership is required
if (!mustBeOwner) { if (!mustBeOwner) {
// Step 2: Check if asset is part of an album shared with me
if (await this._albumRepository.getSharedAlbumCount(authUser.id, assetId) > 0) {
continue;
} }
//TODO: Step 3: Check if asset is part of a public album
}
throw new ForbiddenException(); throw new ForbiddenException();
} }
} }