Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/backend/strict null check #279

Merged
merged 18 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 54 additions & 26 deletions backend/src/chat/chat.gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ export class ChatGateway {
this.logger.error('invalid userId');
return;
}
const user = this.chatService.getUser(client);
if (!user) {
this.logger.error('invalid user');
return;
}

const MutedUsers = await this.muteService.findAll(data.roomId);
if (MutedUsers.some((user) => user.id === data.userId)) {
Expand All @@ -68,44 +73,67 @@ export class ChatGateway {
const room = this.server
.to(data.roomId.toString())
.except('block' + data.userId);
room.emit(
'message',
new MessageEntity(data, this.chatService.getUser(client)),
);
room.emit('message', new MessageEntity(data, user));
}

@SubscribeMessage('request-match')
async handleRequestMatch(
@MessageBody() data: { userId: number },
@ConnectedSocket() client: Socket,
) {
const inviteUser = this.chatService.getUser(client);
const invitedUserWsId = this.chatService.getWsFromUserId(data.userId)?.id;
if (!invitedUserWsId) {
// Check if the requesting user is valid
const requestingUser = this.chatService.getUser(client);
if (!requestingUser) {
this.logger.error('invalid requesting user');
return;
}
// Check if the requested user is connected
const requestedUserWsId = this.chatService.getWsFromUserId(data.userId)?.id;
if (!requestedUserWsId) {
this.logger.error('invalid requested user');
return;
} else {
const blockings = await this.chatService.getUsersBlockedBy(data.userId);
if (blockings.some((user) => user.id === inviteUser.id)) return;
const blocked = await this.chatService.getUsersBlockedBy(inviteUser.id);
if (blocked.some((user) => user.id === data.userId)) return;
this.server
.to(invitedUserWsId)
.emit('request-match', { userId: inviteUser.id });
this.chatService.addInvite(inviteUser.id, data.userId);
}
// Check if the requesting user is blocked by the requested user
const blockings = await this.chatService.getUsersBlockedBy(data.userId);
if (blockings.some((user) => user.id === requestingUser.id)) return;
// Check if the requested user is blocked by the requesting user
const blocked = await this.chatService.getUsersBlockedBy(requestingUser.id);
if (blocked.some((user) => user.id === data.userId)) return;
// Send the request
this.server
.to(requestedUserWsId)
.emit('request-match', { userId: requestingUser.id });
// Save the request
this.chatService.addMatchRequest(requestingUser.id, data.userId);
}

@SubscribeMessage('cancel-request-match')
handleCancelRequestMatch(@ConnectedSocket() client: Socket) {
const inviteUser = this.chatService.getUser(client);
const invitee = this.chatService.getInvite(inviteUser.id);
if (!invitee) {
// Check if the requesting user is valid
const requestingUser = this.chatService.getUser(client);
if (!requestingUser) {
this.logger.error('invalid requesting user');
return;
}
// Check if the request exists
const requestedUser = this.chatService.getMatchRequest(requestingUser.id);
if (!requestedUser) {
this.logger.error('invalid requested user');
this.server.to(client.id).emit('error-pong', 'No pending invite found.');
return;
}
const inviteeWsId = this.chatService.getWsFromUserId(invitee)?.id;
this.chatService.removeInvite(inviteUser.id);
this.server.to(inviteeWsId).emit('cancel-request-match', inviteUser);
// Cancel the request
this.chatService.removeMatchRequest(requestingUser.id);
// Check if the requested user is connected
const requestedUserWsId =
this.chatService.getWsFromUserId(requestedUser)?.id;
if (!requestedUserWsId) {
return;
}
// Send the cancel request
this.server
.to(requestedUserWsId)
.emit('cancel-request-match', requestingUser);
}

@SubscribeMessage('approve-pong')
Expand All @@ -118,7 +146,7 @@ export class ChatGateway {
return;
} else {
if (
this.chatService.getInvite(data.userId) !==
this.chatService.getMatchRequest(data.userId) !==
this.chatService.getUserId(client)
) {
this.server
Expand All @@ -129,7 +157,7 @@ export class ChatGateway {
const emitData = { roomId: v4() };
this.server.to(client.id).emit('match-pong', emitData);
this.server.to(approvedUserWsId).emit('match-pong', emitData);
this.chatService.removeInvite(data.userId);
this.chatService.removeMatchRequest(data.userId);
}
}

Expand All @@ -143,7 +171,7 @@ export class ChatGateway {
return;
} else {
if (
this.chatService.getInvite(data.userId) !==
this.chatService.getMatchRequest(data.userId) !==
this.chatService.getUserId(client)
) {
this.server
Expand All @@ -152,7 +180,7 @@ export class ChatGateway {
return;
}
this.server.to(deniedUserWsId).emit('deny-pong');
this.chatService.removeInvite(data.userId);
this.chatService.removeMatchRequest(data.userId);
}
}

Expand Down
26 changes: 13 additions & 13 deletions backend/src/chat/chat.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { UnblockEvent } from 'src/common/events/unblock.event';
import { PrismaService } from 'src/prisma/prisma.service';
import { UserService } from 'src/user/user.service';
import { CreateMessageDto } from './dto/create-message.dto';
import { PublicUserEntity } from './entities/message.entity';
import { WsPublicUserEntity } from './entities/message.entity';

export enum UserStatus {
Offline = 0b0,
Expand All @@ -35,9 +35,9 @@ export class ChatService {

// Map<User.id, Socket>
private clients = new Map<User['id'], Socket>();
// key: inviter, value: invitee
private users = new Map<Socket['id'], PublicUserEntity>();
private invite = new Map<User['id'], User['id']>();
private users = new Map<Socket['id'], WsPublicUserEntity>();
// key: requestingUserId, value: requestedUserId
private matchRequests = new Map<User['id'], User['id']>();
private statuses = new Map<User['id'], UserStatus>();

getUser(client: Socket) {
Expand All @@ -58,7 +58,7 @@ export class ChatService {

addClient(user: User, client: Socket) {
this.clients.set(user.id, client);
this.users.set(client.id, new PublicUserEntity(user));
this.users.set(client.id, new WsPublicUserEntity(user));
}

removeClient(client: Socket) {
Expand All @@ -67,20 +67,20 @@ export class ChatService {
this.statuses.delete(user.id);
this.clients.delete(user.id);
this.users.delete(client.id);
this.removeInvite(user.id);
this.removeMatchRequest(user.id);
}
}

addInvite(inviterId: number, inviteeId: number) {
this.invite.set(inviterId, inviteeId);
addMatchRequest(requestingUserId: number, requestedUserId: number) {
this.matchRequests.set(requestingUserId, requestedUserId);
}

getInvite(inviterId: number) {
return this.invite.get(inviterId);
getMatchRequest(requestingUserId: number) {
return this.matchRequests.get(requestingUserId);
}

removeInvite(inviterId: number) {
this.invite.delete(inviterId);
removeMatchRequest(requestingUserId: number) {
this.matchRequests.delete(requestingUserId);
}

addUserToRoom(roomId: number, userId: number) {
Expand Down Expand Up @@ -215,7 +215,7 @@ export class ChatService {
const emitData = {
userId: this.getUserId(client),
status: UserStatus.Offline,
name: this.getUser(client).name,
name: this.getUser(client)?.name,
};
if (emitData.userId) {
client.broadcast.emit('online-status', [emitData]);
Expand Down
20 changes: 10 additions & 10 deletions backend/src/chat/entities/message.entity.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
export class PublicUserEntity {
constructor(partial: Partial<PublicUserEntity>) {
this.id = partial.id;
this.name = partial.name;
this.avatarURL = partial.avatarURL;
export class WsPublicUserEntity {
constructor(user: WsPublicUserEntity) {
this.id = user.id;
this.name = user.name;
this.avatarURL = user.avatarURL;
}
id: number;
name: string;
avatarURL?: string;
avatarURL: string | null;
}
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constructor of WsPublicUserEntity takes an instance of its own class as a parameter, which seems unusual for typical use cases. This pattern might be intended for cloning instances, but if that's not the case, it could lead to confusion or misuse. Consider revising the constructor's parameter to match the intended use case, such as accepting raw user data instead.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確かに。まー引数にはPrismaのUserを取っておくか。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@usatie: 確かに、PrismaのUser型をコンストラクタの引数として使用する提案は、初期のコメントで提起された懸念に直接対処します。この変更により、コンストラクタの目的がより明確になり、データベースからの生データを使ってエンティティを初期化するという一般的な使用例に合致します。この方向での修正がコードの明確性と使いやすさを向上させるでしょう。もし追加でサポートや説明が必要であれば、お知らせください。


export class MessageEntity {
constructor(partial: Partial<MessageEntity>, user: PublicUserEntity) {
this.content = partial.content;
this.roomId = partial.roomId;
constructor(message: Omit<MessageEntity, 'user'>, user: WsPublicUserEntity) {
this.content = message.content;
this.roomId = message.roomId;
this.user = user;
}
content: string;
roomId: number;
user: PublicUserEntity;
user: WsPublicUserEntity;
}
3 changes: 1 addition & 2 deletions backend/src/room/dto/update-UserOnRoom.dto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { PartialType } from '@nestjs/swagger';
import { CreateUserOnRoomDto } from './create-UserOnRoom.dto';

export class UpdateUserOnRoomDto extends PartialType(CreateUserOnRoomDto) {}
export class UpdateUserOnRoomDto extends CreateUserOnRoomDto {}
2 changes: 1 addition & 1 deletion backend/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"strictNullChecks": true,
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
Expand Down
Loading