Browse Source
delete channel and chatServices to check is a user is... fixed friends invitations LINT lintmaster
nicolas-arnaud
2 years ago
26 changed files with 423 additions and 299 deletions
@ -1,99 +1,97 @@ |
|||
import { |
|||
BadRequestException, |
|||
Body, |
|||
Controller, |
|||
Delete, |
|||
Get, |
|||
NotFoundException, |
|||
Param, |
|||
ParseIntPipe, |
|||
Post, |
|||
} from "@nestjs/common"; |
|||
//import { channel, Channel } from "diagnostics_channel";
|
|||
import { Channel } from './entity/channel.entity'; |
|||
import { ChannelService } from "./chat.service"; |
|||
import { CreateChannelDto } from "./dto/create-channel.dto"; |
|||
import { UsersService } from "src/users/users.service"; |
|||
import { UpdateChannelDto } from "./dto/update-channel.dto"; |
|||
import { User } from "src/users/entity/user.entity"; |
|||
UseGuards |
|||
} from '@nestjs/common' |
|||
import { AuthenticatedGuard } from 'src/auth/42-auth.guard' |
|||
import { UsersService } from 'src/users/users.service' |
|||
import { ChannelService } from './chat.service' |
|||
|
|||
@Controller("chat") |
|||
import { CreateChannelDto } from './dto/create-channel.dto' |
|||
import { UpdateChannelDto } from './dto/update-channel.dto' |
|||
|
|||
import type User from 'src/users/entity/user.entity' |
|||
import type Channel from './entity/channel.entity' |
|||
import { Profile42 } from 'src/auth/42.decorator' |
|||
import { Profile } from 'passport-42' |
|||
|
|||
@Controller('channels') |
|||
export class ChatController { |
|||
private readonly channelService: ChannelService; |
|||
private readonly usersService: UsersService; |
|||
constructor ( |
|||
private readonly channelService: ChannelService, |
|||
private readonly usersService: UsersService |
|||
) {} |
|||
|
|||
@Get("channels/:id") |
|||
getChannelsForUser(@Param("id") id: number): Promise<Array<Channel>> { |
|||
return this.channelService.getChannelsForUser(id); |
|||
@Post(':id/admin') |
|||
async addAdmin (@Param('id') id: number, @Body() userId: number) { |
|||
const channel = await this.channelService.getChannel(id) |
|||
const user: User | null = await this.usersService.findUser(userId) |
|||
if (user == null) throw new NotFoundException(`User #${userId} not found`) |
|||
channel.admins.push(user) |
|||
this.channelService.update(channel) |
|||
} |
|||
|
|||
@Post("channels") |
|||
async createChannel(@Body() channel: CreateChannelDto) { |
|||
return await this.channelService.createChannel(channel); |
|||
@Delete(':id/admin') |
|||
async removeAdmin (@Param('id') id: number, @Body() userId: number) { |
|||
const channel = await this.channelService.getChannel(id) |
|||
channel.admins = channel.admins.filter((usr: User) => { |
|||
return usr.ftId !== userId |
|||
}) |
|||
this.channelService.update(channel) |
|||
} |
|||
|
|||
@Delete("channels/:id") |
|||
async deleteChannel(@Param("id") id: number) { |
|||
return await this.channelService.removeChannel(id); |
|||
@Post(':id/ban') |
|||
async addBan (@Param('id') id: number, @Body() userId: number) { |
|||
const channel = await this.channelService.getChannel(id) |
|||
const user: User | null = await this.usersService.findUser(userId) |
|||
if (user == null) throw new NotFoundException(`User #${userId} not found`) |
|||
channel.banned.push(user) |
|||
this.channelService.update(channel) |
|||
} |
|||
|
|||
@Post("channels/:id/owner") |
|||
async moveOwner(@Param("id") id: number, @Body() userId: number) { |
|||
const channel = await this.channelService.getChannel(id); |
|||
const user: User | null = await this.usersService.findUser(userId); |
|||
if (user == null) throw new NotFoundException(`User #${userId} not found`); |
|||
channel.owner = user; |
|||
this.channelService.update(channel); |
|||
@Post(':id/mute') |
|||
async addMute (@Param('id') id: number, @Body() userId: number) { |
|||
const channel = await this.channelService.getChannel(id) |
|||
const user: User | null = await this.usersService.findUser(userId) |
|||
if (user == null) throw new NotFoundException(`User #${userId} not found`) |
|||
channel.muted.push(user) |
|||
this.channelService.update(channel) |
|||
} |
|||
|
|||
@Post("channels/:id/admin") |
|||
async addAdmin(@Param("id") id: number, @Body() userId: number) { |
|||
const channel = await this.channelService.getChannel(id); |
|||
const user: User | null = await this.usersService.findUser(userId); |
|||
if (user == null) throw new NotFoundException(`User #${userId} not found`); |
|||
channel.admins.push(user); |
|||
this.channelService.update(channel); |
|||
@Delete(':id/mute') |
|||
async removeMute (@Param('id') id: number, @Body() userId: number) { |
|||
const channel = await this.channelService.getChannel(id) |
|||
channel.muted = channel.muted.filter((usr: User) => { |
|||
return usr.ftId !== userId |
|||
}) |
|||
this.channelService.update(channel) |
|||
} |
|||
|
|||
@Delete("channels/:id/admin") |
|||
async removeAdmin(@Param("id") id: number, @Body() userId: number) { |
|||
const channel = await this.channelService.getChannel(id); |
|||
channel.admins = channel.admins.filter((a) => { |
|||
return a.ftId !== userId; |
|||
}); |
|||
this.channelService.update(channel); |
|||
@Delete(':id') |
|||
@UseGuards(AuthenticatedGuard) |
|||
async deleteChannel (@Profile42() profile: Profile, @Param('id') id: number) { |
|||
if (await this.channelService.isOwner(id, +profile.id)) { |
|||
await this.channelService.removeChannel(id) |
|||
return |
|||
} |
|||
|
|||
@Post("channels/:id/ban") |
|||
async addBan(@Param("id") id: number, @Body() userId: number) { |
|||
const channel = await this.channelService.getChannel(id); |
|||
const user: User | null = await this.usersService.findUser(userId); |
|||
if (user == null) throw new NotFoundException(`User #${userId} not found`); |
|||
channel.banned.push(user); |
|||
this.channelService.update(channel); |
|||
throw new BadRequestException('You are not the owner of this channel') |
|||
} |
|||
|
|||
@Delete("channels/:id/ban") |
|||
async removeBan(@Param("id") id: number, @Body() userId: number) { |
|||
const channel = await this.channelService.getChannel(id); |
|||
channel.banned = channel.banned.filter((a) => { |
|||
return a.ftId !== userId; |
|||
}); |
|||
this.channelService.update(channel); |
|||
@Get() |
|||
@UseGuards(AuthenticatedGuard) |
|||
async getChannelsForUser (@Profile42() profile: Profile): Promise<Channel[]> { |
|||
return await this.channelService.getChannelsForUser(profile.id) |
|||
} |
|||
|
|||
@Post("channels/:id/mute") |
|||
async addMute(@Param("id") id: number, @Body() userId: number) { |
|||
const channel = await this.channelService.getChannel(id); |
|||
const user: User | null = await this.usersService.findUser(userId); |
|||
if (user == null) throw new NotFoundException(`User #${userId} not found`); |
|||
channel.mute.push(user); |
|||
this.channelService.update(channel); |
|||
} |
|||
@Delete("channels/:id/mute") |
|||
async removeMute(@Param("id") id: number, @Body() userId: number) { |
|||
const channel = await this.channelService.getChannel(id); |
|||
channel.mute = channel.mute.filter((a) => { |
|||
return a.ftId !== userId; |
|||
}); |
|||
this.channelService.update(channel); |
|||
@Post() |
|||
async createChannel (@Body() channel: CreateChannelDto) { |
|||
return await this.channelService.createChannel(channel) |
|||
} |
|||
} |
|||
|
@ -1,56 +1,118 @@ |
|||
import { Injectable, NotFoundException } from '@nestjs/common'; |
|||
import { InjectRepository } from '@nestjs/typeorm'; |
|||
import { Channel } from './entity/channel.entity'; |
|||
import { User } from 'src/users/entity/user.entity'; |
|||
import { Repository } from 'typeorm'; |
|||
import { CreateChannelDto } from './dto/create-channel.dto'; |
|||
import { UsersService } from 'src/users/users.service'; |
|||
import { Injectable, NotFoundException } from '@nestjs/common' |
|||
import { InjectRepository } from '@nestjs/typeorm' |
|||
import { Repository } from 'typeorm' |
|||
|
|||
import { type CreateChannelDto } from './dto/create-channel.dto' |
|||
import { UsersService } from 'src/users/users.service' |
|||
|
|||
import type User from 'src/users/entity/user.entity' |
|||
import Channel from './entity/channel.entity' |
|||
import { classToPlain, plainToClass } from 'class-transformer' |
|||
|
|||
@Injectable() |
|||
export class ChannelService { |
|||
constructor ( |
|||
@InjectRepository(Channel) |
|||
private readonly ChannelRepository: Repository<Channel>, |
|||
private readonly usersService: UsersService, |
|||
private readonly usersService: UsersService |
|||
) {} |
|||
|
|||
async createChannel (channel: CreateChannelDto): Promise<Channel> { |
|||
const newChannel = this.ChannelRepository.create({ |
|||
name: channel.name, |
|||
password: channel.password, |
|||
}); |
|||
let user: User| null = await this.usersService.findUser(channel.owner); |
|||
if (user == null) throw new NotFoundException(`User #${channel.owner} not found`) |
|||
newChannel.owner = user; |
|||
return await this.ChannelRepository.save(newChannel); |
|||
} |
|||
|
|||
async getChannelsForUser(ftId: number): Promise<Array<Channel>> { |
|||
const query = await this.ChannelRepository.createQueryBuilder('room') |
|||
const user: User | null = await this.usersService.findUser(channel.owner) |
|||
if (user == null) { |
|||
throw new NotFoundException(`User #${channel.owner} not found`) |
|||
} |
|||
const newChannel = new Channel() |
|||
newChannel.owner = user |
|||
newChannel.users = [user] |
|||
newChannel.admins = [user] |
|||
newChannel.name = channel.name |
|||
newChannel.isPrivate = channel.isPrivate |
|||
newChannel.password = channel.password |
|||
return await this.ChannelRepository.save(newChannel) |
|||
} |
|||
|
|||
async getChannelsForUser (ftId: number): Promise<Channel[]> { |
|||
let rooms: Channel[] = [] |
|||
rooms = [ |
|||
...(await this.ChannelRepository.createQueryBuilder('room') |
|||
.where('room.isPrivate = false') |
|||
.getMany()) |
|||
] |
|||
|
|||
rooms = [ |
|||
...rooms, |
|||
...(await this.ChannelRepository.createQueryBuilder('room') |
|||
.innerJoin('room.users', 'users') |
|||
.where('users.ftId = :ftId', { ftId }) |
|||
.leftJoinAndSelect('room.users', 'all_users') |
|||
.orderBy('room.id', 'DESC') // TODO: order by last message
|
|||
.getRawMany(); |
|||
return query; //where userId is in User[] of channel?
|
|||
.where('room.isPrivate = true') |
|||
.andWhere('users.ftId = :ftId', { ftId }) |
|||
.getMany()) |
|||
] |
|||
return rooms |
|||
} |
|||
|
|||
async addUserToChannel (channel: Channel, user: User): Promise<Channel> { |
|||
channel.owner = user; |
|||
return await this.ChannelRepository.save(channel); |
|||
channel.owner = user |
|||
return await this.ChannelRepository.save(channel) |
|||
} |
|||
|
|||
async getChannel (id: number): Promise<Channel> { |
|||
const channel = await this.ChannelRepository.findOneBy({ id }); |
|||
if (!channel) throw new NotFoundException(`Channel #${id} not found`); |
|||
return channel; |
|||
const channel = await this.ChannelRepository.findOneBy({ id }) |
|||
if (channel == null) { throw new NotFoundException(`Channel #${id} not found`) } |
|||
return channel |
|||
} |
|||
|
|||
async update (channel: Channel) { |
|||
this.ChannelRepository.update(channel.id, channel); |
|||
this.ChannelRepository.update(channel.id, channel) |
|||
} |
|||
|
|||
async removeChannel (channelId: number) { |
|||
await this.ChannelRepository.delete(channelId) |
|||
} |
|||
async removeChannel(id: number) { |
|||
await this.ChannelRepository.delete(id); |
|||
|
|||
async isOwner (id: number, userId: number): Promise<boolean> { |
|||
const channel = await this.ChannelRepository.findOne({ |
|||
where: { id }, |
|||
relations: { owner: true } |
|||
}) |
|||
if (channel == null) { throw new NotFoundException(`Channel #${id} not found`) } |
|||
console.log(channel.owner.ftId, userId) |
|||
return channel.owner.ftId == userId |
|||
} |
|||
|
|||
async isAdmin (id: number, userId: number): Promise<boolean> { |
|||
const channel = await this.ChannelRepository.findOne({ |
|||
where: { id }, |
|||
relations: { admins: true } |
|||
}) |
|||
if (channel == null) { throw new NotFoundException(`Channel #${id} not found`) } |
|||
return channel.admins.findIndex((user) => user.ftId == userId) != -1 |
|||
} |
|||
|
|||
async isUser (id: number, userId: number): Promise<boolean> { |
|||
const channel = await this.ChannelRepository.findOne({ |
|||
where: { id }, |
|||
relations: { users: true } |
|||
}) |
|||
if (channel == null) { throw new NotFoundException(`Channel #${id} not found`) } |
|||
return channel.users.findIndex((user) => user.ftId == userId) != -1 |
|||
} |
|||
|
|||
async isBanned (id: number, userId: number): Promise<boolean> { |
|||
const channel = await this.ChannelRepository.findOne({ |
|||
where: { id }, |
|||
relations: { banned: true } |
|||
}) |
|||
if (channel == null) { throw new NotFoundException(`Channel #${id} not found`) } |
|||
return channel.banned.findIndex((user) => user.ftId == userId) != -1 |
|||
} |
|||
|
|||
async isMuted (id: number, userId: number): Promise<boolean> { |
|||
const channel = await this.ChannelRepository.findOne({ |
|||
where: { id }, |
|||
relations: { muted: true } |
|||
}) |
|||
if (channel == null) { throw new NotFoundException(`Channel #${id} not found`) } |
|||
return channel.muted.findIndex((user) => user.ftId == userId) != -1 |
|||
} |
|||
} |
|||
|
@ -1,10 +1,13 @@ |
|||
import { IsNumber } from 'class-validator'; |
|||
import { IsNumber, IsOptional, IsString } from 'class-validator' |
|||
|
|||
export class ConnectionDto { |
|||
@IsNumber() |
|||
UserId: number; |
|||
@IsNumber() |
|||
ChannelId: number; |
|||
UserId: number |
|||
|
|||
@IsNumber() |
|||
SocketId: number; |
|||
ChannelId: number |
|||
|
|||
@IsString() |
|||
@IsOptional() |
|||
pwd: string |
|||
} |
|||
|
@ -1,13 +1,28 @@ |
|||
import { IsPositive, IsAlpha, IsString, IsOptional } from 'class-validator'; |
|||
import { Transform } from 'class-transformer' |
|||
import { |
|||
IsPositive, |
|||
IsAlpha, |
|||
IsString, |
|||
IsOptional, |
|||
IsNumber, |
|||
IsBoolean |
|||
} from 'class-validator' |
|||
|
|||
export class CreateChannelDto { |
|||
@IsOptional() |
|||
@IsPositive() |
|||
id: number |
|||
|
|||
@IsString() |
|||
@IsAlpha() |
|||
name: string; |
|||
name: string |
|||
|
|||
@IsPositive() |
|||
owner: number; |
|||
@IsNumber() |
|||
owner: number |
|||
|
|||
@IsOptional() |
|||
password: string; |
|||
password: string |
|||
|
|||
@IsBoolean() |
|||
@Transform(({ value }) => value === 'true') |
|||
isPrivate: boolean |
|||
} |
|||
|
@ -1,12 +1,12 @@ |
|||
import { IsNumber, IsString } from 'class-validator'; |
|||
import { IsNumber, IsString } from 'class-validator' |
|||
|
|||
export class CreateMessageDto { |
|||
@IsString() |
|||
text: string; |
|||
text: string |
|||
|
|||
@IsNumber() |
|||
UserId: number; |
|||
UserId: number |
|||
|
|||
@IsNumber() |
|||
ChannelId: number; |
|||
ChannelId: number |
|||
} |
|||
|
@ -1,20 +1,30 @@ |
|||
import { PartialType } from '@nestjs/mapped-types'; |
|||
import { CreateChannelDto } from './create-channel.dto'; |
|||
import { IsOptional, IsString } from 'class-validator'; |
|||
import { PartialType } from '@nestjs/mapped-types' |
|||
import { CreateChannelDto } from './create-channel.dto' |
|||
import { IsNumber, IsOptional, IsString } from 'class-validator' |
|||
|
|||
export class UpdateChannelDto extends PartialType(CreateChannelDto) { |
|||
id: number; |
|||
id: number |
|||
@IsOptional() |
|||
users: [number]; |
|||
@IsNumber() |
|||
users: [number] |
|||
|
|||
@IsOptional() |
|||
messages: [number]; |
|||
@IsNumber() |
|||
messages: [number] |
|||
|
|||
@IsOptional() |
|||
owners: [number]; //user id
|
|||
@IsNumber() |
|||
owners: [number] // user id
|
|||
|
|||
@IsOptional() |
|||
banned: [number]; //user id
|
|||
@IsNumber() |
|||
banned: [number] // user id
|
|||
|
|||
@IsOptional() |
|||
muted: [number]; //user id
|
|||
@IsNumber() |
|||
muted: [number] // user id
|
|||
|
|||
@IsString() |
|||
@IsOptional() |
|||
password: string; |
|||
password: string |
|||
} |
|||
|
@ -0,0 +1,16 @@ |
|||
import { Column, Entity, OneToOne } from 'typeorm' |
|||
|
|||
import Channel from './channel.entity' |
|||
import User from 'src/users/entity/user.entity' |
|||
|
|||
@Entity() |
|||
export class connectedUser { |
|||
@OneToOne(() => User) |
|||
user: User |
|||
|
|||
@OneToOne(() => Channel, (channel) => channel.id) |
|||
channel: Channel |
|||
|
|||
@Column() |
|||
socket: string |
|||
} |
@ -0,0 +1,15 @@ |
|||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm' |
|||
import Message from './message.entity' |
|||
import type User from 'src/users/entity/user.entity' |
|||
|
|||
@Entity() |
|||
export class Channel { |
|||
@PrimaryGeneratedColumn() |
|||
id: number |
|||
|
|||
@Column() |
|||
users: User[] |
|||
|
|||
@OneToMany(() => Message, (message) => message.channel) |
|||
messages: Message[] |
|||
} |
@ -0,0 +1,33 @@ |
|||
import { |
|||
Controller, |
|||
Get, |
|||
Param, |
|||
ParseIntPipe, |
|||
UseGuards |
|||
} from '@nestjs/common' |
|||
import { Paginate, type Paginated, PaginateQuery } from 'nestjs-paginate' |
|||
import { AuthenticatedGuard } from 'src/auth/42-auth.guard' |
|||
import type Result from './entity/result.entity' |
|||
import { PongService } from './pong.service' |
|||
|
|||
@Controller('results') |
|||
export class PongController { |
|||
constructor (private readonly pongService: PongService) {} |
|||
|
|||
@Get('global') |
|||
@UseGuards(AuthenticatedGuard) |
|||
async getGlobalHistory ( |
|||
@Paginate() query: PaginateQuery |
|||
): Promise<Paginated<Result>> { |
|||
return await this.pongService.getHistory(query, 0) |
|||
} |
|||
|
|||
@Get(':id') |
|||
@UseGuards(AuthenticatedGuard) |
|||
async getHistoryById ( |
|||
@Param('id', ParseIntPipe) id: number, |
|||
@Paginate() query: PaginateQuery |
|||
): Promise<Paginated<Result>> { |
|||
return await this.pongService.getHistory(query, id) |
|||
} |
|||
} |
Loading…
Reference in new issue