mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:27:09 -05:00 
			
		
		
		
	refactor: album user entity (#17524)
This commit is contained in:
		
							parent
							
								
									94dba29298
								
							
						
					
					
						commit
						8aea07b750
					
				@ -1,4 +1,4 @@
 | 
				
			|||||||
import { AssetStatus, AssetType, MemoryType, Permission, UserStatus } from 'src/enum';
 | 
					import { AlbumUserRole, AssetStatus, AssetType, MemoryType, Permission, UserStatus } from 'src/enum';
 | 
				
			||||||
import { OnThisDayData, UserMetadataItem } from 'src/types';
 | 
					import { OnThisDayData, UserMetadataItem } from 'src/types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type AuthUser = {
 | 
					export type AuthUser = {
 | 
				
			||||||
@ -10,6 +10,11 @@ export type AuthUser = {
 | 
				
			|||||||
  quotaSizeInBytes: number | null;
 | 
					  quotaSizeInBytes: number | null;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AlbumUser = {
 | 
				
			||||||
 | 
					  user: User;
 | 
				
			||||||
 | 
					  role: AlbumUserRole;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type Library = {
 | 
					export type Library = {
 | 
				
			||||||
  id: string;
 | 
					  id: string;
 | 
				
			||||||
  ownerId: string;
 | 
					  ownerId: string;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +0,0 @@
 | 
				
			|||||||
import { User } from 'src/database';
 | 
					 | 
				
			||||||
import { AlbumEntity } from 'src/entities/album.entity';
 | 
					 | 
				
			||||||
import { AlbumUserRole } from 'src/enum';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export class AlbumUserEntity {
 | 
					 | 
				
			||||||
  albumId!: string;
 | 
					 | 
				
			||||||
  userId!: string;
 | 
					 | 
				
			||||||
  album!: AlbumEntity;
 | 
					 | 
				
			||||||
  user!: User;
 | 
					 | 
				
			||||||
  role!: AlbumUserRole;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,5 +1,4 @@
 | 
				
			|||||||
import { User } from 'src/database';
 | 
					import { AlbumUser, User } from 'src/database';
 | 
				
			||||||
import { AlbumUserEntity } from 'src/entities/album-user.entity';
 | 
					 | 
				
			||||||
import { AssetEntity } from 'src/entities/asset.entity';
 | 
					import { AssetEntity } from 'src/entities/asset.entity';
 | 
				
			||||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
 | 
					import { SharedLinkEntity } from 'src/entities/shared-link.entity';
 | 
				
			||||||
import { AssetOrder } from 'src/enum';
 | 
					import { AssetOrder } from 'src/enum';
 | 
				
			||||||
@ -16,7 +15,7 @@ export class AlbumEntity {
 | 
				
			|||||||
  deletedAt!: Date | null;
 | 
					  deletedAt!: Date | null;
 | 
				
			||||||
  albumThumbnailAsset!: AssetEntity | null;
 | 
					  albumThumbnailAsset!: AssetEntity | null;
 | 
				
			||||||
  albumThumbnailAssetId!: string | null;
 | 
					  albumThumbnailAssetId!: string | null;
 | 
				
			||||||
  albumUsers!: AlbumUserEntity[];
 | 
					  albumUsers!: AlbumUser[];
 | 
				
			||||||
  assets!: AssetEntity[];
 | 
					  assets!: AssetEntity[];
 | 
				
			||||||
  sharedLinks!: SharedLinkEntity[];
 | 
					  sharedLinks!: SharedLinkEntity[];
 | 
				
			||||||
  isActivityEnabled!: boolean;
 | 
					  isActivityEnabled!: boolean;
 | 
				
			||||||
 | 
				
			|||||||
@ -7,13 +7,13 @@ import {
 | 
				
			|||||||
  CreateAlbumDto,
 | 
					  CreateAlbumDto,
 | 
				
			||||||
  GetAlbumsDto,
 | 
					  GetAlbumsDto,
 | 
				
			||||||
  UpdateAlbumDto,
 | 
					  UpdateAlbumDto,
 | 
				
			||||||
 | 
					  UpdateAlbumUserDto,
 | 
				
			||||||
  mapAlbum,
 | 
					  mapAlbum,
 | 
				
			||||||
  mapAlbumWithAssets,
 | 
					  mapAlbumWithAssets,
 | 
				
			||||||
  mapAlbumWithoutAssets,
 | 
					  mapAlbumWithoutAssets,
 | 
				
			||||||
} from 'src/dtos/album.dto';
 | 
					} from 'src/dtos/album.dto';
 | 
				
			||||||
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
 | 
					import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
 | 
				
			||||||
import { AuthDto } from 'src/dtos/auth.dto';
 | 
					import { AuthDto } from 'src/dtos/auth.dto';
 | 
				
			||||||
import { AlbumUserEntity } from 'src/entities/album-user.entity';
 | 
					 | 
				
			||||||
import { AlbumEntity } from 'src/entities/album.entity';
 | 
					import { AlbumEntity } from 'src/entities/album.entity';
 | 
				
			||||||
import { Permission } from 'src/enum';
 | 
					import { Permission } from 'src/enum';
 | 
				
			||||||
import { AlbumAssetCount, AlbumInfoOptions } from 'src/repositories/album.repository';
 | 
					import { AlbumAssetCount, AlbumInfoOptions } from 'src/repositories/album.repository';
 | 
				
			||||||
@ -247,7 +247,7 @@ export class AlbumService extends BaseService {
 | 
				
			|||||||
    await this.albumUserRepository.delete({ albumsId: id, usersId: userId });
 | 
					    await this.albumUserRepository.delete({ albumsId: id, usersId: userId });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async updateUser(auth: AuthDto, id: string, userId: string, dto: Partial<AlbumUserEntity>): Promise<void> {
 | 
					  async updateUser(auth: AuthDto, id: string, userId: string, dto: UpdateAlbumUserDto): Promise<void> {
 | 
				
			||||||
    await this.requireAccess({ auth, permission: Permission.ALBUM_SHARE, ids: [id] });
 | 
					    await this.requireAccess({ auth, permission: Permission.ALBUM_SHARE, ids: [id] });
 | 
				
			||||||
    await this.albumUserRepository.update({ albumsId: id, usersId: userId }, { role: dto.role });
 | 
					    await this.albumUserRepository.update({ albumsId: id, usersId: userId }, { role: dto.role });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { plainToInstance } from 'class-transformer';
 | 
					import { plainToInstance } from 'class-transformer';
 | 
				
			||||||
import { defaults, SystemConfig } from 'src/config';
 | 
					import { defaults, SystemConfig } from 'src/config';
 | 
				
			||||||
 | 
					import { AlbumUser } from 'src/database';
 | 
				
			||||||
import { SystemConfigDto } from 'src/dtos/system-config.dto';
 | 
					import { SystemConfigDto } from 'src/dtos/system-config.dto';
 | 
				
			||||||
import { AlbumUserEntity } from 'src/entities/album-user.entity';
 | 
					 | 
				
			||||||
import { AssetFileEntity } from 'src/entities/asset-files.entity';
 | 
					import { AssetFileEntity } from 'src/entities/asset-files.entity';
 | 
				
			||||||
import { AssetFileType, JobName, JobStatus, UserMetadataKey } from 'src/enum';
 | 
					import { AssetFileType, JobName, JobStatus, UserMetadataKey } from 'src/enum';
 | 
				
			||||||
import { EmailTemplate } from 'src/repositories/notification.repository';
 | 
					import { EmailTemplate } from 'src/repositories/notification.repository';
 | 
				
			||||||
@ -503,7 +503,7 @@ describe(NotificationService.name, () => {
 | 
				
			|||||||
    it('should skip recipient that could not be looked up', async () => {
 | 
					    it('should skip recipient that could not be looked up', async () => {
 | 
				
			||||||
      mocks.album.getById.mockResolvedValue({
 | 
					      mocks.album.getById.mockResolvedValue({
 | 
				
			||||||
        ...albumStub.emptyWithValidThumbnail,
 | 
					        ...albumStub.emptyWithValidThumbnail,
 | 
				
			||||||
        albumUsers: [{ user: { id: userStub.user1.id } } as AlbumUserEntity],
 | 
					        albumUsers: [{ user: { id: userStub.user1.id } } as AlbumUser],
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      mocks.user.get.mockResolvedValueOnce(userStub.user1);
 | 
					      mocks.user.get.mockResolvedValueOnce(userStub.user1);
 | 
				
			||||||
      mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' });
 | 
					      mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' });
 | 
				
			||||||
@ -516,7 +516,7 @@ describe(NotificationService.name, () => {
 | 
				
			|||||||
    it('should skip recipient with disabled email notifications', async () => {
 | 
					    it('should skip recipient with disabled email notifications', async () => {
 | 
				
			||||||
      mocks.album.getById.mockResolvedValue({
 | 
					      mocks.album.getById.mockResolvedValue({
 | 
				
			||||||
        ...albumStub.emptyWithValidThumbnail,
 | 
					        ...albumStub.emptyWithValidThumbnail,
 | 
				
			||||||
        albumUsers: [{ user: { id: userStub.user1.id } } as AlbumUserEntity],
 | 
					        albumUsers: [{ user: { id: userStub.user1.id } } as AlbumUser],
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      mocks.user.get.mockResolvedValue({
 | 
					      mocks.user.get.mockResolvedValue({
 | 
				
			||||||
        ...userStub.user1,
 | 
					        ...userStub.user1,
 | 
				
			||||||
@ -537,7 +537,7 @@ describe(NotificationService.name, () => {
 | 
				
			|||||||
    it('should skip recipient with disabled email notifications for the album update event', async () => {
 | 
					    it('should skip recipient with disabled email notifications for the album update event', async () => {
 | 
				
			||||||
      mocks.album.getById.mockResolvedValue({
 | 
					      mocks.album.getById.mockResolvedValue({
 | 
				
			||||||
        ...albumStub.emptyWithValidThumbnail,
 | 
					        ...albumStub.emptyWithValidThumbnail,
 | 
				
			||||||
        albumUsers: [{ user: { id: userStub.user1.id } } as AlbumUserEntity],
 | 
					        albumUsers: [{ user: { id: userStub.user1.id } } as AlbumUser],
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      mocks.user.get.mockResolvedValue({
 | 
					      mocks.user.get.mockResolvedValue({
 | 
				
			||||||
        ...userStub.user1,
 | 
					        ...userStub.user1,
 | 
				
			||||||
@ -558,7 +558,7 @@ describe(NotificationService.name, () => {
 | 
				
			|||||||
    it('should send email', async () => {
 | 
					    it('should send email', async () => {
 | 
				
			||||||
      mocks.album.getById.mockResolvedValue({
 | 
					      mocks.album.getById.mockResolvedValue({
 | 
				
			||||||
        ...albumStub.emptyWithValidThumbnail,
 | 
					        ...albumStub.emptyWithValidThumbnail,
 | 
				
			||||||
        albumUsers: [{ user: { id: userStub.user1.id } } as AlbumUserEntity],
 | 
					        albumUsers: [{ user: { id: userStub.user1.id } } as AlbumUser],
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      mocks.user.get.mockResolvedValue(userStub.user1);
 | 
					      mocks.user.get.mockResolvedValue(userStub.user1);
 | 
				
			||||||
      mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' });
 | 
					      mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' });
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										12
									
								
								server/test/fixtures/album.stub.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								server/test/fixtures/album.stub.ts
									
									
									
									
										vendored
									
									
								
							@ -38,10 +38,7 @@ export const albumStub = {
 | 
				
			|||||||
    albumUsers: [
 | 
					    albumUsers: [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        user: userStub.user1,
 | 
					        user: userStub.user1,
 | 
				
			||||||
        album: undefined as unknown as AlbumEntity,
 | 
					 | 
				
			||||||
        role: AlbumUserRole.EDITOR,
 | 
					        role: AlbumUserRole.EDITOR,
 | 
				
			||||||
        userId: userStub.user1.id,
 | 
					 | 
				
			||||||
        albumId: 'album-2',
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    isActivityEnabled: true,
 | 
					    isActivityEnabled: true,
 | 
				
			||||||
@ -63,17 +60,11 @@ export const albumStub = {
 | 
				
			|||||||
    albumUsers: [
 | 
					    albumUsers: [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        user: userStub.user1,
 | 
					        user: userStub.user1,
 | 
				
			||||||
        album: undefined as unknown as AlbumEntity,
 | 
					 | 
				
			||||||
        role: AlbumUserRole.EDITOR,
 | 
					        role: AlbumUserRole.EDITOR,
 | 
				
			||||||
        userId: userStub.user1.id,
 | 
					 | 
				
			||||||
        albumId: 'album-3',
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        user: userStub.user2,
 | 
					        user: userStub.user2,
 | 
				
			||||||
        album: undefined as unknown as AlbumEntity,
 | 
					 | 
				
			||||||
        role: AlbumUserRole.EDITOR,
 | 
					        role: AlbumUserRole.EDITOR,
 | 
				
			||||||
        userId: userStub.user2.id,
 | 
					 | 
				
			||||||
        albumId: 'album-3',
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    isActivityEnabled: true,
 | 
					    isActivityEnabled: true,
 | 
				
			||||||
@ -95,10 +86,7 @@ export const albumStub = {
 | 
				
			|||||||
    albumUsers: [
 | 
					    albumUsers: [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        user: userStub.admin,
 | 
					        user: userStub.admin,
 | 
				
			||||||
        album: undefined as unknown as AlbumEntity,
 | 
					 | 
				
			||||||
        role: AlbumUserRole.EDITOR,
 | 
					        role: AlbumUserRole.EDITOR,
 | 
				
			||||||
        userId: userStub.admin.id,
 | 
					 | 
				
			||||||
        albumId: 'album-3',
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    isActivityEnabled: true,
 | 
					    isActivityEnabled: true,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user