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

@ -1,7 +1,7 @@
import { Module } from '@nestjs/common'
import { PrismaService } from './prisma/prisma.service'
import { PrismaModule } from './prisma/prisma.module'
import { UsersModule } from './users/users.module'
import { PlayersModule } from './players/players.module'
import { AuthModule } from './auth/auth.module'
import { GeolocationsModule } from './geolocations/geolocations.module'
import { ChallengesModule } from './challenges/challenges.module'
@ -10,7 +10,7 @@ import { TrainsModule } from './trains/trains.module'
import { MoneyUpdatesModule } from './money-updates/money-updates.module'
@Module({
imports: [PrismaModule, UsersModule, AuthModule, GeolocationsModule, ChallengesModule, ChallengeActionsModule, TrainsModule, MoneyUpdatesModule],
imports: [PrismaModule, PlayersModule, AuthModule, GeolocationsModule, ChallengesModule, ChallengeActionsModule, TrainsModule, MoneyUpdatesModule],
providers: [PrismaService],
})
export class AppModule {}

View File

@ -5,7 +5,7 @@ import { PrismaModule } from 'src/prisma/prisma.module'
import { PassportModule } from '@nestjs/passport'
import { JwtModule } from '@nestjs/jwt'
import { env } from 'process'
import { UsersModule } from 'src/users/users.module'
import { PlayersModule } from 'src/players/players.module'
import { JwtStrategy } from './jwt.strategy'
export const JWT_SECRET = env.JWT_SECRET
@ -18,7 +18,7 @@ export const JWT_SECRET = env.JWT_SECRET
secret: JWT_SECRET,
signOptions: { expiresIn: '12h' },
}),
UsersModule,
PlayersModule,
],
controllers: [AuthController],
providers: [AuthService, JwtStrategy],

View File

