mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-03 19:17:11 -05:00 
			
		
		
		
	fix(server): require asset permission when creating an album with them (#8686)
require asset permission when creating an album with them
This commit is contained in:
		
							parent
							
								
									56079527ef
								
							
						
					
					
						commit
						ad5d115abe
					
				@ -4,7 +4,9 @@ import {
 | 
			
		||||
  AssetOrder,
 | 
			
		||||
  LoginResponseDto,
 | 
			
		||||
  SharedLinkType,
 | 
			
		||||
  addAssetsToAlbum,
 | 
			
		||||
  deleteUser,
 | 
			
		||||
  getAlbumInfo,
 | 
			
		||||
} from '@immich/sdk';
 | 
			
		||||
import { createUserDto, uuidDto } from 'src/fixtures';
 | 
			
		||||
import { errorDto } from 'src/responses';
 | 
			
		||||
@ -65,7 +67,6 @@ describe('/album', () => {
 | 
			
		||||
      utils.createAlbum(user2.accessToken, {
 | 
			
		||||
        albumName: user2SharedUser,
 | 
			
		||||
        sharedWithUserIds: [user1.userId],
 | 
			
		||||
        assetIds: [user1Asset1.id],
 | 
			
		||||
      }),
 | 
			
		||||
      utils.createAlbum(user2.accessToken, { albumName: user2SharedLink }),
 | 
			
		||||
      utils.createAlbum(user2.accessToken, { albumName: user2NotShared }),
 | 
			
		||||
@ -77,6 +78,13 @@ describe('/album', () => {
 | 
			
		||||
      }),
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    await addAssetsToAlbum(
 | 
			
		||||
      { id: albums[3].id, bulkIdsDto: { ids: [user1Asset1.id] } },
 | 
			
		||||
      { headers: asBearerAuth(user1.accessToken) },
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    albums[3] = await getAlbumInfo({ id: albums[3].id }, { headers: asBearerAuth(user2.accessToken) });
 | 
			
		||||
 | 
			
		||||
    user1Albums = albums.slice(0, 3);
 | 
			
		||||
    user2Albums = albums.slice(3, 6);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -175,6 +175,7 @@ describe(AlbumService.name, () => {
 | 
			
		||||
    it('creates album', async () => {
 | 
			
		||||
      albumMock.create.mockResolvedValue(albumStub.empty);
 | 
			
		||||
      userMock.get.mockResolvedValue(userStub.user1);
 | 
			
		||||
      accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['123']));
 | 
			
		||||
 | 
			
		||||
      await sut.create(authStub.admin, {
 | 
			
		||||
        albumName: 'Empty album',
 | 
			
		||||
@ -193,6 +194,7 @@ describe(AlbumService.name, () => {
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(userMock.get).toHaveBeenCalledWith('user-id', {});
 | 
			
		||||
      expect(accessMock.asset.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['123']));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should require valid userIds', async () => {
 | 
			
		||||
@ -206,6 +208,31 @@ describe(AlbumService.name, () => {
 | 
			
		||||
      expect(userMock.get).toHaveBeenCalledWith('user-3', {});
 | 
			
		||||
      expect(albumMock.create).not.toHaveBeenCalled();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should only add assets the user is allowed to access', async () => {
 | 
			
		||||
      userMock.get.mockResolvedValue(userStub.user1);
 | 
			
		||||
      albumMock.create.mockResolvedValue(albumStub.oneAsset);
 | 
			
		||||
      accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset-1']));
 | 
			
		||||
 | 
			
		||||
      await sut.create(authStub.admin, {
 | 
			
		||||
        albumName: 'Test album',
 | 
			
		||||
        description: '',
 | 
			
		||||
        assetIds: ['asset-1', 'asset-2'],
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(albumMock.create).toHaveBeenCalledWith({
 | 
			
		||||
        ownerId: authStub.admin.user.id,
 | 
			
		||||
        albumName: 'Test album',
 | 
			
		||||
        description: '',
 | 
			
		||||
        sharedUsers: [],
 | 
			
		||||
        assets: [{ id: 'asset-1' }],
 | 
			
		||||
        albumThumbnailAssetId: 'asset-1',
 | 
			
		||||
      });
 | 
			
		||||
      expect(accessMock.asset.checkOwnerAccess).toHaveBeenCalledWith(
 | 
			
		||||
        authStub.admin.user.id,
 | 
			
		||||
        new Set(['asset-1', 'asset-2']),
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('update', () => {
 | 
			
		||||
 | 
			
		||||
@ -119,13 +119,16 @@ export class AlbumService {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const allowedAssetIdsSet = await this.access.checkAccess(auth, Permission.ASSET_SHARE, new Set(dto.assetIds));
 | 
			
		||||
    const assets = [...allowedAssetIdsSet].map((id) => ({ id }) as AssetEntity);
 | 
			
		||||
 | 
			
		||||
    const album = await this.albumRepository.create({
 | 
			
		||||
      ownerId: auth.user.id,
 | 
			
		||||
      albumName: dto.albumName,
 | 
			
		||||
      description: dto.description,
 | 
			
		||||
      sharedUsers: dto.sharedWithUserIds?.map((value) => ({ id: value }) as UserEntity) ?? [],
 | 
			
		||||
      assets: (dto.assetIds || []).map((id) => ({ id }) as AssetEntity),
 | 
			
		||||
      albumThumbnailAssetId: dto.assetIds?.[0] || null,
 | 
			
		||||
      assets,
 | 
			
		||||
      albumThumbnailAssetId: assets[0]?.id || null,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return mapAlbumWithAssets(album);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user