fix db schema annotations

This commit is contained in:
mgabor
2024-04-16 22:02:40 +02:00
parent 9677d6108a
commit 1b56fb8914
9 changed files with 38 additions and 51 deletions

View File

@@ -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,
});
}

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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`);
}
}

View File

@@ -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> {

View File

@@ -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,
},

View File

@@ -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 } });
}
}

View File

@@ -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,
},

View File

@@ -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');
}