diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..bddb62b4 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +**/.git +**/.svn +**/.hg +**/node_modules +**/*.json diff --git a/backend/src/auth/auth.controller.ts b/backend/src/auth/auth.controller.ts index b0f6919d..e0a73c9f 100644 --- a/backend/src/auth/auth.controller.ts +++ b/backend/src/auth/auth.controller.ts @@ -9,11 +9,11 @@ import type { User } from '@prisma/client'; import { CurrentUser } from 'src/common/decorators/current-user.decorator'; import { AuthService } from './auth.service'; import { LoginDto } from './dto/login.dto'; +import { OauthDto } from './dto/oauth.dto'; import { TwoFactorAuthenticationDto } from './dto/twoFactorAuthentication.dto'; import { TwoFactorAuthenticationEnableDto } from './dto/twoFactorAuthenticationEnable.dto'; import { AuthEntity } from './entity/auth.entity'; import { JwtGuardWithout2FA } from './jwt-auth.guard'; -import { OauthDto } from './dto/oauth.dto'; @Controller('auth') @ApiTags('auth') diff --git a/backend/src/auth/auth.service.ts b/backend/src/auth/auth.service.ts index 61e458f7..11c70e45 100644 --- a/backend/src/auth/auth.service.ts +++ b/backend/src/auth/auth.service.ts @@ -10,13 +10,13 @@ import * as bcrypt from 'bcrypt'; import { authenticator } from 'otplib'; import { toFileStream } from 'qrcode'; import { PrismaService } from 'src/prisma/prisma.service'; +import { CreateUserDto } from 'src/user/dto/create-user.dto'; +import { UserEntity } from 'src/user/entities/user.entity'; import { jwtConstants } from './auth.module'; +import { OauthDto } from './dto/oauth.dto'; import { TwoFactorAuthenticationDto } from './dto/twoFactorAuthentication.dto'; import { TwoFactorAuthenticationEnableDto } from './dto/twoFactorAuthenticationEnable.dto'; import { AuthEntity } from './entity/auth.entity'; -import { CreateUserDto } from 'src/user/dto/create-user.dto'; -import { UserEntity } from 'src/user/entities/user.entity'; -import { OauthDto } from './dto/oauth.dto'; @Injectable() export class AuthService { diff --git a/backend/src/chat/chat.controller.spec.ts b/backend/src/chat/chat.controller.spec.ts index 371d7b10..e678e13d 100644 --- a/backend/src/chat/chat.controller.spec.ts +++ b/backend/src/chat/chat.controller.spec.ts @@ -2,8 +2,8 @@ import { EventEmitter2 } from '@nestjs/event-emitter'; import { JwtService } from '@nestjs/jwt'; import { Test, TestingModule } from '@nestjs/testing'; import { AuthService } from 'src/auth/auth.service'; -import { UserService } from 'src/user/user.service'; import { PrismaService } from 'src/prisma/prisma.service'; +import { UserService } from 'src/user/user.service'; import { ChatController } from './chat.controller'; import { ChatService } from './chat.service'; diff --git a/backend/src/chat/chat.gateway.ts b/backend/src/chat/chat.gateway.ts index 0edadb51..efad6063 100644 --- a/backend/src/chat/chat.gateway.ts +++ b/backend/src/chat/chat.gateway.ts @@ -1,4 +1,5 @@ import { Logger } from '@nestjs/common'; +import { OnEvent } from '@nestjs/event-emitter'; import { ConnectedSocket, MessageBody, @@ -7,21 +8,10 @@ import { WebSocketServer, } from '@nestjs/websockets'; import { Server, Socket } from 'socket.io'; -import { UserService } from '../user/user.service'; +import { RoomLeftEvent } from 'src/common/events/room-left.event'; import { ChatService } from './chat.service'; -import { CreateDirectMessageDto } from './dto/create-direct-message.dto'; import { CreateMessageDto } from './dto/create-message.dto'; import { MessageEntity } from './entities/message.entity'; -import { RoomLeftEvent } from 'src/common/events/room-left.event'; -import { OnEvent } from '@nestjs/event-emitter'; - -//type PrivateMessage = { -// conversationId: string; -// from: string; -// to: string; -// userName: string; -// text: string; -//}; @WebSocketGateway({ cors: { @@ -31,49 +21,13 @@ import { OnEvent } from '@nestjs/event-emitter'; cookie: true, }) export class ChatGateway { - constructor( - private readonly chatService: ChatService, - private readonly userService: UserService, - ) {} + constructor(private readonly chatService: ChatService) {} @WebSocketServer() server: Server; private logger: Logger = new Logger('ChatGateway'); - private userMap = new Map(); - - private getValueToKey = (map, findValue): number | undefined => { - for (const [key, value] of map.entries()) { - if (value == findValue) { - return key; - } - } - return undefined; - }; - - @SubscribeMessage('privateMessage') - privateMessageToUser( - @MessageBody() data: CreateDirectMessageDto, - @ConnectedSocket() client: Socket, - ): void { - this.logger.log('private message received'); - this.logger.log(data); - - const userId = this.getValueToKey(this.userMap, client.id); - if (userId) { - const userName = 'hoge'; //TODO mapを増やすか、mapのvalueを増やすか user name取得関数実装 - this.chatService.createDirectMessage(userId, data); - this.server - .except('block' + userId) - .to(client.id) - .to(this.userMap.get(data.receiverId)) //TODO receiverIdが見つからなかった時のvalidation - .emit('sendToUser', { ...data, senderId: userId, userName }, client.id); - } else { - this.logger.error('No user id was found for socket id'); - } - } - @SubscribeMessage('message') async handleMessage( @MessageBody() data: CreateMessageDto, @@ -107,7 +61,7 @@ export class ChatGateway { @OnEvent('room.leave', { async: true }) async handleLeave(event: RoomLeftEvent) { - this.server.in(event.roomId.toString()).emit('left-room', event.userId); + this.server.in(event.roomId.toString()).emit('leave', event); await this.chatService.removeUserFromRoom(event); } diff --git a/backend/src/chat/chat.service.spec.ts b/backend/src/chat/chat.service.spec.ts index 885e8e26..52c8b083 100644 --- a/backend/src/chat/chat.service.spec.ts +++ b/backend/src/chat/chat.service.spec.ts @@ -2,8 +2,8 @@ import { EventEmitter2 } from '@nestjs/event-emitter'; import { JwtService } from '@nestjs/jwt'; import { Test, TestingModule } from '@nestjs/testing'; import { AuthService } from 'src/auth/auth.service'; -import { UserService } from 'src/user/user.service'; import { PrismaService } from 'src/prisma/prisma.service'; +import { UserService } from 'src/user/user.service'; import { ChatService } from './chat.service'; describe('ChatService', () => { diff --git a/backend/src/chat/chat.service.ts b/backend/src/chat/chat.service.ts index 82f9bb91..32c9e918 100644 --- a/backend/src/chat/chat.service.ts +++ b/backend/src/chat/chat.service.ts @@ -4,15 +4,13 @@ import { WebSocketGateway, WsException } from '@nestjs/websockets'; import { User } from '@prisma/client'; import { Socket } from 'socket.io'; import { AuthService } from 'src/auth/auth.service'; -import { UserService } from 'src/user/user.service'; +import { BlockEvent } from 'src/common/events/block.event'; import { RoomCreatedEvent } from 'src/common/events/room-created.event'; import { RoomEnteredEvent } from 'src/common/events/room-entered.event'; import { RoomLeftEvent } from 'src/common/events/room-left.event'; -import { BlockEvent } from 'src/common/events/block.event'; import { UnblockEvent } from 'src/common/events/unblock.event'; -import { Logger } from '@nestjs/common'; import { PrismaService } from 'src/prisma/prisma.service'; -import { CreateDirectMessageDto } from './dto/create-direct-message.dto'; +import { UserService } from 'src/user/user.service'; import { CreateMessageDto } from './dto/create-message.dto'; @Injectable() @@ -24,8 +22,6 @@ export class ChatService { private userService: UserService, ) {} - private logger: Logger = new Logger('ChatService'); - // Map private clients = new Map(); private users = new Map(); @@ -156,15 +152,6 @@ export class ChatService { this.removeClient(client); } - async createDirectMessage(senderId: number, dto: CreateDirectMessageDto) { - return this.prisma.directMessage.create({ - data: { - senderId, - ...dto, //TODO receiverIdのvalidationどうする? - }, - }); - } - private async expectNotBlockedBy(blockerId: number, userId: number) { const blockedBy = await this.prisma.user .findFirstOrThrow({ diff --git a/backend/src/chat/dto/create-direct-message.dto.ts b/backend/src/chat/dto/create-direct-message.dto.ts deleted file mode 100644 index 96baf9cd..00000000 --- a/backend/src/chat/dto/create-direct-message.dto.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, IsNumber, IsString } from 'class-validator'; - -export class CreateDirectMessageDto { - @IsString() - @IsNotEmpty() - @ApiProperty() - content: string; - - @IsNumber() - @ApiProperty() - receiverId: number; -} diff --git a/backend/src/user/user.service.ts b/backend/src/user/user.service.ts index d389b6aa..db2a150b 100644 --- a/backend/src/user/user.service.ts +++ b/backend/src/user/user.service.ts @@ -2,10 +2,10 @@ import { Injectable } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { User } from '@prisma/client'; import { hash } from 'bcrypt'; -import { BlockEvent } from 'src/common/events/block.event'; -import { UnblockEvent } from 'src/common/events/unblock.event'; import * as fs from 'fs'; import * as path from 'path'; +import { BlockEvent } from 'src/common/events/block.event'; +import { UnblockEvent } from 'src/common/events/unblock.event'; import { PrismaService } from 'src/prisma/prisma.service'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; diff --git a/backend/test/chat-gateway.e2e-spec.ts b/backend/test/chat-gateway.e2e-spec.ts index 7872cf5a..4fc9e6a7 100644 --- a/backend/test/chat-gateway.e2e-spec.ts +++ b/backend/test/chat-gateway.e2e-spec.ts @@ -487,43 +487,24 @@ describe('ChatGateway and ChatController (e2e)', () => { .expect(200); }); - let ctx5, ctx6, ctx7, ctx8, ctx9: Promise; - it('setup promises to recv left-room event with user id', async () => { - ctx5 = new Promise((resolve) => { - ws1.on('left-room', (data) => { - expect(data).toEqual(kickedUser1.id); - ws1.off('left-room'); - resolve(); - }); - }); - ctx6 = new Promise((resolve) => { - ws2.on('left-room', (data) => { - expect(data).toEqual(kickedUser1.id); - ws2.off('left-room'); - resolve(); - }); - }); - ctx7 = new Promise((resolve) => { - ws3.on('left-room', (data) => { - expect(data).toEqual(kickedUser1.id); - ws3.off('left-room'); - resolve(); - }); - }); - ctx8 = new Promise((resolve) => { - ws4.on('left-room', (data) => { - expect(data).toEqual(kickedUser1.id); - ws4.off('left-room'); - resolve(); - }); - }); - ctx9 = new Promise((resolve) => { - ws6.on('left-room', (data) => { - expect(data).toEqual(kickedUser1.id); - ws6.off('left-room'); - resolve(); - }); - }); + let ctx5: Promise; + it('setup promises to recv leave event with user id', async () => { + const expectedEvent = { + userId: kickedUser1.id, + roomId: room.id, + }; + const promises = [ws1, ws2, ws3, ws4, ws5, ws6].map( + (ws) => + new Promise((resolve) => { + ws.on('leave', (data) => { + expect(data).toEqual(expectedEvent); + ws.off('leave'); + resolve(); + }); + }), + ); + + ctx5 = Promise.all(promises); }); it('user1 kicks kickedUser1', async () => { @@ -532,12 +513,8 @@ describe('ChatGateway and ChatController (e2e)', () => { .expect(204); }); - it('all users (except kickedUser1) should receive left-room event with kickedUser1 id', async () => { + it('all users (except kickedUser1) should receive leave event with kickedUser1 id', async () => { await ctx5; - await ctx6; - await ctx7; - await ctx8; - await ctx9; }); it('kickedUser1 sends message', () => { diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 95f5641c..3ad2f748 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -16,6 +16,6 @@ "noImplicitAny": false, "strictBindCallApply": false, "forceConsistentCasingInFileNames": false, - "noFallthroughCasesInSwitch": false - } + "noFallthroughCasesInSwitch": false, + }, } diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index 4d38eb15..c4812626 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -3,6 +3,7 @@ import type { Metadata } from "next"; import { Inter } from "next/font/google"; import AuthProvider from "@/app/lib/client-auth-provider"; +import SocketProvider from "@/app/lib/client-socket-provider"; import { getAccessTokenPayload } from "@/app/lib/session"; // components @@ -48,6 +49,7 @@ export default async function RootLayout({