mirror of
https://github.com/immich-app/immich.git
synced 2026-02-11 19:38:54 +03:00
fix db schema annotations
This commit is contained in:
@@ -125,9 +125,9 @@ export const mapAlbum = (entity: AlbumEntity, withAssets: boolean, auth?: AuthDt
|
||||
|
||||
if (entity.sharedUsers) {
|
||||
for (const permission of entity.sharedUsers) {
|
||||
sharedUsers.push(mapUser(permission.users));
|
||||
sharedUsers.push(mapUser(permission.user));
|
||||
sharedUsersV2.push({
|
||||
user: mapUser(permission.users),
|
||||
user: mapUser(permission.user),
|
||||
readonly: permission.readonly,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import { AlbumEntity } from 'src/entities/album.entity';
|
||||
import { UserEntity } from 'src/entities/user.entity';
|
||||
import { Column, Entity, Index, ManyToOne, PrimaryColumn } from 'typeorm';
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm';
|
||||
|
||||
@Entity('albums_shared_users_users')
|
||||
// Indices for JoinTable
|
||||
@Index('IDX_427c350ad49bd3935a50baab73', ['albums'])
|
||||
@Index('IDX_f48513bf9bccefd6ff3ad30bd0', ['users'])
|
||||
// Pre-existing indices from original album <--> user ManyToMany mapping
|
||||
@Index('IDX_427c350ad49bd3935a50baab73', ['album'])
|
||||
@Index('IDX_f48513bf9bccefd6ff3ad30bd0', ['user'])
|
||||
export class AlbumUserEntity {
|
||||
@PrimaryColumn({ type: 'uuid', name: 'albumsId' })
|
||||
@JoinColumn({ name: 'albumsId' })
|
||||
@ManyToOne(() => AlbumEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
|
||||
albums!: AlbumEntity;
|
||||
album!: AlbumEntity;
|
||||
|
||||
@PrimaryColumn({ type: 'uuid', name: 'usersId' })
|
||||
@JoinColumn({ name: 'usersId' })
|
||||
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
|
||||
users!: UserEntity;
|
||||
user!: UserEntity;
|
||||
|
||||
@Column({ default: true })
|
||||
@Column({ default: false })
|
||||
readonly!: boolean;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ export class AlbumEntity {
|
||||
@Column({ comment: 'Asset ID to be used as thumbnail', nullable: true })
|
||||
albumThumbnailAssetId!: string | null;
|
||||
|
||||
@OneToMany(() => AlbumUserEntity, (permission) => permission.albums)
|
||||
@OneToMany(() => AlbumUserEntity, (permission) => permission.album)
|
||||
sharedUsers!: AlbumUserEntity[];
|
||||
|
||||
@ManyToMany(() => AssetEntity, (asset) => asset.albums)
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class SetReadonlyDefault1712905931092 implements MigrationInterface {
|
||||
name = 'SetReadonlyDefault1712905931092'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "albums_shared_users_users" ALTER COLUMN "readonly" SET DEFAULT true`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "albums_shared_users_users" ALTER COLUMN "readonly" SET DEFAULT false`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class AddAlbumPermission1712905775156 implements MigrationInterface {
|
||||
name = 'AddAlbumPermission1712905775156'
|
||||
export class AddAlbumUserReadonly1713298646379 implements MigrationInterface {
|
||||
name = 'AddAlbumUserReadonly1713298646379'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "albums_shared_users_users" ADD "readonly" boolean NOT NULL DEFAULT false`);
|
||||
await queryRunner.query(`ALTER TABLE "albums_shared_users_users" ALTER COLUMN "readonly" SET DEFAULT true`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
@@ -132,7 +132,7 @@ class AlbumAccess implements IAlbumAccess {
|
||||
where: {
|
||||
id: In([...albumIds]),
|
||||
sharedUsers: {
|
||||
users: Equal(userId),
|
||||
user: Equal(userId),
|
||||
// If write is needed we check for it, otherwise both are accepted
|
||||
readonly: readWrite === 'write' ? false : undefined,
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { AlbumUserEntity } from 'src/entities/album-user.entity';
|
||||
import { AlbumPermissionId, IAlbumUserRepository } from 'src/interfaces/album-user.interface';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { Equal, Repository } from 'typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
@Injectable()
|
||||
@@ -11,21 +11,19 @@ export class AlbumUserRepository implements IAlbumUserRepository {
|
||||
constructor(@InjectRepository(AlbumUserEntity) private repository: Repository<AlbumUserEntity>) {}
|
||||
|
||||
async create(dto: Partial<AlbumUserEntity>): Promise<AlbumUserEntity> {
|
||||
const { users, albums } = await this.repository.save(dto);
|
||||
return this.repository.findOneOrFail({ where: { users, albums }, relations: { users: true } });
|
||||
const { user, album } = await this.repository.save(dto);
|
||||
return this.repository.findOneOrFail({ where: { user, album }, relations: { user: true } });
|
||||
}
|
||||
|
||||
async update({ userId, albumId }: AlbumPermissionId, dto: Partial<AlbumUserEntity>): Promise<AlbumUserEntity> {
|
||||
// @ts-expect-error I'm pretty sure I messed something up with the entity because
|
||||
// if I follow what typescript says I get postgres errors
|
||||
await this.repository.update({ users: userId, albums: albumId }, dto);
|
||||
await this.repository.update({ user: { id: userId }, album: { id: albumId } }, dto);
|
||||
return this.repository.findOneOrFail({
|
||||
where: { users: Equal(userId), albums: Equal(albumId) },
|
||||
relations: { users: true },
|
||||
where: { user: { id: userId }, album: { id: albumId } },
|
||||
relations: { user: true },
|
||||
});
|
||||
}
|
||||
|
||||
async delete({ userId, albumId }: AlbumPermissionId): Promise<void> {
|
||||
await this.repository.delete({ users: { id: userId }, albums: { id: albumId } });
|
||||
await this.repository.delete({ user: { id: userId }, album: { id: albumId } });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
getById(id: string, options: AlbumInfoOptions): Promise<AlbumEntity | null> {
|
||||
const relations: FindOptionsRelations<AlbumEntity> = {
|
||||
owner: true,
|
||||
sharedUsers: { users: true },
|
||||
sharedUsers: { user: true },
|
||||
assets: false,
|
||||
sharedLinks: true,
|
||||
};
|
||||
@@ -52,7 +52,7 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
},
|
||||
relations: {
|
||||
owner: true,
|
||||
sharedUsers: { users: true },
|
||||
sharedUsers: { user: true },
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -62,9 +62,9 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
return this.repository.find({
|
||||
where: [
|
||||
{ ownerId, assets: { id: assetId } },
|
||||
{ sharedUsers: { users: Equal(ownerId) }, assets: { id: assetId } },
|
||||
{ sharedUsers: { user: Equal(ownerId) }, assets: { id: assetId } },
|
||||
],
|
||||
relations: { owner: true, sharedUsers: { users: true } },
|
||||
relations: { owner: true, sharedUsers: { user: 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: { users: true }, sharedLinks: true, owner: true },
|
||||
relations: { sharedUsers: { user: 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: { users: true }, sharedLinks: true, owner: true },
|
||||
relations: { sharedUsers: { user: true }, sharedLinks: true, owner: true },
|
||||
where: [
|
||||
{ sharedUsers: { users: Equal(ownerId) } },
|
||||
{ sharedUsers: { user: Equal(ownerId) } },
|
||||
{ sharedLinks: { userId: ownerId } },
|
||||
{ ownerId, sharedUsers: { users: Not(IsNull()) } },
|
||||
{ ownerId, sharedUsers: { user: Not(IsNull()) } },
|
||||
],
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
@@ -158,7 +158,7 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
getNotShared(ownerId: string): Promise<AlbumEntity[]> {
|
||||
return this.repository.find({
|
||||
relations: { sharedUsers: true, sharedLinks: true, owner: true },
|
||||
where: { ownerId, sharedUsers: { users: IsNull() }, sharedLinks: { id: IsNull() } },
|
||||
where: { ownerId, sharedUsers: { user: IsNull() }, sharedLinks: { id: IsNull() } },
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
}
|
||||
@@ -282,7 +282,7 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
where: { id },
|
||||
relations: {
|
||||
owner: true,
|
||||
sharedUsers: { users: true },
|
||||
sharedUsers: { user: true },
|
||||
sharedLinks: true,
|
||||
assets: true,
|
||||
},
|
||||
|
||||
@@ -128,7 +128,7 @@ export class AlbumService {
|
||||
ownerId: auth.user.id,
|
||||
albumName: dto.albumName,
|
||||
description: dto.description,
|
||||
sharedUsers: dto.sharedWithUserIds?.map((userId) => ({ users: { id: userId } }) as AlbumUserEntity) ?? [],
|
||||
sharedUsers: dto.sharedWithUserIds?.map((userId) => ({ user: { id: userId } }) as AlbumUserEntity) ?? [],
|
||||
assets,
|
||||
albumThumbnailAssetId: assets[0]?.id || null,
|
||||
});
|
||||
@@ -221,7 +221,7 @@ export class AlbumService {
|
||||
throw new BadRequestException('Cannot be shared with owner');
|
||||
}
|
||||
|
||||
const exists = album.sharedUsers.find(({ users: { id } }) => id === userId);
|
||||
const exists = album.sharedUsers.find(({ user: { id } }) => id === userId);
|
||||
if (exists) {
|
||||
throw new BadRequestException('User already added');
|
||||
}
|
||||
@@ -232,7 +232,7 @@ export class AlbumService {
|
||||
}
|
||||
|
||||
album.sharedUsers.push(
|
||||
await this.albumPermissionRepository.create({ users: { id: userId }, albums: { id } } as AlbumUserEntity),
|
||||
await this.albumPermissionRepository.create({ user: { id: userId }, album: { id } } as AlbumUserEntity),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ export class AlbumService {
|
||||
throw new BadRequestException('Cannot remove album owner');
|
||||
}
|
||||
|
||||
const exists = album.sharedUsers.find(({ users: { id } }) => id === userId);
|
||||
const exists = album.sharedUsers.find(({ user: { id } }) => id === userId);
|
||||
if (!exists) {
|
||||
throw new BadRequestException('Album not shared with user');
|
||||
}
|
||||
@@ -268,7 +268,7 @@ export class AlbumService {
|
||||
|
||||
const album = await this.findOrFail(id, { withAssets: false });
|
||||
|
||||
const permission = album.sharedUsers.find(({ users: { id } }) => id === userId);
|
||||
const permission = album.sharedUsers.find(({ user: { id } }) => id === userId);
|
||||
if (!permission) {
|
||||
throw new BadRequestException('Album not shared with user');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user