nicolas-arnaud
2 years ago
22 changed files with 443 additions and 211 deletions
@ -0,0 +1,8 @@ |
|||
import { type Request } from 'express' |
|||
import type User from 'src/users/user.entity' |
|||
|
|||
interface RequestWithUser extends Request { |
|||
user: User |
|||
} |
|||
|
|||
export default RequestWithUser |
@ -1,20 +1,20 @@ |
|||
import { Module } from '@nestjs/common'; |
|||
import { TypeOrmModule } from '@nestjs/typeorm'; |
|||
import { AuthModule } from 'src/auth/auth.module'; |
|||
import { UsersModule } from 'src/users/users.module'; |
|||
import { ChatGateway } from './chat.gateway'; |
|||
import { ChatService } from './chat.service'; |
|||
import { UsersService } from 'src/users/users.service'; |
|||
import { Channel } from './model/channel.entity'; |
|||
import { Message } from './model/message.entity'; |
|||
import { Module } from '@nestjs/common' |
|||
import { TypeOrmModule } from '@nestjs/typeorm' |
|||
import { AuthModule } from 'src/auth/auth.module' |
|||
import { UsersModule } from 'src/users/users.module' |
|||
import { ChatGateway } from './chat.gateway' |
|||
import { ChatService } from './chat.service' |
|||
import { UsersService } from 'src/users/users.service' |
|||
import { Channel } from './model/channel.entity' |
|||
import { Message } from './model/message.entity' |
|||
|
|||
@Module({ |
|||
imports: [ |
|||
AuthModule, |
|||
UsersModule, |
|||
TypeOrmModule.forFeature([Channel]), |
|||
TypeOrmModule.forFeature([Message]), |
|||
TypeOrmModule.forFeature([Message]) |
|||
], |
|||
providers: [ChatGateway, ChatService], |
|||
providers: [ChatGateway, ChatService] |
|||
}) |
|||
export class ChatModule {} |
|||
|
@ -1,61 +1,57 @@ |
|||
import { Injectable } from '@nestjs/common'; |
|||
import { InjectRepository } from '@nestjs/typeorm'; |
|||
import { Repository } from 'typeorm'; |
|||
import * as bcrypt from 'bcrypt' |
|||
|
|||
import { Channel } from 'src/chat/model/channel.entity'; |
|||
import { User } from 'src/users/user.entity'; |
|||
import { Message } from './model/message.entity'; |
|||
import { Injectable } from '@nestjs/common' |
|||
import { InjectRepository } from '@nestjs/typeorm' |
|||
import { Channel } from 'src/chat/model/channel.entity' |
|||
import { type User } from 'src/users/user.entity' |
|||
import { Repository } from 'typeorm' |
|||
import { Message } from './model/message.entity' |
|||
import { CreateChannelDto } from './model/create-channel.dto' |
|||
|
|||
@Injectable() |
|||
export class ChatService { |
|||
constructor( |
|||
constructor ( |
|||
@InjectRepository(Channel) |
|||
private readonly ChannelRepository: Repository<Channel>, |
|||
@InjectRepository(Message) |
|||
private readonly MessageRepository: Repository<Message>, |
|||
) { } |
|||
|
|||
async createChannel(channelDatas: CreateChannelDto, creator: User): Promise<Channel> { |
|||
channelDatas.password = await bcrypt.hash(channelDatas.password, 10); |
|||
const newChannel = this.ChannelRepository.create(channelDatas); |
|||
await this.addCreatorToChannel(newChannel, creator); |
|||
this.ChannelRepository.save(newChannel); |
|||
newChannel.password = undefined; |
|||
return newChannel; |
|||
private readonly MessageRepository: Repository<Message> |
|||
) {} |
|||
|
|||
async createChannel (Channel: Channel, creator: User): Promise<Channel> { |
|||
const newChannel = await this.addCreatorToChannel(Channel, creator) |
|||
return await this.ChannelRepository.save(newChannel) |
|||
} |
|||
|
|||
async getChannelsForUser(userId: number): Promise<Channel[]> { |
|||
return this.ChannelRepository.find({}); //where userId is in User[] of channel?
|
|||
async getChannelsForUser (userId: number): Promise<Channel[]> { |
|||
return await this.ChannelRepository.find({}) // where userId is in User[] of channel?
|
|||
} |
|||
|
|||
async addCreatorToChannel(Channel: Channel, creator: User): Promise<Channel> { |
|||
Channel.users.push(creator); |
|||
return Channel; |
|||
async addCreatorToChannel (Channel: Channel, creator: User): Promise<Channel> { |
|||
Channel.users.push(creator) |
|||
return Channel |
|||
} |
|||
|
|||
async createMessage(message: Message): Promise<Message> { |
|||
return this.MessageRepository.save(this.MessageRepository.create(message)); |
|||
async createMessage (message: Message): Promise<Message> { |
|||
return await this.MessageRepository.save( |
|||
this.MessageRepository.create(message) |
|||
) |
|||
} |
|||
|
|||
async deleteBySocketId(socketId: string) { |
|||
return this.ChannelRepository.delete({}); // for disconnect
|
|||
async deleteBySocketId (socketId: string) { |
|||
return await this.ChannelRepository.delete({}) // for disconnect
|
|||
} |
|||
|
|||
async getChannel(id: number): Promise<Channel | null> { |
|||
return this.ChannelRepository.findOneBy({ id }); |
|||
async getChannel (id: number): Promise<Channel | null> { |
|||
return await this.ChannelRepository.findOneBy({ id }) |
|||
} |
|||
|
|||
async findMessagesInChannelForUser( |
|||
async findMessagesInChannelForUser ( |
|||
channel: Channel, |
|||
user: User, |
|||
): Promise<Message> { |
|||
return this.MessageRepository.findOne({ |
|||
where: { |
|||
channel: { id: channel.id } |
|||
}, |
|||
relations: { channel: true }, |
|||
}) |
|||
user: User |
|||
): Promise<Message[]> { |
|||
return await this.MessageRepository.createQueryBuilder('message') |
|||
.where('message.channel = :chan', { chan: channel }) |
|||
.andWhere('message.author NOT IN (:...blocked)', { |
|||
blocked: user.blocked |
|||
}) |
|||
.getMany() |
|||
} |
|||
} |
|||
|
@ -1,13 +1,13 @@ |
|||
import { IsPositive, IsAlpha, IsString, IsOptional } from 'class-validator'; |
|||
import { IsPositive, IsAlpha, IsString, IsOptional } from 'class-validator' |
|||
|
|||
export class CreateChannelDto { |
|||
@IsString() |
|||
@IsAlpha() |
|||
name: string; |
|||
name: string |
|||
|
|||
@IsPositive() |
|||
owner: number; |
|||
owner: number |
|||
|
|||
@IsOptional() |
|||
password: string; |
|||
password: string |
|||
} |
|||
|
@ -1,22 +1,22 @@ |
|||
import { PartialType } from '@nestjs/mapped-types'; |
|||
import { CreateChannelDto } from './create-channel.dto'; |
|||
import { Message } from './message.entity'; |
|||
import { User } from 'src/users/user.entity'; |
|||
import { IsString } from 'class-validator'; |
|||
import { PartialType } from '@nestjs/mapped-types' |
|||
import { CreateChannelDto } from './create-channel.dto' |
|||
import { type Message } from './message.entity' |
|||
import { type User } from 'src/users/user.entity' |
|||
import { IsString } from 'class-validator' |
|||
|
|||
export class UpdateChannelDto extends PartialType(CreateChannelDto) { |
|||
id: number; |
|||
id: number |
|||
|
|||
users: [User]; |
|||
users: [User] |
|||
|
|||
messages: [Message]; |
|||
messages: [Message] |
|||
|
|||
owners: [number]; //user id
|
|||
owners: [number] // user id
|
|||
|
|||
banned: [number]; //user id
|
|||
banned: [number] // user id
|
|||
|
|||
muted: [number]; //user id
|
|||
muted: [number] // user id
|
|||
|
|||
@IsString() |
|||
password: string; |
|||
password: string |
|||
} |
|||
|
@ -1,5 +1,5 @@ |
|||
declare module 'passport-42' { |
|||
export type Profile = any; |
|||
export type VerifyCallback = any; |
|||
export class Strategy {}; |
|||
export type Profile = any |
|||
export type VerifyCallback = any |
|||
export class Strategy {} |
|||
} |
|||
|
@ -1,39 +1,44 @@ |
|||
import { |
|||
Column, |
|||
Entity, |
|||
ManyToMany, |
|||
OneToMany, |
|||
PrimaryGeneratedColumn, |
|||
} from 'typeorm'; |
|||
import { Message } from 'src/chat/model/message.entity'; |
|||
import { Channel } from 'src/chat/model/channel.entity'; |
|||
Column, |
|||
OneToOne, |
|||
OneToMany, |
|||
ManyToMany, |
|||
JoinColumn |
|||
} from 'typeorm' |
|||
|
|||
import Message from 'src/chat/model/message.entity' |
|||
import Channel from 'src/chat/model/channel.entity' |
|||
|
|||
@Entity() |
|||
export class User { |
|||
@PrimaryGeneratedColumn() |
|||
id: number; |
|||
|
|||
@Column({ unique: true }) |
|||
id_42: number; |
|||
id_42: number |
|||
|
|||
@Column({ unique: true }) |
|||
username: string; |
|||
|
|||
@Column({ default: '' }) |
|||
avatar: string; |
|||
username: string |
|||
|
|||
@Column({ default: 'online' }) |
|||
status: string; |
|||
status: string |
|||
|
|||
@Column({ name: 'avatar' }) |
|||
public avatar?: string |
|||
|
|||
@OneToMany(() => Message, (message: Message) => message.author) |
|||
messages: Message[]; |
|||
messages: Message[] |
|||
|
|||
@ManyToMany(() => Channel, (channel: Channel) => channel.users) |
|||
rooms: Channel[]; |
|||
rooms: Channel[] |
|||
|
|||
@ManyToMany(() => User) |
|||
blocked: User[] |
|||
|
|||
@OneToMany(() => User, (user) => user.id) //filter messages
|
|||
blocked: User[]; |
|||
@ManyToMany(() => User) |
|||
friends: User[] |
|||
|
|||
//@Column({ default: { wr: -1, place: -1 } })
|
|||
//rank: { wr: number; place: number };
|
|||
// @Column({ default: { wr: -1, place: -1 } })
|
|||
// rank: { wr: number; place: number };
|
|||
} |
|||
|
|||
export default User |
|||
|
@ -1,52 +1,60 @@ |
|||
import { |
|||
Injectable, |
|||
NotFoundException |
|||
} from '@nestjs/common' |
|||
import { Injectable, NotFoundException } from '@nestjs/common' |
|||
import { InjectRepository } from '@nestjs/typeorm' |
|||
import { Repository } from 'typeorm' |
|||
import { User } from './user.entity' |
|||
import { type CreateUserDto, type UpdateUserDto } from './user.dto' |
|||
import { type Channel } from 'src/chat/model/channel.entity' |
|||
|
|||
@Injectable() |
|||
export class UsersService { |
|||
constructor( |
|||
constructor ( |
|||
@InjectRepository(User) private readonly usersRepository: Repository<User> |
|||
) { } |
|||
) {} |
|||
|
|||
async getAllUsers(): Promise<User[]> { |
|||
async getAllUsers (): Promise<User[]> { |
|||
return await this.usersRepository.find({}) |
|||
} |
|||
|
|||
async getOneUser(username: string): Promise<User | null> { |
|||
const user = await this.usersRepository.findOneBy({ username: username }) |
|||
if (user) return user |
|||
throw new NotFoundException(`User with username: ${username} not found`) |
|||
async getOneUser (username: string): Promise<User | null> { |
|||
return await this.usersRepository.findOneBy({ username }) |
|||
} |
|||
|
|||
async getOneUser42(id_42: number): Promise<User | null> { |
|||
const user = await this.usersRepository.findOneBy({ id_42: id_42 }) |
|||
if (user) return user; |
|||
throw new NotFoundException(`User with id_42: ${id_42} not found`) |
|||
async getOneUser42 (id_42: number): Promise<User | null> { |
|||
return await this.usersRepository.findOneBy({ id_42 }) |
|||
} |
|||
|
|||
async create(userData: CreateUserDto) { |
|||
async create (userData: CreateUserDto) { |
|||
try { |
|||
const newUser= this.usersRepository.create(userData) |
|||
const newUser = this.usersRepository.create(userData) |
|||
return await this.usersRepository.save(newUser) |
|||
} catch (err) { |
|||
throw new Error(`Error creating ${err} user ${err.message}`) |
|||
} |
|||
} |
|||
|
|||
async findOne(id: number) { |
|||
const user = await this.usersRepository.findOneBy({ id: id }) |
|||
if (user) return user; |
|||
async findOne (id: number) { |
|||
const user = await this.usersRepository.findOneBy({ id }) |
|||
if (user) return user |
|||
throw new NotFoundException(`User #${id} not found`) |
|||
} |
|||
|
|||
async update(id: number, changes: UpdateUserDto) { |
|||
async findOnlineInChannel (channel: Channel): Promise<User[]> { |
|||
return await this.usersRepository |
|||
.createQueryBuilder('user') |
|||
.where('user.channel = :chan', { chan: channel }) |
|||
.andWhere('user.status := status)', { status: 'online' }) |
|||
.getMany() |
|||
} |
|||
|
|||
async update (id: number, changes: UpdateUserDto) { |
|||
const updatedUser = await this.findOne(id) |
|||
this.usersRepository.merge(updatedUser, changes) |
|||
return await this.usersRepository.save(updatedUser) |
|||
} |
|||
|
|||
async addAvatar (userId: number, filename: string) { |
|||
await this.usersRepository.update(userId, { |
|||
avatar: filename |
|||
}) |
|||
} |
|||
} |
|||
|
Loading…
Reference in new issue