diff --git a/srcs/requirements/nestjs/api_back/src/users/dto/partial-users.dto.ts b/srcs/requirements/nestjs/api_back/src/users/dto/partial-users.dto.ts index eda9cc14..f8e18af0 100644 --- a/srcs/requirements/nestjs/api_back/src/users/dto/partial-users.dto.ts +++ b/srcs/requirements/nestjs/api_back/src/users/dto/partial-users.dto.ts @@ -1,4 +1,4 @@ import { OmitType, PartialType } from "@nestjs/mapped-types"; import { CreateUsersDto } from "./create-users.dto"; -export class PartialUsersDto extends OmitType(CreateUsersDto, ['fortyTwoId'] as const){} +export class PartialUsersDto extends OmitType(CreateUsersDto, ['fortyTwoId', 'email'] as const){} diff --git a/srcs/requirements/nestjs/api_back/src/users/entities/user.entity.ts b/srcs/requirements/nestjs/api_back/src/users/entities/user.entity.ts index b0a97c9a..f7b4e6f6 100644 --- a/srcs/requirements/nestjs/api_back/src/users/entities/user.entity.ts +++ b/srcs/requirements/nestjs/api_back/src/users/entities/user.entity.ts @@ -1,7 +1,8 @@ import { Exclude } from "class-transformer"; import { IsEmail, Length } from "class-validator"; -import { Column, Entity, JoinTable, ManyToMany, OneToMany, PrimaryGeneratedColumn, Unique } from "typeorm"; +import { Column, Entity, JoinTable, ManyToMany, OneToMany, OneToOne, PrimaryGeneratedColumn, Unique } from "typeorm"; import { Friendship } from "../../friendship/entities/friendship.entity"; +import { UserStats } from "./userStat.entities"; @Entity('user') @@ -49,4 +50,8 @@ export class User { @JoinTable() @OneToMany(type => Friendship , (friendship) => friendship.addresseeId) addresseeId: Friendship[]; + + @JoinTable() + @OneToOne(() => UserStats, { cascade: true }) + stats: UserStats; } diff --git a/srcs/requirements/nestjs/api_back/src/users/entities/userStat.entities.ts b/srcs/requirements/nestjs/api_back/src/users/entities/userStat.entities.ts new file mode 100644 index 00000000..a57279d3 --- /dev/null +++ b/srcs/requirements/nestjs/api_back/src/users/entities/userStat.entities.ts @@ -0,0 +1,19 @@ +import { Column, Entity, OneToOne, PrimaryGeneratedColumn } from "typeorm"; + +@Entity('stats') +export class UserStats { + @PrimaryGeneratedColumn() + id: number; + + @Column({ default: 0 }) + winGame: number; + + @Column({ default: 0 }) + loseGame: number; + + @Column({ default: 0 }) + drawGame: number; + + @Column({ default: 0 }) + totalGame: number; +} diff --git a/srcs/requirements/nestjs/api_back/src/users/users.controller.ts b/srcs/requirements/nestjs/api_back/src/users/users.controller.ts index 84cdeb3e..a576cd44 100644 --- a/srcs/requirements/nestjs/api_back/src/users/users.controller.ts +++ b/srcs/requirements/nestjs/api_back/src/users/users.controller.ts @@ -1,5 +1,5 @@ import { - Body, Controller, Delete, Get, NotFoundException, Patch, Post, Query, Req, Res, UploadedFile, UseGuards, UseInterceptors + Body, Controller, Delete, Get, NotFoundException, Param, Patch, Post, Query, Req, Res, UploadedFile, UseGuards, UseInterceptors } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; import { AuthenticateGuard, TwoFactorGuard } from 'src/auth/42/guards/42guards'; @@ -41,12 +41,21 @@ export class UsersController { return this.usersService.findOne(req.user.id); } - // @UseGuards(AuthenticateGuard) - // @Post() - // @HttpCode(HttpStatus.CREATED) - // create(@Body() createUsersDto : CreateUsersDto ) { - // return this.usersService.create(createUsersDto); - // } + // GET http://transcendance:8080/user?username=NomDuUser + @UseGuards(AuthenticateGuard) + @UseGuards(TwoFactorGuard) + @Get('search') + findOneByUsername(@Query('username') username: string) { + return this.usersService.findOneByUsername(username); + } + + @UseGuards(AuthenticateGuard) + @UseGuards(TwoFactorGuard) + @Get('stats') + getStats(@Req() request) { + return this.usersService.getStats(request.user.id); + } + @UseGuards(AuthenticateGuard) @UseGuards(TwoFactorGuard) diff --git a/srcs/requirements/nestjs/api_back/src/users/users.service.ts b/srcs/requirements/nestjs/api_back/src/users/users.service.ts index 475aa484..a8f1055a 100644 --- a/srcs/requirements/nestjs/api_back/src/users/users.service.ts +++ b/srcs/requirements/nestjs/api_back/src/users/users.service.ts @@ -10,6 +10,7 @@ import { isNumberString } from 'class-validator'; import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto'; import { PartialUsersDto } from './dto/partial-users.dto'; import { join } from 'path'; +import { UserStats } from './entities/userStat.entities'; // On va devoir sûrement trouver un moyen plus simple pour passer l'id, sûrement via des pipes // ou des interceptors, mais pour l'instant on va faire comme ça. @@ -35,7 +36,10 @@ export class UsersService { } async findOne(id: string) { - const user = await this.userRepository.findOneBy({id: +id}); + const user = await this.userRepository.createQueryBuilder('user') + .leftJoinAndSelect('user.stats', 'stats') + .where('user.id = :id', { id: id }) + .getOne(); if (!user) throw new NotFoundException(`The requested user not found.`); const partialUser : Partial = { @@ -43,6 +47,7 @@ export class UsersService { image_url: user.image_url, isEnabledTwoFactorAuth: user.isEnabledTwoFactorAuth, status: user.status, + stats: user.stats, }; return partialUser; } @@ -55,13 +60,17 @@ export class UsersService { } async findOneByUsername(username: string) { - const user = await this.userRepository.findOneBy({username : username}); + const user = await this.userRepository.createQueryBuilder('user') + .leftJoinAndSelect('user.stats', 'stats') + .where('user.username = :username', { username: username }) + .getOne(); if (!user) throw new HttpException(`The user could not be found.`,HttpStatus.NOT_FOUND); const partialUser : Partial = { username: user.username, image_url: user.image_url, status: user.status, + stats: user.stats, }; return partialUser; } @@ -81,6 +90,7 @@ export class UsersService { const user = this.userRepository.create(createUserDto); if (!user) throw new HttpException(`The user could not be created.`,HttpStatus.NOT_FOUND); + user.stats = new UserStats(); return this.userRepository.save(user); } @@ -130,4 +140,50 @@ export class UsersService { console.log(user.image_url); return user.image_url; } + + async getStats(id: number) { + const user = await this.userRepository.createQueryBuilder('user') + .leftJoinAndSelect('user.stats', 'stats') + .where('user.id = :id', { id: id }) + .getOne(); + if (!user.stats || !user) + throw new HttpException(`The user's stats could not be found.`,HttpStatus.NOT_FOUND); + return user.stats; + } + + async incrementVictories(id: number) { + const user = await this.userRepository.createQueryBuilder('user') + .leftJoinAndSelect('user.stats', 'stats') + .where('user.id = :id', { id: id }) + .getOne(); + if (!user.stats || !user) + throw new HttpException(`The user's stats could not be found.`,HttpStatus.NOT_FOUND); + user.stats.winGame++; + user.stats.totalGame++; + this.userRepository.save(user); + } + + async incrementDefeats(id: number) { + const user = await this.userRepository.createQueryBuilder('user') + .leftJoinAndSelect('user.stats', 'stats') + .where('user.id = :id', { id: id }) + .getOne(); + if (!user.stats || !user) + throw new HttpException(`The user's stats could not be found.`,HttpStatus.NOT_FOUND); + user.stats.loseGame++; + user.stats.totalGame++; + this.userRepository.save(user); + } + + async incrementDraws(id: number) { + const user = await this.userRepository.createQueryBuilder('user') + .leftJoinAndSelect('user.stats', 'stats') + .where('user.id = :id', { id: id }) + .getOne(); + if (!user.stats || !user) + throw new HttpException(`The user's stats could not be found.`,HttpStatus.NOT_FOUND); + user.stats.winGame++; + user.stats.totalGame++; + this.userRepository.save(user); + } }