User => Player

This commit is contained in:
2024-12-08 13:41:37 +01:00
parent c6da328023
commit 65576fc5b1
39 changed files with 193 additions and 240 deletions

View File

@ -0,0 +1,10 @@
import { ApiProperty } from '@nestjs/swagger'
import { IsNotEmpty, IsString, MinLength } from 'class-validator'
export class UpdatePasswordDto {
@IsString()
@IsNotEmpty()
@MinLength(8)
@ApiProperty()
password: string
}

View File

@ -0,0 +1,24 @@
import { ApiProperty } from "@nestjs/swagger"
import { Player } from "@prisma/client"
import { Exclude } from 'class-transformer'
export class PlayerEntity implements Player {
constructor(partial: Partial<PlayerEntity>) {
Object.assign(this, partial)
}
@ApiProperty({description: "Identifiant unique"})
id: number
@ApiProperty({description: "Nom de læ joueur⋅se"})
name: string
@Exclude()
password: string
@ApiProperty({description: "Nombre de jetons dont dispose actuellement læ joueur⋅se"})
money: number
@ApiProperty({description: "Est-ce que cet⋅te joueur⋅se est cellui actuellement en course"})
currentRunner: boolean
}

View File

@ -0,0 +1,20 @@
import { Test, TestingModule } from '@nestjs/testing'
import { PlayersController } from './players.controller'
import { PlayersService } from './players.service'
describe('PlayersController', () => {
let controller: PlayersController
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [PlayersController],
providers: [PlayersService],
}).compile()
controller = module.get<PlayersController>(PlayersController)
})
it('should be defined', () => {
expect(controller).toBeDefined()
})
})

View File

@ -0,0 +1,51 @@
import { Body, Controller, Get, HttpCode, NotFoundException, Param, ParseIntPipe, Patch, Query, Req, UseGuards } from '@nestjs/common'
import { PlayersService } from './players.service'
import { ApiBadRequestResponse, ApiBearerAuth, ApiForbiddenResponse, ApiNoContentResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger'
import { PlayerEntity } from './entities/player.entity'
import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard'
import { UpdatePasswordDto } from './dto/player_password.dto'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils'
import { PaginateOutputDto } from 'src/common/dto/pagination-output.dto'
@Controller('players')
export class PlayersController {
constructor(private readonly playersService: PlayersService) {}
@Get()
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOkResponsePaginated(PlayerEntity)
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
async findAll(@Query() queryPagination?: QueryPaginationDto): Promise<PaginateOutputDto<PlayerEntity>> {
const [players, total] = await this.playersService.findAll(queryPagination)
return paginateOutput<PlayerEntity>(players.map(player => new PlayerEntity(player)), total, queryPagination)
}
@Get(':id')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOkResponse({ type: PlayerEntity })
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
@ApiNotFoundResponse({ description: "Joueur⋅se non trouvé⋅e" })
async findOne(@Param('id', ParseIntPipe) id: number) {
const player = await this.playersService.findOne(id)
if (!player)
throw new NotFoundException(`Læ joueur⋅se avec l'identifiant ${id} n'existe pas`)
return new PlayerEntity(player)
}
@Patch('/update-password')
@HttpCode(204)
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiNoContentResponse({description: "Le mot de passe a bien été modifié."})
@ApiBadRequestResponse({description: "Erreur dans la saisie du nouveau mot de passe."})
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
async updatePassword(@Req() request: AuthenticatedRequest, @Body() body: UpdatePasswordDto) {
await this.playersService.updatePassword(request.user, body)
}
}

View File

@ -0,0 +1,12 @@
import { Module } from '@nestjs/common'
import { PlayersService } from './players.service'
import { PlayersController } from './players.controller'
import { PrismaModule } from 'src/prisma/prisma.module'
@Module({
controllers: [PlayersController],
providers: [PlayersService],
imports: [PrismaModule],
exports: [PlayersService],
})
export class PlayersModule {}

View File

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing'
import { PlayersService } from './players.service'
describe('PlayersService', () => {
let service: PlayersService
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [PlayersService],
}).compile()
service = module.get<PlayersService>(PlayersService)
})
it('should be defined', () => {
expect(service).toBeDefined()
})
})

View File

@ -0,0 +1,31 @@
import { Injectable } from '@nestjs/common'
import { Player } from '@prisma/client'
import { PrismaService } from 'src/prisma/prisma.service'
import * as bcrypt from 'bcrypt'
import { UpdatePasswordDto } from './dto/player_password.dto'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { paginate } from 'src/common/utils/pagination.utils'
@Injectable()
export class PlayersService {
constructor(private prisma: PrismaService) {}
async findAll(queryPagination?: QueryPaginationDto): Promise<[Player[], number]> {
return [
await this.prisma.player.findMany({ ...paginate(queryPagination) }),
await this.prisma.player.count()
]
}
async findOne(id: number): Promise<Player> {
return await this.prisma.player.findUnique({ where: { id: id } })
}
async updatePassword(user: Player, { password }: UpdatePasswordDto): Promise<void> {
const hashedPassword = await bcrypt.hash(password, 10)
await this.prisma.player.update({
where: { id: user.id },
data: { password: hashedPassword }
})
}
}