From c8bf1900d8c472124921390cae66cc11fc9e7b19 Mon Sep 17 00:00:00 2001 From: L4168 <L4168@student.jamk.fi> Date: Tue, 2 Jul 2019 10:03:53 +0300 Subject: [PATCH 01/10] added nestedvalidation centerJSON --- src/game/game.dto.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/game/game.dto.ts b/src/game/game.dto.ts index 09c39b7..4b1fa9b 100644 --- a/src/game/game.dto.ts +++ b/src/game/game.dto.ts @@ -7,11 +7,15 @@ import { Validate, Min, Max, + ValidateNested, + Allow, } from 'class-validator'; import { ObjectivePointEntity } from './game.entity'; import { CenterJSON } from '../shared/custom-validation'; import { FactionDTO } from '../faction/faction.dto'; +import { CenterDTO } from './game.json.dto'; +import { Type } from 'class-transformer'; export class GameDTO { @IsString() @@ -22,9 +26,12 @@ export class GameDTO { @Length(1, 255) desc: string; @IsNotEmpty() - @Validate(CenterJSON) - center: JSON; + @ValidateNested() + @Type(() => CenterDTO) + center: CenterDTO; + @Allow() map?: JSON; + @Allow() nodesettings?: JSON; @IsDateString() @IsNotEmpty() @@ -32,7 +39,9 @@ export class GameDTO { @IsDateString() @IsNotEmpty() enddate: string; + @Allow() factions?: FactionDTO[]; + @Allow() objective_points?: FlagboxDTO[]; } -- GitLab From 6c62d19a0dffa92f3f2d75f8d8b62de3c7e81410 Mon Sep 17 00:00:00 2001 From: L4168 <L4168@student.jamk.fi> Date: Tue, 2 Jul 2019 10:04:35 +0300 Subject: [PATCH 02/10] center: CenterDTO --- src/game/game.entity.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/game.entity.ts b/src/game/game.entity.ts index b580665..030e81d 100644 --- a/src/game/game.entity.ts +++ b/src/game/game.entity.ts @@ -14,6 +14,7 @@ import { PersonEntity } from '../user/user.entity'; import { GameGroupEntity } from '../faction/faction.entity'; import { FactionEntity } from '../faction/faction.entity'; import { TaskEntity } from '../task/task.entity'; +import { CenterDTO } from './game.json.dto'; // table that stores all created games @Entity('Game') @@ -21,7 +22,7 @@ export class GameEntity { @PrimaryGeneratedColumn('uuid') id: string; @Column('text') name: string; @Column('text') desc: string; - @Column('json') center: JSON; + @Column('json') center: CenterDTO; @Column({ type: 'json', nullable: true }) map: JSON; @Column({ type: 'json', nullable: true }) nodesettings?: JSON; @Column('timestamp') startdate: Timestamp; -- GitLab From 763d20b7b41b005b73fc1952cc12d2529f8380f2 Mon Sep 17 00:00:00 2001 From: L4168 <L4168@student.jamk.fi> Date: Tue, 2 Jul 2019 10:04:52 +0300 Subject: [PATCH 03/10] subDTO for centerJSON --- src/game/game.json.dto.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/game/game.json.dto.ts diff --git a/src/game/game.json.dto.ts b/src/game/game.json.dto.ts new file mode 100644 index 0000000..31bb481 --- /dev/null +++ b/src/game/game.json.dto.ts @@ -0,0 +1,9 @@ +import { GameDTO } from './game.dto'; +import { IsNumber } from 'class-validator'; + +export class CenterDTO { + @IsNumber() + lat: number; + @IsNumber() + lng: number; +} -- GitLab From 08f590520234f346a34644eabe865ef80fcc58e6 Mon Sep 17 00:00:00 2001 From: L4168 <L4168@student.jamk.fi> Date: Tue, 2 Jul 2019 10:07:20 +0300 Subject: [PATCH 04/10] forbidNonWhitelisted: true --- src/shared/validation.pipe.ts | 81 ++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/src/shared/validation.pipe.ts b/src/shared/validation.pipe.ts index 27f078b..68eb4e8 100644 --- a/src/shared/validation.pipe.ts +++ b/src/shared/validation.pipe.ts @@ -1,44 +1,57 @@ - -import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException, HttpException, HttpStatus } from '@nestjs/common'; +import { + PipeTransform, + Injectable, + ArgumentMetadata, + HttpException, + HttpStatus, +} from '@nestjs/common'; import { validate } from 'class-validator'; import { plainToClass } from 'class-transformer'; @Injectable() export class ValidationPipe implements PipeTransform<any> { - async transform(value: any, metadata: ArgumentMetadata) { - - if (value instanceof Object && this.isEmpty(value)) { - throw new HttpException( - 'Validation failed: No body submitted', HttpStatus.BAD_REQUEST - ); - } - - const { metatype } = metadata; - if (!metatype || !this.toValidate(metatype)) { - return value; - } - const object = plainToClass(metatype, value); - const errors = await validate(object); - if (errors.length > 0) { - throw new HttpException(`Validation failed: ${this.formatErrors(errors)}`, HttpStatus.BAD_REQUEST); - } - return value; + async transform(value: any, metadata: ArgumentMetadata) { + if (value instanceof Object && this.isEmpty(value)) { + throw new HttpException( + 'Validation failed: No body submitted', + HttpStatus.BAD_REQUEST, + ); } - private toValidate(metatype: Function): boolean { - const types: Function[] = [String, Boolean, Number, Array, Object]; - return !types.includes(metatype); + const { metatype } = metadata; + if (!metatype || !this.toValidate(metatype)) { + return value; } - - private formatErrors(errors: any[]) { - return errors.map(err => { - for (let property in err.constraints) { - return err.constraints[property] - } - }).join(", "); + const object = plainToClass(metatype, value); + const errors = await validate(object, { + whitelist: true, + forbidNonWhitelisted: true, + }); + if (errors.length > 0) { + throw new HttpException( + `Validation failed: ${this.formatErrors(errors)}`, + HttpStatus.BAD_REQUEST, + ); } + return value; + } - private isEmpty(value: any) { - return (Object.keys(value).length > 0) ? false : true; - } -} \ No newline at end of file + private toValidate(metatype: Function): boolean { + const types: Function[] = [String, Boolean, Number, Array, Object]; + return !types.includes(metatype); + } + + private formatErrors(errors: any[]) { + return errors + .map(err => { + for (let property in err.constraints) { + return err.constraints[property]; + } + }) + .join(', '); + } + + private isEmpty(value: any) { + return Object.keys(value).length > 0 ? false : true; + } +} -- GitLab From 70993d76c6f7caac93a05a719603b00cf3f43fe8 Mon Sep 17 00:00:00 2001 From: L4168 <L4168@student.jamk.fi> Date: Tue, 2 Jul 2019 17:08:25 +0300 Subject: [PATCH 05/10] json validation for node_settings --- src/game/game.dto.ts | 9 +++++---- src/game/game.entity.ts | 4 ++-- src/game/game.json-nested.dto.ts | 16 ++++++++++++++++ src/game/game.json.dto.ts | 11 +++++++++-- 4 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 src/game/game.json-nested.dto.ts diff --git a/src/game/game.dto.ts b/src/game/game.dto.ts index 4b1fa9b..e4f12e3 100644 --- a/src/game/game.dto.ts +++ b/src/game/game.dto.ts @@ -14,7 +14,7 @@ import { import { ObjectivePointEntity } from './game.entity'; import { CenterJSON } from '../shared/custom-validation'; import { FactionDTO } from '../faction/faction.dto'; -import { CenterDTO } from './game.json.dto'; +import { CenterDTO, NodeSettingsDTO } from './game.json.dto'; import { Type } from 'class-transformer'; export class GameDTO { @@ -25,14 +25,15 @@ export class GameDTO { @IsNotEmpty() @Length(1, 255) desc: string; - @IsNotEmpty() @ValidateNested() @Type(() => CenterDTO) center: CenterDTO; @Allow() - map?: JSON; + @ValidateNested() + @Type(() => NodeSettingsDTO) + nodesettings?: NodeSettingsDTO; @Allow() - nodesettings?: JSON; + map?: JSON; @IsDateString() @IsNotEmpty() startdate: string; diff --git a/src/game/game.entity.ts b/src/game/game.entity.ts index 030e81d..5f019e8 100644 --- a/src/game/game.entity.ts +++ b/src/game/game.entity.ts @@ -14,7 +14,7 @@ import { PersonEntity } from '../user/user.entity'; import { GameGroupEntity } from '../faction/faction.entity'; import { FactionEntity } from '../faction/faction.entity'; import { TaskEntity } from '../task/task.entity'; -import { CenterDTO } from './game.json.dto'; +import { CenterDTO, NodeSettingsDTO } from './game.json.dto'; // table that stores all created games @Entity('Game') @@ -24,7 +24,7 @@ export class GameEntity { @Column('text') desc: string; @Column('json') center: CenterDTO; @Column({ type: 'json', nullable: true }) map: JSON; - @Column({ type: 'json', nullable: true }) nodesettings?: JSON; + @Column({ type: 'json', nullable: true }) nodesettings?: NodeSettingsDTO; @Column('timestamp') startdate: Timestamp; @Column('timestamp') enddate: Timestamp; diff --git a/src/game/game.json-nested.dto.ts b/src/game/game.json-nested.dto.ts new file mode 100644 index 0000000..df67071 --- /dev/null +++ b/src/game/game.json-nested.dto.ts @@ -0,0 +1,16 @@ +import { IsNumber } from 'class-validator'; + +export class NodeCoreSettingsDTO { + @IsNumber() + capture_time: number; + @IsNumber() + confirmation_time: number; + @IsNumber() + owner: number; + @IsNumber() + capture: number; + @IsNumber() + buttons_available: number; + @IsNumber() + heartbeat_interval: number; +} diff --git a/src/game/game.json.dto.ts b/src/game/game.json.dto.ts index 31bb481..5b9484a 100644 --- a/src/game/game.json.dto.ts +++ b/src/game/game.json.dto.ts @@ -1,5 +1,6 @@ -import { GameDTO } from './game.dto'; -import { IsNumber } from 'class-validator'; +import { IsNumber, ValidateNested } from 'class-validator'; +import { NodeCoreSettingsDTO } from './game.json-nested.dto'; +import { Type } from 'class-transformer'; export class CenterDTO { @IsNumber() @@ -7,3 +8,9 @@ export class CenterDTO { @IsNumber() lng: number; } + +export class NodeSettingsDTO { + @ValidateNested() + @Type(() => NodeCoreSettingsDTO) + node_settings: NodeCoreSettingsDTO; +} -- GitLab From 54dd811e3308af7d167c9cb5d2a190db07f6142a Mon Sep 17 00:00:00 2001 From: Ronnie Friman <L4168@student.jamk.fi> Date: Tue, 2 Jul 2019 19:22:13 +0300 Subject: [PATCH 06/10] added nested validation errors --- src/shared/validation.pipe.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/shared/validation.pipe.ts b/src/shared/validation.pipe.ts index 68eb4e8..cff51f1 100644 --- a/src/shared/validation.pipe.ts +++ b/src/shared/validation.pipe.ts @@ -7,6 +7,7 @@ import { } from '@nestjs/common'; import { validate } from 'class-validator'; import { plainToClass } from 'class-transformer'; +import { AdvancedConsoleLogger } from 'typeorm'; @Injectable() export class ValidationPipe implements PipeTransform<any> { @@ -44,13 +45,20 @@ export class ValidationPipe implements PipeTransform<any> { private formatErrors(errors: any[]) { return errors .map(err => { - for (let property in err.constraints) { - return err.constraints[property]; - } + return this.returnError(err); }) .join(', '); } + private returnError(err) { + if (err['children'] !== undefined && err['children'].length != 0) { + return this.formatErrors(err['children']); + } + for (let property in err.constraints) { + return err.constraints[property]; + } + } + private isEmpty(value: any) { return Object.keys(value).length > 0 ? false : true; } -- GitLab From 6dacd4ece0eb8908c0651a57d717762a66320fa8 Mon Sep 17 00:00:00 2001 From: Ronnie Friman <L4168@student.jamk.fi> Date: Tue, 2 Jul 2019 19:22:53 +0300 Subject: [PATCH 07/10] added json validation for editgame factions --- src/faction/faction.dto.ts | 11 ++++++++++- src/game/game.dto.ts | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/faction/faction.dto.ts b/src/faction/faction.dto.ts index 1db90ce..a5b9f04 100644 --- a/src/faction/faction.dto.ts +++ b/src/faction/faction.dto.ts @@ -4,6 +4,9 @@ import { Validate, IsString, IsNotEmpty, + IsNumber, + Min, + Max, } from 'class-validator'; import { GameEntity } from '../game/game.entity'; @@ -14,9 +17,15 @@ import { FactionEntity, GameGroupEntity } from './faction.entity'; export class FactionDTO { @IsString() @IsNotEmpty() - @Length(2, 15) + @Length(2, 31) factionName: string; + @IsString() + @IsNotEmpty() + @Length(3, 15) factionPassword: string; + @IsNumber() + @Min(1) + @Max(3) multiplier?: number; game: GameDTO; } diff --git a/src/game/game.dto.ts b/src/game/game.dto.ts index e4f12e3..5549aa0 100644 --- a/src/game/game.dto.ts +++ b/src/game/game.dto.ts @@ -40,7 +40,8 @@ export class GameDTO { @IsDateString() @IsNotEmpty() enddate: string; - @Allow() + @ValidateNested() + @Type(() => FactionDTO) factions?: FactionDTO[]; @Allow() objective_points?: FlagboxDTO[]; -- GitLab From 511334e49ba415581243dcd494726f84bac8e1d4 Mon Sep 17 00:00:00 2001 From: Ronnie Friman <L4168@student.jamk.fi> Date: Tue, 2 Jul 2019 19:24:55 +0300 Subject: [PATCH 08/10] added json validation for editgame flagboxes --- src/game/game.dto.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/game.dto.ts b/src/game/game.dto.ts index 5549aa0..913b6c0 100644 --- a/src/game/game.dto.ts +++ b/src/game/game.dto.ts @@ -43,7 +43,8 @@ export class GameDTO { @ValidateNested() @Type(() => FactionDTO) factions?: FactionDTO[]; - @Allow() + @ValidateNested() + @Type(() => FlagboxDTO) objective_points?: FlagboxDTO[]; } -- GitLab From a78ac42689cdd0a7ec43394dec70cb818b34ddcb Mon Sep 17 00:00:00 2001 From: L4168 <L4168@student.jamk.fi> Date: Wed, 3 Jul 2019 09:45:56 +0300 Subject: [PATCH 09/10] added listFactions for gm --- src/game/game.controller.ts | 7 +++++++ src/game/game.service.ts | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/src/game/game.controller.ts b/src/game/game.controller.ts index a97155c..015baf9 100644 --- a/src/game/game.controller.ts +++ b/src/game/game.controller.ts @@ -17,6 +17,7 @@ import { User } from '../user/user.decorator'; import { GameDTO, FlagboxEventDTO } from './game.dto'; import { ValidationPipe } from '../shared/validation.pipe'; import { Roles } from '../shared/roles.decorator'; +import { GameEntity } from './game.entity'; @Controller('game') export class GameController { @@ -48,6 +49,12 @@ export class GameController { return this.gameservice.returnGameInfo(id); } + @Get('get-factions/:id') + @Roles('admin') + async returnGameFactions(@Param('id') id: GameEntity) { + return this.gameservice.listFactions(id); + } + @Get('flag/:id') async flagboxQuery(@Param('id') id: string) { return this.gameservice.flagboxQuery(id); diff --git a/src/game/game.service.ts b/src/game/game.service.ts index 9a74a46..37f2e47 100644 --- a/src/game/game.service.ts +++ b/src/game/game.service.ts @@ -110,6 +110,10 @@ export class GameService { }; } + async listFactions(game: GameEntity) { + return this.factionRepository.find({ game }); + } + async deleteGame(id) { // TODO: Delete factions from Faction table associated with the deleted game await this.gameRepository.delete({ id }); -- GitLab From c3a2e613304003b08b703a21e7905f10faa07a9b Mon Sep 17 00:00:00 2001 From: L4168 <L4168@student.jamk.fi> Date: Wed, 3 Jul 2019 12:48:05 +0300 Subject: [PATCH 10/10] added response codes --- src/faction/faction.service.ts | 2 ++ src/game/game.service.ts | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/src/faction/faction.service.ts b/src/faction/faction.service.ts index 4402878..76242df 100644 --- a/src/faction/faction.service.ts +++ b/src/faction/faction.service.ts @@ -94,6 +94,7 @@ export class FactionService { await this.game_PersonRepository.save(gamePerson); return { + code: 201, message: 'created new group', }; } @@ -113,6 +114,7 @@ export class FactionService { gamePerson.group = data.groupId; await this.game_PersonRepository.save(gamePerson); return { + code: 200, message: 'Joined group', }; } diff --git a/src/game/game.service.ts b/src/game/game.service.ts index 37f2e47..573bb22 100644 --- a/src/game/game.service.ts +++ b/src/game/game.service.ts @@ -48,6 +48,7 @@ export class GameService { }); await this.game_PersonRepository.insert(gamePerson); return { + code: 201, message: 'New game added', }; } @@ -106,6 +107,7 @@ export class GameService { // TO DO: ADD FLAGBOX LOCATION TO MAPDRAWING ENTITY return { + code: 200, message: 'Game updated', }; } @@ -118,6 +120,7 @@ export class GameService { // TODO: Delete factions from Faction table associated with the deleted game await this.gameRepository.delete({ id }); return { + code: 200, message: 'Game deleted', }; } @@ -168,5 +171,9 @@ export class GameService { await this.objectivePoint_HistoryRepository.insert(eventUpdate); // send flagbox event to flagbox subscribers this.notificationGateway.server.emit('flagbox', 'event update'); + return { + code: 201, + message: 'OK', + }; } } -- GitLab