From 998c22b85fb038eda4a4bc33a7ac57cf73fda7f7 Mon Sep 17 00:00:00 2001 From: kakiba <97882386+kotto5@users.noreply.github.com> Date: Tue, 14 Nov 2023 13:05:42 +0900 Subject: [PATCH] Feat/backend/room enteruser (#50) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ログインしているユーザーは部屋を作ったり、他人のルームに入ることができます。 * [DB modify] User と Room の中間テーブル(useronroom) を作成し、n to m の関係になりました。 --- .../migration.sql | 8 + backend/prisma/schema.prisma | 5 +- backend/src/room/dto/user-on-room.dto.ts | 16 ++ backend/src/room/room.controller.ts | 14 +- backend/src/room/room.service.spec.ts | 155 +++++++++++++++++- backend/src/room/room.service.ts | 39 ++++- 6 files changed, 230 insertions(+), 7 deletions(-) create mode 100644 backend/prisma/migrations/20231113075959_unique_roomid_userid/migration.sql create mode 100644 backend/src/room/dto/user-on-room.dto.ts diff --git a/backend/prisma/migrations/20231113075959_unique_roomid_userid/migration.sql b/backend/prisma/migrations/20231113075959_unique_roomid_userid/migration.sql new file mode 100644 index 00000000..0397a166 --- /dev/null +++ b/backend/prisma/migrations/20231113075959_unique_roomid_userid/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - A unique constraint covering the columns `[userid,roomid]` on the table `useronroom` will be added. If there are existing duplicate values, this will fail. + +*/ +-- CreateIndex +CREATE UNIQUE INDEX "useronroom_userid_roomid_key" ON "useronroom"("userid", "roomid"); diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index 3649b95a..58833d18 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -27,8 +27,11 @@ model Room { model useronroom { id Int @id @default(autoincrement()) user User @relation(fields: [userid], references: [id]) - userid Int + userid Int role String + // CHECK (role IN ('owner', 'administrator', 'member')) + // CHECK ENUM('owner', 'administrator', 'member') room Room @relation(fields: [roomid], references: [id]) roomid Int + @@unique(fields: [userid, roomid], name: "userid_roomid_unique") } diff --git a/backend/src/room/dto/user-on-room.dto.ts b/backend/src/room/dto/user-on-room.dto.ts new file mode 100644 index 00000000..54e8f0be --- /dev/null +++ b/backend/src/room/dto/user-on-room.dto.ts @@ -0,0 +1,16 @@ +import { IsString, IsNotEmpty, IsNumber } from 'class-validator'; + +export class UserOnRoomDto { + @IsNumber() + id: number; + + @IsNumber() + userid: number; + + @IsString() + @IsNotEmpty() + role: string; + + @IsNumber() + roomid: number; +} diff --git a/backend/src/room/room.controller.ts b/backend/src/room/room.controller.ts index 56fbb51c..9c833a49 100644 --- a/backend/src/room/room.controller.ts +++ b/backend/src/room/room.controller.ts @@ -49,9 +49,11 @@ export class RoomController { } @Get(':id') + @UseGuards(JwtAuthGuard) + @ApiBearerAuth() @ApiOkResponse({ type: RoomEntity }) - findOne(@Param('id', ParseIntPipe) id: number) { - return this.roomService.findOne(id); + findOne(@Param('id', ParseIntPipe) id: number, @Req() request: Request) { + return this.roomService.findOne(id, request['user']['id']); } @Patch(':id') @@ -68,4 +70,12 @@ export class RoomController { remove(@Param('id', ParseIntPipe) id: number) { return this.roomService.remove(id); } + + @Post(':id') + @UseGuards(JwtAuthGuard) + @ApiBearerAuth() + @ApiOkResponse({ type: RoomEntity }) + enterRoom(@Param('id', ParseIntPipe) id: number, @Req() request: Request) { + return this.roomService.enterRoom(id, request['user']['id']); + } } diff --git a/backend/src/room/room.service.spec.ts b/backend/src/room/room.service.spec.ts index 02a69671..398b5ac6 100644 --- a/backend/src/room/room.service.spec.ts +++ b/backend/src/room/room.service.spec.ts @@ -1,6 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { RoomService } from './room.service'; import { PrismaService } from 'src/prisma/prisma.service'; +import { CreateRoomDto } from './dto/create-room.dto'; describe('RoomService', () => { let service: RoomService; @@ -13,7 +14,157 @@ describe('RoomService', () => { service = module.get(RoomService); }); - it('should be defined', () => { - expect(service).toBeDefined(); + // it('should be defined', () => { + // expect(service).toBeDefined(); + // }); + + describe('findAll()', () => { + it('should return an array of rooms', async () => { + const rooms = await service.findAll(); + expect(rooms).toBeInstanceOf(Array); + }); + }); + + describe('enterRoom()', () => { + const user = { id: 1, name: 'test' }; + const createRoomDto: CreateRoomDto = { name: 'testRoom1', userId: user.id }; + + it('should create a room', async () => { + const room = await service.create(createRoomDto); + console.log(room); + expect(room).toHaveProperty('id'); + expect(room).toHaveProperty('name'); + }); + it('should create a room', async () => { + const room = await service.create(createRoomDto); + console.log(room); + expect(room).toHaveProperty('name'); + }); + it('should not create a room', async () => { + const NotExistUserId = 10000000; + await expect( + service.create({ name: 'testRoom1', userId: NotExistUserId }), + ).rejects.toThrow(); + }); + }); + + describe('findOne()', () => { + const user = { id: 1, name: 'test' }; + let roomId: number; + const createRoomDto: CreateRoomDto = { name: 'testRoom1', userId: user.id }; + it('should throw error', async () => { + await expect(service.findOne(10000000, user.id)).rejects.toThrow(); + }); + it('should return a room', async () => { + const room = await service.create(createRoomDto); + console.log(room); + expect(room).toHaveProperty('id'); + expect(room).toHaveProperty('name'); + roomId = room.id; + }); + it('should return a room', async () => { + const room = await service.findOne(roomId, user.id); + console.log(room); + expect(room).toHaveProperty('id'); + expect(room).toHaveProperty('name'); + expect(room).toHaveProperty('users'); + }); + }); + + describe('leaveRoom()', () => { + const user = { id: 1, name: 'test' }; + let roomId: number; + const createRoomDto: CreateRoomDto = { name: 'testRoom1', userId: user.id }; + it('should throw error', async () => { + await expect(service.leaveRoom(10000000, user.id)).rejects.toThrow(); + }); + it('should return a room', async () => { + const room = await service.create(createRoomDto); + console.log(room); + expect(room).toHaveProperty('id'); + expect(room).toHaveProperty('name'); + roomId = room.id; + }); + it('should return a room', () => { + return service + .leaveRoom(roomId, user.id) + .then((room) => { + console.log(room); + expect(room.id).toBe(roomId); + expect(room.userid).toBe(user.id); + }) + .catch((err) => { + console.log(err); + }); + }); }); + // describe('/room/:id (POST)', () => { + // let roomId: number; + // const user = {id: 1, name: 'test'}; + // const createRoomDto: CreateRoomDto = {name: 'testRoom1', userId: user.id}; + + // const room = await service.create(createRoomDto); + // it('should enter a room', async () => { + // const room = await service.create(createRoomDto); + // console.log(room); + // expect(room).toHaveProperty('id'); + // expect(room).toHaveProperty('name'); + // roomId = room.id; + // }) + // it('should not create a room', async () => { + // const NotExistUserId = 10000000; + // await expect(service.create({name: 'testRoom1', userId: NotExistUserId})).rejects.toThrow(); + // }) + + // }) + + // it('should return a room', async () => { + // const room = await service.findOne(roomId, user.id); + // console.log(room); + // expect(room).toHaveProperty('id'); + // expect(room).toHaveProperty('name'); + // }) + // it('should return an error', async () => { + // const room = await service.findOne(roomId + 1, user.id); + // console.log(room); + + // }) + // it('should return an error', async () => { + // const room = await service.findOne(roomId, user.id + 1); + // console.log(room); + // expect(room).toHaveProperty('error'); + // }) + // it('should remove a room', async () => { + // const room = await service.leaveRoom(roomId, user.id); + // console.log(room); + // expect(room).toHaveProperty('id'); + // expect(room).toHaveProperty('name'); + // }) + // it('should return an error', async () => { + // const room = await service.leaveRoom(roomId, user.id); + // console.log(room); + // expect(room).toHaveProperty('error'); + // }) + // it('should return an error', async () => { + // const room = await service.findOne(roomId, user.id); + // console.log(room); + // }) + + // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjMsImlhdCI6MTY5OTg2Mjg3NiwiZXhwIjoxNjk5ODY0Njc2fQ.ks3iRk8bKv6PGLV8V04zuB18xJ1l9CcVCQH_xjaIFnE + + /* +{ + "email": "susami@example.com", + "password": "password-susami" +} +*/ + + /* +{ + "email": "kakiba@example.com", + "password": "password-kakiba" +} +*/ + + // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImlhdCI6MTY5OTg2MjgwMiwiZXhwIjoxNjk5ODY0NjAyfQ.OaQlF9NZTfbKaQ9-Ac4cSqZQU6oJE2de1Z-a-fsvH4A }); diff --git a/backend/src/room/room.service.ts b/backend/src/room/room.service.ts index 317c62ed..613af256 100644 --- a/backend/src/room/room.service.ts +++ b/backend/src/room/room.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { CreateRoomDto } from './dto/create-room.dto'; import { UpdateRoomDto } from './dto/update-room.dto'; import { PrismaService } from 'src/prisma/prisma.service'; +import { UserOnRoomDto } from './dto/user-on-room.dto'; @Injectable() export class RoomService { @@ -27,8 +28,21 @@ export class RoomService { return this.prisma.room.findMany(); } - findOne(id: number) { - return this.prisma.room.findUniqueOrThrow({ where: { id: id } }); + async findOne(id: number, userId: number) { + await this.prisma.useronroom.findUniqueOrThrow({ + where: { + userid_roomid_unique: { + userid: userId, + roomid: id, + }, + }, + }); + return this.prisma.room.findUnique({ + where: { id }, + include: { + users: true, + }, + }); } update(id: number, updateRoomDto: UpdateRoomDto) { @@ -41,4 +55,25 @@ export class RoomService { remove(id: number) { return this.prisma.room.delete({ where: { id } }); } + + async enterRoom(id: number, userId: number): Promise { + return this.prisma.useronroom.create({ + data: { + roomid: id, + userid: userId, + role: 'member', + }, + }); + } + + leaveRoom(id: number, userId: number): Promise { + return this.prisma.useronroom.delete({ + where: { + userid_roomid_unique: { + roomid: id, + userid: userId, + }, + }, + }); + } }