expose albumPermissions on the API, deprecate sharedUsers
This commit is contained in:
@@ -83,6 +83,11 @@ export class AlbumCountResponseDto {
|
|||||||
notShared!: number;
|
notShared!: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class AlbumPermissionResponseDto {
|
||||||
|
user!: UserResponseDto;
|
||||||
|
readonly!: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export class AlbumResponseDto {
|
export class AlbumResponseDto {
|
||||||
id!: string;
|
id!: string;
|
||||||
ownerId!: string;
|
ownerId!: string;
|
||||||
@@ -92,7 +97,9 @@ export class AlbumResponseDto {
|
|||||||
updatedAt!: Date;
|
updatedAt!: Date;
|
||||||
albumThumbnailAssetId!: string | null;
|
albumThumbnailAssetId!: string | null;
|
||||||
shared!: boolean;
|
shared!: boolean;
|
||||||
|
@ApiProperty({ deprecated: true, description: 'Deprecated in favor of albumPermissions' })
|
||||||
sharedUsers!: UserResponseDto[];
|
sharedUsers!: UserResponseDto[];
|
||||||
|
albumPermissions!: AlbumPermissionResponseDto[];
|
||||||
hasSharedLink!: boolean;
|
hasSharedLink!: boolean;
|
||||||
assets!: AssetResponseDto[];
|
assets!: AssetResponseDto[];
|
||||||
owner!: UserResponseDto;
|
owner!: UserResponseDto;
|
||||||
@@ -109,10 +116,15 @@ export class AlbumResponseDto {
|
|||||||
|
|
||||||
export const mapAlbum = (entity: AlbumEntity, withAssets: boolean, auth?: AuthDto): AlbumResponseDto => {
|
export const mapAlbum = (entity: AlbumEntity, withAssets: boolean, auth?: AuthDto): AlbumResponseDto => {
|
||||||
const sharedUsers: UserResponseDto[] = [];
|
const sharedUsers: UserResponseDto[] = [];
|
||||||
|
const albumPermissions: AlbumPermissionResponseDto[] = [];
|
||||||
|
|
||||||
if (entity.sharedUsers) {
|
if (entity.albumPermissions) {
|
||||||
for (const user of entity.sharedUsers) {
|
for (const permission of entity.albumPermissions) {
|
||||||
sharedUsers.push(mapUser(user));
|
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,
|
ownerId: entity.ownerId,
|
||||||
owner: mapUser(entity.owner),
|
owner: mapUser(entity.owner),
|
||||||
sharedUsers,
|
sharedUsers,
|
||||||
|
albumPermissions,
|
||||||
shared: hasSharedUser || hasSharedLink,
|
shared: hasSharedUser || hasSharedLink,
|
||||||
hasSharedLink,
|
hasSharedLink,
|
||||||
startDate,
|
startDate,
|
||||||
|
|||||||
@@ -53,13 +53,6 @@ export class AlbumEntity {
|
|||||||
@Column({ comment: 'Asset ID to be used as thumbnail', nullable: true })
|
@Column({ comment: 'Asset ID to be used as thumbnail', nullable: true })
|
||||||
albumThumbnailAssetId!: string | null;
|
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)
|
@OneToMany(() => AlbumPermissionEntity, (permission) => permission.albums)
|
||||||
albumPermissions!: AlbumPermissionEntity[];
|
albumPermissions!: AlbumPermissionEntity[];
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { AssetEntity } from 'src/entities/asset.entity';
|
|||||||
import { AlbumAsset, AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.interface';
|
import { AlbumAsset, AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.interface';
|
||||||
import { Instrumentation } from 'src/utils/instrumentation';
|
import { Instrumentation } from 'src/utils/instrumentation';
|
||||||
import { setUnion } from 'src/utils/set';
|
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()
|
@Instrumentation()
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@@ -23,7 +23,7 @@ export class AlbumRepository implements IAlbumRepository {
|
|||||||
getById(id: string, options: AlbumInfoOptions): Promise<AlbumEntity | null> {
|
getById(id: string, options: AlbumInfoOptions): Promise<AlbumEntity | null> {
|
||||||
const relations: FindOptionsRelations<AlbumEntity> = {
|
const relations: FindOptionsRelations<AlbumEntity> = {
|
||||||
owner: true,
|
owner: true,
|
||||||
sharedUsers: true,
|
albumPermissions: { users: true },
|
||||||
assets: false,
|
assets: false,
|
||||||
sharedLinks: true,
|
sharedLinks: true,
|
||||||
};
|
};
|
||||||
@@ -52,7 +52,7 @@ export class AlbumRepository implements IAlbumRepository {
|
|||||||
},
|
},
|
||||||
relations: {
|
relations: {
|
||||||
owner: true,
|
owner: true,
|
||||||
sharedUsers: true,
|
albumPermissions: { users: true },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -62,9 +62,9 @@ export class AlbumRepository implements IAlbumRepository {
|
|||||||
return this.repository.find({
|
return this.repository.find({
|
||||||
where: [
|
where: [
|
||||||
{ ownerId, assets: { id: assetId } },
|
{ 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' },
|
order: { createdAt: 'DESC' },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,7 @@ export class AlbumRepository implements IAlbumRepository {
|
|||||||
@GenerateSql({ params: [DummyValue.UUID] })
|
@GenerateSql({ params: [DummyValue.UUID] })
|
||||||
getOwned(ownerId: string): Promise<AlbumEntity[]> {
|
getOwned(ownerId: string): Promise<AlbumEntity[]> {
|
||||||
return this.repository.find({
|
return this.repository.find({
|
||||||
relations: { sharedUsers: true, sharedLinks: true, owner: true },
|
relations: { albumPermissions: { users: true }, sharedLinks: true, owner: true },
|
||||||
where: { ownerId },
|
where: { ownerId },
|
||||||
order: { createdAt: 'DESC' },
|
order: { createdAt: 'DESC' },
|
||||||
});
|
});
|
||||||
@@ -141,11 +141,11 @@ export class AlbumRepository implements IAlbumRepository {
|
|||||||
@GenerateSql({ params: [DummyValue.UUID] })
|
@GenerateSql({ params: [DummyValue.UUID] })
|
||||||
getShared(ownerId: string): Promise<AlbumEntity[]> {
|
getShared(ownerId: string): Promise<AlbumEntity[]> {
|
||||||
return this.repository.find({
|
return this.repository.find({
|
||||||
relations: { sharedUsers: true, sharedLinks: true, owner: true },
|
relations: { albumPermissions: { users: true }, sharedLinks: true, owner: true },
|
||||||
where: [
|
where: [
|
||||||
{ sharedUsers: { id: ownerId } },
|
{ albumPermissions: { users: Equal(ownerId) } },
|
||||||
{ sharedLinks: { userId: ownerId } },
|
{ sharedLinks: { userId: ownerId } },
|
||||||
{ ownerId, sharedUsers: { id: Not(IsNull()) } },
|
{ ownerId, albumPermissions: { users: Not(IsNull()) } },
|
||||||
],
|
],
|
||||||
order: { createdAt: 'DESC' },
|
order: { createdAt: 'DESC' },
|
||||||
});
|
});
|
||||||
@@ -157,8 +157,8 @@ export class AlbumRepository implements IAlbumRepository {
|
|||||||
@GenerateSql({ params: [DummyValue.UUID] })
|
@GenerateSql({ params: [DummyValue.UUID] })
|
||||||
getNotShared(ownerId: string): Promise<AlbumEntity[]> {
|
getNotShared(ownerId: string): Promise<AlbumEntity[]> {
|
||||||
return this.repository.find({
|
return this.repository.find({
|
||||||
relations: { sharedUsers: true, sharedLinks: true, owner: true },
|
relations: { albumPermissions: true, sharedLinks: true, owner: true },
|
||||||
where: { ownerId, sharedUsers: { id: IsNull() }, sharedLinks: { id: IsNull() } },
|
where: { ownerId, albumPermissions: { users: IsNull() }, sharedLinks: { id: IsNull() } },
|
||||||
order: { createdAt: 'DESC' },
|
order: { createdAt: 'DESC' },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -282,7 +282,7 @@ export class AlbumRepository implements IAlbumRepository {
|
|||||||
where: { id },
|
where: { id },
|
||||||
relations: {
|
relations: {
|
||||||
owner: true,
|
owner: true,
|
||||||
sharedUsers: true,
|
albumPermissions: { users: true },
|
||||||
sharedLinks: true,
|
sharedLinks: true,
|
||||||
assets: true,
|
assets: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import {
|
|||||||
} 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 { AlbumPermissionEntity } from 'src/entities/album-permission.entity';
|
||||||
import { AlbumEntity } from 'src/entities/album.entity';
|
import { AlbumEntity } from 'src/entities/album.entity';
|
||||||
import { AssetEntity } from 'src/entities/asset.entity';
|
import { AssetEntity } from 'src/entities/asset.entity';
|
||||||
import { UserEntity } from 'src/entities/user.entity';
|
|
||||||
import { IAccessRepository } from 'src/interfaces/access.interface';
|
import { IAccessRepository } from 'src/interfaces/access.interface';
|
||||||
import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.interface';
|
import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.interface';
|
||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||||
@@ -123,7 +123,8 @@ export class AlbumService {
|
|||||||
ownerId: auth.user.id,
|
ownerId: auth.user.id,
|
||||||
albumName: dto.albumName,
|
albumName: dto.albumName,
|
||||||
description: dto.description,
|
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),
|
assets: (dto.assetIds || []).map((id) => ({ id }) as AssetEntity),
|
||||||
albumThumbnailAssetId: dto.assetIds?.[0] || null,
|
albumThumbnailAssetId: dto.assetIds?.[0] || null,
|
||||||
});
|
});
|
||||||
@@ -216,7 +217,7 @@ export class AlbumService {
|
|||||||
throw new BadRequestException('Cannot be shared with owner');
|
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) {
|
if (exists) {
|
||||||
throw new BadRequestException('User already added');
|
throw new BadRequestException('User already added');
|
||||||
}
|
}
|
||||||
@@ -226,14 +227,14 @@ export class AlbumService {
|
|||||||
throw new BadRequestException('User not found');
|
throw new BadRequestException('User not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
album.sharedUsers.push({ id: userId } as UserEntity);
|
album.albumPermissions.push({ users: { id: userId } } as AlbumPermissionEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.albumRepository
|
return this.albumRepository
|
||||||
.update({
|
.update({
|
||||||
id: album.id,
|
id: album.id,
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
sharedUsers: album.sharedUsers,
|
albumPermissions: album.albumPermissions,
|
||||||
})
|
})
|
||||||
.then(mapAlbumWithoutAssets);
|
.then(mapAlbumWithoutAssets);
|
||||||
}
|
}
|
||||||
@@ -249,7 +250,7 @@ export class AlbumService {
|
|||||||
throw new BadRequestException('Cannot remove album owner');
|
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) {
|
if (!exists) {
|
||||||
throw new BadRequestException('Album not shared with user');
|
throw new BadRequestException('Album not shared with user');
|
||||||
}
|
}
|
||||||
@@ -262,7 +263,7 @@ export class AlbumService {
|
|||||||
await this.albumRepository.update({
|
await this.albumRepository.update({
|
||||||
id: album.id,
|
id: album.id,
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
sharedUsers: album.sharedUsers.filter((user) => user.id !== userId),
|
albumPermissions: album.albumPermissions.filter(({ users: { id } }) => id !== userId),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user