expose albumPermissions on the API, deprecate sharedUsers

pull/8720/head
mgabor 2024-04-12 13:48:55 +07:00
parent 48149e4384
commit 06028a283b
4 changed files with 37 additions and 30 deletions

@ -83,6 +83,11 @@ export class AlbumCountResponseDto {
notShared!: number;
}
export class AlbumPermissionResponseDto {
user!: UserResponseDto;
readonly!: boolean;
}
export class AlbumResponseDto {
id!: string;
ownerId!: string;
@ -92,7 +97,9 @@ export class AlbumResponseDto {
updatedAt!: Date;
albumThumbnailAssetId!: string | null;
shared!: boolean;
@ApiProperty({ deprecated: true, description: 'Deprecated in favor of albumPermissions' })
sharedUsers!: UserResponseDto[];
albumPermissions!: AlbumPermissionResponseDto[];
hasSharedLink!: boolean;
assets!: AssetResponseDto[];
owner!: UserResponseDto;
@ -109,10 +116,15 @@ export class AlbumResponseDto {
export const mapAlbum = (entity: AlbumEntity, withAssets: boolean, auth?: AuthDto): AlbumResponseDto => {
const sharedUsers: UserResponseDto[] = [];
if (entity.sharedUsers) {
for (const user of entity.sharedUsers) {
sharedUsers.push(mapUser(user));
const albumPermissions: AlbumPermissionResponseDto[] = [];
if (entity.albumPermissions) {
for (const permission of entity.albumPermissions) {
sharedUsers.push(mapUser(permission.users));
albumPermissions.push({
user: mapUser(permission.users),
readonly: permission.readonly,
});
}
}
@ -138,6 +150,7 @@ export const mapAlbum = (entity: AlbumEntity, withAssets: boolean, auth?: AuthDt
ownerId: entity.ownerId,
owner: mapUser(entity.owner),
sharedUsers,
albumPermissions,
shared: hasSharedUser || hasSharedLink,
hasSharedLink,
startDate,

@ -53,13 +53,6 @@ export class AlbumEntity {
@Column({ comment: 'Asset ID to be used as thumbnail', nullable: true })
albumThumbnailAssetId!: string | null;
@ManyToMany(() => UserEntity)
@JoinTable({
name: 'albums_shared_users_users',
synchronize: false, // Table is managed by AlbumPermissionEntity
})
sharedUsers!: UserEntity[];
@OneToMany(() => AlbumPermissionEntity, (permission) => permission.albums)
albumPermissions!: AlbumPermissionEntity[];

@ -8,7 +8,7 @@ import { AssetEntity } from 'src/entities/asset.entity';
import { AlbumAsset, AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.interface';
import { Instrumentation } from 'src/utils/instrumentation';
import { setUnion } from 'src/utils/set';
import { DataSource, FindOptionsOrder, FindOptionsRelations, In, IsNull, Not, Repository } from 'typeorm';
import { DataSource, Equal, FindOptionsOrder, FindOptionsRelations, In, IsNull, Not, Repository } from 'typeorm';
@Instrumentation()
@Injectable()
@ -23,7 +23,7 @@ export class AlbumRepository implements IAlbumRepository {
getById(id: string, options: AlbumInfoOptions): Promise<AlbumEntity | null> {
const relations: FindOptionsRelations<AlbumEntity> = {
owner: true,
sharedUsers: true,
albumPermissions: { users: true },
assets: false,
sharedLinks: true,
};
@ -52,7 +52,7 @@ export class AlbumRepository implements IAlbumRepository {
},
relations: {
owner: true,
sharedUsers: true,
albumPermissions: { users: true },
},
});
}
@ -62,9 +62,9 @@ export class AlbumRepository implements IAlbumRepository {
return this.repository.find({
where: [
{ ownerId, assets: { id: assetId } },
{ sharedUsers: { id: ownerId }, assets: { id: assetId } },
{ albumPermissions: { users: Equal(ownerId) }, assets: { id: assetId } },
],
relations: { owner: true, sharedUsers: true },
relations: { owner: true, albumPermissions: { users: true } },
order: { createdAt: 'DESC' },
});
}
@ -129,7 +129,7 @@ export class AlbumRepository implements IAlbumRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getOwned(ownerId: string): Promise<AlbumEntity[]> {
return this.repository.find({
relations: { sharedUsers: true, sharedLinks: true, owner: true },
relations: { albumPermissions: { users: true }, sharedLinks: true, owner: true },
where: { ownerId },
order: { createdAt: 'DESC' },
});
@ -141,11 +141,11 @@ export class AlbumRepository implements IAlbumRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getShared(ownerId: string): Promise<AlbumEntity[]> {
return this.repository.find({
relations: { sharedUsers: true, sharedLinks: true, owner: true },
relations: { albumPermissions: { users: true }, sharedLinks: true, owner: true },
where: [
{ sharedUsers: { id: ownerId } },
{ albumPermissions: { users: Equal(ownerId) } },
{ sharedLinks: { userId: ownerId } },
{ ownerId, sharedUsers: { id: Not(IsNull()) } },
{ ownerId, albumPermissions: { users: Not(IsNull()) } },
],
order: { createdAt: 'DESC' },
});
@ -157,8 +157,8 @@ export class AlbumRepository implements IAlbumRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getNotShared(ownerId: string): Promise<AlbumEntity[]> {
return this.repository.find({
relations: { sharedUsers: true, sharedLinks: true, owner: true },
where: { ownerId, sharedUsers: { id: IsNull() }, sharedLinks: { id: IsNull() } },
relations: { albumPermissions: true, sharedLinks: true, owner: true },
where: { ownerId, albumPermissions: { users: IsNull() }, sharedLinks: { id: IsNull() } },
order: { createdAt: 'DESC' },
});
}
@ -282,7 +282,7 @@ export class AlbumRepository implements IAlbumRepository {
where: { id },
relations: {
owner: true,
sharedUsers: true,
albumPermissions: { users: true },
sharedLinks: true,
assets: true,
},

@ -14,9 +14,9 @@ import {
} from 'src/dtos/album.dto';
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { AlbumPermissionEntity } from 'src/entities/album-permission.entity';
import { AlbumEntity } from 'src/entities/album.entity';
import { AssetEntity } from 'src/entities/asset.entity';
import { UserEntity } from 'src/entities/user.entity';
import { IAccessRepository } from 'src/interfaces/access.interface';
import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.interface';
import { IAssetRepository } from 'src/interfaces/asset.interface';
@ -123,7 +123,8 @@ export class AlbumService {
ownerId: auth.user.id,
albumName: dto.albumName,
description: dto.description,
sharedUsers: dto.sharedWithUserIds?.map((value) => ({ id: value }) as UserEntity) ?? [],
albumPermissions:
dto.sharedWithUserIds?.map((userId) => ({ users: { id: userId } }) as AlbumPermissionEntity) ?? [],
assets: (dto.assetIds || []).map((id) => ({ id }) as AssetEntity),
albumThumbnailAssetId: dto.assetIds?.[0] || null,
});
@ -216,7 +217,7 @@ export class AlbumService {
throw new BadRequestException('Cannot be shared with owner');
}
const exists = album.sharedUsers.find((user) => user.id === userId);
const exists = album.albumPermissions.find(({ users: { id } }) => id === userId);
if (exists) {
throw new BadRequestException('User already added');
}
@ -226,14 +227,14 @@ export class AlbumService {
throw new BadRequestException('User not found');
}
album.sharedUsers.push({ id: userId } as UserEntity);
album.albumPermissions.push({ users: { id: userId } } as AlbumPermissionEntity);
}
return this.albumRepository
.update({
id: album.id,
updatedAt: new Date(),
sharedUsers: album.sharedUsers,
albumPermissions: album.albumPermissions,
})
.then(mapAlbumWithoutAssets);
}
@ -249,7 +250,7 @@ export class AlbumService {
throw new BadRequestException('Cannot remove album owner');
}
const exists = album.sharedUsers.find((user) => user.id === userId);
const exists = album.albumPermissions.find(({ users: { id } }) => id === userId);
if (!exists) {
throw new BadRequestException('Album not shared with user');
}
@ -262,7 +263,7 @@ export class AlbumService {
await this.albumRepository.update({
id: album.id,
updatedAt: new Date(),
sharedUsers: album.sharedUsers.filter((user) => user.id !== userId),
albumPermissions: album.albumPermissions.filter(({ users: { id } }) => id !== userId),
});
}