Ajout endpoint géolocalisation
This commit is contained in:
parent
1ae6b6634c
commit
86427bb41b
@ -0,0 +1,14 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- Added the required column `accuracy` to the `Geolocation` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `altitude` to the `Geolocation` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `altitudeAccuracy` to the `Geolocation` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `speed` to the `Geolocation` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Geolocation" ADD COLUMN "accuracy" DOUBLE PRECISION NOT NULL,
|
||||
ADD COLUMN "altitude" DOUBLE PRECISION NOT NULL,
|
||||
ADD COLUMN "altitudeAccuracy" DOUBLE PRECISION NOT NULL,
|
||||
ADD COLUMN "speed" DOUBLE PRECISION NOT NULL;
|
@ -20,12 +20,16 @@ model User {
|
||||
}
|
||||
|
||||
model Geolocation {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
longitude Float
|
||||
latitude Float
|
||||
timestamp DateTime
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
id Int @id @default(autoincrement())
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
longitude Float
|
||||
latitude Float
|
||||
speed Float
|
||||
accuracy Float
|
||||
altitude Float
|
||||
altitudeAccuracy Float
|
||||
timestamp DateTime
|
||||
}
|
||||
|
||||
model Challenge {
|
||||
@ -38,17 +42,18 @@ model Challenge {
|
||||
|
||||
model ChallengeAction {
|
||||
id Int @id @default(autoincrement())
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
challenge Challenge @relation(fields: [challengeId], references: [id])
|
||||
challengeId Int @unique
|
||||
active Boolean @default(false)
|
||||
success Boolean @default(false)
|
||||
challenge Challenge @relation(fields: [challengeId], references: [id])
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
moneyUpdate MoneyUpdate?
|
||||
}
|
||||
|
||||
model TrainTrip {
|
||||
id String @id
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
distance Float
|
||||
from String
|
||||
@ -58,20 +63,19 @@ model TrainTrip {
|
||||
infoJson Json
|
||||
geometry String
|
||||
moneyUpdate MoneyUpdate?
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
}
|
||||
|
||||
model MoneyUpdate {
|
||||
id Int @id @default(autoincrement())
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
before Int
|
||||
after Int
|
||||
reason MoneyUpdateType
|
||||
actionId Int? @unique
|
||||
tripId String? @unique
|
||||
action ChallengeAction? @relation(fields: [actionId], references: [id])
|
||||
actionId Int? @unique
|
||||
trip TrainTrip? @relation(fields: [tripId], references: [id])
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
tripId String? @unique
|
||||
}
|
||||
|
||||
enum MoneyUpdateType {
|
||||
|
@ -3,9 +3,10 @@ import { PrismaService } from './prisma/prisma.service'
|
||||
import { PrismaModule } from './prisma/prisma.module'
|
||||
import { UsersModule } from './users/users.module'
|
||||
import { AuthModule } from './auth/auth.module'
|
||||
import { GeolocationsModule } from './geolocations/geolocations.module'
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, UsersModule, AuthModule],
|
||||
imports: [PrismaModule, UsersModule, AuthModule, GeolocationsModule],
|
||||
providers: [PrismaService],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
@ -1,5 +1,9 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { AuthGuard } from '@nestjs/passport'
|
||||
import { User } from '@prisma/client'
|
||||
import { Request } from 'express'
|
||||
|
||||
@Injectable()
|
||||
export class JwtAuthGuard extends AuthGuard('jwt') {}
|
||||
|
||||
export type AuthenticatedRequest = Request & { user: User }
|
||||
|
24
server/src/geolocations/dto/create-geolocation.dto.ts
Normal file
24
server/src/geolocations/dto/create-geolocation.dto.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { ApiProperty } from "@nestjs/swagger"
|
||||
|
||||
export class CreateGeolocationDto {
|
||||
@ApiProperty({description: "Longitude en degrés"})
|
||||
longitude: number
|
||||
|
||||
@ApiProperty({description: "Latitude en degrés"})
|
||||
latitude: number
|
||||
|
||||
@ApiProperty({description: "Vitesse en mètres par seconde"})
|
||||
speed: number
|
||||
|
||||
@ApiProperty({description: "Précision en mètres de la position obtenue"})
|
||||
accuracy: number
|
||||
|
||||
@ApiProperty({description: "Altitude en mètres"})
|
||||
altitude: number
|
||||
|
||||
@ApiProperty({description: "Précision de l'altitude en mètres"})
|
||||
altitudeAccuracy: number
|
||||
|
||||
@ApiProperty({description: "Date et heure de capture de la géolocalisation"})
|
||||
timestamp: Date
|
||||
}
|
35
server/src/geolocations/entities/geolocation.entity.ts
Normal file
35
server/src/geolocations/entities/geolocation.entity.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { ApiProperty } from "@nestjs/swagger"
|
||||
import { Geolocation } from "@prisma/client"
|
||||
|
||||
export class GeolocationEntity implements Geolocation {
|
||||
constructor(partial: Partial<GeolocationEntity>) {
|
||||
Object.assign(this, partial)
|
||||
}
|
||||
|
||||
@ApiProperty({description: "Identifiant unique"})
|
||||
id: number
|
||||
|
||||
@ApiProperty({description: "Utilisateur⋅rice ayant émis la géolocalisation"})
|
||||
userId: number
|
||||
|
||||
@ApiProperty({description: "Longitude en degrés"})
|
||||
longitude: number
|
||||
|
||||
@ApiProperty({description: "Latitude en degrés"})
|
||||
latitude: number
|
||||
|
||||
@ApiProperty({description: "Vitesse en mètres par seconde"})
|
||||
speed: number
|
||||
|
||||
@ApiProperty({description: "Précision en mètres de la position obtenue"})
|
||||
accuracy: number
|
||||
|
||||
@ApiProperty({description: "Altitude en mètres"})
|
||||
altitude: number
|
||||
|
||||
@ApiProperty({description: "Précision de l'altitude en mètres"})
|
||||
altitudeAccuracy: number
|
||||
|
||||
@ApiProperty({description: "Date et heure de capture de la géolocalisation"})
|
||||
timestamp: Date
|
||||
}
|
20
server/src/geolocations/geolocations.controller.spec.ts
Normal file
20
server/src/geolocations/geolocations.controller.spec.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing'
|
||||
import { GeolocationsController } from './geolocations.controller'
|
||||
import { GeolocationsService } from './geolocations.service'
|
||||
|
||||
describe('GeolocationsController', () => {
|
||||
let controller: GeolocationsController
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [GeolocationsController],
|
||||
providers: [GeolocationsService],
|
||||
}).compile()
|
||||
|
||||
controller = module.get<GeolocationsController>(GeolocationsController)
|
||||
})
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined()
|
||||
})
|
||||
})
|
63
server/src/geolocations/geolocations.controller.ts
Normal file
63
server/src/geolocations/geolocations.controller.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { Controller, Get, Post, Body, Patch, Param, Delete, ParseIntPipe, UseGuards, HttpCode, Req, NotFoundException } from '@nestjs/common'
|
||||
import { GeolocationsService } from './geolocations.service'
|
||||
import { CreateGeolocationDto } from './dto/create-geolocation.dto'
|
||||
import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard'
|
||||
import { ApiBearerAuth, ApiCreatedResponse, ApiForbiddenResponse, ApiNoContentResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger'
|
||||
import { GeolocationEntity } from './entities/geolocation.entity'
|
||||
|
||||
@Controller('geolocations')
|
||||
export class GeolocationsController {
|
||||
constructor(private readonly geolocationsService: GeolocationsService) {}
|
||||
|
||||
@Post()
|
||||
@HttpCode(201)
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiCreatedResponse({ type: GeolocationEntity, description: "Objet créé avec succès" })
|
||||
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
|
||||
@ApiForbiddenResponse({ description: "Permission refusée" })
|
||||
@ApiNotFoundResponse({ description: "Object non trouvé" })
|
||||
async create(@Req() request: AuthenticatedRequest, @Body() createGeolocationDto: CreateGeolocationDto): Promise<GeolocationEntity> {
|
||||
const user = request.user
|
||||
const geolocation = await this.geolocationsService.create(user, createGeolocationDto)
|
||||
return new GeolocationEntity(geolocation)
|
||||
}
|
||||
|
||||
@Get()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOkResponse({ type: GeolocationEntity, isArray: true })
|
||||
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
|
||||
@ApiForbiddenResponse({ description: "Permission refusée" })
|
||||
@ApiNotFoundResponse({ description: "Objet non trouvé" })
|
||||
async findAll(): Promise<GeolocationEntity[]> {
|
||||
const geolocations = await this.geolocationsService.findAll()
|
||||
return geolocations.map(geolocation => new GeolocationEntity(geolocation))
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOkResponse({ type: GeolocationEntity })
|
||||
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
|
||||
@ApiForbiddenResponse({ description: "Permission refusée" })
|
||||
@ApiNotFoundResponse({ description: "Objet non trouvé" })
|
||||
async findOne(@Param('id', ParseIntPipe) id: number): Promise<GeolocationEntity> {
|
||||
const geolocation = await this.geolocationsService.findOne(+id)
|
||||
if (!geolocation)
|
||||
throw new NotFoundException(`Géolocalisation inexistante avec l'identifiant ${id}`)
|
||||
return new GeolocationEntity(geolocation)
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@HttpCode(204)
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiNoContentResponse({ description: "Objet supprimé avec succès" })
|
||||
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
|
||||
@ApiForbiddenResponse({ description: "Permission refusée" })
|
||||
@ApiNotFoundResponse({ description: "Objet non trouvé" })
|
||||
async remove(@Param('id', ParseIntPipe) id: number): Promise<void> {
|
||||
await this.geolocationsService.remove(+id)
|
||||
}
|
||||
}
|
11
server/src/geolocations/geolocations.module.ts
Normal file
11
server/src/geolocations/geolocations.module.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Module } from '@nestjs/common'
|
||||
import { GeolocationsService } from './geolocations.service'
|
||||
import { GeolocationsController } from './geolocations.controller'
|
||||
import { PrismaModule } from 'src/prisma/prisma.module'
|
||||
|
||||
@Module({
|
||||
controllers: [GeolocationsController],
|
||||
providers: [GeolocationsService],
|
||||
imports: [PrismaModule],
|
||||
})
|
||||
export class GeolocationsModule {}
|
18
server/src/geolocations/geolocations.service.spec.ts
Normal file
18
server/src/geolocations/geolocations.service.spec.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing'
|
||||
import { GeolocationsService } from './geolocations.service'
|
||||
|
||||
describe('GeolocationsService', () => {
|
||||
let service: GeolocationsService
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [GeolocationsService],
|
||||
}).compile()
|
||||
|
||||
service = module.get<GeolocationsService>(GeolocationsService)
|
||||
})
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined()
|
||||
})
|
||||
})
|
27
server/src/geolocations/geolocations.service.ts
Normal file
27
server/src/geolocations/geolocations.service.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { CreateGeolocationDto } from './dto/create-geolocation.dto'
|
||||
import { PrismaService } from 'src/prisma/prisma.service'
|
||||
import { Geolocation, User } from '@prisma/client'
|
||||
|
||||
@Injectable()
|
||||
export class GeolocationsService {
|
||||
constructor(private prisma: PrismaService) { }
|
||||
|
||||
async create(authenticatedUser: User, createGeolocationDto: CreateGeolocationDto): Promise<Geolocation> {
|
||||
const data = { ...createGeolocationDto, userId: authenticatedUser.id }
|
||||
return await this.prisma.geolocation.create({ data: data })
|
||||
}
|
||||
|
||||
async findAll(): Promise<Geolocation[]> {
|
||||
return await this.prisma.geolocation.findMany()
|
||||
}
|
||||
|
||||
async findOne(id: number): Promise<Geolocation> {
|
||||
return await this.prisma.geolocation.findUnique({ where: { id } })
|
||||
}
|
||||
|
||||
|
||||
async remove(id: number): Promise<Geolocation> {
|
||||
return await this.prisma.geolocation.delete({ where: { id } })
|
||||
}
|
||||
}
|
@ -1,13 +1,10 @@
|
||||
import { Body, Controller, Get, HttpCode, NotFoundException, Param, ParseIntPipe, Patch, Post, Req, UseGuards } from '@nestjs/common'
|
||||
import { Body, Controller, Get, HttpCode, NotFoundException, Param, ParseIntPipe, Patch, Req, UseGuards } from '@nestjs/common'
|
||||
import { UsersService } from './users.service'
|
||||
import { ApiBadRequestResponse, ApiBearerAuth, ApiForbiddenResponse, ApiNoContentResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger'
|
||||
import { UserEntity } from './entities/user.entity'
|
||||
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard'
|
||||
import { User } from '@prisma/client'
|
||||
import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard'
|
||||
import { UpdatePasswordDto } from './dto/user_password.dto'
|
||||
|
||||
export type AuthenticatedRequest = Request & { user: User }
|
||||
|
||||
@Controller('users')
|
||||
export class UsersController {
|
||||
constructor(private readonly usersService: UsersService) {}
|
||||
@ -45,8 +42,8 @@ export class UsersController {
|
||||
@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() { password }: UpdatePasswordDto) {
|
||||
async updatePassword(@Req() request: AuthenticatedRequest, @Body() body: UpdatePasswordDto) {
|
||||
const user = request.user
|
||||
await this.usersService.updatePassword(user, password)
|
||||
await this.usersService.updatePassword(user, body)
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'
|
||||
import { User } from '@prisma/client'
|
||||
import { PrismaService } from 'src/prisma/prisma.service'
|
||||
import * as bcrypt from 'bcrypt'
|
||||
import { UpdatePasswordDto } from './dto/user_password.dto'
|
||||
|
||||
@Injectable()
|
||||
export class UsersService {
|
||||
@ -15,7 +16,7 @@ export class UsersService {
|
||||
return await this.prisma.user.findUnique({ where: { id } })
|
||||
}
|
||||
|
||||
async updatePassword(user: User, password: string) {
|
||||
async updatePassword(user: User, { password }: UpdatePasswordDto) {
|
||||
const hashedPassword = await bcrypt.hash(password, 10)
|
||||
await this.prisma.user.update({
|
||||
where: { id: user.id },
|
||||
|
Loading…
Reference in New Issue
Block a user