@ -9,17 +9,17 @@ export class AuthService {
constructor(private prisma: PrismaService, private jwtService: JwtService) {}
async login(name: string, password: string): Promise<AuthEntity> {
const user = await this.prisma.user.findUnique({ where: { name: name } })
if (!user) {
throw new NotFoundException(`Aucun⋅e utilisateur⋅rice avec pour nom ${name}`)
const player = await this.prisma.player.findUnique({ where: { name: name } })
if (!player) {
throw new NotFoundException(`Aucun⋅e joueur⋅se avec pour nom ${name}`)
}
const isPasswordValid = await bcrypt.compare(password, user.password)
const isPasswordValid = await bcrypt.compare(password, player.password)
if (!isPasswordValid) {
throw new UnauthorizedException('Mot de passe incorrect')
}
return {
accessToken: this.jwtService.sign({ userId: user.id }),
accessToken: this.jwtService.sign({ playerId: player.id }),
}
}
}

View File

@ -1,9 +1,9 @@
import { Injectable } from '@nestjs/common'
import { AuthGuard } from '@nestjs/passport'
import { User } from '@prisma/client'
import { Player } from '@prisma/client'
import { Request } from 'express'
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
export type AuthenticatedRequest = Request & { user: User }
export type AuthenticatedRequest = Request & { user: Player }

View File

@ -2,23 +2,24 @@ import { Injectable, UnauthorizedException } from '@nestjs/common'
import { PassportStrategy } from '@nestjs/passport'
import { ExtractJwt, Strategy } from 'passport-jwt'
import { JWT_SECRET } from './auth.module'
import { UsersService } from 'src/users/users.service'
import { User } from '@prisma/client'
import { PlayersService } from 'src/players/players.service'
import { Player } from '@prisma/client'
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
constructor(private usersService: UsersService) {
constructor(private playersService: PlayersService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: JWT_SECRET,
})
}
async validate(payload: { userId: number }): Promise<User> {
const user = await this.usersService.findOne(payload.userId)
if (!user) {
async validate(payload: { playerId: number }): Promise<Player> {
console.log(payload)
const player = await this.playersService.findOne(payload.playerId)
if (!player) {
throw new UnauthorizedException()
}
return user
return player
}
}

View File

@ -23,8 +23,7 @@ export class ChallengeActionsController {
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
async create(@Req() request: AuthenticatedRequest, @Body() createChallengeActionDto: CreateChallengeActionDto): Promise<ChallengeActionEntity> {
const user = request.user
const challenge = await this.challengeActionsService.create(user, createChallengeActionDto)
const challenge = await this.challengeActionsService.create(request.user, createChallengeActionDto)
return new ChallengeActionEntity(challenge)
}

View File

@ -1,7 +1,7 @@
import { Injectable, NotAcceptableException } from '@nestjs/common'
import { CreateChallengeActionDto } from './dto/create-challenge-action.dto'
import { UpdateChallengeActionDto } from './dto/update-challenge-action.dto'
import { ChallengeAction, User } from '@prisma/client'
import { ChallengeAction, Player } from '@prisma/client'
import { PrismaService } from 'src/prisma/prisma.service'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { paginate } from 'src/common/utils/pagination.utils'
@ -11,8 +11,8 @@ import { FilterChallengeActionsDto } from './dto/filter-challenge-action.dto'
export class ChallengeActionsService {
constructor(private prisma: PrismaService) { }
async create(authenticatedUser: User, createChallengeActionDto: CreateChallengeActionDto): Promise<ChallengeAction> {
const data = { ...createChallengeActionDto, userId: authenticatedUser.id }
async create(authenticatedPlayer: Player, createChallengeActionDto: CreateChallengeActionDto): Promise<ChallengeAction> {
const data = { ...createChallengeActionDto, playerId: authenticatedPlayer.id }
return await this.prisma.challengeAction.create({
data: data,
})
@ -49,10 +49,10 @@ export class ChallengeActionsService {
})
}
async endCurrentChallenge(user: User, success: boolean): Promise<ChallengeAction> {
async endCurrentChallenge(player: Player, success: boolean): Promise<ChallengeAction> {
const challengeAction = await this.prisma.challengeAction.findFirst({
where: {
userId: user.id,
playerId: player.id,
active: true,
}
})

View File

@ -7,8 +7,8 @@ export class FilterChallengeActionsDto {
@IsOptional()
@IsInt()
@Type(() => Number)
@ApiProperty({ description: "Identifiant de l'utilisateur⋅rice qui effectue le défi", required: false })
userId?: number
@ApiProperty({ description: "Identifiant de læ joueur⋅se qui effectue le défi", required: false })
playerId?: number
@IsOptional()
@IsInt()

View File

@ -10,8 +10,8 @@ export class ChallengeActionEntity implements ChallengeAction {
@ApiProperty({ description: "Identifiant unique" })
id: number
@ApiProperty({ description: "Identifiant de l'utilisateur⋅rice effectuant le défi" })
userId: number
@ApiProperty({ description: "Identifiant de læ joueur⋅se effectuant le défi" })
playerId: number
@ApiProperty({ description: "Identifiant du défi rattaché à l'action" })
challengeId: number

View File

@ -1,7 +1,7 @@
import { Injectable, NotAcceptableException, NotFoundException } from '@nestjs/common'
import { CreateChallengeDto } from './dto/create-challenge.dto'
import { UpdateChallengeDto } from './dto/update-challenge.dto'
import { Challenge, User } from '@prisma/client'
import { Challenge, Player } from '@prisma/client'
import { PrismaService } from 'src/prisma/prisma.service'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { paginate } from 'src/common/utils/pagination.utils'
@ -56,10 +56,10 @@ export class ChallengesService {
})
}
async drawRandom(user: User): Promise<ChallengeEntity> {
async drawRandom(player: Player): Promise<ChallengeEntity> {
const currentChallengeAction = await this.prisma.challengeAction.findFirst({
where: {
userId: user.id,
playerId: player.id,
active: true,
}
})
@ -82,7 +82,7 @@ export class ChallengesService {
const challengeEntity: ChallengeEntity = new ChallengeEntity(challenge)
const action = await this.prisma.challengeAction.create({
data: {
userId: user.id,
playerId: player.id,
challengeId: challenge.id,
active: true,
success: false,

View File

@ -1,9 +1,9 @@
import { Type } from "class-transformer"
import { IsNumber, IsOptional } from "class-validator"
export class UserFilterDto {
export class PlayerFilterDto {
@IsOptional()
@IsNumber()
@Type(() => Number)
userId?: number
playerId?: number
}

View File

@ -9,8 +9,8 @@ export class GeolocationEntity implements Geolocation {
@ApiProperty({description: "Identifiant unique"})
id: number
@ApiProperty({description: "Utilisateur⋅rice ayant émis la géolocalisation"})
userId: number
@ApiProperty({description: "Joueur⋅se ayant émis la géolocalisation"})
playerId: number
@ApiProperty({description: "Longitude en degrés"})
longitude: number

View File

@ -7,7 +7,7 @@ import { GeolocationEntity } from './entities/geolocation.entity'
import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { PaginateOutputDto } from 'src/common/dto/pagination-output.dto'
import { UserFilterDto } from 'src/common/dto/user_filter.dto'
import { PlayerFilterDto } from 'src/common/dto/player_filter.dto'
@Controller('geolocations')
export class GeolocationsController {
@ -21,8 +21,7 @@ export class GeolocationsController {
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
async create(@Req() request: AuthenticatedRequest, @Body() createGeolocationDto: CreateGeolocationDto): Promise<GeolocationEntity> {
const user = request.user
const geolocation = await this.geolocationsService.create(user, createGeolocationDto)
const geolocation = await this.geolocationsService.create(request.user, createGeolocationDto)
return new GeolocationEntity(geolocation)
}
@ -32,8 +31,8 @@ export class GeolocationsController {
@ApiOkResponsePaginated(GeolocationEntity)
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
async findAll(@Query() queryPagination?: QueryPaginationDto, @Query() userFilter?: UserFilterDto): Promise<PaginateOutputDto<GeolocationEntity>> {
const [geolocations, total] = await this.geolocationsService.findAll(queryPagination, userFilter)
async findAll(@Query() queryPagination?: QueryPaginationDto, @Query() playerFilter?: PlayerFilterDto): Promise<PaginateOutputDto<GeolocationEntity>> {
const [geolocations, total] = await this.geolocationsService.findAll(queryPagination, playerFilter)
return paginateOutput<GeolocationEntity>(geolocations.map(geolocation => new GeolocationEntity(geolocation)), total, queryPagination)
}
@ -51,17 +50,17 @@ export class GeolocationsController {
return new GeolocationEntity(geolocation)
}
@Get('/last-location/:userId')
@Get('/last-location/:playerId')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOkResponse({ type: GeolocationEntity })
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
@ApiNotFoundResponse({ description: "Aucune localisation trouvée" })
async findLastLocation(@Param('userId', ParseIntPipe) userId: number): Promise<GeolocationEntity> {
const geolocation = await this.geolocationsService.findLastLocation(userId)
async findLastLocation(@Param('playerId', ParseIntPipe) playerId: number): Promise<GeolocationEntity> {
const geolocation = await this.geolocationsService.findLastLocation(playerId)
if (!geolocation)
throw new NotFoundException(`Géolocalisation inexistante pour l'utilisateur⋅rice ${userId}`)
throw new NotFoundException(`Géolocalisation inexistante pour læ joueur⋅se ${playerId}`)
return new GeolocationEntity(geolocation)
}

View File

@ -1,23 +1,23 @@
import { Injectable } from '@nestjs/common'
import { CreateGeolocationDto } from './dto/create-geolocation.dto'
import { PrismaService } from 'src/prisma/prisma.service'
import { Geolocation, Prisma, User } from '@prisma/client'
import { Geolocation, Player, Prisma } from '@prisma/client'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { paginate } from 'src/common/utils/pagination.utils'
import { UserFilterDto } from 'src/common/dto/user_filter.dto'
import { PlayerFilterDto } from 'src/common/dto/player_filter.dto'
@Injectable()
export class GeolocationsService {
constructor(private prisma: PrismaService) { }
async create(authenticatedUser: User, createGeolocationDto: CreateGeolocationDto): Promise<Geolocation> {
const data = { ...createGeolocationDto, userId: authenticatedUser.id }
async create(authenticatedPlayer: Player, createGeolocationDto: CreateGeolocationDto): Promise<Geolocation> {
const data = { ...createGeolocationDto, playerId: authenticatedPlayer.id }
return await this.prisma.geolocation.create({ data: data })
}
async findAll(queryPagination?: QueryPaginationDto, userFilter?: UserFilterDto): Promise<[Geolocation[], number]> {
async findAll(queryPagination?: QueryPaginationDto, playerFilter?: PlayerFilterDto): Promise<[Geolocation[], number]> {
const filter = {
where: (userFilter?.userId ? { userId: userFilter.userId } : {}),
where: (playerFilter?.playerId ? { playerId: playerFilter.playerId } : {}),
orderBy: { timestamp: Prisma.SortOrder.desc },
}
return [
@ -33,9 +33,9 @@ export class GeolocationsService {
return await this.prisma.geolocation.findUnique({ where: { id } })
}
async findLastLocation(userId: number): Promise<Geolocation> {
async findLastLocation(playerId: number): Promise<Geolocation> {
return await this.prisma.geolocation.findFirst({
where: { userId: userId },
where: { playerId: playerId },
orderBy: { timestamp: Prisma.SortOrder.desc },
take: 1
})

View File

@ -9,8 +9,8 @@ export class MoneyUpdateEntity implements MoneyUpdate {
@ApiProperty({ description: "Identifiant unique de la mise à jour de solde" })
id: number
@ApiProperty({ description: "Utilisateur⋅rice concerné⋅e par la mise à jour de solde" })
userId: number
@ApiProperty({ description: "Joueur⋅se concerné⋅e par la mise à jour de solde" })
playerId: number
@ApiProperty({ description: "Montant de la modification du solde" })
amount: number

View File

@ -7,7 +7,7 @@ import { ApiBearerAuth, ApiCreatedResponse, ApiForbiddenResponse, ApiNotFoundRes
import { MoneyUpdateEntity } from './entities/money-update.entity'
import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { UserFilterDto } from 'src/common/dto/user_filter.dto'
import { PlayerFilterDto } from 'src/common/dto/player_filter.dto'
import { PaginateOutputDto } from 'src/common/dto/pagination-output.dto'
@Controller('money-updates')
@ -32,8 +32,8 @@ export class MoneyUpdatesController {
@ApiOkResponsePaginated(MoneyUpdateEntity)
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
async findAll(@Query() queryPagination: QueryPaginationDto, @Query() userFilter: UserFilterDto): Promise<PaginateOutputDto<MoneyUpdateEntity>> {
const [trains, total] = await this.moneyUpdatesService.findAll(queryPagination, userFilter)
async findAll(@Query() queryPagination: QueryPaginationDto, @Query() playerFilter: PlayerFilterDto): Promise<PaginateOutputDto<MoneyUpdateEntity>> {
const [trains, total] = await this.moneyUpdatesService.findAll(queryPagination, playerFilter)
return paginateOutput<MoneyUpdateEntity>(trains.map(train => new MoneyUpdateEntity(train)), total, queryPagination)
}

View File

@ -2,32 +2,32 @@ import { Injectable } from '@nestjs/common'
import { CreateMoneyUpdateDto } from './dto/create-money-update.dto'
import { UpdateMoneyUpdateDto } from './dto/update-money-update.dto'
import { PrismaService } from 'src/prisma/prisma.service'
import { MoneyUpdate, User } from '@prisma/client'
import { MoneyUpdate, Player } from '@prisma/client'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { UserFilterDto } from 'src/common/dto/user_filter.dto'
import { PlayerFilterDto } from 'src/common/dto/player_filter.dto'
import { paginate } from 'src/common/utils/pagination.utils'
@Injectable()
export class MoneyUpdatesService {
constructor(private prisma: PrismaService) { }
async create(user: User, createMoneyUpdateDto: CreateMoneyUpdateDto): Promise<MoneyUpdate> {
async create(player: Player, createMoneyUpdateDto: CreateMoneyUpdateDto): Promise<MoneyUpdate> {
return await this.prisma.moneyUpdate.create({
data: {
...createMoneyUpdateDto,
userId: user.id,
playerId: player.id,
}
})
}
async findAll(queryPagination: QueryPaginationDto, userFilter: UserFilterDto): Promise<[MoneyUpdate[], number]> {
async findAll(queryPagination: QueryPaginationDto, playerFilter: PlayerFilterDto): Promise<[MoneyUpdate[], number]> {
return [
await this.prisma.moneyUpdate.findMany({
where: userFilter,
where: playerFilter,
...paginate(queryPagination),
}),
await this.prisma.moneyUpdate.count({
where: userFilter,
where: playerFilter,
}),
]
}

View File

@ -1,9 +1,9 @@
import { ApiProperty } from "@nestjs/swagger"
import { User } from "@prisma/client"
import { Player } from "@prisma/client"
import { Exclude } from 'class-transformer'
export class UserEntity implements User {
constructor(partial: Partial<UserEntity>) {
export class PlayerEntity implements Player {
constructor(partial: Partial<PlayerEntity>) {
Object.assign(this, partial)
}

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

@ -1,40 +1,40 @@
import { Body, Controller, Get, HttpCode, NotFoundException, Param, ParseIntPipe, Patch, Query, Req, UseGuards } from '@nestjs/common'
import { UsersService } from './users.service'
import { PlayersService } from './players.service'
import { ApiBadRequestResponse, ApiBearerAuth, ApiForbiddenResponse, ApiNoContentResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger'
import { UserEntity } from './entities/user.entity'
import { PlayerEntity } from './entities/player.entity'
import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard'
import { UpdatePasswordDto } from './dto/user_password.dto'
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('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Controller('players')
export class PlayersController {
constructor(private readonly playersService: PlayersService) {}
@Get()
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOkResponsePaginated(UserEntity)
@ApiOkResponsePaginated(PlayerEntity)
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
async findAll(@Query() queryPagination?: QueryPaginationDto): Promise<PaginateOutputDto<UserEntity>> {
const [users, total] = await this.usersService.findAll(queryPagination)
return paginateOutput<UserEntity>(users.map(user => new UserEntity(user)), total, queryPagination)
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: UserEntity })
@ApiOkResponse({ type: PlayerEntity })
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
@ApiNotFoundResponse({ description: "Utilisateur⋅rice non trouvé⋅e" })
@ApiNotFoundResponse({ description: "Joueur⋅se non trouvé⋅e" })
async findOne(@Param('id', ParseIntPipe) id: number) {
const user = await this.usersService.findOne(id)
if (!user)
throw new NotFoundException(`L'utilisateur⋅rice avec l'identifiant ${id} n'existe pas`)
return new UserEntity(user)
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')
@ -46,7 +46,6 @@ export class UsersController {
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
async updatePassword(@Req() request: AuthenticatedRequest, @Body() body: UpdatePasswordDto) {
const user = request.user
await this.usersService.updatePassword(user, body)
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

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

View File

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

View File

@ -1,19 +1,19 @@
import { Injectable } from '@nestjs/common'
import { PrismaClient, } from '@prisma/client'
async function updateUserMoney(prisma: PrismaClient): Promise<void> {
// On calcule le solde par utilisateur⋅rice pour mettre à jour l'objet User
const moneyPerUser = await prisma.moneyUpdate.groupBy({
by: 'userId',
async function updatePlayerMoney(prisma: PrismaClient): Promise<void> {
// On calcule le solde par joueur⋅se pour mettre à jour l'objet Player
const moneyPerPlayer = await prisma.moneyUpdate.groupBy({
by: 'playerId',
_sum: {
amount: true,
}
})
for (const { userId, _sum } of moneyPerUser) {
for (const { playerId, _sum } of moneyPerPlayer) {
const { amount } = _sum
await prisma.user.update({
await prisma.player.update({
where: {
id: userId,
id: playerId,
},
data: {
money: amount
@ -21,7 +21,7 @@ async function updateUserMoney(prisma: PrismaClient): Promise<void> {
})
}
// On réinitialise le solde s'il n'y a plus aucun MoneyUpdate
await prisma.user.updateMany({
await prisma.player.updateMany({
where: {
moneyUpdates: { none: {} }
},
@ -39,7 +39,7 @@ function extendPrismaClient() {
$allOperations({ model, operation, args, query }) {
const result = query(args)
if (!operation.startsWith("find") && !['aggregate', 'count', 'groupBy'].includes(operation))
result.then(() => updateUserMoney(prisma))
result.then(() => updatePlayerMoney(prisma))
return result
}
}

View File

@ -10,8 +10,8 @@ export class CreateTrainDto {
@IsInt()
@Type(() => Number)
@ApiProperty({ description: "Identifiant de l'utilisateur⋅rice effectuant le trajet" })
userId: number
@ApiProperty({ description: "Identifiant de læ joueur⋅se effectuant le trajet" })
playerId: number
@IsNumber()
@Type(() => Number)

View File

@ -10,8 +10,8 @@ export class TrainEntity implements TrainTrip {
@ApiProperty({ description: "Identifiant du train, donné par l'identifiant de partage Interrail" })
id: string
@ApiProperty({ description: "Identifiant de l'utilisateur⋅rice effectuant le trajet" })
userId: number
@ApiProperty({ description: "Identifiant de læ joueur⋅se effectuant le trajet" })
playerId: number
@ApiProperty({ description: "Distance estimée en mètres du trajet" })
distance: number

View File

@ -9,7 +9,7 @@ import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/paginat
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { PaginateOutputDto } from 'src/common/dto/pagination-output.dto'
import { ImportTrainDto } from './dto/import-train.dto'
import { UserFilterDto } from 'src/common/dto/user_filter.dto'
import { PlayerFilterDto } from 'src/common/dto/player_filter.dto'
@Controller('trains')
export class TrainsController {
@ -33,8 +33,8 @@ export class TrainsController {
@ApiOkResponsePaginated(TrainEntity)
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
async findAll(@Query() queryPagination: QueryPaginationDto, @Query() userFilter: UserFilterDto): Promise<PaginateOutputDto<TrainEntity>> {
const [trains, total] = await this.trainsService.findAll(queryPagination, userFilter)
async findAll(@Query() queryPagination: QueryPaginationDto, @Query() playerFilter: PlayerFilterDto): Promise<PaginateOutputDto<TrainEntity>> {
const [trains, total] = await this.trainsService.findAll(queryPagination, playerFilter)
return paginateOutput<TrainEntity>(trains.map(train => new TrainEntity(train)), total, queryPagination)
}

View File

@ -2,13 +2,13 @@ import { Injectable, NotAcceptableException } from '@nestjs/common'
import { CreateTrainDto } from './dto/create-train.dto'
import { UpdateTrainDto } from './dto/update-train.dto'
import { PrismaService } from 'src/prisma/prisma.service'
import { TrainTrip, User } from '@prisma/client'
import { Player, TrainTrip } from '@prisma/client'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { paginate } from 'src/common/utils/pagination.utils'
import { ImportTrainDto } from './dto/import-train.dto'
import { InterrailJourney, InterrailLegInfo, InterrailTravelInfo } from './dto/interrail-api.dto'
import { distanceCoordinates } from 'src/common/utils/calculus.utils'
import { UserFilterDto } from 'src/common/dto/user_filter.dto'
import { PlayerFilterDto } from 'src/common/dto/player_filter.dto'
@Injectable()
export class TrainsService {
@ -18,14 +18,14 @@ export class TrainsService {
return await this.prisma.trainTrip.create({ data: createTrainDto })
}
async findAll(queryPagination: QueryPaginationDto, userFilter: UserFilterDto): Promise<[TrainTrip[], number]> {
async findAll(queryPagination: QueryPaginationDto, playerFilter: PlayerFilterDto): Promise<[TrainTrip[], number]> {
return [
await this.prisma.trainTrip.findMany({
where: userFilter,
where: playerFilter,
...paginate(queryPagination),
}),
await this.prisma.trainTrip.count({
where: userFilter,
where: playerFilter,
}),
]
}
@ -49,7 +49,7 @@ export class TrainsService {
})
}
async import(user: User, { id: trainId }: ImportTrainDto): Promise<TrainTrip> {
async import(player: Player, { id: trainId }: ImportTrainDto): Promise<TrainTrip> {
const interrailResult: InterrailJourney = await fetch(`https://3uiwjsimnh.execute-api.eu-central-1.amazonaws.com/Prod/journey-import?id=${trainId}`)
.then(data => data.json())
if (interrailResult.data.travels.length !== 1)
@ -83,7 +83,7 @@ export class TrainsService {
},
create: {
id: trainId,
userId: user.id,
playerId: player.id,
distance: distance,
from: travel.from,
to: travel.to,
@ -92,7 +92,7 @@ export class TrainsService {
infoJson: leg.infoJson,
},
update: {
userId: user.id,
playerId: player.id,
distance: distance,
from: travel.from,
to: travel.to,

View File

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

View File

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