creation of directs messages

+ can choose myrooms fields
+ trying to make type validation without success
This commit is contained in:
simplonco
2023-01-12 00:36:38 +01:00
parent aa86299e73
commit b851613f0f
15 changed files with 235 additions and 183 deletions

View File

@@ -4,15 +4,15 @@ import { ConnectedSocket } from '@nestjs/websockets';
import { ChatService } from './chat.service';
import { User } from 'src/users/entities/user.entity';
import { PartialUsersDto } from 'src/users/dto/partial-users.dto';
import { createRoomDto } from './dto/createRoom.dto';
import { roomDto } from './dto/room.dto';
import { setCurrentRoomDto } from './dto/setCurrentRoom.dto';
import { ChatGateway } from './chat.gateway';
import { socketDto } from './dto/socket.dto';
import { Chatroom } from './entities/chatroom.entity';
@Controller('chat')
export class ChatController {
constructor(
private chatService: ChatService,
private chatGateway: ChatGateway,
@@ -32,8 +32,12 @@ export class ChatController {
async getMyRooms(@Req() req, @Res() res): Promise<void>
{
console.log("- in getMyRooms controller");
const rooms = await this.chatService.getMyRooms(req.user.username);
let fields = ["name", "type", "users"];
const rooms = await this.chatService.getMyRooms(req.user.username, fields);
res.status(HttpStatus.OK).json({ rooms: rooms });
console.log("- out getMyRooms controller");
}
@@ -43,10 +47,11 @@ export class ChatController {
async getAllRooms(@Req() req, @Res() res): Promise<void>
{
console.log("- in getAllRooms controller");
const rooms = await this.chatService.getAllOtherRoomsAndUsers(req.user.username)
console.log("--- rooms:", rooms);
const rooms: roomDto[] = await this.chatService.getAllOtherRoomsAndUsers(req.user.username)
console.log("--- rooms:", rooms);
res.status(HttpStatus.OK).json({ rooms: rooms });
console.log("- out getAllRooms controller");
}
@@ -56,8 +61,10 @@ export class ChatController {
async setCurrentRoom(@Body() setCurrentRoomDto: setCurrentRoomDto, @Req() req, @Res() res): Promise<void>
{
console.log("- in setCurrentRoom controller");
const response = await this.chatService.setCurrentRoom(req.user.username, setCurrentRoomDto.name);
res.status(HttpStatus.OK).json({ message: response });
console.log("- out setCurrentRoom controller");
}
@@ -67,28 +74,31 @@ export class ChatController {
async allowedChars(@Res() res): Promise<void>
{
console.log("- in allowedChars controller");
res.status(HttpStatus.OK).json({ chars: this.allowed_chars });
console.log("- out allowedChars controller");
}
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Post('create')
async createRoom(@Body() createRoomDto: createRoomDto, @Req() req, @Res() res): Promise<void>
async createRoom(@Body() room: roomDto, @Req() req, @Res() res): Promise<void>
{
console.log("- in createRoom controller");
let chars = this.escape_chars(this.allowed_chars);
let regex_base = `[a-zA-Z0-9\\s${chars}]`;
let test_regex = new RegExp(`^${regex_base}+$`);
if (test_regex.test(createRoomDto.name) === false)
if (test_regex.test(room.name) === false)
{
let forbidden_chars = createRoomDto.name.replace(new RegExp(regex_base, "g"), "");
let forbidden_chars = room.name.replace(new RegExp(regex_base, "g"), "");
throw new HttpException(`Your room name can not contains these characters : ${forbidden_chars}`, HttpStatus.UNPROCESSABLE_ENTITY);
}
const response = await this.chatService.addUserToNewRoom(req.user.username, createRoomDto);
res.status(HttpStatus.OK).json({ room_name: createRoomDto.name, message: response });
await this.chatService.addUserToNewRoom(req.user.username, room);
res.status(HttpStatus.OK).json({ room: room });
console.log("- out createRoom controller");
}
@@ -98,6 +108,7 @@ export class ChatController {
async joinRoom(@Body() room: roomDto, @Req() req, @Res() res): Promise<void>
{
console.log("- in joinRoom controller");
let response = "";
if (room.type === 'direct')
throw new HttpException(`cannot join a direct messages room`, HttpStatus.CONFLICT);
@@ -113,8 +124,8 @@ export class ChatController {
let socket: socketDto = this.chatGateway.sockets.get(req.user.username);
await this.chatService.socketJoinRoom(socket, room.name);
res.status(HttpStatus.OK).json({ room: room });
console.log("- out joinRoom controller");
}
@@ -124,12 +135,12 @@ export class ChatController {
async changeRoom(@Body() room: roomDto, @Req() req, @Res() res): Promise<void>
{
console.log("- in changeRoom controller");
const response = await this.chatService.setCurrentRoom(req.user.username, room.name);
const response = await this.chatService.setCurrentRoom(req.user.username, room.name);
let socket: socketDto = this.chatGateway.sockets.get(req.user.username);
await this.chatService.socketChangeRoom(socket, room.name);
res.status(HttpStatus.OK).json({ room: room });
console.log("- out changeRoom controller");
}
@@ -148,8 +159,10 @@ export class ChatController {
async getMessages(@Req() req, @Res() res): Promise<void>
{
console.log("- in getMessages controller");
const messages = await this.chatService.getMessagesFromCurrentRoom(req.user.username);
res.status(HttpStatus.OK).json({ messages: messages });
console.log("- out getMessages controller");
}
@@ -159,10 +172,12 @@ export class ChatController {
async getRoomUsers(@Req() req, @Res() res): Promise<void>
{
console.log("- in getRoomUsers controller");
const room_name = await this.chatService.getCurrentRoomName(req.user.username);
const room = await this.chatService.getRoomByName(room_name);
const users = room.users;
res.status(HttpStatus.OK).json({ users: users });
console.log("- out getRoomUsers controller");
}
@@ -172,9 +187,11 @@ export class ChatController {
async removeUser(@Req() req, @Res() res): Promise<void>
{
console.log("- in removeUser controller");
const room_name = await this.chatService.getCurrentRoomName(req.user.username);
let response = await this.chatService.removeUserFromRoom(req.user.username, room_name);
res.status(HttpStatus.OK).json({ message: response });
console.log("- out removeUser controller");
}

View File

@@ -4,7 +4,6 @@ import { UsersService } from 'src/users/users.service';
import { Chatroom } from './entities/chatroom.entity';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { createRoomDto } from './dto/createRoom.dto';
import { roomDto } from './dto/room.dto';
import { messagesDto } from './dto/messages.dto';
import { socketDto } from './dto/socket.dto';
@@ -21,7 +20,6 @@ export class ChatService {
private readonly chatroomRepository: Repository<Chatroom>,
) {}
// temp for test
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
@@ -31,13 +29,22 @@ export class ChatService {
/* GETTERS ************************************************
*/
async getMyRooms(username: string): Promise<Chatroom[]>
async getMyRooms(username: string, fieldsToReturn: string[] = null): Promise<Chatroom[]>
{
console.log("-- in getMyRooms service");
const rooms = await this.chatroomRepository
const queryBuilder = this.chatroomRepository
.createQueryBuilder('chatroom')
.where('chatroom.users LIKE :user_name', { user_name: `%${username}%` })
.getMany();
.where('chatroom.users LIKE :user_name', { user_name: `%${username}%` });
if (fieldsToReturn)
{
let fields = fieldsToReturn.map(field => `chatroom.${field}`);
queryBuilder.select(fields);
}
const rooms = await queryBuilder.getMany();
console.log("--- rooms:", rooms);
console.log("-- out getMyRooms service");
return rooms;
@@ -46,6 +53,7 @@ export class ChatService {
async getMyDirects(username: string): Promise<Chatroom[]>
{
console.log("-- in getAllNotMyRooms service");
const my_rooms = await this.getMyRooms(username);
const directs = my_rooms.filter(room => room.type === 'direct');
@@ -56,9 +64,11 @@ export class ChatService {
async getAllRooms(): Promise<Chatroom[]>
{
console.log("-- in getAllRooms service");
const rooms = await this.chatroomRepository
.createQueryBuilder('chatroom')
.getMany();
console.log("--- rooms:", rooms);
console.log("-- out getAllRooms service");
return rooms;
@@ -67,12 +77,14 @@ export class ChatService {
async getAllNotMyRooms(username: string): Promise<Chatroom[]>
{
console.log("-- in getAllNotMyRooms service");
const user_db = await this.getUserByName(username);
const rooms = await this.chatroomRepository
.createQueryBuilder('chatroom')
.where('chatroom.type != :type', { type: 'private' })
.andWhere('chatroom.users NOT LIKE :user_name', { user_name: `%${username}%` })
.getMany();
console.log("--- rooms:", rooms);
console.log("-- out getAllNotMyRooms service");
return rooms;
@@ -81,11 +93,10 @@ export class ChatService {
async getAllOtherRoomsAndUsers(username: string): Promise<roomDto[]>
{
console.log("-- in getAllOtherRoomsAndUsers service");
const all_rooms = await this.getAllNotMyRooms(username);
const all_users = await this.getAllUsersNotMyRooms(username);
console.log("--- all_rooms:", all_rooms)
console.log("--- all_users:", all_users)
let row_rooms = all_rooms.map(room => {
return {
name: room.name,
@@ -99,7 +110,7 @@ export class ChatService {
};
});
let rooms = row_rooms.concat(users);
console.log("--- rooms:", rooms)
console.log("--- rooms:", rooms);
console.log("-- in getAllOtherRoomsAndUsers service");
return rooms;
@@ -108,6 +119,7 @@ export class ChatService {
async getMessagesFromCurrentRoom(username: string): Promise<messagesDto[]>
{
console.log("-- in getMessagesFromCurrentRoom service");
const user_db = await this.getUserByName(username);
const currentRoom = await this.getRoomByName(user_db.currentRoom);
let messages = null;
@@ -121,7 +133,7 @@ export class ChatService {
async getCurrentRoomName(username: string): Promise<string>
{
console.log("-- in getCurrentRoomName service");
console.log('username:', username);
const user_db = await this.getUserByName(username);
console.log("-- out getCurrentRoomName service");
@@ -131,10 +143,12 @@ export class ChatService {
async getRoomByName(room_name: string): Promise<Chatroom>
{
console.log("-- in getRoomByName service");
const room = await this.chatroomRepository
.createQueryBuilder('chatroom')
.where('chatroom.name = :name', { name: room_name.replace("+", "\\+") })
.where('chatroom.name = :name', { name: room_name })
.getOne();
console.log("--- room:", room);
console.log("-- out getRoomByName service");
return room;
@@ -143,10 +157,12 @@ export class ChatService {
async getRoomById(id: number): Promise<Chatroom>
{
console.log("-- in getRoomById service");
const room = await this.chatroomRepository
.createQueryBuilder('chatroom')
.where('chatroom.id = :id', { id: id })
.getOne();
console.log("--- room:", room);
console.log("-- out getRoomById service");
return room;
@@ -159,6 +175,7 @@ export class ChatService {
async setCurrentRoom(username: string, room_name: string): Promise<string>
{
console.log("-- in setCurrentRoom service");
const user_db = await this.getUserByName(username);
user_db.currentRoom = room_name;
this.userRepository.save(user_db);
@@ -171,23 +188,24 @@ export class ChatService {
/* ADDERS *************************************************
*/
async addUserToNewRoom(username: string, createRoomDto: createRoomDto): Promise<void>
async addUserToNewRoom(username: string, room: roomDto): Promise<void>
{
console.log("-- in addUserToNewRoom service");
const room = await this.getRoomByName(createRoomDto.name);
if (room)
const find_room = await this.getRoomByName(room.name);
if (find_room)
throw new HttpException(`This room name already exist`, HttpStatus.CONFLICT);
// create chatroom
const newChatroom = new Chatroom();
newChatroom.name = createRoomDto.name;
newChatroom.type = createRoomDto.type;
newChatroom.name = room.name;
newChatroom.type = room.type;
newChatroom.owner = username;
newChatroom.users = [username];
if (createRoomDto.type === 'direct')
newChatroom.users = createRoomDto.users;
newChatroom.messages = [{ name: "SERVER", message: `creation of room ${createRoomDto.name}` }];
this.chatroomRepository.save(newChatroom);
if (room.type === 'direct')
newChatroom.users = room.users;
newChatroom.messages = [{ name: "SERVER", message: `creation of room ${room.name}` }];
await this.chatroomRepository.save(newChatroom);
console.log("-- out addUserToNewRoom service");
}
@@ -195,31 +213,30 @@ export class ChatService {
async addUserToRoom(username: string, room_name: string): Promise<void>
{
console.log("-- in addUserToRoom service");
const room = await this.getRoomByName(room_name);
if (room.users.includes(username))
throw new HttpException(`your have already join this room`, HttpStatus.CONFLICT);
throw new HttpException(`your have already joined this room`, HttpStatus.CONFLICT);
// update room with new user
room.users.push(username);
this.chatroomRepository.save(room);
await this.setCurrentRoom(username, room_name);
console.log("-- out addUserToRoom service");
}
async addMessageToRoom(room_name: string, username: string, message: string): Promise<void>
{
console.log("-- in addMessageToRoom service");
console.log("--- room_name:", room_name);
const my_room = await this.getRoomByName(room_name);
console.log("--- my_room:", my_room);
let chat_message = {
name: username,
message: message,
};
my_room.messages.push(chat_message);
this.chatroomRepository.save(my_room);
console.log("-- out addMessageToRoom service");
}
@@ -230,6 +247,7 @@ export class ChatService {
async removeUserFromRoom(username: string, room_name: string): Promise<string>
{
console.log("-- in removeUserFromRoom service");
const room = await this.getRoomByName(room_name);
if (!room.users.includes(username))
throw new HttpException(`your are not in this room`, HttpStatus.CONFLICT);
@@ -253,10 +271,12 @@ export class ChatService {
async getUserByName(username: string): Promise<User>
{
console.log("-- in getUserByName service");
const user = await this.userRepository
.createQueryBuilder('user')
.where('user.username = :name', { name: username })
.getOne();
console.log("--- user:", user);
console.log("-- out getUserByName service");
return user;
@@ -267,7 +287,6 @@ export class ChatService {
console.log("-- in getAllUsersNotMyRooms service");
const directs = await this.getMyDirects(username);
console.log("--- directs:", directs);
// get all users from directs
let usernames = directs.map(room => {
@@ -277,14 +296,12 @@ export class ChatService {
return user;
});
usernames.push(username);
console.log("usernames:", usernames);
const users = await this.userRepository
.createQueryBuilder('user')
.where('user.username NOT IN (:...usernames)', { usernames: usernames })
.getMany();
console.log("users:", users);
console.log("--- users:", users);
console.log("-- out getAllUsersNotMyRooms service");
return users;
@@ -301,6 +318,7 @@ export class ChatService {
socket.to(socket.room).emit('message', socket.username, message);
let room_name = await this.getCurrentRoomName(socket.username);
await this.addMessageToRoom(room_name, socket.username, message);
console.log("-- out handleSocketIncommingMessage service");
}
@@ -311,6 +329,7 @@ export class ChatService {
socket.leave(socket.room);
socket.join(room_name);
socket.room = room_name;
console.log('-- out socketChangeRoom service');
}
@@ -324,6 +343,7 @@ export class ChatService {
let message = `${socket.username} has join the room`;
await socket.to(socket.room).emit('message', "SERVER", message);
await this.addMessageToRoom(room_name, "SERVER", message);
console.log('- out socketJoinRoom service');
}

View File

@@ -1,10 +0,0 @@
import { IsString, IsOptional } from "class-validator";
import { roomDto } from './room.dto';
export class createRoomDto extends roomDto
{
@IsString()
@IsOptional()
password?: string;
}

View File

@@ -1,22 +1,19 @@
import { IsBoolean, IsEmpty, IsInt, IsIn, IsNotEmpty, IsNumber, IsString, IsOptional, IsEnum } from "class-validator";
import { Expose } from 'class-transformer';
import { IsBoolean, IsEmpty, IsInt, IsIn, IsNotEmpty, IsNumber, IsArray, IsString, IsOptional, IsEnum } from "class-validator";
export class roomDto
{
@Expose()
@IsString()
@IsNotEmpty()
name: string;
@Expose()
@IsString()
@IsNotEmpty()
@IsIn(["public", "protected", "private", "direct", "user"])
type: string;
@Expose()
@IsString()
@IsArray()
@IsString({ each: true })
@IsOptional()
users?: string[];
users?: string[]; // usernames
}

View File

@@ -1,17 +1,23 @@
import { Entity, Column, ManyToOne, ManyToMany, JoinTable, PrimaryGeneratedColumn } from "typeorm";
import { IsIn } from "class-validator";
import { IsBoolean, IsEmpty, IsInt, IsIn, IsNotEmpty, IsNumber, IsArray, IsString, IsOptional, IsEnum } from "class-validator";
import { Exclude, Expose } from 'class-transformer';
import { User } from 'src/users/entities/user.entity';
import { messagesDto } from 'src/chat/dto/messages.dto';
@Entity('chatroom')
export class Chatroom {
export class Chatroom
{
@PrimaryGeneratedColumn()
id: number;
@Column()
@IsString()
@IsNotEmpty()
name: string;
@Column()
@IsString()
@IsNotEmpty()
@IsIn(["public", "protected", "private", "direct", "user"])
type: string;
@@ -19,7 +25,10 @@ export class Chatroom {
owner: string; // username
@Column("simple-array")
users: string[]; // usernames
@IsArray()
@IsString({ each: true })
@IsOptional()
users?: string[]; // usernames
@Column("json")
messages: messagesDto[];