diff --git a/server/src/bin/sync-sql.ts b/server/src/bin/sync-sql.ts index 2de4fb4127..22dae63750 100644 --- a/server/src/bin/sync-sql.ts +++ b/server/src/bin/sync-sql.ts @@ -86,6 +86,7 @@ class SqlGenerator { this.sqlLogger.logQuery(event.query.sql); } else if (event.level === 'error') { this.sqlLogger.logQueryError(event.error as Error, event.query.sql); + this.sqlLogger.logQuery(event.query.sql); } }, }), diff --git a/server/src/interfaces/album-user.interface.ts b/server/src/interfaces/album-user.interface.ts index d5742ad788..835e835589 100644 --- a/server/src/interfaces/album-user.interface.ts +++ b/server/src/interfaces/album-user.interface.ts @@ -1,14 +1,18 @@ -import { AlbumUserEntity } from 'src/entities/album-user.entity'; +import { Insertable, Selectable, Updateable } from 'kysely'; +import { AlbumsSharedUsersUsers } from 'src/db'; export const IAlbumUserRepository = 'IAlbumUserRepository'; export type AlbumPermissionId = { - albumId: string; - userId: string; + albumsId: string; + usersId: string; }; export interface IAlbumUserRepository { - create(albumUser: Partial): Promise; - update({ userId, albumId }: AlbumPermissionId, albumPermission: Partial): Promise; - delete({ userId, albumId }: AlbumPermissionId): Promise; + create(albumUser: Insertable): Promise>; + update( + id: AlbumPermissionId, + albumPermission: Updateable, + ): Promise>; + delete(id: AlbumPermissionId): Promise; } diff --git a/server/src/queries/album.user.repository.sql b/server/src/queries/album.user.repository.sql new file mode 100644 index 0000000000..d628e4980a --- /dev/null +++ b/server/src/queries/album.user.repository.sql @@ -0,0 +1,25 @@ +-- NOTE: This file is auto generated by ./sql-generator + +-- AlbumUserRepository.create +insert into + "albums_shared_users_users" ("usersId", "albumsId") +values + ($1, $2) +returning + * + +-- AlbumUserRepository.update +update "albums_shared_users_users" +set + "role" = $1 +where + "usersId" = $2 + and "albumsId" = $3 +returning + * + +-- AlbumUserRepository.delete +delete from "albums_shared_users_users" +where + "usersId" = $1 + and "albumsId" = $2 diff --git a/server/src/repositories/album-user.repository.ts b/server/src/repositories/album-user.repository.ts index 9328ea8cfc..5895721b63 100644 --- a/server/src/repositories/album-user.repository.ts +++ b/server/src/repositories/album-user.repository.ts @@ -1,26 +1,40 @@ import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { AlbumUserEntity } from 'src/entities/album-user.entity'; +import { Insertable, Kysely, Selectable, Updateable } from 'kysely'; +import { InjectKysely } from 'nestjs-kysely'; +import { AlbumsSharedUsersUsers, DB } from 'src/db'; +import { DummyValue, GenerateSql } from 'src/decorators'; +import { AlbumUserRole } from 'src/enum'; import { AlbumPermissionId, IAlbumUserRepository } from 'src/interfaces/album-user.interface'; -import { Repository } from 'typeorm'; @Injectable() export class AlbumUserRepository implements IAlbumUserRepository { - constructor(@InjectRepository(AlbumUserEntity) private repository: Repository) {} + constructor(@InjectKysely() private db: Kysely) {} - async create(albumUser: Partial): Promise { - const { userId, albumId } = await this.repository.save(albumUser); - return this.repository.findOneOrFail({ where: { userId, albumId } }); + @GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }] }) + create(albumUser: Insertable): Promise> { + return this.db.insertInto('albums_shared_users_users').values(albumUser).returningAll().executeTakeFirstOrThrow(); } - async update({ userId, albumId }: AlbumPermissionId, dto: Partial): Promise { - await this.repository.update({ userId, albumId }, dto); - return this.repository.findOneOrFail({ - where: { userId, albumId }, - }); + @GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }, { role: AlbumUserRole.VIEWER }] }) + update( + { usersId, albumsId }: AlbumPermissionId, + dto: Updateable, + ): Promise> { + return this.db + .updateTable('albums_shared_users_users') + .set(dto) + .where('usersId', '=', usersId) + .where('albumsId', '=', albumsId) + .returningAll() + .executeTakeFirstOrThrow(); } - async delete({ userId, albumId }: AlbumPermissionId): Promise { - await this.repository.delete({ userId, albumId }); + @GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }] }) + async delete({ usersId, albumsId }: AlbumPermissionId): Promise { + await this.db + .deleteFrom('albums_shared_users_users') + .where('usersId', '=', usersId) + .where('albumsId', '=', albumsId) + .execute(); } } diff --git a/server/src/services/album.service.spec.ts b/server/src/services/album.service.spec.ts index bb1aac8e6e..ca6b56e085 100644 --- a/server/src/services/album.service.spec.ts +++ b/server/src/services/album.service.spec.ts @@ -323,18 +323,16 @@ describe(AlbumService.name, () => { albumMock.update.mockResolvedValue(albumStub.sharedWithAdmin); userMock.get.mockResolvedValue(userStub.user2); albumUserMock.create.mockResolvedValue({ - userId: userStub.user2.id, - user: userStub.user2, - albumId: albumStub.sharedWithAdmin.id, - album: albumStub.sharedWithAdmin, + usersId: userStub.user2.id, + albumsId: albumStub.sharedWithAdmin.id, role: AlbumUserRole.EDITOR, }); await sut.addUsers(authStub.user1, albumStub.sharedWithAdmin.id, { albumUsers: [{ userId: authStub.user2.user.id }], }); expect(albumUserMock.create).toHaveBeenCalledWith({ - userId: authStub.user2.user.id, - albumId: albumStub.sharedWithAdmin.id, + usersId: authStub.user2.user.id, + albumsId: albumStub.sharedWithAdmin.id, }); expect(eventMock.emit).toHaveBeenCalledWith('album.invite', { id: albumStub.sharedWithAdmin.id, @@ -361,8 +359,8 @@ describe(AlbumService.name, () => { expect(albumUserMock.delete).toHaveBeenCalledTimes(1); expect(albumUserMock.delete).toHaveBeenCalledWith({ - albumId: albumStub.sharedWithUser.id, - userId: userStub.user1.id, + albumsId: albumStub.sharedWithUser.id, + usersId: userStub.user1.id, }); expect(albumMock.getById).toHaveBeenCalledWith(albumStub.sharedWithUser.id, { withAssets: false }); }); @@ -388,8 +386,8 @@ describe(AlbumService.name, () => { expect(albumUserMock.delete).toHaveBeenCalledTimes(1); expect(albumUserMock.delete).toHaveBeenCalledWith({ - albumId: albumStub.sharedWithUser.id, - userId: authStub.user1.user.id, + albumsId: albumStub.sharedWithUser.id, + usersId: authStub.user1.user.id, }); }); @@ -400,8 +398,8 @@ describe(AlbumService.name, () => { expect(albumUserMock.delete).toHaveBeenCalledTimes(1); expect(albumUserMock.delete).toHaveBeenCalledWith({ - albumId: albumStub.sharedWithUser.id, - userId: authStub.user1.user.id, + albumsId: albumStub.sharedWithUser.id, + usersId: authStub.user1.user.id, }); }); @@ -433,7 +431,7 @@ describe(AlbumService.name, () => { role: AlbumUserRole.EDITOR, }); expect(albumUserMock.update).toHaveBeenCalledWith( - { albumId: albumStub.sharedWithAdmin.id, userId: userStub.admin.id }, + { albumsId: albumStub.sharedWithAdmin.id, usersId: userStub.admin.id }, { role: AlbumUserRole.EDITOR }, ); }); diff --git a/server/src/services/album.service.ts b/server/src/services/album.service.ts index e57e6b168c..f5685f84eb 100644 --- a/server/src/services/album.service.ts +++ b/server/src/services/album.service.ts @@ -229,7 +229,7 @@ export class AlbumService extends BaseService { throw new BadRequestException('User not found'); } - await this.albumUserRepository.create({ userId, albumId: id, role }); + await this.albumUserRepository.create({ usersId: userId, albumsId: id, role }); await this.eventRepository.emit('album.invite', { id, userId }); } @@ -257,12 +257,12 @@ export class AlbumService extends BaseService { await this.requireAccess({ auth, permission: Permission.ALBUM_SHARE, ids: [id] }); } - await this.albumUserRepository.delete({ albumId: id, userId }); + await this.albumUserRepository.delete({ albumsId: id, usersId: userId }); } async updateUser(auth: AuthDto, id: string, userId: string, dto: Partial): Promise { await this.requireAccess({ auth, permission: Permission.ALBUM_SHARE, ids: [id] }); - await this.albumUserRepository.update({ albumId: id, userId }, { role: dto.role }); + await this.albumUserRepository.update({ albumsId: id, usersId: userId }, { role: dto.role }); } private async findOrFail(id: string, options: AlbumInfoOptions) {