From 52eb7b1afe87c4e96d6975a983dcc69a2989de23 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 11:10:05 +0100 Subject: [PATCH 01/50] Added a barebones runnercard controller ref #77 --- src/controllers/RunnerCardController.ts | 99 +++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/controllers/RunnerCardController.ts diff --git a/src/controllers/RunnerCardController.ts b/src/controllers/RunnerCardController.ts new file mode 100644 index 0000000..d01ab60 --- /dev/null +++ b/src/controllers/RunnerCardController.ts @@ -0,0 +1,99 @@ +import { JsonController } from 'routing-controllers'; +import { OpenAPI } from 'routing-controllers-openapi'; +import { getConnectionManager, Repository } from 'typeorm'; +import { RunnerCard } from '../models/entities/RunnerCard'; + +@JsonController('/cards') +@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) +export class RunnerCardController { + private cardRepository: Repository; + + /** + * Gets the repository of this controller's model/entity. + */ + constructor() { + this.cardRepository = getConnectionManager().get().getRepository(RunnerCard); + } + + // @Get() + // @Authorized("CARD:GET") + // @ResponseSchema(ResponseTrack, { isArray: true }) + // @OpenAPI({ description: 'Lists all tracks.' }) + // async getAll() { + // let responseTracks: ResponseTrack[] = new Array(); + // const tracks = await this.trackRepository.find(); + // tracks.forEach(track => { + // responseTracks.push(new ResponseTrack(track)); + // }); + // return responseTracks; + // } + + // @Get('/:id') + // @Authorized("CARD:GET") + // @ResponseSchema(ResponseTrack) + // @ResponseSchema(TrackNotFoundError, { statusCode: 404 }) + // @OnUndefined(TrackNotFoundError) + // @OpenAPI({ description: "Lists all information about the track whose id got provided." }) + // async getOne(@Param('id') id: number) { + // let track = await this.trackRepository.findOne({ id: id }); + // if (!track) { throw new TrackNotFoundError(); } + // return new ResponseTrack(track); + // } + + // @Post() + // @Authorized("CARD:CREATE") + // @ResponseSchema(ResponseTrack) + // @ResponseSchema(TrackLapTimeCantBeNegativeError, { statusCode: 406 }) + // @OpenAPI({ description: "Create a new track.
Please remember that the track\'s distance must be greater than 0." }) + // async post( + // @Body({ validate: true }) + // track: CreateTrack + // ) { + // return new ResponseTrack(await this.trackRepository.save(track.toTrack())); + // } + + // @Put('/:id') + // @Authorized("CARD:UPDATE") + // @ResponseSchema(ResponseTrack) + // @ResponseSchema(TrackNotFoundError, { statusCode: 404 }) + // @ResponseSchema(TrackIdsNotMatchingError, { statusCode: 406 }) + // @ResponseSchema(TrackLapTimeCantBeNegativeError, { statusCode: 406 }) + // @OpenAPI({ description: "Update the track whose id you provided.
Please remember that ids can't be changed." }) + // async put(@Param('id') id: number, @Body({ validate: true }) updateTrack: UpdateTrack) { + // let oldTrack = await this.trackRepository.findOne({ id: id }); + + // if (!oldTrack) { + // throw new TrackNotFoundError(); + // } + + // if (oldTrack.id != updateTrack.id) { + // throw new TrackIdsNotMatchingError(); + // } + // await this.trackRepository.save(await updateTrack.updateTrack(oldTrack)); + + // return new ResponseTrack(await this.trackRepository.findOne({ id: id })); + // } + + // @Delete('/:id') + // @Authorized("CARD:DELETE") + // @ResponseSchema(ResponseTrack) + // @ResponseSchema(ResponseEmpty, { statusCode: 204 }) + // @OnUndefined(204) + // @OpenAPI({ description: "Delete the track whose id you provided.
If no track with this id exists it will just return 204(no content)." }) + // async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { + // let track = await this.trackRepository.findOne({ id: id }); + // if (!track) { return null; } + + // const trackStations = (await this.trackRepository.findOne({ id: id }, { relations: ["stations"] })).stations; + // if (trackStations.length != 0 && !force) { + // throw new TrackHasScanStationsError(); + // } + // const scanController = new ScanStationController; + // for (let station of trackStations) { + // scanController.remove(station.id, force); + // } + + // await this.trackRepository.delete(track); + // return new ResponseTrack(track); + // } +} \ No newline at end of file From af3a9e5ce249950ebd9d54c9b5521c9bd0aaab8c Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 11:15:29 +0100 Subject: [PATCH 02/50] Added basic response calss for runner cards ref #77 --- src/models/entities/RunnerCard.ts | 3 +- src/models/responses/ResponseRunnerCard.ts | 47 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/models/responses/ResponseRunnerCard.ts diff --git a/src/models/entities/RunnerCard.ts b/src/models/entities/RunnerCard.ts index 4ea40e2..25ce61c 100644 --- a/src/models/entities/RunnerCard.ts +++ b/src/models/entities/RunnerCard.ts @@ -7,6 +7,7 @@ import { IsString } from "class-validator"; import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { ResponseRunnerCard } from '../responses/ResponseRunnerCard'; import { Runner } from "./Runner"; import { TrackScan } from "./TrackScan"; @@ -62,6 +63,6 @@ export class RunnerCard { * Turns this entity into it's response class. */ public toResponse() { - return new Error("NotImplemented"); + return new ResponseRunnerCard(this); } } diff --git a/src/models/responses/ResponseRunnerCard.ts b/src/models/responses/ResponseRunnerCard.ts new file mode 100644 index 0000000..94c7148 --- /dev/null +++ b/src/models/responses/ResponseRunnerCard.ts @@ -0,0 +1,47 @@ +import { IsBoolean, IsEAN, IsInt, IsNotEmpty, IsObject, IsString } from "class-validator"; +import { RunnerCard } from '../entities/RunnerCard'; +import { ResponseRunner } from './ResponseRunner'; + +/** + * Defines the runner card response. +*/ +export class ResponseRunnerCard { + /** + * The card's id. + */ + @IsInt() + id: number;; + + /** + * The card's associated runner. + * This is important to link scans to runners. + */ + @IsObject() + runner: ResponseRunner; + + /** + * The card's code. + */ + @IsEAN() + @IsString() + @IsNotEmpty() + code: string; + + /** + * Is the enabled valid (for fraud reasons). + * The determination of validity will work differently for every child class. + */ + @IsBoolean() + enabled: boolean = true; + + /** + * Creates a ResponseRunnerCard object from a runner card. + * @param card The card the response shall be build for. + */ + public constructor(card: RunnerCard) { + this.id = card.id; + this.runner = card.runner.toResponse() || null; + this.code = card.code; + this.enabled = card.enabled; + } +} From 98f7bf366f916d98cbce0b502923d1054044badf Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 11:21:52 +0100 Subject: [PATCH 03/50] Added card permission target ref #77 --- src/models/enums/PermissionTargets.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/models/enums/PermissionTargets.ts b/src/models/enums/PermissionTargets.ts index dae9192..551ea5c 100644 --- a/src/models/enums/PermissionTargets.ts +++ b/src/models/enums/PermissionTargets.ts @@ -12,5 +12,6 @@ export enum PermissionTarget { STATSCLIENT = 'STATSCLIENT', DONOR = 'DONOR', SCAN = 'SCAN', - STATION = 'STATION' + STATION = 'STATION', + CARD = 'CARD' } \ No newline at end of file From 4faeddc3f3086727432bfbf9bebf4f38d73b74aa Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 11:23:12 +0100 Subject: [PATCH 04/50] Added runner card get endpoints ref #77 --- src/controllers/RunnerCardController.ts | 52 +++++++++++++------------ src/errors/RunnerCardErrors.ts | 25 ++++++++++++ 2 files changed, 52 insertions(+), 25 deletions(-) create mode 100644 src/errors/RunnerCardErrors.ts diff --git a/src/controllers/RunnerCardController.ts b/src/controllers/RunnerCardController.ts index d01ab60..08942d8 100644 --- a/src/controllers/RunnerCardController.ts +++ b/src/controllers/RunnerCardController.ts @@ -1,7 +1,9 @@ -import { JsonController } from 'routing-controllers'; -import { OpenAPI } from 'routing-controllers-openapi'; +import { Authorized, Get, JsonController, OnUndefined, Param } from 'routing-controllers'; +import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; +import { RunnerCardNotFoundError } from '../errors/RunnerCardErrors'; import { RunnerCard } from '../models/entities/RunnerCard'; +import { ResponseRunnerCard } from '../models/responses/ResponseRunnerCard'; @JsonController('/cards') @OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @@ -15,30 +17,30 @@ export class RunnerCardController { this.cardRepository = getConnectionManager().get().getRepository(RunnerCard); } - // @Get() - // @Authorized("CARD:GET") - // @ResponseSchema(ResponseTrack, { isArray: true }) - // @OpenAPI({ description: 'Lists all tracks.' }) - // async getAll() { - // let responseTracks: ResponseTrack[] = new Array(); - // const tracks = await this.trackRepository.find(); - // tracks.forEach(track => { - // responseTracks.push(new ResponseTrack(track)); - // }); - // return responseTracks; - // } + @Get() + @Authorized("CARD:GET") + @ResponseSchema(ResponseRunnerCard, { isArray: true }) + @OpenAPI({ description: 'Lists all card.' }) + async getAll() { + let responseCards: ResponseRunnerCard[] = new Array(); + const cards = await this.cardRepository.find({ relations: ['runner'] }); + cards.forEach(card => { + responseCards.push(new ResponseRunnerCard(card)); + }); + return responseCards; + } - // @Get('/:id') - // @Authorized("CARD:GET") - // @ResponseSchema(ResponseTrack) - // @ResponseSchema(TrackNotFoundError, { statusCode: 404 }) - // @OnUndefined(TrackNotFoundError) - // @OpenAPI({ description: "Lists all information about the track whose id got provided." }) - // async getOne(@Param('id') id: number) { - // let track = await this.trackRepository.findOne({ id: id }); - // if (!track) { throw new TrackNotFoundError(); } - // return new ResponseTrack(track); - // } + @Get('/:id') + @Authorized("CARD:GET") + @ResponseSchema(ResponseRunnerCard) + @ResponseSchema(RunnerCardNotFoundError, { statusCode: 404 }) + @OnUndefined(RunnerCardNotFoundError) + @OpenAPI({ description: "Lists all information about the card whose id got provided." }) + async getOne(@Param('id') id: number) { + let card = await this.cardRepository.findOne({ id: id }, { relations: ['runner'] }); + if (!card) { throw new RunnerCardNotFoundError(); } + return card.toResponse(); + } // @Post() // @Authorized("CARD:CREATE") diff --git a/src/errors/RunnerCardErrors.ts b/src/errors/RunnerCardErrors.ts new file mode 100644 index 0000000..bb0c6f3 --- /dev/null +++ b/src/errors/RunnerCardErrors.ts @@ -0,0 +1,25 @@ +import { IsString } from 'class-validator'; +import { NotAcceptableError, NotFoundError } from 'routing-controllers'; + +/** + * Error to throw when a card couldn't be found. + */ +export class RunnerCardNotFoundError extends NotFoundError { + @IsString() + name = "RunnerCardNotFoundError" + + @IsString() + message = "Card not found!" +} + +/** + * Error to throw when two cards' ids don't match. + * Usually occurs when a user tries to change a card's id. + */ +export class RunnerCardIdsNotMatchingError extends NotAcceptableError { + @IsString() + name = "RunnerCardIdsNotMatchingError" + + @IsString() + message = "The ids don't match! \n And if you wanted to change a cards's id: This isn't allowed" +} \ No newline at end of file From a5bfe4e3d5072718f29e2d4ca324d63bd7393291 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 11:28:59 +0100 Subject: [PATCH 05/50] Added card deletion + errors ref #77 --- src/controllers/RunnerCardController.ts | 47 +++++++++++++------------ src/errors/RunnerCardErrors.ts | 13 ++++++- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/controllers/RunnerCardController.ts b/src/controllers/RunnerCardController.ts index 08942d8..a11b626 100644 --- a/src/controllers/RunnerCardController.ts +++ b/src/controllers/RunnerCardController.ts @@ -1,9 +1,11 @@ -import { Authorized, Get, JsonController, OnUndefined, Param } from 'routing-controllers'; +import { Authorized, Delete, Get, JsonController, OnUndefined, Param, QueryParam } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; -import { RunnerCardNotFoundError } from '../errors/RunnerCardErrors'; +import { RunnerCardHasScansError, RunnerCardNotFoundError } from '../errors/RunnerCardErrors'; import { RunnerCard } from '../models/entities/RunnerCard'; +import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseRunnerCard } from '../models/responses/ResponseRunnerCard'; +import { ScanController } from './ScanController'; @JsonController('/cards') @OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @@ -76,26 +78,27 @@ export class RunnerCardController { // return new ResponseTrack(await this.trackRepository.findOne({ id: id })); // } - // @Delete('/:id') - // @Authorized("CARD:DELETE") - // @ResponseSchema(ResponseTrack) - // @ResponseSchema(ResponseEmpty, { statusCode: 204 }) - // @OnUndefined(204) - // @OpenAPI({ description: "Delete the track whose id you provided.
If no track with this id exists it will just return 204(no content)." }) - // async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { - // let track = await this.trackRepository.findOne({ id: id }); - // if (!track) { return null; } + @Delete('/:id') + @Authorized("CARD:DELETE") + @ResponseSchema(ResponseRunnerCard) + @ResponseSchema(ResponseEmpty, { statusCode: 204 }) + @ResponseSchema(RunnerCardHasScansError, { statusCode: 406 }) + @OnUndefined(204) + @OpenAPI({ description: "Delete the card whose id you provided.
If no card with this id exists it will just return 204(no content).
If the card still has scans associated you have to provide the force=true query param (warning: this deletes all scans associated with by this card - please disable it instead or just remove the runner association)." }) + async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { + let card = await this.cardRepository.findOne({ id: id }); + if (!card) { return null; } - // const trackStations = (await this.trackRepository.findOne({ id: id }, { relations: ["stations"] })).stations; - // if (trackStations.length != 0 && !force) { - // throw new TrackHasScanStationsError(); - // } - // const scanController = new ScanStationController; - // for (let station of trackStations) { - // scanController.remove(station.id, force); - // } + const cardScans = (await this.cardRepository.findOne({ id: id }, { relations: ["scans"] })).scans; + if (cardScans.length != 0 && !force) { + throw new RunnerCardHasScansError(); + } + const scanController = new ScanController; + for (let scan of cardScans) { + scanController.remove(scan.id, force); + } - // await this.trackRepository.delete(track); - // return new ResponseTrack(track); - // } + await this.cardRepository.delete(card); + return card.toResponse(); + } } \ No newline at end of file diff --git a/src/errors/RunnerCardErrors.ts b/src/errors/RunnerCardErrors.ts index bb0c6f3..08edb44 100644 --- a/src/errors/RunnerCardErrors.ts +++ b/src/errors/RunnerCardErrors.ts @@ -22,4 +22,15 @@ export class RunnerCardIdsNotMatchingError extends NotAcceptableError { @IsString() message = "The ids don't match! \n And if you wanted to change a cards's id: This isn't allowed" -} \ No newline at end of file +} + +/** + * Error to throw when a station still has scans associated. + */ +export class RunnerCardHasScansError extends NotAcceptableError { + @IsString() + name = "RunnerCardHasScansError" + + @IsString() + message = "This card still has scans associated with it. \n If you want to delete this card with all it's scans add `?force` to your query. \n Otherwise please consider just diableing it." +} From 36ecae7e6e1eda637bafbc260d3dfa5815a472ff Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 11:48:13 +0100 Subject: [PATCH 06/50] Added card creation #17 --- src/controllers/RunnerCardController.ts | 25 ++++++------ src/models/actions/CreateRunnerCard.ts | 45 ++++++++++++++++++++++ src/models/entities/RunnerCard.ts | 26 ++++++------- src/models/responses/ResponseRunnerCard.ts | 5 ++- 4 files changed, 72 insertions(+), 29 deletions(-) create mode 100644 src/models/actions/CreateRunnerCard.ts diff --git a/src/controllers/RunnerCardController.ts b/src/controllers/RunnerCardController.ts index a11b626..a1eee62 100644 --- a/src/controllers/RunnerCardController.ts +++ b/src/controllers/RunnerCardController.ts @@ -1,7 +1,9 @@ -import { Authorized, Delete, Get, JsonController, OnUndefined, Param, QueryParam } from 'routing-controllers'; +import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, QueryParam } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { RunnerCardHasScansError, RunnerCardNotFoundError } from '../errors/RunnerCardErrors'; +import { RunnerNotFoundError } from '../errors/RunnerErrors'; +import { CreateRunnerCard } from '../models/actions/CreateRunnerCard'; import { RunnerCard } from '../models/entities/RunnerCard'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseRunnerCard } from '../models/responses/ResponseRunnerCard'; @@ -44,17 +46,16 @@ export class RunnerCardController { return card.toResponse(); } - // @Post() - // @Authorized("CARD:CREATE") - // @ResponseSchema(ResponseTrack) - // @ResponseSchema(TrackLapTimeCantBeNegativeError, { statusCode: 406 }) - // @OpenAPI({ description: "Create a new track.
Please remember that the track\'s distance must be greater than 0." }) - // async post( - // @Body({ validate: true }) - // track: CreateTrack - // ) { - // return new ResponseTrack(await this.trackRepository.save(track.toTrack())); - // } + @Post() + @Authorized("CARD:CREATE") + @ResponseSchema(ResponseRunnerCard) + @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) + @OpenAPI({ description: "Create a new card.
You can provide a associated runner by id but you don't have to." }) + async post(@Body({ validate: true }) createCard: CreateRunnerCard) { + let card = await createCard.toEntity(); + card = await this.cardRepository.save(card); + return (await this.cardRepository.findOne({ id: card.id }, { relations: ['runner'] })).toResponse(); + } // @Put('/:id') // @Authorized("CARD:UPDATE") diff --git a/src/models/actions/CreateRunnerCard.ts b/src/models/actions/CreateRunnerCard.ts new file mode 100644 index 0000000..2baf1e9 --- /dev/null +++ b/src/models/actions/CreateRunnerCard.ts @@ -0,0 +1,45 @@ +import { IsBoolean, IsInt, IsOptional } from 'class-validator'; +import { getConnection } from 'typeorm'; +import { RunnerNotFoundError } from '../../errors/RunnerErrors'; +import { Runner } from '../entities/Runner'; +import { RunnerCard } from '../entities/RunnerCard'; + +/** + * This classed is used to create a new RunnerCard entity from a json body (post request). + */ +export class CreateRunnerCard { + /** + * The card's associated runner. + */ + @IsInt() + @IsOptional() + runner?: number; + + /** + * Is the new card enabled (for fraud reasons)? + * Default: true + */ + @IsBoolean() + enabled: boolean = true; + + /** + * Creates a new RunnerCard entity from this. + */ + public async toEntity(): Promise { + let newCard: RunnerCard = new RunnerCard(); + + newCard.enabled = this.enabled; + newCard.runner = await this.getRunner(); + + return newCard; + } + + public async getRunner(): Promise { + if (!this.runner) { return null; } + const runner = await getConnection().getRepository(Runner).findOne({ id: this.runner }); + if (!runner) { + throw new RunnerNotFoundError(); + } + return runner; + } +} \ No newline at end of file diff --git a/src/models/entities/RunnerCard.ts b/src/models/entities/RunnerCard.ts index 25ce61c..0517008 100644 --- a/src/models/entities/RunnerCard.ts +++ b/src/models/entities/RunnerCard.ts @@ -1,10 +1,9 @@ import { IsBoolean, - IsEAN, + IsInt, - IsNotEmpty, - IsOptional, - IsString + + IsOptional } from "class-validator"; import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { ResponseRunnerCard } from '../responses/ResponseRunnerCard'; @@ -33,17 +32,6 @@ export class RunnerCard { @ManyToOne(() => Runner, runner => runner.cards, { nullable: true }) runner: Runner; - /** - * The card's code. - * This has to be able to being converted to something barcode compatible. - * Will get automaticlly generated (not implemented yet). - */ - @Column() - @IsEAN() - @IsString() - @IsNotEmpty() - code: string; - /** * Is the card enabled (for fraud reasons)? * Default: true @@ -59,6 +47,14 @@ export class RunnerCard { @OneToMany(() => TrackScan, scan => scan.track, { nullable: true }) scans: TrackScan[]; + /** + * Generates a ean-13 compliant string for barcode generation. + */ + public get code(): string { + //TODO: Implement the real deal + return '0000000000000' + } + /** * Turns this entity into it's response class. */ diff --git a/src/models/responses/ResponseRunnerCard.ts b/src/models/responses/ResponseRunnerCard.ts index 94c7148..97b9435 100644 --- a/src/models/responses/ResponseRunnerCard.ts +++ b/src/models/responses/ResponseRunnerCard.ts @@ -17,7 +17,7 @@ export class ResponseRunnerCard { * This is important to link scans to runners. */ @IsObject() - runner: ResponseRunner; + runner: ResponseRunner | null; /** * The card's code. @@ -40,7 +40,8 @@ export class ResponseRunnerCard { */ public constructor(card: RunnerCard) { this.id = card.id; - this.runner = card.runner.toResponse() || null; + if (!card.runner) { this.runner = null } + else { this.runner = card.runner.toResponse(); } this.code = card.code; this.enabled = card.enabled; } From 32fda46f0a7e4b63b1119754e9c0ba5327511ceb Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 11:55:32 +0100 Subject: [PATCH 07/50] Implemented runner updateing ref #77 --- src/controllers/RunnerCardController.ts | 41 ++++++++++---------- src/models/actions/UpdateRunnerCard.ts | 51 +++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 20 deletions(-) create mode 100644 src/models/actions/UpdateRunnerCard.ts diff --git a/src/controllers/RunnerCardController.ts b/src/controllers/RunnerCardController.ts index a1eee62..2263f07 100644 --- a/src/controllers/RunnerCardController.ts +++ b/src/controllers/RunnerCardController.ts @@ -1,9 +1,10 @@ -import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, QueryParam } from 'routing-controllers'; +import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; -import { RunnerCardHasScansError, RunnerCardNotFoundError } from '../errors/RunnerCardErrors'; +import { RunnerCardHasScansError, RunnerCardIdsNotMatchingError, RunnerCardNotFoundError } from '../errors/RunnerCardErrors'; import { RunnerNotFoundError } from '../errors/RunnerErrors'; import { CreateRunnerCard } from '../models/actions/CreateRunnerCard'; +import { UpdateRunnerCard } from '../models/actions/UpdateRunnerCard'; import { RunnerCard } from '../models/entities/RunnerCard'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseRunnerCard } from '../models/responses/ResponseRunnerCard'; @@ -57,27 +58,27 @@ export class RunnerCardController { return (await this.cardRepository.findOne({ id: card.id }, { relations: ['runner'] })).toResponse(); } - // @Put('/:id') - // @Authorized("CARD:UPDATE") - // @ResponseSchema(ResponseTrack) - // @ResponseSchema(TrackNotFoundError, { statusCode: 404 }) - // @ResponseSchema(TrackIdsNotMatchingError, { statusCode: 406 }) - // @ResponseSchema(TrackLapTimeCantBeNegativeError, { statusCode: 406 }) - // @OpenAPI({ description: "Update the track whose id you provided.
Please remember that ids can't be changed." }) - // async put(@Param('id') id: number, @Body({ validate: true }) updateTrack: UpdateTrack) { - // let oldTrack = await this.trackRepository.findOne({ id: id }); + @Put('/:id') + @Authorized("CARD:UPDATE") + @ResponseSchema(ResponseRunnerCard) + @ResponseSchema(RunnerCardNotFoundError, { statusCode: 404 }) + @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) + @ResponseSchema(RunnerCardIdsNotMatchingError, { statusCode: 406 }) + @OpenAPI({ description: "Update the card whose id you provided.
Scans created via this card will still be associated with the old runner.
Please remember that ids can't be changed." }) + async put(@Param('id') id: number, @Body({ validate: true }) card: UpdateRunnerCard) { + let oldCard = await this.cardRepository.findOne({ id: id }); - // if (!oldTrack) { - // throw new TrackNotFoundError(); - // } + if (!oldCard) { + throw new RunnerCardNotFoundError(); + } - // if (oldTrack.id != updateTrack.id) { - // throw new TrackIdsNotMatchingError(); - // } - // await this.trackRepository.save(await updateTrack.updateTrack(oldTrack)); + if (oldCard.id != card.id) { + throw new RunnerCardIdsNotMatchingError(); + } - // return new ResponseTrack(await this.trackRepository.findOne({ id: id })); - // } + await this.cardRepository.save(await card.update(oldCard)); + return (await this.cardRepository.findOne({ id: id }, { relations: ['runner'] })).toResponse(); + } @Delete('/:id') @Authorized("CARD:DELETE") diff --git a/src/models/actions/UpdateRunnerCard.ts b/src/models/actions/UpdateRunnerCard.ts new file mode 100644 index 0000000..2ee34ab --- /dev/null +++ b/src/models/actions/UpdateRunnerCard.ts @@ -0,0 +1,51 @@ +import { IsBoolean, IsInt, IsOptional, IsPositive } from 'class-validator'; +import { getConnection } from 'typeorm'; +import { RunnerNotFoundError } from '../../errors/RunnerErrors'; +import { Runner } from '../entities/Runner'; +import { RunnerCard } from '../entities/RunnerCard'; + +/** + * This class is used to update a RunnerCard entity (via put request). + */ +export class UpdateRunnerCard { + /** + * The updated card's id. + * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to). + */ + @IsInt() + @IsPositive() + id?: number; + + /** + * The updated card's associated runner. + */ + @IsInt() + @IsOptional() + runner?: number; + + /** + * Is the updated card enabled (for fraud reasons)? + * Default: true + */ + @IsBoolean() + enabled: boolean = true; + + /** + * Creates a new RunnerCard entity from this. + */ + public async update(card: RunnerCard): Promise { + card.enabled = this.enabled; + card.runner = await this.getRunner(); + + return card; + } + + public async getRunner(): Promise { + if (!this.runner) { return null; } + const runner = await getConnection().getRepository(Runner).findOne({ id: this.runner }); + if (!runner) { + throw new RunnerNotFoundError(); + } + return runner; + } +} \ No newline at end of file From df39166279723f13d38288dd09f3120c26a628f1 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 11:59:20 +0100 Subject: [PATCH 08/50] Added card get tests ref #77 --- src/tests/cards/cards_get.spec.ts | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/tests/cards/cards_get.spec.ts diff --git a/src/tests/cards/cards_get.spec.ts b/src/tests/cards/cards_get.spec.ts new file mode 100644 index 0000000..6ca41ec --- /dev/null +++ b/src/tests/cards/cards_get.spec.ts @@ -0,0 +1,46 @@ +import axios from 'axios'; +import { config } from '../../config'; +const base = "http://localhost:" + config.internal_port + +let access_token; +let axios_config; + +beforeAll(async () => { + const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); + access_token = res.data["access_token"]; + axios_config = { + headers: { "authorization": "Bearer " + access_token }, + validateStatus: undefined + }; +}); + +describe('GET /api/cards sucessfully', () => { + it('basic get should return 200', async () => { + const res = await axios.get(base + '/api/cards', axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('GET /api/cards illegally', () => { + it('get for non-existant track should return 404', async () => { + const res = await axios.get(base + '/api/cards/-1', axios_config); + expect(res.status).toEqual(404); + expect(res.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('adding + getting cards (no runner)', () => { + let added_card; + it('correct distance and runner input should return 200', async () => { + const res = await axios.post(base + '/api/cards', null, axios_config); + added_card = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('check if scans was added (no parameter validation)', async () => { + const res = await axios.get(base + '/api/cards/' + added_card.id, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + }); +}); \ No newline at end of file From 860680d001191ac8ab4f5190618b4b0937915992 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 12:24:05 +0100 Subject: [PATCH 09/50] Implmented the EAN generation ref #77 --- src/errors/RunnerCardErrors.ts | 14 ++++++++++++- src/models/entities/RunnerCard.ts | 24 ++++++++++++++++++++-- src/models/responses/ResponseRunnerCard.ts | 7 ++++++- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/errors/RunnerCardErrors.ts b/src/errors/RunnerCardErrors.ts index 08edb44..63c3485 100644 --- a/src/errors/RunnerCardErrors.ts +++ b/src/errors/RunnerCardErrors.ts @@ -25,7 +25,7 @@ export class RunnerCardIdsNotMatchingError extends NotAcceptableError { } /** - * Error to throw when a station still has scans associated. + * Error to throw when a card still has scans associated. */ export class RunnerCardHasScansError extends NotAcceptableError { @IsString() @@ -34,3 +34,15 @@ export class RunnerCardHasScansError extends NotAcceptableError { @IsString() message = "This card still has scans associated with it. \n If you want to delete this card with all it's scans add `?force` to your query. \n Otherwise please consider just diableing it." } + +/** + * Error to throw when a card's id is too big to generate a ean-13 barcode for it. + * This error should never reach a enduser. + */ +export class RunnerCardIdOutOfRangeError extends Error { + @IsString() + name = "RunnerCardIdOutOfRangeError" + + @IsString() + message = "The card's id is too big to fit into a ean-13 barcode. \n This has a very low probability of happening but means that you might want to switch your barcode format for something that can accept numbers over 9999999999." +} \ No newline at end of file diff --git a/src/models/entities/RunnerCard.ts b/src/models/entities/RunnerCard.ts index 0517008..a7bccc4 100644 --- a/src/models/entities/RunnerCard.ts +++ b/src/models/entities/RunnerCard.ts @@ -6,6 +6,7 @@ import { IsOptional } from "class-validator"; import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { RunnerCardIdOutOfRangeError } from '../../errors/RunnerCardErrors'; import { ResponseRunnerCard } from '../responses/ResponseRunnerCard'; import { Runner } from "./Runner"; import { TrackScan } from "./TrackScan"; @@ -51,8 +52,27 @@ export class RunnerCard { * Generates a ean-13 compliant string for barcode generation. */ public get code(): string { - //TODO: Implement the real deal - return '0000000000000' + const multiply = [1, 3]; + let total = 0; + this.paddedId.split('').forEach((letter, index) => { + total += parseInt(letter, 10) * multiply[index % 2]; + }); + const checkSum = (Math.ceil(total / 10) * 10) - total; + return this.paddedId + checkSum.toString(); + } + + /** + * Returns this card's id as a string padded to the length of 12 characters with leading zeros. + */ + private get paddedId(): string { + let id: string = this.id.toString(); + + if (id.length > 12) { + throw new RunnerCardIdOutOfRangeError(); + } + while (id.length < 12) { id = '0' + id; } + + return id; } /** diff --git a/src/models/responses/ResponseRunnerCard.ts b/src/models/responses/ResponseRunnerCard.ts index 97b9435..f895a9c 100644 --- a/src/models/responses/ResponseRunnerCard.ts +++ b/src/models/responses/ResponseRunnerCard.ts @@ -42,7 +42,12 @@ export class ResponseRunnerCard { this.id = card.id; if (!card.runner) { this.runner = null } else { this.runner = card.runner.toResponse(); } - this.code = card.code; + try { + this.code = card.code; + } catch (error) { + this.code = "0000000000000" + } + this.enabled = card.enabled; } } From 8463bee25312b4ddf5badb2af26716c2bcf9d9dc Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 12:32:47 +0100 Subject: [PATCH 10/50] added card add tests ref #77 --- src/tests/cards/cards_add.spec.ts | 144 ++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 src/tests/cards/cards_add.spec.ts diff --git a/src/tests/cards/cards_add.spec.ts b/src/tests/cards/cards_add.spec.ts new file mode 100644 index 0000000..c89e55b --- /dev/null +++ b/src/tests/cards/cards_add.spec.ts @@ -0,0 +1,144 @@ +import axios from 'axios'; +import { config } from '../../config'; +const base = "http://localhost:" + config.internal_port + +let access_token; +let axios_config; + +beforeAll(async () => { + const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); + access_token = res.data["access_token"]; + axios_config = { + headers: { "authorization": "Bearer " + access_token }, + validateStatus: undefined + }; +}); + + +describe('POST /api/cards illegally', () => { + it('non-existant runner input should return 404', async () => { + const res = await axios.post(base + '/api/cards', { + "runner": 999999999999999999999999 + }, axios_config); + expect(res.status).toEqual(404); + expect(res.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('POST /api/cards successfully (without runner)', () => { + it('creating a card with the minimum amount of parameters should return 200', async () => { + const res = await axios.post(base + '/api/cards', null, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + delete res.data.id; + delete res.data.code; + expect(res.data).toEqual({ + "runner": null, + "enabled": true + }); + }); + it('creating a disabled card should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "enabled": false + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + delete res.data.id; + delete res.data.code; + expect(res.data).toEqual({ + "runner": null, + "enabled": false + }); + }); + it('creating a enabled card should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "enabled": true + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + delete res.data.id; + delete res.data.code; + expect(res.data).toEqual({ + "runner": null, + "enabled": true + }); + }); +}); +// --------------- +describe('POST /api/cards successfully (with runner)', () => { + let added_org; + let added_runner; + it('creating a new org with just a name should return 200', async () => { + const res1 = await axios.post(base + '/api/organisations', { + "name": "test123" + }, axios_config); + added_org = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/runners', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + delete res2.data.group; + added_runner = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a card with the minimum amount of parameters should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "runner": added_runner.id + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + delete res.data.id; + delete res.data.code; + expect(res.data).toEqual({ + "runner": added_runner, + "enabled": true + }); + }); + it('creating a card with runner (no optional params) should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "runner": added_runner.id + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + delete res.data.id; + delete res.data.code; + expect(res.data).toEqual({ + "runner": added_runner, + "enabled": true + }); + }); + it('creating a enabled card with runner should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "runner": added_runner.id, + "enabled": true + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + delete res.data.id; + delete res.data.code; + expect(res.data).toEqual({ + "runner": added_runner, + "enabled": true + }); + }); + it('creating a disabled card with runner should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "runner": added_runner.id, + "enabled": false + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + delete res.data.id; + delete res.data.code; + expect(res.data).toEqual({ + "runner": added_runner, + "enabled": false + }); + }); +}); \ No newline at end of file From ebf66821a2a0956905a2e7d3e7bbdd0cd2296152 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 12:41:59 +0100 Subject: [PATCH 11/50] Added card delete tests ref #77 --- src/tests/cards/cards_delete.spec.ts | 45 ++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/tests/cards/cards_delete.spec.ts diff --git a/src/tests/cards/cards_delete.spec.ts b/src/tests/cards/cards_delete.spec.ts new file mode 100644 index 0000000..1e657c8 --- /dev/null +++ b/src/tests/cards/cards_delete.spec.ts @@ -0,0 +1,45 @@ +import axios from 'axios'; +import { config } from '../../config'; +const base = "http://localhost:" + config.internal_port + +let access_token; +let axios_config; + +beforeAll(async () => { + const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); + access_token = res.data["access_token"]; + axios_config = { + headers: { "authorization": "Bearer " + access_token }, + validateStatus: undefined + }; +}); + +// --------------- + +describe('DELETE card', () => { + let added_card; + it('creating card without runner should return 200', async () => { + const res = await axios.post(base + '/api/cards', null, axios_config); + added_card = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('delete card', async () => { + const res2 = await axios.delete(base + '/api/cards/' + added_card.id, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + expect(res2.data).toEqual(added_card); + }); + it('check if card really was deleted', async () => { + const res3 = await axios.get(base + '/api/cards/' + added_card.id, axios_config); + expect(res3.status).toEqual(404); + expect(res3.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('DELETE card (non-existant)', () => { + it('delete', async () => { + const res2 = await axios.delete(base + '/api/cards/0', axios_config); + expect(res2.status).toEqual(204); + }); +}); From 35ea3154d132d095fc29d1d302964d680d082b4e Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 12:42:41 +0100 Subject: [PATCH 12/50] Added card update tests ref #77 --- src/tests/cards/cards_update.spec.ts | 163 +++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 src/tests/cards/cards_update.spec.ts diff --git a/src/tests/cards/cards_update.spec.ts b/src/tests/cards/cards_update.spec.ts new file mode 100644 index 0000000..4ef31ee --- /dev/null +++ b/src/tests/cards/cards_update.spec.ts @@ -0,0 +1,163 @@ +import axios from 'axios'; +import { config } from '../../config'; +const base = "http://localhost:" + config.internal_port + +let access_token; +let axios_config; + +beforeAll(async () => { + const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); + access_token = res.data["access_token"]; + axios_config = { + headers: { "authorization": "Bearer " + access_token }, + validateStatus: undefined + }; +}); + +describe('adding + updating illegally', () => { + let added_card; + it('creating card without runner should return 200', async () => { + const res = await axios.post(base + '/api/cards', null, axios_config); + added_card = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('updating empty should return 400', async () => { + const res2 = await axios.put(base + '/api/cards/' + added_card.id, null, axios_config); + expect(res2.status).toEqual(400); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('updating with wrong id should return 406', async () => { + const res2 = await axios.put(base + '/api/cards/' + added_card.id, { + "id": added_card.id + 1 + }, axios_config); + expect(res2.status).toEqual(406); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('update with invalid runner id should return 404', async () => { + const res2 = await axios.put(base + '/api/cards/' + added_card.id, { + "id": added_card.id, + "runner": 9999999999999999999999999 + }, axios_config); + expect(res2.status).toEqual(404); + expect(res2.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('adding + updating card.runner successfully', () => { + let added_org; + let added_runner; + let added_runner2; + let added_card; + it('creating a new org with just a name should return 200', async () => { + const res1 = await axios.post(base + '/api/organisations', { + "name": "test123" + }, axios_config); + added_org = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/runners', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + delete res2.data.group; + added_runner = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/runners', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + delete res2.data.group; + added_runner2 = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating card without runner should return 200', async () => { + const res = await axios.post(base + '/api/cards', null, axios_config); + added_card = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('valid runner update (add runner) should return 200', async () => { + const res2 = await axios.put(base + '/api/cards/' + added_card.id, { + "id": added_card.id, + "runner": added_runner.id + }, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json"); + expect(res2.data).toEqual({ + "id": added_card.id, + "runner": added_runner, + "enabled": true, + "code": added_card.code + }); + }); + it('valid runner update (change runner) should return 200', async () => { + const res2 = await axios.put(base + '/api/cards/' + added_card.id, { + "id": added_card.id, + "runner": added_runner2.id + }, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json"); + expect(res2.data).toEqual({ + "id": added_card.id, + "runner": added_runner2, + "enabled": true, + "code": added_card.code + }); + }); +}); +// --------------- +describe('adding + updating other values successfully', () => { + let added_card; + it('creating card without runner should return 200', async () => { + const res = await axios.post(base + '/api/cards', null, axios_config); + added_card = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('valid update changeing nothing should return 200', async () => { + const res2 = await axios.put(base + '/api/cards/' + added_card.id, { + "id": added_card.id + }, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json"); + expect(res2.data).toEqual(added_card); + }); + it('valid disable update should return 200', async () => { + const res2 = await axios.put(base + '/api/cards/' + added_card.id, { + "id": added_card.id, + "enabled": false + }, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json"); + expect(res2.data).toEqual({ + "id": added_card.id, + "runner": null, + "enabled": false, + "code": added_card.code + }); + }); + it('valid enable update should return 200', async () => { + const res2 = await axios.put(base + '/api/cards/' + added_card.id, { + "id": added_card.id, + "enabled": true + }, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json"); + expect(res2.data).toEqual({ + "id": added_card.id, + "runner": null, + "enabled": true, + "code": added_card.code + }); + }); +}); + From e1ce052d3caa051b88c0e9525977b0610605b078 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 14:23:47 +0100 Subject: [PATCH 13/50] Fixed runner total distance not getting resolved ref #78 --- src/controllers/ScanController.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/controllers/ScanController.ts b/src/controllers/ScanController.ts index ed7df91..b7aa72f 100644 --- a/src/controllers/ScanController.ts +++ b/src/controllers/ScanController.ts @@ -59,7 +59,7 @@ export class ScanController { async post(@Body({ validate: true }) createScan: CreateScan) { let scan = await createScan.toScan(); scan = await this.scanRepository.save(scan); - return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner'] })).toResponse(); + return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'runner.scans', 'runner.scans.track'] })).toResponse(); } @Post("/trackscans") @@ -68,7 +68,9 @@ export class ScanController { @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @OpenAPI({ description: 'Create a new track scan.
This is just a alias for posting /scans', security: [{ "ScanApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) async postTrackScans(@Body({ validate: true }) createScan: CreateTrackScan) { - return this.post(createScan); + let scan = await createScan.toScan(); + scan = await this.scanRepository.save(scan); + return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track'] })).toResponse(); } @Put('/:id') From 3ceb5a0c0fc49e28ac26e1bccaa1b5ee044e616c Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 14:24:16 +0100 Subject: [PATCH 14/50] Removed total distance from tests ref #78 --- src/tests/scans/scans_add.spec.ts | 8 ++++++++ src/tests/scans/scans_delete.spec.ts | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/tests/scans/scans_add.spec.ts b/src/tests/scans/scans_add.spec.ts index c08ee01..580ecd8 100644 --- a/src/tests/scans/scans_add.spec.ts +++ b/src/tests/scans/scans_add.spec.ts @@ -84,6 +84,7 @@ describe('POST /api/scans successfully', () => { "group": added_org.id }, axios_config); delete res2.data.group; + delete res2.data.distance; added_runner = res2.data; expect(res2.status).toEqual(200); expect(res2.headers['content-type']).toContain("application/json") @@ -96,6 +97,7 @@ describe('POST /api/scans successfully', () => { expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json"); delete res.data.id; + delete res.data.runner.distance; expect(res.data).toEqual({ "runner": added_runner, "distance": 200, @@ -111,6 +113,7 @@ describe('POST /api/scans successfully', () => { expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json"); delete res.data.id; + delete res.data.runner.distance; expect(res.data).toEqual({ "runner": added_runner, "distance": 200, @@ -126,6 +129,7 @@ describe('POST /api/scans successfully', () => { expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json"); delete res.data.id; + delete res.data.runner.distance; expect(res.data).toEqual({ "runner": added_runner, "distance": 200, @@ -154,6 +158,7 @@ describe('POST /api/scans successfully via scan station', () => { "group": added_org.id }, axios_config); delete res2.data.group; + delete res2.data.distance; added_runner = res2.data; expect(res2.status).toEqual(200); expect(res2.headers['content-type']).toContain("application/json") @@ -186,6 +191,7 @@ describe('POST /api/scans successfully via scan station', () => { expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json"); delete res.data.id; + delete res.data.runner.distance; expect(res.data).toEqual({ "runner": added_runner, "distance": 200, @@ -204,6 +210,7 @@ describe('POST /api/scans successfully via scan station', () => { expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json"); delete res.data.id; + delete res.data.runner.distance; expect(res.data).toEqual({ "runner": added_runner, "distance": 200, @@ -222,6 +229,7 @@ describe('POST /api/scans successfully via scan station', () => { expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json"); delete res.data.id; + delete res.data.runner.distance; expect(res.data).toEqual({ "runner": added_runner, "distance": 200, diff --git a/src/tests/scans/scans_delete.spec.ts b/src/tests/scans/scans_delete.spec.ts index e88e812..0ff0b72 100644 --- a/src/tests/scans/scans_delete.spec.ts +++ b/src/tests/scans/scans_delete.spec.ts @@ -44,6 +44,7 @@ describe('DELETE scan', () => { "distance": 1000 }, axios_config); added_scan = res.data; + delete res.data.runner.distance; expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json") }); @@ -51,6 +52,7 @@ describe('DELETE scan', () => { const res2 = await axios.delete(base + '/api/scans/' + added_scan.id, axios_config); expect(res2.status).toEqual(200); expect(res2.headers['content-type']).toContain("application/json") + delete res2.data.runner.distance; expect(res2.data).toEqual(added_scan); }); it('check if scan really was deleted', async () => { From 188f26ad650a0099fba2b2b683e5dc5c9ea4613e Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 14:52:08 +0100 Subject: [PATCH 15/50] Fixed manual trackscan creation ref #78 --- src/controllers/ScanController.ts | 17 +++++++++-------- src/models/actions/CreateTrackScan.ts | 19 ++++++------------- src/models/responses/ResponseTrackScan.ts | 13 +++++++------ 3 files changed, 22 insertions(+), 27 deletions(-) diff --git a/src/controllers/ScanController.ts b/src/controllers/ScanController.ts index b7aa72f..09833dc 100644 --- a/src/controllers/ScanController.ts +++ b/src/controllers/ScanController.ts @@ -1,6 +1,6 @@ import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam, UseBefore } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; -import { getConnectionManager, Repository } from 'typeorm'; +import { getConnection, getConnectionManager, Repository } from 'typeorm'; import { RunnerNotFoundError } from '../errors/RunnerErrors'; import { ScanIdsNotMatchingError, ScanNotFoundError } from '../errors/ScanErrors'; import ScanAuth from '../middlewares/ScanAuth'; @@ -8,6 +8,7 @@ import { CreateScan } from '../models/actions/CreateScan'; import { CreateTrackScan } from '../models/actions/CreateTrackScan'; import { UpdateScan } from '../models/actions/UpdateScan'; import { Scan } from '../models/entities/Scan'; +import { TrackScan } from '../models/entities/TrackScan'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseScan } from '../models/responses/ResponseScan'; import { ResponseTrackScan } from '../models/responses/ResponseTrackScan'; @@ -31,7 +32,7 @@ export class ScanController { @OpenAPI({ description: 'Lists all scans (normal or track) from all runners.
This includes the scan\'s runner\'s distance ran.' }) async getAll() { let responseScans: ResponseScan[] = new Array(); - const scans = await this.scanRepository.find({ relations: ['runner', 'runner.scans', 'runner.scans.track'] }); + const scans = await this.scanRepository.find({ relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] }); scans.forEach(scan => { responseScans.push(scan.toResponse()); }); @@ -46,7 +47,7 @@ export class ScanController { @OnUndefined(ScanNotFoundError) @OpenAPI({ description: 'Lists all information about the scan whose id got provided. This includes the scan\'s runner\'s distance ran.' }) async getOne(@Param('id') id: number) { - let scan = await this.scanRepository.findOne({ id: id }, { relations: ['runner', 'runner.scans', 'runner.scans.track'] }) + let scan = await this.scanRepository.findOne({ id: id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] }) if (!scan) { throw new ScanNotFoundError(); } return scan.toResponse(); } @@ -59,7 +60,7 @@ export class ScanController { async post(@Body({ validate: true }) createScan: CreateScan) { let scan = await createScan.toScan(); scan = await this.scanRepository.save(scan); - return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'runner.scans', 'runner.scans.track'] })).toResponse(); + return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse(); } @Post("/trackscans") @@ -69,8 +70,8 @@ export class ScanController { @OpenAPI({ description: 'Create a new track scan.
This is just a alias for posting /scans', security: [{ "ScanApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) async postTrackScans(@Body({ validate: true }) createScan: CreateTrackScan) { let scan = await createScan.toScan(); - scan = await this.scanRepository.save(scan); - return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track'] })).toResponse(); + scan = await getConnection().getRepository(TrackScan).save(scan); + return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse(); } @Put('/:id') @@ -92,7 +93,7 @@ export class ScanController { } await this.scanRepository.save(await scan.updateScan(oldScan)); - return (await this.scanRepository.findOne({ id: id }, { relations: ['runner'] })).toResponse(); + return (await this.scanRepository.findOne({ id: id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse(); } @Delete('/:id') @@ -104,7 +105,7 @@ export class ScanController { async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let scan = await this.scanRepository.findOne({ id: id }); if (!scan) { return null; } - const responseScan = await this.scanRepository.findOne({ id: scan.id }, { relations: ["runner"] }); + const responseScan = await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] }); await this.scanRepository.delete(scan); return responseScan.toResponse(); diff --git a/src/models/actions/CreateTrackScan.ts b/src/models/actions/CreateTrackScan.ts index 2303352..44877f0 100644 --- a/src/models/actions/CreateTrackScan.ts +++ b/src/models/actions/CreateTrackScan.ts @@ -1,35 +1,28 @@ -import { IsNotEmpty } from 'class-validator'; +import { IsInt, IsPositive } from 'class-validator'; import { getConnection } from 'typeorm'; import { RunnerNotFoundError } from '../../errors/RunnerErrors'; import { RunnerCard } from '../entities/RunnerCard'; import { ScanStation } from '../entities/ScanStation'; import { TrackScan } from '../entities/TrackScan'; -import { CreateScan } from './CreateScan'; /** * This classed is used to create a new Scan entity from a json body (post request). */ -export class CreateTrackScan extends CreateScan { - - /** - * The scan's associated track. - * This is used to determine the scan's distance. - */ - @IsNotEmpty() - track: number; - +export class CreateTrackScan { /** * The runnerCard associated with the scan. * This get's saved for documentation and management purposes. */ - @IsNotEmpty() + @IsInt() + @IsPositive() card: number; /** * The scanning station that created the scan. * Mainly used for logging and traceing back scans (or errors) */ - @IsNotEmpty() + @IsInt() + @IsPositive() station: number; /** diff --git a/src/models/responses/ResponseTrackScan.ts b/src/models/responses/ResponseTrackScan.ts index 724a8fd..dba450c 100644 --- a/src/models/responses/ResponseTrackScan.ts +++ b/src/models/responses/ResponseTrackScan.ts @@ -1,8 +1,8 @@ import { IsDateString, IsNotEmpty } from "class-validator"; -import { RunnerCard } from '../entities/RunnerCard'; -import { ScanStation } from '../entities/ScanStation'; import { TrackScan } from '../entities/TrackScan'; +import { ResponseRunnerCard } from './ResponseRunnerCard'; import { ResponseScan } from './ResponseScan'; +import { ResponseScanStation } from './ResponseScanStation'; import { ResponseTrack } from './ResponseTrack'; /** @@ -19,13 +19,13 @@ export class ResponseTrackScan extends ResponseScan { * The runnerCard associated with the scan. */ @IsNotEmpty() - card: RunnerCard; + card: ResponseRunnerCard; /** * The scanning station that created the scan. */ @IsNotEmpty() - station: ScanStation; + station: ResponseScanStation; /** * The scan's creation timestamp. @@ -41,8 +41,9 @@ export class ResponseTrackScan extends ResponseScan { public constructor(scan: TrackScan) { super(scan); this.track = new ResponseTrack(scan.track); - this.card = scan.card; - this.station = scan.station; + this.card = scan.card.toResponse(); + this.station = scan.station.toResponse(); this.timestamp = scan.timestamp; + this.distance = scan.distance; } } From 9013b9492c89c8128664cf86f4cf0ab9d4122e55 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 15:25:11 +0100 Subject: [PATCH 16/50] Fixed runner distance resolution ref #78 --- src/controllers/RunnerController.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/controllers/RunnerController.ts b/src/controllers/RunnerController.ts index 9eeb916..5d1e5e8 100644 --- a/src/controllers/RunnerController.ts +++ b/src/controllers/RunnerController.ts @@ -27,7 +27,7 @@ export class RunnerController { @OpenAPI({ description: 'Lists all runners from all teams/orgs.
This includes the runner\'s group and distance ran.' }) async getAll() { let responseRunners: ResponseRunner[] = new Array(); - const runners = await this.runnerRepository.find({ relations: ['scans', 'group'] }); + const runners = await this.runnerRepository.find({ relations: ['scans', 'group', 'scans.track', 'cards'] }); runners.forEach(runner => { responseRunners.push(new ResponseRunner(runner)); }); @@ -41,7 +41,7 @@ export class RunnerController { @OnUndefined(RunnerNotFoundError) @OpenAPI({ description: 'Lists all information about the runner whose id got provided.' }) async getOne(@Param('id') id: number) { - let runner = await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group'] }) + let runner = await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group', 'scans.track', 'cards'] }) if (!runner) { throw new RunnerNotFoundError(); } return new ResponseRunner(runner); } @@ -61,7 +61,7 @@ export class RunnerController { } runner = await this.runnerRepository.save(runner) - return new ResponseRunner(await this.runnerRepository.findOne(runner, { relations: ['scans', 'group'] })); + return new ResponseRunner(await this.runnerRepository.findOne(runner, { relations: ['scans', 'group', 'scans.track', 'cards'] })); } @Put('/:id') @@ -82,7 +82,7 @@ export class RunnerController { } await this.runnerRepository.save(await runner.updateRunner(oldRunner)); - return new ResponseRunner(await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group'] })); + return new ResponseRunner(await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group', 'scans.track', 'cards'] })); } @Delete('/:id') @@ -94,7 +94,7 @@ export class RunnerController { async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let runner = await this.runnerRepository.findOne({ id: id }); if (!runner) { return null; } - const responseRunner = await this.runnerRepository.findOne(runner, { relations: ['scans', 'group'] }); + const responseRunner = await this.runnerRepository.findOne(runner, { relations: ['scans', 'group', 'scans.track', 'cards'] }); if (!runner) { throw new RunnerNotFoundError(); From 1a5493facf5635d8a0fb3773df70a2c6f2f4c767 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 15:43:52 +0100 Subject: [PATCH 17/50] Implemented cascading scan, track and card deletion ref #78 --- src/controllers/RunnerController.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/controllers/RunnerController.ts b/src/controllers/RunnerController.ts index 5d1e5e8..0a92ad2 100644 --- a/src/controllers/RunnerController.ts +++ b/src/controllers/RunnerController.ts @@ -8,6 +8,7 @@ import { UpdateRunner } from '../models/actions/UpdateRunner'; import { Runner } from '../models/entities/Runner'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseRunner } from '../models/responses/ResponseRunner'; +import { ScanController } from './ScanController'; @JsonController('/runners') @OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @@ -100,6 +101,12 @@ export class RunnerController { throw new RunnerNotFoundError(); } + const runnerScans = (await this.runnerRepository.findOne({ id: runner.id }, { relations: ["scans"] })).scans; + const scanController = new ScanController; + for (let scan of runnerScans) { + scanController.remove(scan.id, force); + } + await this.runnerRepository.delete(runner); return new ResponseRunner(responseRunner); } From 3d07aac9441b529ec38a47146ee2d8dcb9b5ea73 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 15:43:52 +0100 Subject: [PATCH 18/50] Implemented cascading scan, track and card deletion ref #78 --- src/controllers/RunnerCardController.ts | 2 +- src/controllers/RunnerController.ts | 14 ++++++++++++++ src/controllers/ScanStationController.ts | 2 +- src/controllers/TrackController.ts | 4 ++-- src/controllers/UserGroupController.ts | 4 ++-- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/controllers/RunnerCardController.ts b/src/controllers/RunnerCardController.ts index 2263f07..1366bed 100644 --- a/src/controllers/RunnerCardController.ts +++ b/src/controllers/RunnerCardController.ts @@ -97,7 +97,7 @@ export class RunnerCardController { } const scanController = new ScanController; for (let scan of cardScans) { - scanController.remove(scan.id, force); + await scanController.remove(scan.id, force); } await this.cardRepository.delete(card); diff --git a/src/controllers/RunnerController.ts b/src/controllers/RunnerController.ts index 5d1e5e8..a11d2c6 100644 --- a/src/controllers/RunnerController.ts +++ b/src/controllers/RunnerController.ts @@ -8,6 +8,8 @@ import { UpdateRunner } from '../models/actions/UpdateRunner'; import { Runner } from '../models/entities/Runner'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseRunner } from '../models/responses/ResponseRunner'; +import { RunnerCardController } from './RunnerCardController'; +import { ScanController } from './ScanController'; @JsonController('/runners') @OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) @@ -100,6 +102,18 @@ export class RunnerController { throw new RunnerNotFoundError(); } + const runnerCards = (await this.runnerRepository.findOne({ id: runner.id }, { relations: ["cards"] })).cards; + const cardController = new RunnerCardController; + for (let scan of runnerCards) { + await cardController.remove(scan.id, force); + } + + const runnerScans = (await this.runnerRepository.findOne({ id: runner.id }, { relations: ["scans"] })).scans; + const scanController = new ScanController; + for (let scan of runnerScans) { + await scanController.remove(scan.id, force); + } + await this.runnerRepository.delete(runner); return new ResponseRunner(responseRunner); } diff --git a/src/controllers/ScanStationController.ts b/src/controllers/ScanStationController.ts index 4e32971..df85d0e 100644 --- a/src/controllers/ScanStationController.ts +++ b/src/controllers/ScanStationController.ts @@ -98,7 +98,7 @@ export class ScanStationController { } const scanController = new ScanController; for (let scan of stationScans) { - scanController.remove(scan.id, force); + await scanController.remove(scan.id, force); } const responseStation = await this.stationRepository.findOne({ id: station.id }, { relations: ["track"] }); diff --git a/src/controllers/TrackController.ts b/src/controllers/TrackController.ts index 094756c..42feb7c 100644 --- a/src/controllers/TrackController.ts +++ b/src/controllers/TrackController.ts @@ -94,9 +94,9 @@ export class TrackController { if (trackStations.length != 0 && !force) { throw new TrackHasScanStationsError(); } - const scanController = new ScanStationController; + const stationController = new ScanStationController; for (let station of trackStations) { - scanController.remove(station.id, force); + await stationController.remove(station.id, force); } await this.trackRepository.delete(track); diff --git a/src/controllers/UserGroupController.ts b/src/controllers/UserGroupController.ts index 4b484fc..160a99e 100644 --- a/src/controllers/UserGroupController.ts +++ b/src/controllers/UserGroupController.ts @@ -88,9 +88,9 @@ export class UserGroupController { if (!group) { return null; } const responseGroup = await this.userGroupsRepository.findOne({ id: id }, { relations: ['permissions'] }); - const permissionControler = new PermissionController(); + const permissionController = new PermissionController(); for (let permission of responseGroup.permissions) { - await permissionControler.remove(permission.id, true); + await permissionController.remove(permission.id, true); } await this.userGroupsRepository.delete(group); From e7cd68e1c8bd419772de33e250292e1d7d65a16b Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 15:59:36 +0100 Subject: [PATCH 19/50] removed distance checks from tests ref #78 --- src/tests/scans/scans_update.spec.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/tests/scans/scans_update.spec.ts b/src/tests/scans/scans_update.spec.ts index b4ff86c..60b7fb1 100644 --- a/src/tests/scans/scans_update.spec.ts +++ b/src/tests/scans/scans_update.spec.ts @@ -100,6 +100,7 @@ describe('adding + updating successfilly', () => { "group": added_org.id }, axios_config); delete res2.data.group; + delete res2.data.distance; added_runner = res2.data; expect(res2.status).toEqual(200); expect(res2.headers['content-type']).toContain("application/json") @@ -121,6 +122,7 @@ describe('adding + updating successfilly', () => { }, axios_config); expect(res2.status).toEqual(200); expect(res2.headers['content-type']).toContain("application/json") + delete res2.data.runner.distance; expect(res2.data).toEqual({ "id": added_scan.id, "runner": added_runner, @@ -137,7 +139,8 @@ describe('adding + updating successfilly', () => { "valid": false }, axios_config); expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") + expect(res2.headers['content-type']).toContain("application/json"); + delete res2.data.runner.distance; expect(res2.data).toEqual({ "id": added_scan.id, "runner": added_runner, @@ -152,6 +155,7 @@ describe('adding + updating successfilly', () => { "group": added_org.id }, axios_config); delete res2.data.group; + delete res2.data.distance; added_runner2 = res2.data; expect(res2.status).toEqual(200); expect(res2.headers['content-type']).toContain("application/json") @@ -164,6 +168,7 @@ describe('adding + updating successfilly', () => { }, axios_config); expect(res2.status).toEqual(200); expect(res2.headers['content-type']).toContain("application/json"); + delete res2.data.runner.distance; expect(res2.data).toEqual({ "id": added_scan.id, "runner": added_runner2, From 638898fa28bbb686c920ff5603e9ef6b68af3d83 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 16:17:50 +0100 Subject: [PATCH 20/50] Implemented trackscan updateing ref #78 --- src/controllers/RunnerController.ts | 2 +- src/controllers/ScanController.ts | 39 +++++++++++-- src/models/actions/UpdateTrackScan.ts | 79 +++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 src/models/actions/UpdateTrackScan.ts diff --git a/src/controllers/RunnerController.ts b/src/controllers/RunnerController.ts index a11d2c6..4e74330 100644 --- a/src/controllers/RunnerController.ts +++ b/src/controllers/RunnerController.ts @@ -92,7 +92,7 @@ export class RunnerController { @ResponseSchema(ResponseRunner) @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @OnUndefined(204) - @OpenAPI({ description: 'Delete the runner whose id you provided.
If no runner with this id exists it will just return 204(no content).' }) + @OpenAPI({ description: 'Delete the runner whose id you provided.
This will also delete all scans and cards associated with the runner.
If no runner with this id exists it will just return 204(no content).' }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let runner = await this.runnerRepository.findOne({ id: id }); if (!runner) { return null; } diff --git a/src/controllers/ScanController.ts b/src/controllers/ScanController.ts index 09833dc..46c7ba1 100644 --- a/src/controllers/ScanController.ts +++ b/src/controllers/ScanController.ts @@ -1,12 +1,14 @@ import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam, UseBefore } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; -import { getConnection, getConnectionManager, Repository } from 'typeorm'; +import { getConnectionManager, Repository } from 'typeorm'; import { RunnerNotFoundError } from '../errors/RunnerErrors'; import { ScanIdsNotMatchingError, ScanNotFoundError } from '../errors/ScanErrors'; +import { ScanStationNotFoundError } from '../errors/ScanStationErrors'; import ScanAuth from '../middlewares/ScanAuth'; import { CreateScan } from '../models/actions/CreateScan'; import { CreateTrackScan } from '../models/actions/CreateTrackScan'; import { UpdateScan } from '../models/actions/UpdateScan'; +import { UpdateTrackScan } from '../models/actions/UpdateTrackScan'; import { Scan } from '../models/entities/Scan'; import { TrackScan } from '../models/entities/TrackScan'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; @@ -17,12 +19,14 @@ import { ResponseTrackScan } from '../models/responses/ResponseTrackScan'; @OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class ScanController { private scanRepository: Repository; + private trackScanRepository: Repository; /** * Gets the repository of this controller's model/entity. */ constructor() { this.scanRepository = getConnectionManager().get().getRepository(Scan); + this.trackScanRepository = getConnectionManager().get().getRepository(TrackScan); } @Get() @@ -56,7 +60,7 @@ export class ScanController { @UseBefore(ScanAuth) @ResponseSchema(ResponseScan) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) - @OpenAPI({ description: 'Create a new scan.
Please remeber to provide the scan\'s runner\'s id and distance for normal scans.', security: [{ "ScanApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) + @OpenAPI({ description: 'Create a new scan (not track scan - use /scans/trackscans instead).
Please rmemember to provide the scan\'s runner\'s id and distance.', security: [{ "ScanApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) async post(@Body({ validate: true }) createScan: CreateScan) { let scan = await createScan.toScan(); scan = await this.scanRepository.save(scan); @@ -65,12 +69,12 @@ export class ScanController { @Post("/trackscans") @UseBefore(ScanAuth) - @ResponseSchema(ResponseScan) + @ResponseSchema(ResponseTrackScan) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) - @OpenAPI({ description: 'Create a new track scan.
This is just a alias for posting /scans', security: [{ "ScanApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) + @OpenAPI({ description: 'Create a new track scan (for "normal" scans use /scans instead).
Please remember that to provide the scan\'s card\'s station\'s id.', security: [{ "ScanApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) async postTrackScans(@Body({ validate: true }) createScan: CreateTrackScan) { let scan = await createScan.toScan(); - scan = await getConnection().getRepository(TrackScan).save(scan); + scan = await this.trackScanRepository.save(scan); return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse(); } @@ -80,7 +84,7 @@ export class ScanController { @ResponseSchema(ScanNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @ResponseSchema(ScanIdsNotMatchingError, { statusCode: 406 }) - @OpenAPI({ description: "Update the scan whose id you provided.
Please remember that ids can't be changed and distances must be positive." }) + @OpenAPI({ description: "Update the scan (not track scan use /scans/trackscans/:id instead) whose id you provided.
Please remember that ids can't be changed and distances must be positive." }) async put(@Param('id') id: number, @Body({ validate: true }) scan: UpdateScan) { let oldScan = await this.scanRepository.findOne({ id: id }); @@ -96,6 +100,29 @@ export class ScanController { return (await this.scanRepository.findOne({ id: id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse(); } + @Put('/trackscans/:id') + @Authorized("SCAN:UPDATE") + @ResponseSchema(ResponseTrackScan) + @ResponseSchema(ScanNotFoundError, { statusCode: 404 }) + @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) + @ResponseSchema(ScanStationNotFoundError, { statusCode: 404 }) + @ResponseSchema(ScanIdsNotMatchingError, { statusCode: 406 }) + @OpenAPI({ description: 'Update the track scan (not "normal" scan use /scans/trackscans/:id instead) whose id you provided.
Please remember that only the validity, runner and track can be changed.' }) + async putTrackScan(@Param('id') id: number, @Body({ validate: true }) scan: UpdateTrackScan) { + let oldScan = await this.trackScanRepository.findOne({ id: id }); + + if (!oldScan) { + throw new ScanNotFoundError(); + } + + if (oldScan.id != scan.id) { + throw new ScanIdsNotMatchingError(); + } + + await this.trackScanRepository.save(await scan.updateScan(oldScan)); + return (await this.scanRepository.findOne({ id: id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse(); + } + @Delete('/:id') @Authorized("SCAN:DELETE") @ResponseSchema(ResponseScan) diff --git a/src/models/actions/UpdateTrackScan.ts b/src/models/actions/UpdateTrackScan.ts new file mode 100644 index 0000000..9d0e754 --- /dev/null +++ b/src/models/actions/UpdateTrackScan.ts @@ -0,0 +1,79 @@ +import { IsBoolean, IsInt, IsOptional, IsPositive } from 'class-validator'; +import { getConnection } from 'typeorm'; +import { RunnerNotFoundError } from '../../errors/RunnerErrors'; +import { ScanStationNotFoundError } from '../../errors/ScanStationErrors'; +import { Runner } from '../entities/Runner'; +import { ScanStation } from '../entities/ScanStation'; +import { TrackScan } from '../entities/TrackScan'; + +/** + * This class is used to update a TrackScan entity (via put request) + */ +export abstract class UpdateTrackScan { + /** + * The updated scan's id. + * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to). + */ + @IsInt() + id: number; + + /** + * The updated scan's associated runner. + * This is important to link ran distances to runners. + */ + @IsInt() + @IsPositive() + runner: number; + + /** + * Is the updated scan valid (for fraud reasons). + */ + @IsBoolean() + @IsOptional() + valid?: boolean = true; + + /** + * The updated scan's associated station. + * This is important to link ran distances to runners. + */ + @IsInt() + @IsOptional() + public station?: number; + + /** + * Update a TrackScan entity based on this. + * @param scan The scan that shall be updated. + */ + public async updateScan(scan: TrackScan): Promise { + scan.valid = this.valid; + scan.runner = await this.getRunner(); + if (this.station) { + scan.station = await this.getStation(); + } + scan.track = scan.station.track; + + return scan; + } + + /** + * Gets a runner based on the runner id provided via this.runner. + */ + public async getRunner(): Promise { + const runner = await getConnection().getRepository(Runner).findOne({ id: this.runner }); + if (!runner) { + throw new RunnerNotFoundError(); + } + return runner; + } + + /** + * Gets a runner based on the runner id provided via this.runner. + */ + public async getStation(): Promise { + const station = await getConnection().getRepository(ScanStation).findOne({ id: this.station }); + if (!station) { + throw new ScanStationNotFoundError(); + } + return station; + } +} \ No newline at end of file From 0c86e5dae173c04422cf7254c72da961eca96e35 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 16:44:52 +0100 Subject: [PATCH 21/50] added trackscan add tests ref #78 --- src/tests/trackscans/trackscans_add.spec.ts | 239 ++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 src/tests/trackscans/trackscans_add.spec.ts diff --git a/src/tests/trackscans/trackscans_add.spec.ts b/src/tests/trackscans/trackscans_add.spec.ts new file mode 100644 index 0000000..4b5de54 --- /dev/null +++ b/src/tests/trackscans/trackscans_add.spec.ts @@ -0,0 +1,239 @@ +import axios from 'axios'; +import { config } from '../../config'; +const base = "http://localhost:" + config.internal_port + +let access_token; +let axios_config; + +beforeAll(async () => { + const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); + access_token = res.data["access_token"]; + axios_config = { + headers: { "authorization": "Bearer " + access_token }, + validateStatus: undefined + }; +}); + + +describe('POST /api/scans illegally', () => { + let added_org; + let added_runner; + let added_card; + let added_track; + let added_station; + it('creating a new org with just a name should return 200', async () => { + const res1 = await axios.post(base + '/api/organisations', { + "name": "test123" + }, axios_config); + added_org = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/runners', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + added_runner = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a card with the minimum amount of parameters should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "runner": added_runner.id + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + added_card = res.data; + }); + it('creating a track should return 200', async () => { + const res1 = await axios.post(base + '/api/tracks', { + "name": "test123", + "distance": 123 + }, axios_config); + added_track = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('correct description and track input for station creation return 200', async () => { + const res = await axios.post(base + '/api/stations', { + "track": added_track.id, + "description": "I am but a simple test." + }, axios_config); + added_station = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('no input should return 400', async () => { + const res = await axios.post(base + '/api/scans/trackscans', null, axios_config); + expect(res.status).toEqual(400); + expect(res.headers['content-type']).toContain("application/json") + }); + it('no station should return 400', async () => { + const res = await axios.post(base + '/api/scans/trackscans', { + "card": added_card.id + }, axios_config); + expect(res.status).toEqual(400); + expect(res.headers['content-type']).toContain("application/json") + }); + it('no card should return 400', async () => { + const res = await axios.post(base + '/api/scans/trackscans', { + "station": added_station.id, + }, axios_config); + expect(res.status).toEqual(400); + expect(res.headers['content-type']).toContain("application/json") + }); + it('invalid card input should return 404', async () => { + const res = await axios.post(base + '/api/scans/trackscans', { + "card": 999999999999999999999999, + "station": added_station.id + }, axios_config); + expect(res.status).toEqual(404); + expect(res.headers['content-type']).toContain("application/json") + }); + it('invalid station input should return 404', async () => { + const res = await axios.post(base + '/api/scans/trackscans', { + "card": added_card.id, + "station": 999999999999999999999999 + }, axios_config); + expect(res.status).toEqual(404); + expect(res.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('POST /api/scans successfully', () => { + let added_org; + let added_runner; + let added_card; + let added_track; + let added_station; + it('creating a new org with just a name should return 200', async () => { + const res1 = await axios.post(base + '/api/organisations', { + "name": "test123" + }, axios_config); + added_org = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/runners', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + added_runner = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a card with the minimum amount of parameters should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "runner": added_runner.id + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + added_card = res.data; + }); + it('creating a track should return 200', async () => { + const res1 = await axios.post(base + '/api/tracks', { + "name": "test123", + "distance": 123 + }, axios_config); + added_track = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('correct description and track input for station creation return 200', async () => { + const res = await axios.post(base + '/api/stations', { + "track": added_track.id, + "description": "I am but a simple test." + }, axios_config); + added_station = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('creating a scan should return 200', async () => { + const res = await axios.post(base + '/api/scans/trackscans', { + "card": added_card.id, + "station": added_station.id + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + }); +}); +// --------------- +describe('POST /api/scans successfully via scan station', () => { + let added_org; + let added_runner; + let added_card; + let added_track; + let added_station; + it('creating a new org with just a name should return 200', async () => { + const res1 = await axios.post(base + '/api/organisations', { + "name": "test123" + }, axios_config); + added_org = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/runners', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + added_runner = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a card with the minimum amount of parameters should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "runner": added_runner.id + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + added_card = res.data; + }); + it('creating a track should return 200', async () => { + const res1 = await axios.post(base + '/api/tracks', { + "name": "test123", + "distance": 123, + "minimumLapTime": 30 + }, axios_config); + added_track = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('correct description and track input for station creation return 200', async () => { + const res = await axios.post(base + '/api/stations', { + "track": added_track.id, + "description": "I am but a simple test." + }, axios_config); + added_station = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('creating a scan should return 200', async () => { + const res = await axios.post(base + '/api/scans/trackscans', { + "card": added_card.id, + "station": added_station.id + }, { + headers: { "authorization": "Bearer " + added_station.key }, + validateStatus: undefined + }); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + }); + it('creating a invalid scan should return 200', async () => { + const res = await axios.post(base + '/api/scans/trackscans', { + "card": added_card.id, + "station": added_station.id + }, { + headers: { "authorization": "Bearer " + added_station.key }, + validateStatus: undefined + }); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + expect(res.data.vaild).toEqual(false); + }); +}); \ No newline at end of file From 61cf0fc08d3af733b30640880f4b3981cd9f827a Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 16:47:54 +0100 Subject: [PATCH 22/50] Implemented proper scan invalidation ref #78 --- src/models/actions/CreateTrackScan.ts | 20 +++++++++++--------- src/models/entities/TrackScan.ts | 6 ++---- src/models/responses/ResponseTrackScan.ts | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/models/actions/CreateTrackScan.ts b/src/models/actions/CreateTrackScan.ts index 44877f0..51078c4 100644 --- a/src/models/actions/CreateTrackScan.ts +++ b/src/models/actions/CreateTrackScan.ts @@ -1,6 +1,8 @@ import { IsInt, IsPositive } from 'class-validator'; import { getConnection } from 'typeorm'; +import { RunnerCardNotFoundError } from '../../errors/RunnerCardErrors'; import { RunnerNotFoundError } from '../../errors/RunnerErrors'; +import { ScanStationNotFoundError } from '../../errors/ScanStationErrors'; import { RunnerCard } from '../entities/RunnerCard'; import { ScanStation } from '../entities/ScanStation'; import { TrackScan } from '../entities/TrackScan'; @@ -41,7 +43,7 @@ export class CreateTrackScan { throw new RunnerNotFoundError(); } - newScan.timestamp = new Date(Date.now()).toString(); + newScan.timestamp = Math.round(new Date().getTime() / 1000); newScan.valid = await this.validateScan(newScan); return newScan; @@ -50,25 +52,25 @@ export class CreateTrackScan { public async getCard(): Promise { const track = await getConnection().getRepository(RunnerCard).findOne({ id: this.card }, { relations: ["runner"] }); if (!track) { - throw new Error(); + throw new RunnerCardNotFoundError(); } return track; } public async getStation(): Promise { - const track = await getConnection().getRepository(ScanStation).findOne({ id: this.card }, { relations: ["track"] }); - if (!track) { - throw new Error(); + const station = await getConnection().getRepository(ScanStation).findOne({ id: this.station }, { relations: ["track"] }); + if (!station) { + throw new ScanStationNotFoundError(); } - return track; + return station; } public async validateScan(scan: TrackScan): Promise { - const scans = await getConnection().getRepository(TrackScan).find({ where: { runner: scan.runner }, relations: ["track"] }); + const scans = await getConnection().getRepository(TrackScan).find({ where: { runner: scan.runner, valid: true }, relations: ["track"] }); if (scans.length == 0) { return true; } - const newestScan = scans[0]; - if ((new Date(scan.timestamp).getTime() - new Date(newestScan.timestamp).getTime()) > scan.track.minimumLapTime) { + const newestScan = scans[scans.length - 1]; + if ((scan.timestamp - newestScan.timestamp) > scan.track.minimumLapTime) { return true; } diff --git a/src/models/entities/TrackScan.ts b/src/models/entities/TrackScan.ts index 8c4143b..cd8049a 100644 --- a/src/models/entities/TrackScan.ts +++ b/src/models/entities/TrackScan.ts @@ -1,5 +1,4 @@ import { - IsDateString, IsInt, IsNotEmpty, @@ -57,9 +56,8 @@ export class TrackScan extends Scan { * Will be used to implement fraud detection. */ @Column() - @IsDateString() - @IsNotEmpty() - timestamp: string; + @IsInt() + timestamp: number; /** * Turns this entity into it's response class. diff --git a/src/models/responses/ResponseTrackScan.ts b/src/models/responses/ResponseTrackScan.ts index dba450c..d52b4f7 100644 --- a/src/models/responses/ResponseTrackScan.ts +++ b/src/models/responses/ResponseTrackScan.ts @@ -32,7 +32,7 @@ export class ResponseTrackScan extends ResponseScan { */ @IsDateString() @IsNotEmpty() - timestamp: string; + timestamp: number; /** * Creates a ResponseTrackScan object from a scan. From f1dee1061dc8dc9b76d3100b7c66d7c12434fd8f Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 16:49:17 +0100 Subject: [PATCH 23/50] added trackscan get tests ref #78 --- src/tests/trackscans/trackscans_get.spec.ts | 102 ++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 src/tests/trackscans/trackscans_get.spec.ts diff --git a/src/tests/trackscans/trackscans_get.spec.ts b/src/tests/trackscans/trackscans_get.spec.ts new file mode 100644 index 0000000..1f0eaed --- /dev/null +++ b/src/tests/trackscans/trackscans_get.spec.ts @@ -0,0 +1,102 @@ +import axios from 'axios'; +import { config } from '../../config'; +const base = "http://localhost:" + config.internal_port + +let access_token; +let axios_config; + +beforeAll(async () => { + const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); + access_token = res.data["access_token"]; + axios_config = { + headers: { "authorization": "Bearer " + access_token }, + validateStatus: undefined + }; +}); + +describe('GET /api/scans sucessfully', () => { + it('basic get should return 200', async () => { + const res = await axios.get(base + '/api/scans', axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('GET /api/scans illegally', () => { + it('get for non-existant track should return 404', async () => { + const res = await axios.get(base + '/api/scans/-1', axios_config); + expect(res.status).toEqual(404); + expect(res.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('adding + getting scans', () => { + let added_org; + let added_runner; + let added_card; + let added_track; + let added_station; + let added_scan; + it('creating a new org with just a name should return 200', async () => { + const res1 = await axios.post(base + '/api/organisations', { + "name": "test123" + }, axios_config); + added_org = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/runners', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + added_runner = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a card with the minimum amount of parameters should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "runner": added_runner.id + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + added_card = res.data; + }); + it('creating a track should return 200', async () => { + const res1 = await axios.post(base + '/api/tracks', { + "name": "test123", + "distance": 123, + "minimumLapTime": 30 + }, axios_config); + added_track = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('correct description and track input for station creation return 200', async () => { + const res = await axios.post(base + '/api/stations', { + "track": added_track.id, + "description": "I am but a simple test." + }, axios_config); + added_station = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('creating a scan should return 200', async () => { + const res = await axios.post(base + '/api/scans/trackscans', { + "card": added_card.id, + "station": added_station.id + }, { + headers: { "authorization": "Bearer " + added_station.key }, + validateStatus: undefined + }); + added_scan = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + }); + it('check if scans was added (no parameter validation)', async () => { + const res = await axios.get(base + '/api/scans/' + added_scan.id, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + }); +}); \ No newline at end of file From 4fea6906706872ca6157679d47b22b70d7ff2255 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 16:54:19 +0100 Subject: [PATCH 24/50] Added missing parameter fro negative-test ref #78 --- src/tests/trackscans/trackscans_add.spec.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/tests/trackscans/trackscans_add.spec.ts b/src/tests/trackscans/trackscans_add.spec.ts index 4b5de54..a4b475d 100644 --- a/src/tests/trackscans/trackscans_add.spec.ts +++ b/src/tests/trackscans/trackscans_add.spec.ts @@ -137,7 +137,8 @@ describe('POST /api/scans successfully', () => { it('creating a track should return 200', async () => { const res1 = await axios.post(base + '/api/tracks', { "name": "test123", - "distance": 123 + "distance": 123, + "minimumLapTime": 30 }, axios_config); added_track = res1.data expect(res1.status).toEqual(200); @@ -160,6 +161,15 @@ describe('POST /api/scans successfully', () => { expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json"); }); + it('creating a invalid scan should return 200', async () => { + const res = await axios.post(base + '/api/scans/trackscans', { + "card": added_card.id, + "station": added_station.id + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + expect(res.data.valid).toEqual(false); + }); }); // --------------- describe('POST /api/scans successfully via scan station', () => { @@ -234,6 +244,6 @@ describe('POST /api/scans successfully via scan station', () => { }); expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json"); - expect(res.data.vaild).toEqual(false); + expect(res.data.valid).toEqual(false); }); }); \ No newline at end of file From efe1a1f543aa2eebd2b2a3c2be89ce1a08c6bcd4 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 16:56:57 +0100 Subject: [PATCH 25/50] added trackscan delete tests ref #78 --- .../trackscans/trackscans_delete.spec.ts | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/tests/trackscans/trackscans_delete.spec.ts diff --git a/src/tests/trackscans/trackscans_delete.spec.ts b/src/tests/trackscans/trackscans_delete.spec.ts new file mode 100644 index 0000000..646c189 --- /dev/null +++ b/src/tests/trackscans/trackscans_delete.spec.ts @@ -0,0 +1,101 @@ +import axios from 'axios'; +import { config } from '../../config'; +const base = "http://localhost:" + config.internal_port + +let access_token; +let axios_config; + +beforeAll(async () => { + const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); + access_token = res.data["access_token"]; + axios_config = { + headers: { "authorization": "Bearer " + access_token }, + validateStatus: undefined + }; +}); + +// --------------- + +describe('DELETE scan', () => { + let added_org; + let added_runner; + let added_card; + let added_track; + let added_station; + let added_scan; + it('creating a new org with just a name should return 200', async () => { + const res1 = await axios.post(base + '/api/organisations', { + "name": "test123" + }, axios_config); + added_org = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/runners', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + added_runner = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a card with the minimum amount of parameters should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "runner": added_runner.id + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + added_card = res.data; + }); + it('creating a track should return 200', async () => { + const res1 = await axios.post(base + '/api/tracks', { + "name": "test123", + "distance": 123, + "minimumLapTime": 30 + }, axios_config); + added_track = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('correct description and track input for station creation return 200', async () => { + const res = await axios.post(base + '/api/stations', { + "track": added_track.id, + "description": "I am but a simple test." + }, axios_config); + added_station = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('creating a scan should return 200', async () => { + const res = await axios.post(base + '/api/scans/trackscans', { + "card": added_card.id, + "station": added_station.id + }, { + headers: { "authorization": "Bearer " + added_station.key }, + validateStatus: undefined + }); + added_scan = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + }); + it('delete scan', async () => { + const res2 = await axios.delete(base + '/api/scans/' + added_scan.id, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + expect(res2.data).toEqual(added_scan); + }); + it('check if scan really was deleted', async () => { + const res3 = await axios.get(base + '/api/scans/' + added_scan.id, axios_config); + expect(res3.status).toEqual(404); + expect(res3.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('DELETE scan (non-existant)', () => { + it('delete', async () => { + const res2 = await axios.delete(base + '/api/scans/0', axios_config); + expect(res2.status).toEqual(204); + }); +}); From 7e95103a2d68e9f55a6550290d36b6e62add973f Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 17:18:33 +0100 Subject: [PATCH 26/50] added trackscan update tests ref #78 --- src/models/actions/UpdateTrackScan.ts | 10 +- .../trackscans/trackscans_update.spec.ts | 239 ++++++++++++++++++ 2 files changed, 245 insertions(+), 4 deletions(-) create mode 100644 src/tests/trackscans/trackscans_update.spec.ts diff --git a/src/models/actions/UpdateTrackScan.ts b/src/models/actions/UpdateTrackScan.ts index 9d0e754..43c37cd 100644 --- a/src/models/actions/UpdateTrackScan.ts +++ b/src/models/actions/UpdateTrackScan.ts @@ -1,4 +1,4 @@ -import { IsBoolean, IsInt, IsOptional, IsPositive } from 'class-validator'; +import { IsBoolean, IsInt, IsOptional } from 'class-validator'; import { getConnection } from 'typeorm'; import { RunnerNotFoundError } from '../../errors/RunnerErrors'; import { ScanStationNotFoundError } from '../../errors/ScanStationErrors'; @@ -22,8 +22,8 @@ export abstract class UpdateTrackScan { * This is important to link ran distances to runners. */ @IsInt() - @IsPositive() - runner: number; + @IsOptional() + runner?: number; /** * Is the updated scan valid (for fraud reasons). @@ -46,7 +46,9 @@ export abstract class UpdateTrackScan { */ public async updateScan(scan: TrackScan): Promise { scan.valid = this.valid; - scan.runner = await this.getRunner(); + if (this.runner) { + scan.runner = await this.getRunner(); + } if (this.station) { scan.station = await this.getStation(); } diff --git a/src/tests/trackscans/trackscans_update.spec.ts b/src/tests/trackscans/trackscans_update.spec.ts new file mode 100644 index 0000000..131f3b4 --- /dev/null +++ b/src/tests/trackscans/trackscans_update.spec.ts @@ -0,0 +1,239 @@ +import axios from 'axios'; +import { config } from '../../config'; +const base = "http://localhost:" + config.internal_port + +let access_token; +let axios_config; + +beforeAll(async () => { + const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); + access_token = res.data["access_token"]; + axios_config = { + headers: { "authorization": "Bearer " + access_token }, + validateStatus: undefined + }; +}); + +describe('adding + updating illegally', () => { + let added_org; + let added_runner; + let added_card; + let added_track; + let added_station; + let added_scan; + it('creating a new org with just a name should return 200', async () => { + const res1 = await axios.post(base + '/api/organisations', { + "name": "test123" + }, axios_config); + added_org = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/runners', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + added_runner = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a card with the minimum amount of parameters should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "runner": added_runner.id + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + added_card = res.data; + }); + it('creating a track should return 200', async () => { + const res1 = await axios.post(base + '/api/tracks', { + "name": "test123", + "distance": 123, + "minimumLapTime": 30 + }, axios_config); + added_track = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('correct description and track input for station creation return 200', async () => { + const res = await axios.post(base + '/api/stations', { + "track": added_track.id, + "description": "I am but a simple test." + }, axios_config); + added_station = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('creating a scan should return 200', async () => { + const res = await axios.post(base + '/api/scans/trackscans', { + "card": added_card.id, + "station": added_station.id + }, { + headers: { "authorization": "Bearer " + added_station.key }, + validateStatus: undefined + }); + added_scan = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + }); + it('updating empty should return 400', async () => { + const res2 = await axios.put(base + '/api/scans/trackscans/' + added_scan.id, null, axios_config); + expect(res2.status).toEqual(400); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('updating with wrong id should return 406', async () => { + const res2 = await axios.put(base + '/api/scans/trackscans/' + added_scan.id, { + "id": added_scan.id + 1, + "station": added_station.id, + "runner": added_runner.id + }, axios_config); + expect(res2.status).toEqual(406); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('updating with invalid station should return 404', async () => { + const res2 = await axios.put(base + '/api/scans/trackscans/' + added_scan.id, { + "id": added_scan.id, + "station": 9999999999999999, + "runner": added_runner.id + }, axios_config); + expect(res2.status).toEqual(404); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('updating with invalid runner should return 404', async () => { + const res2 = await axios.put(base + '/api/scans/trackscans/' + added_scan.id, { + "id": added_scan.id, + "station": added_station.id, + "runner": 9999999999999999999 + }, axios_config); + expect(res2.status).toEqual(404); + expect(res2.headers['content-type']).toContain("application/json") + }); +}); +//--------------- +describe('adding + updating successfilly', () => { + let added_org; + let added_runner; + let added_runner2; + let added_card; + let added_track; + let added_track2; + let added_station; + let added_station2; + let added_scan; + it('creating a new org with just a name should return 200', async () => { + const res1 = await axios.post(base + '/api/organisations', { + "name": "test123" + }, axios_config); + added_org = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/runners', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + added_runner = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/runners', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + added_runner2 = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a card with the minimum amount of parameters should return 200', async () => { + const res = await axios.post(base + '/api/cards', { + "runner": added_runner.id + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + added_card = res.data; + }); + it('creating a track should return 200', async () => { + const res1 = await axios.post(base + '/api/tracks', { + "name": "test123", + "distance": 123, + "minimumLapTime": 30 + }, axios_config); + added_track = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a track should return 200', async () => { + const res1 = await axios.post(base + '/api/tracks', { + "name": "test123", + "distance": 123, + "minimumLapTime": 30 + }, axios_config); + added_track2 = res1.data + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('correct description and track input for station creation return 200', async () => { + const res = await axios.post(base + '/api/stations', { + "track": added_track.id, + "description": "I am but a simple test." + }, axios_config); + added_station = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('correct description and track input for station creation return 200', async () => { + const res = await axios.post(base + '/api/stations', { + "track": added_track.id, + "description": "I am but a simple test." + }, axios_config); + added_station2 = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('creating a scan should return 200', async () => { + const res = await axios.post(base + '/api/scans/trackscans', { + "card": added_card.id, + "station": added_station.id + }, { + headers: { "authorization": "Bearer " + added_station.key }, + validateStatus: undefined + }); + added_scan = res.data; + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + }); + it('updating with new runner should return 200', async () => { + const res2 = await axios.put(base + '/api/scans/trackscans/' + added_scan.id, { + "id": added_scan.id, + "station": added_station.id, + "runner": added_runner2.id + }, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('updating with new station should return 200', async () => { + const res2 = await axios.put(base + '/api/scans/trackscans/' + added_scan.id, { + "id": added_scan.id, + "station": added_station2.id, + "runner": added_runner.id + }, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('updating with valid=false should return 200', async () => { + const res2 = await axios.put(base + '/api/scans/trackscans/' + added_scan.id, { + "id": added_scan.id, + "station": added_station2.id, + "runner": added_runner.id, + "valid": false + }, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); +}); From 154c7637195f6f13fcb2f2e1b92fa0d6f2d05b34 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 18:08:36 +0100 Subject: [PATCH 27/50] Temporary: extended live logging ref https://git.odit.services/lfk/frontend/issues/28 --- src/middlewares/authchecker.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/middlewares/authchecker.ts b/src/middlewares/authchecker.ts index 61ca231..fbeee41 100644 --- a/src/middlewares/authchecker.ts +++ b/src/middlewares/authchecker.ts @@ -19,6 +19,7 @@ const authchecker = async (action: Action, permissions: string[] | string) => { } else { required_permissions = permissions } + console.log(required_permissions); let jwtPayload = undefined try { @@ -26,6 +27,7 @@ const authchecker = async (action: Action, permissions: string[] | string) => { jwtPayload = jwt.verify(provided_token, config.jwt_secret); jwtPayload = jwtPayload["userdetails"]; } catch (error) { + console.log(action.request.headers["authorization"]); jwtPayload = await refresh(action); } @@ -39,6 +41,7 @@ const authchecker = async (action: Action, permissions: string[] | string) => { for (let required_permission of required_permissions) { if (!(jwtPayload["permissions"].includes(required_permission))) { return false; } } + console.log("success"); return true; } @@ -52,6 +55,9 @@ const refresh = async (action: Action) => { refresh_token = cookie.parse(action.request.headers["cookie"])["lfk_backend__refresh_token"]; } catch { + console.log(action.request.headers["cookie"]) + console.log("cookie fail here") + console.log(cookie.parse(action.request.headers["cookie"])) throw new IllegalJWTError(); } @@ -59,6 +65,8 @@ const refresh = async (action: Action) => { try { jwtPayload = jwt.verify(refresh_token, config.jwt_secret); } catch (error) { + console.log(refresh_token); + console.log("jwt fail") throw new IllegalJWTError(); } From 1e371862471057d49ba10f18f32533d652eba3a7 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 18:45:44 +0100 Subject: [PATCH 28/50] Revert "Temporary: extended live logging" This reverts commit 154c7637195f6f13fcb2f2e1b92fa0d6f2d05b34. --- src/middlewares/authchecker.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/middlewares/authchecker.ts b/src/middlewares/authchecker.ts index fbeee41..61ca231 100644 --- a/src/middlewares/authchecker.ts +++ b/src/middlewares/authchecker.ts @@ -19,7 +19,6 @@ const authchecker = async (action: Action, permissions: string[] | string) => { } else { required_permissions = permissions } - console.log(required_permissions); let jwtPayload = undefined try { @@ -27,7 +26,6 @@ const authchecker = async (action: Action, permissions: string[] | string) => { jwtPayload = jwt.verify(provided_token, config.jwt_secret); jwtPayload = jwtPayload["userdetails"]; } catch (error) { - console.log(action.request.headers["authorization"]); jwtPayload = await refresh(action); } @@ -41,7 +39,6 @@ const authchecker = async (action: Action, permissions: string[] | string) => { for (let required_permission of required_permissions) { if (!(jwtPayload["permissions"].includes(required_permission))) { return false; } } - console.log("success"); return true; } @@ -55,9 +52,6 @@ const refresh = async (action: Action) => { refresh_token = cookie.parse(action.request.headers["cookie"])["lfk_backend__refresh_token"]; } catch { - console.log(action.request.headers["cookie"]) - console.log("cookie fail here") - console.log(cookie.parse(action.request.headers["cookie"])) throw new IllegalJWTError(); } @@ -65,8 +59,6 @@ const refresh = async (action: Action) => { try { jwtPayload = jwt.verify(refresh_token, config.jwt_secret); } catch (error) { - console.log(refresh_token); - console.log("jwt fail") throw new IllegalJWTError(); } From 7b4e89555ea138acc9908b218491c5b913f1a168 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 18:47:11 +0100 Subject: [PATCH 29/50] Temporary: extended live logging --- src/models/actions/HandleLogout.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/models/actions/HandleLogout.ts b/src/models/actions/HandleLogout.ts index 40bd572..2f4626b 100644 --- a/src/models/actions/HandleLogout.ts +++ b/src/models/actions/HandleLogout.ts @@ -25,6 +25,7 @@ export class HandleLogout { */ public async logout(): Promise { let logout: Logout = new Logout(); + console.log(this.token) if (!this.token || this.token === undefined) { throw new JwtNotProvidedError() } @@ -32,14 +33,17 @@ export class HandleLogout { try { decoded = jsonwebtoken.verify(this.token, config.jwt_secret) } catch (error) { + console.log("decoding error") throw new IllegalJWTError() } logout.timestamp = Math.floor(Date.now() / 1000) let found_user: User = await getConnectionManager().get().getRepository(User).findOne({ id: decoded["id"] }); if (!found_user) { + console.log("user error") throw new UserNotFoundError() } if (found_user.refreshTokenCount !== decoded["refreshTokenCount"]) { + console.log("invalid rtc") throw new RefreshTokenCountInvalidError() } found_user.refreshTokenCount++; From 89926b2c3121ab54213492ec8d0c1749b0f610cf Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 18:47:11 +0100 Subject: [PATCH 30/50] Temporary: extended live logging --- src/models/actions/HandleLogout.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/models/actions/HandleLogout.ts b/src/models/actions/HandleLogout.ts index 40bd572..8437346 100644 --- a/src/models/actions/HandleLogout.ts +++ b/src/models/actions/HandleLogout.ts @@ -25,6 +25,7 @@ export class HandleLogout { */ public async logout(): Promise { let logout: Logout = new Logout(); + console.log(this.token) if (!this.token || this.token === undefined) { throw new JwtNotProvidedError() } @@ -32,18 +33,22 @@ export class HandleLogout { try { decoded = jsonwebtoken.verify(this.token, config.jwt_secret) } catch (error) { + console.log("decoding error") throw new IllegalJWTError() } logout.timestamp = Math.floor(Date.now() / 1000) let found_user: User = await getConnectionManager().get().getRepository(User).findOne({ id: decoded["id"] }); if (!found_user) { + console.log("user error") throw new UserNotFoundError() } if (found_user.refreshTokenCount !== decoded["refreshTokenCount"]) { + console.log("invalid rtc") throw new RefreshTokenCountInvalidError() } found_user.refreshTokenCount++; await getConnectionManager().get().getRepository(User).update({ id: found_user.id }, found_user) + console.log("success") return logout; } } \ No newline at end of file From 8a54b027d059365c1573c34da26dfa8dd5ee4456 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 18:55:16 +0100 Subject: [PATCH 31/50] Reverted temporary logging --- src/models/actions/HandleLogout.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/models/actions/HandleLogout.ts b/src/models/actions/HandleLogout.ts index 8437346..a6d63f4 100644 --- a/src/models/actions/HandleLogout.ts +++ b/src/models/actions/HandleLogout.ts @@ -33,22 +33,18 @@ export class HandleLogout { try { decoded = jsonwebtoken.verify(this.token, config.jwt_secret) } catch (error) { - console.log("decoding error") throw new IllegalJWTError() } logout.timestamp = Math.floor(Date.now() / 1000) let found_user: User = await getConnectionManager().get().getRepository(User).findOne({ id: decoded["id"] }); if (!found_user) { - console.log("user error") throw new UserNotFoundError() } if (found_user.refreshTokenCount !== decoded["refreshTokenCount"]) { - console.log("invalid rtc") throw new RefreshTokenCountInvalidError() } found_user.refreshTokenCount++; await getConnectionManager().get().getRepository(User).update({ id: found_user.id }, found_user) - console.log("success") return logout; } } \ No newline at end of file From 02e3239848a045220f75a7ee3ddd603b5e9a552f Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 9 Jan 2021 18:55:16 +0100 Subject: [PATCH 32/50] Reverted temporary logging --- src/models/actions/HandleLogout.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/models/actions/HandleLogout.ts b/src/models/actions/HandleLogout.ts index 8437346..40bd572 100644 --- a/src/models/actions/HandleLogout.ts +++ b/src/models/actions/HandleLogout.ts @@ -25,7 +25,6 @@ export class HandleLogout { */ public async logout(): Promise { let logout: Logout = new Logout(); - console.log(this.token) if (!this.token || this.token === undefined) { throw new JwtNotProvidedError() } @@ -33,22 +32,18 @@ export class HandleLogout { try { decoded = jsonwebtoken.verify(this.token, config.jwt_secret) } catch (error) { - console.log("decoding error") throw new IllegalJWTError() } logout.timestamp = Math.floor(Date.now() / 1000) let found_user: User = await getConnectionManager().get().getRepository(User).findOne({ id: decoded["id"] }); if (!found_user) { - console.log("user error") throw new UserNotFoundError() } if (found_user.refreshTokenCount !== decoded["refreshTokenCount"]) { - console.log("invalid rtc") throw new RefreshTokenCountInvalidError() } found_user.refreshTokenCount++; await getConnectionManager().get().getRepository(User).update({ id: found_user.id }, found_user) - console.log("success") return logout; } } \ No newline at end of file From f96b256ad3ed492367eb4087c6537a9ca116e3cc Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 16:03:56 +0100 Subject: [PATCH 33/50] Fixed some typos and extended comments for the middlewares ref #76 --- src/middlewares/RawBody.ts | 4 ++-- src/middlewares/ScanAuth.ts | 9 +++++---- src/middlewares/StatsAuth.ts | 5 +++-- src/middlewares/authchecker.ts | 4 ++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/middlewares/RawBody.ts b/src/middlewares/RawBody.ts index 57efefa..52f6664 100644 --- a/src/middlewares/RawBody.ts +++ b/src/middlewares/RawBody.ts @@ -1,8 +1,8 @@ import { Request, Response } from 'express'; /** - * Custom express middleware that appends the raw body to the request obeject. - * Mainly used for parsing csvs from boddies. + * Custom express middleware that appends the raw body to the request object. + * Mainly used for parsing csvs from bodies. */ const RawBodyMiddleware = (req: Request, res: Response, next: () => void) => { diff --git a/src/middlewares/ScanAuth.ts b/src/middlewares/ScanAuth.ts index 7b16420..2f39bbf 100644 --- a/src/middlewares/ScanAuth.ts +++ b/src/middlewares/ScanAuth.ts @@ -5,8 +5,9 @@ import { ScanStation } from '../models/entities/ScanStation'; import authchecker from './authchecker'; /** - * This middleware handels the authentification of scan station api tokens. - * The tokens have to be provided via Bearer auth header. + * This middleware handles the authentication of scan station api tokens. + * The tokens have to be provided via Bearer authorization header. + * You have to manually use this middleware via @UseBefore(ScanAuth) instead of using @Authorized(). * @param req Express request object. * @param res Express response object. * @param next Next function to call on success. @@ -31,7 +32,7 @@ const ScanAuth = async (req: Request, res: Response, next: () => void) => { } finally { if (prefix == "" || prefix == undefined || prefix == null) { - res.status(401).send("Api token non-existant or invalid syntax."); + res.status(401).send("Api token non-existent or invalid syntax."); return; } } @@ -45,7 +46,7 @@ const ScanAuth = async (req: Request, res: Response, next: () => void) => { } finally { if (user_authorized == false) { - res.status(401).send("Api token non-existant or invalid syntax."); + res.status(401).send("Api token non-existent or invalid syntax."); return; } else { diff --git a/src/middlewares/StatsAuth.ts b/src/middlewares/StatsAuth.ts index 990206b..a6928be 100644 --- a/src/middlewares/StatsAuth.ts +++ b/src/middlewares/StatsAuth.ts @@ -5,8 +5,9 @@ import { StatsClient } from '../models/entities/StatsClient'; import authchecker from './authchecker'; /** - * This middleware handels the authentification of stats client api tokens. - * The tokens have to be provided via Bearer auth header. + * This middleware handles the authentication of stats client api tokens. + * The tokens have to be provided via Bearer authorization header. + * You have to manually use this middleware via @UseBefore(StatsAuth) instead of using @Authorized(). * @param req Express request object. * @param res Express response object. * @param next Next function to call on success. diff --git a/src/middlewares/authchecker.ts b/src/middlewares/authchecker.ts index 61ca231..45294d9 100644 --- a/src/middlewares/authchecker.ts +++ b/src/middlewares/authchecker.ts @@ -8,7 +8,7 @@ import { JwtCreator, JwtUser } from '../jwtcreator'; import { User } from '../models/entities/User'; /** - * Handels authorisation verification via jwt's for all api endpoints using the @Authorized decorator. + * Handles authentication via jwt's (Bearer authorization header) for all api endpoints using the @Authorized decorator. * @param action Routing-Controllers action object that provides request and response objects among other stuff. * @param permissions The permissions that the endpoint using @Authorized requires. */ @@ -43,7 +43,7 @@ const authchecker = async (action: Action, permissions: string[] | string) => { } /** - * Handels soft-refreshing of access-tokens. + * Handles soft-refreshing of access-tokens. * @param action Routing-Controllers action object that provides request and response objects among other stuff. */ const refresh = async (action: Action) => { From ee9df21ae53cb4c4787f6605ba981bdff909f9f3 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 16:07:37 +0100 Subject: [PATCH 34/50] Fixed some typos in errors ref #76 --- src/errors/AddressErrors.ts | 4 ++-- src/errors/AuthError.ts | 2 +- src/errors/GroupContactErrors.ts | 2 +- src/errors/PrincipalErrors.ts | 4 ++-- src/errors/RunnerCardErrors.ts | 4 ++-- src/errors/RunnerErrors.ts | 2 +- src/errors/RunnerOrganisationErrors.ts | 2 +- src/errors/ScanStationErrors.ts | 2 +- src/errors/StatsClientErrors.ts | 2 +- src/errors/UserGroupErrors.ts | 10 +++++----- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/errors/AddressErrors.ts b/src/errors/AddressErrors.ts index 18cf624..27f2e5f 100644 --- a/src/errors/AddressErrors.ts +++ b/src/errors/AddressErrors.ts @@ -9,11 +9,11 @@ export class AddressWrongTypeError extends NotAcceptableError { name = "AddressWrongTypeError" @IsString() - message = "The address must be an existing adress's id. \n You provided a object of another type." + message = "The address must be an existing address's id. \n You provided a object of another type." } /** - * Error to throw, when a non-existant address get's loaded. + * Error to throw, when a non-existent address get's loaded. */ export class AddressNotFoundError extends NotFoundError { @IsString() diff --git a/src/errors/AuthError.ts b/src/errors/AuthError.ts index 848ce78..6e3cd9d 100644 --- a/src/errors/AuthError.ts +++ b/src/errors/AuthError.ts @@ -118,7 +118,7 @@ export class RefreshTokenCountInvalidError extends NotAcceptableError { } /** - * Error to throw when someone tryes to reset a user's password more than once in 15 minutes. + * Error to throw when someone tries to reset a user's password more than once in 15 minutes. */ export class ResetAlreadyRequestedError extends NotAcceptableError { @IsString() diff --git a/src/errors/GroupContactErrors.ts b/src/errors/GroupContactErrors.ts index 7dc19e8..92fd4a2 100644 --- a/src/errors/GroupContactErrors.ts +++ b/src/errors/GroupContactErrors.ts @@ -13,7 +13,7 @@ export class GroupContactWrongTypeError extends NotAcceptableError { } /** - * Error to throw, when a non-existant groupContact get's loaded. + * Error to throw, when a non-existent groupContact get's loaded. */ export class GroupContactNotFoundError extends NotFoundError { @IsString() diff --git a/src/errors/PrincipalErrors.ts b/src/errors/PrincipalErrors.ts index d519dc7..bd7677c 100644 --- a/src/errors/PrincipalErrors.ts +++ b/src/errors/PrincipalErrors.ts @@ -13,12 +13,12 @@ export class PrincipalNotFoundError extends NotFoundError { } /** - * Error to throw, when a provided runnerOrganisation doesn't belong to the accepted types. + * Error to throw, when a provided runner organization doesn't belong to the accepted types. */ export class PrincipalWrongTypeError extends NotAcceptableError { @IsString() name = "PrincipalWrongTypeError" @IsString() - message = "The princial must have an existing principal's id. \n You provided a object of another type." + message = "The principal must have an existing principal's id. \n You provided a object of another type." } diff --git a/src/errors/RunnerCardErrors.ts b/src/errors/RunnerCardErrors.ts index 63c3485..7976dc9 100644 --- a/src/errors/RunnerCardErrors.ts +++ b/src/errors/RunnerCardErrors.ts @@ -32,12 +32,12 @@ export class RunnerCardHasScansError extends NotAcceptableError { name = "RunnerCardHasScansError" @IsString() - message = "This card still has scans associated with it. \n If you want to delete this card with all it's scans add `?force` to your query. \n Otherwise please consider just diableing it." + message = "This card still has scans associated with it. \n If you want to delete this card with all it's scans add `?force` to your query. \n Otherwise please consider just disabling it." } /** * Error to throw when a card's id is too big to generate a ean-13 barcode for it. - * This error should never reach a enduser. + * This error should never reach a end user. */ export class RunnerCardIdOutOfRangeError extends Error { @IsString() diff --git a/src/errors/RunnerErrors.ts b/src/errors/RunnerErrors.ts index 6ef12c5..b60a70d 100644 --- a/src/errors/RunnerErrors.ts +++ b/src/errors/RunnerErrors.ts @@ -32,5 +32,5 @@ export class RunnerGroupNeededError extends NotAcceptableError { name = "RunnerGroupNeededError" @IsString() - message = "Runner's need to be part of one group (team or organisiation)! \n You provided neither." + message = "Runner's need to be part of one group (team or organisation)! \n You provided neither." } \ No newline at end of file diff --git a/src/errors/RunnerOrganisationErrors.ts b/src/errors/RunnerOrganisationErrors.ts index b004acf..081fbf0 100644 --- a/src/errors/RunnerOrganisationErrors.ts +++ b/src/errors/RunnerOrganisationErrors.ts @@ -13,7 +13,7 @@ export class RunnerOrganisationNotFoundError extends NotFoundError { } /** - * Error to throw when two runner organisations' ids don't match. + * Error to throw when two runner organisation's ids don't match. * Usually occurs when a user tries to change a runner organisation's id. */ export class RunnerOrganisationIdsNotMatchingError extends NotAcceptableError { diff --git a/src/errors/ScanStationErrors.ts b/src/errors/ScanStationErrors.ts index c013cf5..3b01f5e 100644 --- a/src/errors/ScanStationErrors.ts +++ b/src/errors/ScanStationErrors.ts @@ -2,7 +2,7 @@ import { IsString } from 'class-validator'; import { NotAcceptableError, NotFoundError } from 'routing-controllers'; /** - * Error to throw, when a non-existant scan station get's loaded. + * Error to throw, when a non-existent scan station get's loaded. */ export class ScanStationNotFoundError extends NotFoundError { @IsString() diff --git a/src/errors/StatsClientErrors.ts b/src/errors/StatsClientErrors.ts index ab7f1ef..68a088d 100644 --- a/src/errors/StatsClientErrors.ts +++ b/src/errors/StatsClientErrors.ts @@ -2,7 +2,7 @@ import { IsString } from 'class-validator'; import { NotAcceptableError, NotFoundError } from 'routing-controllers'; /** - * Error to throw, when a non-existant stats client get's loaded. + * Error to throw, when a non-existent stats client get's loaded. */ export class StatsClientNotFoundError extends NotFoundError { @IsString() diff --git a/src/errors/UserGroupErrors.ts b/src/errors/UserGroupErrors.ts index 7edd6fd..07f4224 100644 --- a/src/errors/UserGroupErrors.ts +++ b/src/errors/UserGroupErrors.ts @@ -2,7 +2,7 @@ import { IsString } from 'class-validator'; import { NotAcceptableError, NotFoundError } from 'routing-controllers'; /** - * Error to throw when no groupname is set. + * Error to throw when no group name is set. */ export class GroupNameNeededError extends NotFoundError { @IsString() @@ -13,7 +13,7 @@ export class GroupNameNeededError extends NotFoundError { } /** - * Error to throw when a usergroup couldn't be found. + * Error to throw when a user group couldn't be found. */ export class UserGroupNotFoundError extends NotFoundError { @IsString() @@ -24,13 +24,13 @@ export class UserGroupNotFoundError extends NotFoundError { } /** - * Error to throw when two usergroups' ids don't match. - * Usually occurs when a user tries to change a usergroups's id. + * Error to throw when two user groups' ids don't match. + * Usually occurs when a user tries to change a user groups's id. */ export class UserGroupIdsNotMatchingError extends NotAcceptableError { @IsString() name = "UserGroupIdsNotMatchingError" @IsString() - message = "The ids don't match!! \n If you wanted to change a usergroup's id: This isn't allowed!" + message = "The ids don't match!! \n If you wanted to change a user group's id: This isn't allowed!" } \ No newline at end of file From 3bc172e7e0633a662811787f66bf30fbcf533868 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 16:10:02 +0100 Subject: [PATCH 35/50] Intruduced a new folder structure for action models ref #76 --- src/controllers/DonorController.ts | 2 +- .../actions/{ => create}/CreateAddress.ts | 4 +- src/models/actions/{ => create}/CreateAuth.ts | 0 .../actions/{ => create}/CreateDonor.ts | 0 .../{ => create}/CreateGroupContact.ts | 168 +++++------ .../actions/{ => create}/CreateParticipant.ts | 142 +++++----- .../actions/{ => create}/CreatePermission.ts | 0 .../actions/{ => create}/CreateResetToken.ts | 0 .../actions/{ => create}/CreateRunner.ts | 0 .../actions/{ => create}/CreateRunnerCard.ts | 0 .../actions/{ => create}/CreateRunnerGroup.ts | 0 .../{ => create}/CreateRunnerOrganisation.ts | 0 .../actions/{ => create}/CreateRunnerTeam.ts | 0 src/models/actions/{ => create}/CreateScan.ts | 0 .../actions/{ => create}/CreateScanStation.ts | 0 .../actions/{ => create}/CreateStatsClient.ts | 0 .../actions/{ => create}/CreateTrack.ts | 0 .../actions/{ => create}/CreateTrackScan.ts | 0 src/models/actions/{ => create}/CreateUser.ts | 262 +++++++++--------- .../actions/{ => create}/CreateUserGroup.ts | 0 .../actions/{ => update}/UpdateDonor.ts | 4 +- .../actions/{ => update}/UpdatePermission.ts | 0 .../actions/{ => update}/UpdateRunner.ts | 0 .../actions/{ => update}/UpdateRunnerCard.ts | 0 .../{ => update}/UpdateRunnerOrganisation.ts | 0 .../actions/{ => update}/UpdateRunnerTeam.ts | 0 src/models/actions/{ => update}/UpdateScan.ts | 0 .../actions/{ => update}/UpdateScanStation.ts | 0 .../actions/{ => update}/UpdateTrack.ts | 0 .../actions/{ => update}/UpdateTrackScan.ts | 0 src/models/actions/{ => update}/UpdateUser.ts | 0 31 files changed, 291 insertions(+), 291 deletions(-) rename src/models/actions/{ => create}/CreateAddress.ts (94%) rename src/models/actions/{ => create}/CreateAuth.ts (100%) rename src/models/actions/{ => create}/CreateDonor.ts (100%) rename src/models/actions/{ => create}/CreateGroupContact.ts (96%) rename src/models/actions/{ => create}/CreateParticipant.ts (96%) rename src/models/actions/{ => create}/CreatePermission.ts (100%) rename src/models/actions/{ => create}/CreateResetToken.ts (100%) rename src/models/actions/{ => create}/CreateRunner.ts (100%) rename src/models/actions/{ => create}/CreateRunnerCard.ts (100%) rename src/models/actions/{ => create}/CreateRunnerGroup.ts (100%) rename src/models/actions/{ => create}/CreateRunnerOrganisation.ts (100%) rename src/models/actions/{ => create}/CreateRunnerTeam.ts (100%) rename src/models/actions/{ => create}/CreateScan.ts (100%) rename src/models/actions/{ => create}/CreateScanStation.ts (100%) rename src/models/actions/{ => create}/CreateStatsClient.ts (100%) rename src/models/actions/{ => create}/CreateTrack.ts (100%) rename src/models/actions/{ => create}/CreateTrackScan.ts (100%) rename src/models/actions/{ => create}/CreateUser.ts (96%) rename src/models/actions/{ => create}/CreateUserGroup.ts (100%) rename src/models/actions/{ => update}/UpdateDonor.ts (90%) rename src/models/actions/{ => update}/UpdatePermission.ts (100%) rename src/models/actions/{ => update}/UpdateRunner.ts (100%) rename src/models/actions/{ => update}/UpdateRunnerCard.ts (100%) rename src/models/actions/{ => update}/UpdateRunnerOrganisation.ts (100%) rename src/models/actions/{ => update}/UpdateRunnerTeam.ts (100%) rename src/models/actions/{ => update}/UpdateScan.ts (100%) rename src/models/actions/{ => update}/UpdateScanStation.ts (100%) rename src/models/actions/{ => update}/UpdateTrack.ts (100%) rename src/models/actions/{ => update}/UpdateTrackScan.ts (100%) rename src/models/actions/{ => update}/UpdateUser.ts (100%) diff --git a/src/controllers/DonorController.ts b/src/controllers/DonorController.ts index 54a5ba4..078d37a 100644 --- a/src/controllers/DonorController.ts +++ b/src/controllers/DonorController.ts @@ -3,7 +3,7 @@ import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { DonorIdsNotMatchingError, DonorNotFoundError } from '../errors/DonorErrors'; import { CreateDonor } from '../models/actions/CreateDonor'; -import { UpdateDonor } from '../models/actions/UpdateDonor'; +import { UpdateDonor } from '../models/actions/update/UpdateDonor'; import { Donor } from '../models/entities/Donor'; import { ResponseDonor } from '../models/responses/ResponseDonor'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; diff --git a/src/models/actions/CreateAddress.ts b/src/models/actions/create/CreateAddress.ts similarity index 94% rename from src/models/actions/CreateAddress.ts rename to src/models/actions/create/CreateAddress.ts index 66ee9bd..365035e 100644 --- a/src/models/actions/CreateAddress.ts +++ b/src/models/actions/create/CreateAddress.ts @@ -1,6 +1,6 @@ import { IsNotEmpty, IsOptional, IsPostalCode, IsString } from 'class-validator'; -import { config } from '../../config'; -import { Address } from '../entities/Address'; +import { config } from '../../../config'; +import { Address } from '../../entities/Address'; /** * This classed is used to create a new Address entity from a json body (post request). diff --git a/src/models/actions/CreateAuth.ts b/src/models/actions/create/CreateAuth.ts similarity index 100% rename from src/models/actions/CreateAuth.ts rename to src/models/actions/create/CreateAuth.ts diff --git a/src/models/actions/CreateDonor.ts b/src/models/actions/create/CreateDonor.ts similarity index 100% rename from src/models/actions/CreateDonor.ts rename to src/models/actions/create/CreateDonor.ts diff --git a/src/models/actions/CreateGroupContact.ts b/src/models/actions/create/CreateGroupContact.ts similarity index 96% rename from src/models/actions/CreateGroupContact.ts rename to src/models/actions/create/CreateGroupContact.ts index 915f897..711d14a 100644 --- a/src/models/actions/CreateGroupContact.ts +++ b/src/models/actions/create/CreateGroupContact.ts @@ -1,85 +1,85 @@ -import { IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; -import { getConnectionManager } from 'typeorm'; -import { config } from '../../config'; -import { AddressNotFoundError, AddressWrongTypeError } from '../../errors/AddressErrors'; -import { Address } from '../entities/Address'; -import { GroupContact } from '../entities/GroupContact'; - -/** - * This classed is used to create a new Group entity from a json body (post request). - */ -export class CreateGroupContact { - /** - * The new contact's first name. - */ - @IsNotEmpty() - @IsString() - firstname: string; - - /** - * The new contact's middle name. - */ - @IsOptional() - @IsString() - middlename?: string; - - /** - * The new contact's last name. - */ - @IsNotEmpty() - @IsString() - lastname: string; - - /** - * The new contact's address. - * Must be the address's id. - */ - @IsInt() - @IsOptional() - address?: number; - - /** - * The contact's phone number. - * This will be validated against the configured country phone numer syntax (default: international). - */ - @IsOptional() - @IsPhoneNumber(config.phone_validation_countrycode) - phone?: string; - - /** - * The contact's email address. - */ - @IsOptional() - @IsEmail() - email?: string; - - /** - * Gets the new contact's address by it's id. - */ - public async getAddress(): Promise
{ - if (this.address === undefined || this.address === null) { - return null; - } - if (!isNaN(this.address)) { - let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address }); - if (!address) { throw new AddressNotFoundError; } - return address; - } - - throw new AddressWrongTypeError; - } - - /** - * Creates a new Address entity from this. - */ - public async toGroupContact(): Promise { - let contact: GroupContact = new GroupContact(); - contact.firstname = this.firstname; - contact.middlename = this.middlename; - contact.lastname = this.lastname; - contact.email = this.email; - contact.phone = this.phone; - contact.address = await this.getAddress(); - return null; - } +import { IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; +import { getConnectionManager } from 'typeorm'; +import { config } from '../../config'; +import { AddressNotFoundError, AddressWrongTypeError } from '../../errors/AddressErrors'; +import { Address } from '../entities/Address'; +import { GroupContact } from '../entities/GroupContact'; + +/** + * This classed is used to create a new Group entity from a json body (post request). + */ +export class CreateGroupContact { + /** + * The new contact's first name. + */ + @IsNotEmpty() + @IsString() + firstname: string; + + /** + * The new contact's middle name. + */ + @IsOptional() + @IsString() + middlename?: string; + + /** + * The new contact's last name. + */ + @IsNotEmpty() + @IsString() + lastname: string; + + /** + * The new contact's address. + * Must be the address's id. + */ + @IsInt() + @IsOptional() + address?: number; + + /** + * The contact's phone number. + * This will be validated against the configured country phone numer syntax (default: international). + */ + @IsOptional() + @IsPhoneNumber(config.phone_validation_countrycode) + phone?: string; + + /** + * The contact's email address. + */ + @IsOptional() + @IsEmail() + email?: string; + + /** + * Gets the new contact's address by it's id. + */ + public async getAddress(): Promise
{ + if (this.address === undefined || this.address === null) { + return null; + } + if (!isNaN(this.address)) { + let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address }); + if (!address) { throw new AddressNotFoundError; } + return address; + } + + throw new AddressWrongTypeError; + } + + /** + * Creates a new Address entity from this. + */ + public async toGroupContact(): Promise { + let contact: GroupContact = new GroupContact(); + contact.firstname = this.firstname; + contact.middlename = this.middlename; + contact.lastname = this.lastname; + contact.email = this.email; + contact.phone = this.phone; + contact.address = await this.getAddress(); + return null; + } } \ No newline at end of file diff --git a/src/models/actions/CreateParticipant.ts b/src/models/actions/create/CreateParticipant.ts similarity index 96% rename from src/models/actions/CreateParticipant.ts rename to src/models/actions/create/CreateParticipant.ts index 165bddb..cba347a 100644 --- a/src/models/actions/CreateParticipant.ts +++ b/src/models/actions/create/CreateParticipant.ts @@ -1,72 +1,72 @@ -import { IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; -import { getConnectionManager } from 'typeorm'; -import { config } from '../../config'; -import { AddressNotFoundError, AddressWrongTypeError } from '../../errors/AddressErrors'; -import { Address } from '../entities/Address'; - -/** - * This classed is used to create a new Participant entity from a json body (post request). - */ -export abstract class CreateParticipant { - /** - * The new participant's first name. - */ - @IsString() - @IsNotEmpty() - firstname: string; - - /** - * The new participant's middle name. - */ - @IsString() - @IsOptional() - middlename?: string; - - /** - * The new participant's last name. - */ - @IsString() - @IsNotEmpty() - lastname: string; - - /** - * The new participant's phone number. - * This will be validated against the configured country phone numer syntax (default: international). - */ - @IsString() - @IsOptional() - @IsPhoneNumber(config.phone_validation_countrycode) - phone?: string; - - /** - * The new participant's e-mail address. - */ - @IsString() - @IsOptional() - @IsEmail() - email?: string; - - /** - * The new participant's address. - * Must be of type number (address id). - */ - @IsInt() - @IsOptional() - address?: number; - - /** - * Gets the new participant's address by it's address. - */ - public async getAddress(): Promise
{ - if (this.address === undefined || this.address === null) { - return null; - } - if (!isNaN(this.address)) { - let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address }); - if (!address) { throw new AddressNotFoundError; } - return address; - } - - throw new AddressWrongTypeError; - } +import { IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; +import { getConnectionManager } from 'typeorm'; +import { config } from '../../config'; +import { AddressNotFoundError, AddressWrongTypeError } from '../../errors/AddressErrors'; +import { Address } from '../entities/Address'; + +/** + * This classed is used to create a new Participant entity from a json body (post request). + */ +export abstract class CreateParticipant { + /** + * The new participant's first name. + */ + @IsString() + @IsNotEmpty() + firstname: string; + + /** + * The new participant's middle name. + */ + @IsString() + @IsOptional() + middlename?: string; + + /** + * The new participant's last name. + */ + @IsString() + @IsNotEmpty() + lastname: string; + + /** + * The new participant's phone number. + * This will be validated against the configured country phone numer syntax (default: international). + */ + @IsString() + @IsOptional() + @IsPhoneNumber(config.phone_validation_countrycode) + phone?: string; + + /** + * The new participant's e-mail address. + */ + @IsString() + @IsOptional() + @IsEmail() + email?: string; + + /** + * The new participant's address. + * Must be of type number (address id). + */ + @IsInt() + @IsOptional() + address?: number; + + /** + * Gets the new participant's address by it's address. + */ + public async getAddress(): Promise
{ + if (this.address === undefined || this.address === null) { + return null; + } + if (!isNaN(this.address)) { + let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address }); + if (!address) { throw new AddressNotFoundError; } + return address; + } + + throw new AddressWrongTypeError; + } } \ No newline at end of file diff --git a/src/models/actions/CreatePermission.ts b/src/models/actions/create/CreatePermission.ts similarity index 100% rename from src/models/actions/CreatePermission.ts rename to src/models/actions/create/CreatePermission.ts diff --git a/src/models/actions/CreateResetToken.ts b/src/models/actions/create/CreateResetToken.ts similarity index 100% rename from src/models/actions/CreateResetToken.ts rename to src/models/actions/create/CreateResetToken.ts diff --git a/src/models/actions/CreateRunner.ts b/src/models/actions/create/CreateRunner.ts similarity index 100% rename from src/models/actions/CreateRunner.ts rename to src/models/actions/create/CreateRunner.ts diff --git a/src/models/actions/CreateRunnerCard.ts b/src/models/actions/create/CreateRunnerCard.ts similarity index 100% rename from src/models/actions/CreateRunnerCard.ts rename to src/models/actions/create/CreateRunnerCard.ts diff --git a/src/models/actions/CreateRunnerGroup.ts b/src/models/actions/create/CreateRunnerGroup.ts similarity index 100% rename from src/models/actions/CreateRunnerGroup.ts rename to src/models/actions/create/CreateRunnerGroup.ts diff --git a/src/models/actions/CreateRunnerOrganisation.ts b/src/models/actions/create/CreateRunnerOrganisation.ts similarity index 100% rename from src/models/actions/CreateRunnerOrganisation.ts rename to src/models/actions/create/CreateRunnerOrganisation.ts diff --git a/src/models/actions/CreateRunnerTeam.ts b/src/models/actions/create/CreateRunnerTeam.ts similarity index 100% rename from src/models/actions/CreateRunnerTeam.ts rename to src/models/actions/create/CreateRunnerTeam.ts diff --git a/src/models/actions/CreateScan.ts b/src/models/actions/create/CreateScan.ts similarity index 100% rename from src/models/actions/CreateScan.ts rename to src/models/actions/create/CreateScan.ts diff --git a/src/models/actions/CreateScanStation.ts b/src/models/actions/create/CreateScanStation.ts similarity index 100% rename from src/models/actions/CreateScanStation.ts rename to src/models/actions/create/CreateScanStation.ts diff --git a/src/models/actions/CreateStatsClient.ts b/src/models/actions/create/CreateStatsClient.ts similarity index 100% rename from src/models/actions/CreateStatsClient.ts rename to src/models/actions/create/CreateStatsClient.ts diff --git a/src/models/actions/CreateTrack.ts b/src/models/actions/create/CreateTrack.ts similarity index 100% rename from src/models/actions/CreateTrack.ts rename to src/models/actions/create/CreateTrack.ts diff --git a/src/models/actions/CreateTrackScan.ts b/src/models/actions/create/CreateTrackScan.ts similarity index 100% rename from src/models/actions/CreateTrackScan.ts rename to src/models/actions/create/CreateTrackScan.ts diff --git a/src/models/actions/CreateUser.ts b/src/models/actions/create/CreateUser.ts similarity index 96% rename from src/models/actions/CreateUser.ts rename to src/models/actions/create/CreateUser.ts index ad0f905..838d1e0 100644 --- a/src/models/actions/CreateUser.ts +++ b/src/models/actions/create/CreateUser.ts @@ -1,132 +1,132 @@ -import * as argon2 from "argon2"; -import { IsBoolean, IsEmail, IsOptional, IsPhoneNumber, IsString, IsUrl } from 'class-validator'; -import { getConnectionManager } from 'typeorm'; -import * as uuid from 'uuid'; -import { config } from '../../config'; -import { UsernameOrEmailNeededError } from '../../errors/UserErrors'; -import { UserGroupNotFoundError } from '../../errors/UserGroupErrors'; -import { User } from '../entities/User'; -import { UserGroup } from '../entities/UserGroup'; - -/** - * This classed is used to create a new User entity from a json body (post request). - */ -export class CreateUser { - /** - * The new user's first name. - */ - @IsString() - firstname: string; - - /** - * The new user's middle name. - */ - @IsString() - @IsOptional() - middlename?: string; - - /** - * The new user's last name. - */ - @IsString() - lastname: string; - - /** - * The new user's username. - * You have to provide at least one of: {email, username}. - */ - @IsOptional() - @IsString() - username?: string; - - /** - * The new user's email address. - * You have to provide at least one of: {email, username}. - */ - @IsEmail() - @IsString() - @IsOptional() - email?: string; - - /** - * The new user's phone number. - * This will be validated against the configured country phone numer syntax (default: international). - */ - @IsPhoneNumber(config.phone_validation_countrycode) - @IsOptional() - phone?: string; - - /** - * The new user's password. - * This will of course not be saved in plaintext :) - */ - @IsString() - password: string; - - /** - * Will the new user be enabled from the start? - * Default: true - */ - @IsBoolean() - @IsOptional() - enabled?: boolean = true; - - /** - * The new user's groups' id(s). - * You can provide either one groupId or an array of groupIDs. - */ - @IsOptional() - groups?: number[] | number - - /** - * The user's profile pic (or rather a url pointing to it). - */ - @IsString() - @IsUrl() - @IsOptional() - profilePic?: string; - - /** - * Converts this to a User entity. - */ - public async toUser(): Promise { - let newUser: User = new User(); - - if (this.email === undefined && this.username === undefined) { - throw new UsernameOrEmailNeededError(); - } - - newUser.email = this.email - newUser.username = this.username - newUser.firstname = this.firstname - newUser.middlename = this.middlename - newUser.lastname = this.lastname - newUser.uuid = uuid.v4() - newUser.phone = this.phone - newUser.password = await argon2.hash(this.password + newUser.uuid); - newUser.groups = await this.getGroups(); - newUser.enabled = this.enabled; - - if (!this.profilePic) { newUser.profilePic = `https://dev.lauf-fuer-kaya.de/lfk-logo.png`; } - else { newUser.profilePic = this.profilePic; } - - return newUser; - } - - /** - * Get's all groups for this user by their id's; - */ - public async getGroups() { - if (!this.groups) { return null; } - let groups = new Array(); - if (!Array.isArray(this.groups)) { - this.groups = [this.groups] - } - for (let group of this.groups) { - let found = await getConnectionManager().get().getRepository(UserGroup).findOne({ id: group }); - if (!found) { throw new UserGroupNotFoundError(); } - groups.push(found); - } - return groups; - } +import * as argon2 from "argon2"; +import { IsBoolean, IsEmail, IsOptional, IsPhoneNumber, IsString, IsUrl } from 'class-validator'; +import { getConnectionManager } from 'typeorm'; +import * as uuid from 'uuid'; +import { config } from '../../config'; +import { UsernameOrEmailNeededError } from '../../errors/UserErrors'; +import { UserGroupNotFoundError } from '../../errors/UserGroupErrors'; +import { User } from '../entities/User'; +import { UserGroup } from '../entities/UserGroup'; + +/** + * This classed is used to create a new User entity from a json body (post request). + */ +export class CreateUser { + /** + * The new user's first name. + */ + @IsString() + firstname: string; + + /** + * The new user's middle name. + */ + @IsString() + @IsOptional() + middlename?: string; + + /** + * The new user's last name. + */ + @IsString() + lastname: string; + + /** + * The new user's username. + * You have to provide at least one of: {email, username}. + */ + @IsOptional() + @IsString() + username?: string; + + /** + * The new user's email address. + * You have to provide at least one of: {email, username}. + */ + @IsEmail() + @IsString() + @IsOptional() + email?: string; + + /** + * The new user's phone number. + * This will be validated against the configured country phone numer syntax (default: international). + */ + @IsPhoneNumber(config.phone_validation_countrycode) + @IsOptional() + phone?: string; + + /** + * The new user's password. + * This will of course not be saved in plaintext :) + */ + @IsString() + password: string; + + /** + * Will the new user be enabled from the start? + * Default: true + */ + @IsBoolean() + @IsOptional() + enabled?: boolean = true; + + /** + * The new user's groups' id(s). + * You can provide either one groupId or an array of groupIDs. + */ + @IsOptional() + groups?: number[] | number + + /** + * The user's profile pic (or rather a url pointing to it). + */ + @IsString() + @IsUrl() + @IsOptional() + profilePic?: string; + + /** + * Converts this to a User entity. + */ + public async toUser(): Promise { + let newUser: User = new User(); + + if (this.email === undefined && this.username === undefined) { + throw new UsernameOrEmailNeededError(); + } + + newUser.email = this.email + newUser.username = this.username + newUser.firstname = this.firstname + newUser.middlename = this.middlename + newUser.lastname = this.lastname + newUser.uuid = uuid.v4() + newUser.phone = this.phone + newUser.password = await argon2.hash(this.password + newUser.uuid); + newUser.groups = await this.getGroups(); + newUser.enabled = this.enabled; + + if (!this.profilePic) { newUser.profilePic = `https://dev.lauf-fuer-kaya.de/lfk-logo.png`; } + else { newUser.profilePic = this.profilePic; } + + return newUser; + } + + /** + * Get's all groups for this user by their id's; + */ + public async getGroups() { + if (!this.groups) { return null; } + let groups = new Array(); + if (!Array.isArray(this.groups)) { + this.groups = [this.groups] + } + for (let group of this.groups) { + let found = await getConnectionManager().get().getRepository(UserGroup).findOne({ id: group }); + if (!found) { throw new UserGroupNotFoundError(); } + groups.push(found); + } + return groups; + } } \ No newline at end of file diff --git a/src/models/actions/CreateUserGroup.ts b/src/models/actions/create/CreateUserGroup.ts similarity index 100% rename from src/models/actions/CreateUserGroup.ts rename to src/models/actions/create/CreateUserGroup.ts diff --git a/src/models/actions/UpdateDonor.ts b/src/models/actions/update/UpdateDonor.ts similarity index 90% rename from src/models/actions/UpdateDonor.ts rename to src/models/actions/update/UpdateDonor.ts index b7139c8..21b2eb1 100644 --- a/src/models/actions/UpdateDonor.ts +++ b/src/models/actions/update/UpdateDonor.ts @@ -1,6 +1,6 @@ import { IsBoolean, IsInt, IsOptional } from 'class-validator'; -import { DonorReceiptAddressNeededError } from '../../errors/DonorErrors'; -import { Donor } from '../entities/Donor'; +import { DonorReceiptAddressNeededError } from '../../../errors/DonorErrors'; +import { Donor } from '../../entities/Donor'; import { CreateParticipant } from './CreateParticipant'; /** diff --git a/src/models/actions/UpdatePermission.ts b/src/models/actions/update/UpdatePermission.ts similarity index 100% rename from src/models/actions/UpdatePermission.ts rename to src/models/actions/update/UpdatePermission.ts diff --git a/src/models/actions/UpdateRunner.ts b/src/models/actions/update/UpdateRunner.ts similarity index 100% rename from src/models/actions/UpdateRunner.ts rename to src/models/actions/update/UpdateRunner.ts diff --git a/src/models/actions/UpdateRunnerCard.ts b/src/models/actions/update/UpdateRunnerCard.ts similarity index 100% rename from src/models/actions/UpdateRunnerCard.ts rename to src/models/actions/update/UpdateRunnerCard.ts diff --git a/src/models/actions/UpdateRunnerOrganisation.ts b/src/models/actions/update/UpdateRunnerOrganisation.ts similarity index 100% rename from src/models/actions/UpdateRunnerOrganisation.ts rename to src/models/actions/update/UpdateRunnerOrganisation.ts diff --git a/src/models/actions/UpdateRunnerTeam.ts b/src/models/actions/update/UpdateRunnerTeam.ts similarity index 100% rename from src/models/actions/UpdateRunnerTeam.ts rename to src/models/actions/update/UpdateRunnerTeam.ts diff --git a/src/models/actions/UpdateScan.ts b/src/models/actions/update/UpdateScan.ts similarity index 100% rename from src/models/actions/UpdateScan.ts rename to src/models/actions/update/UpdateScan.ts diff --git a/src/models/actions/UpdateScanStation.ts b/src/models/actions/update/UpdateScanStation.ts similarity index 100% rename from src/models/actions/UpdateScanStation.ts rename to src/models/actions/update/UpdateScanStation.ts diff --git a/src/models/actions/UpdateTrack.ts b/src/models/actions/update/UpdateTrack.ts similarity index 100% rename from src/models/actions/UpdateTrack.ts rename to src/models/actions/update/UpdateTrack.ts diff --git a/src/models/actions/UpdateTrackScan.ts b/src/models/actions/update/UpdateTrackScan.ts similarity index 100% rename from src/models/actions/UpdateTrackScan.ts rename to src/models/actions/update/UpdateTrackScan.ts diff --git a/src/models/actions/UpdateUser.ts b/src/models/actions/update/UpdateUser.ts similarity index 100% rename from src/models/actions/UpdateUser.ts rename to src/models/actions/update/UpdateUser.ts From a00231dd3ca028c4e36a1825ccb6ee589bddf060 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 16:23:09 +0100 Subject: [PATCH 36/50] Updated imports ref #76 --- src/controllers/AuthController.ts | 4 ++-- src/controllers/DonorController.ts | 2 +- src/controllers/PermissionController.ts | 4 ++-- src/controllers/RunnerCardController.ts | 4 ++-- src/controllers/RunnerController.ts | 4 ++-- src/controllers/RunnerOrganisationController.ts | 4 ++-- src/controllers/RunnerTeamController.ts | 4 ++-- src/controllers/ScanController.ts | 8 ++++---- src/controllers/ScanStationController.ts | 4 ++-- src/controllers/StatsClientController.ts | 2 +- src/controllers/TrackController.ts | 4 ++-- src/controllers/UserController.ts | 4 ++-- src/controllers/UserGroupController.ts | 2 +- src/models/actions/ImportRunner.ts | 2 +- src/models/actions/create/CreateAuth.ts | 10 +++++----- src/models/actions/create/CreateDonor.ts | 4 ++-- src/models/actions/create/CreateGroupContact.ts | 8 ++++---- src/models/actions/create/CreateParticipant.ts | 6 +++--- src/models/actions/create/CreatePermission.ts | 10 +++++----- src/models/actions/create/CreateResetToken.ts | 8 ++++---- src/models/actions/create/CreateRunner.ts | 10 +++++----- src/models/actions/create/CreateRunnerCard.ts | 6 +++--- src/models/actions/create/CreateRunnerGroup.ts | 4 ++-- .../actions/create/CreateRunnerOrganisation.ts | 6 +++--- src/models/actions/create/CreateRunnerTeam.ts | 8 ++++---- src/models/actions/create/CreateScan.ts | 6 +++--- src/models/actions/create/CreateScanStation.ts | 6 +++--- src/models/actions/create/CreateStatsClient.ts | 2 +- src/models/actions/create/CreateTrack.ts | 4 ++-- src/models/actions/create/CreateTrackScan.ts | 12 ++++++------ src/models/actions/create/CreateUser.ts | 10 +++++----- src/models/actions/create/CreateUserGroup.ts | 2 +- src/models/actions/update/UpdateDonor.ts | 2 +- src/models/actions/update/UpdatePermission.ts | 12 ++++++------ src/models/actions/update/UpdateRunner.ts | 12 ++++++------ src/models/actions/update/UpdateRunnerCard.ts | 6 +++--- .../actions/update/UpdateRunnerOrganisation.ts | 8 ++++---- src/models/actions/update/UpdateRunnerTeam.ts | 10 +++++----- src/models/actions/update/UpdateScan.ts | 6 +++--- src/models/actions/update/UpdateScanStation.ts | 2 +- src/models/actions/update/UpdateTrack.ts | 4 ++-- src/models/actions/update/UpdateTrackScan.ts | 10 +++++----- src/models/actions/update/UpdateUser.ts | 10 +++++----- src/seeds/SeedUsers.ts | 6 +++--- 44 files changed, 131 insertions(+), 131 deletions(-) diff --git a/src/controllers/AuthController.ts b/src/controllers/AuthController.ts index 9672de5..5615de9 100644 --- a/src/controllers/AuthController.ts +++ b/src/controllers/AuthController.ts @@ -2,8 +2,8 @@ import { Body, CookieParam, JsonController, Param, Post, Req, Res } from 'routin import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { IllegalJWTError, InvalidCredentialsError, JwtNotProvidedError, PasswordNeededError, RefreshTokenCountInvalidError, UsernameOrEmailNeededError } from '../errors/AuthError'; import { UserNotFoundError } from '../errors/UserErrors'; -import { CreateAuth } from '../models/actions/CreateAuth'; -import { CreateResetToken } from '../models/actions/CreateResetToken'; +import { CreateAuth } from '../models/actions/create/CreateAuth'; +import { CreateResetToken } from '../models/actions/create/CreateResetToken'; import { HandleLogout } from '../models/actions/HandleLogout'; import { RefreshAuth } from '../models/actions/RefreshAuth'; import { ResetPassword } from '../models/actions/ResetPassword'; diff --git a/src/controllers/DonorController.ts b/src/controllers/DonorController.ts index 078d37a..9a13784 100644 --- a/src/controllers/DonorController.ts +++ b/src/controllers/DonorController.ts @@ -2,7 +2,7 @@ import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { DonorIdsNotMatchingError, DonorNotFoundError } from '../errors/DonorErrors'; -import { CreateDonor } from '../models/actions/CreateDonor'; +import { CreateDonor } from '../models/actions/create/CreateDonor'; import { UpdateDonor } from '../models/actions/update/UpdateDonor'; import { Donor } from '../models/entities/Donor'; import { ResponseDonor } from '../models/responses/ResponseDonor'; diff --git a/src/controllers/PermissionController.ts b/src/controllers/PermissionController.ts index 15ad301..9080cac 100644 --- a/src/controllers/PermissionController.ts +++ b/src/controllers/PermissionController.ts @@ -3,8 +3,8 @@ import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { PermissionIdsNotMatchingError, PermissionNeedsPrincipalError, PermissionNotFoundError } from '../errors/PermissionErrors'; import { PrincipalNotFoundError } from '../errors/PrincipalErrors'; -import { CreatePermission } from '../models/actions/CreatePermission'; -import { UpdatePermission } from '../models/actions/UpdatePermission'; +import { CreatePermission } from '../models/actions/create/CreatePermission'; +import { UpdatePermission } from '../models/actions/update/UpdatePermission'; import { Permission } from '../models/entities/Permission'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponsePermission } from '../models/responses/ResponsePermission'; diff --git a/src/controllers/RunnerCardController.ts b/src/controllers/RunnerCardController.ts index 1366bed..ae74e86 100644 --- a/src/controllers/RunnerCardController.ts +++ b/src/controllers/RunnerCardController.ts @@ -3,8 +3,8 @@ import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { RunnerCardHasScansError, RunnerCardIdsNotMatchingError, RunnerCardNotFoundError } from '../errors/RunnerCardErrors'; import { RunnerNotFoundError } from '../errors/RunnerErrors'; -import { CreateRunnerCard } from '../models/actions/CreateRunnerCard'; -import { UpdateRunnerCard } from '../models/actions/UpdateRunnerCard'; +import { CreateRunnerCard } from '../models/actions/create/CreateRunnerCard'; +import { UpdateRunnerCard } from '../models/actions/update/UpdateRunnerCard'; import { RunnerCard } from '../models/entities/RunnerCard'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseRunnerCard } from '../models/responses/ResponseRunnerCard'; diff --git a/src/controllers/RunnerController.ts b/src/controllers/RunnerController.ts index 4e74330..494876c 100644 --- a/src/controllers/RunnerController.ts +++ b/src/controllers/RunnerController.ts @@ -3,8 +3,8 @@ import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { RunnerGroupNeededError, RunnerIdsNotMatchingError, RunnerNotFoundError } from '../errors/RunnerErrors'; import { RunnerGroupNotFoundError } from '../errors/RunnerGroupErrors'; -import { CreateRunner } from '../models/actions/CreateRunner'; -import { UpdateRunner } from '../models/actions/UpdateRunner'; +import { CreateRunner } from '../models/actions/create/CreateRunner'; +import { UpdateRunner } from '../models/actions/update/UpdateRunner'; import { Runner } from '../models/entities/Runner'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseRunner } from '../models/responses/ResponseRunner'; diff --git a/src/controllers/RunnerOrganisationController.ts b/src/controllers/RunnerOrganisationController.ts index e10d415..ac06cbb 100644 --- a/src/controllers/RunnerOrganisationController.ts +++ b/src/controllers/RunnerOrganisationController.ts @@ -2,8 +2,8 @@ import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { RunnerOrganisationHasRunnersError, RunnerOrganisationHasTeamsError, RunnerOrganisationIdsNotMatchingError, RunnerOrganisationNotFoundError } from '../errors/RunnerOrganisationErrors'; -import { CreateRunnerOrganisation } from '../models/actions/CreateRunnerOrganisation'; -import { UpdateRunnerOrganisation } from '../models/actions/UpdateRunnerOrganisation'; +import { CreateRunnerOrganisation } from '../models/actions/create/CreateRunnerOrganisation'; +import { UpdateRunnerOrganisation } from '../models/actions/update/UpdateRunnerOrganisation'; import { RunnerOrganisation } from '../models/entities/RunnerOrganisation'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseRunnerOrganisation } from '../models/responses/ResponseRunnerOrganisation'; diff --git a/src/controllers/RunnerTeamController.ts b/src/controllers/RunnerTeamController.ts index bc99d79..6587a84 100644 --- a/src/controllers/RunnerTeamController.ts +++ b/src/controllers/RunnerTeamController.ts @@ -2,8 +2,8 @@ import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { RunnerTeamHasRunnersError, RunnerTeamIdsNotMatchingError, RunnerTeamNotFoundError } from '../errors/RunnerTeamErrors'; -import { CreateRunnerTeam } from '../models/actions/CreateRunnerTeam'; -import { UpdateRunnerTeam } from '../models/actions/UpdateRunnerTeam'; +import { CreateRunnerTeam } from '../models/actions/create/CreateRunnerTeam'; +import { UpdateRunnerTeam } from '../models/actions/update/UpdateRunnerTeam'; import { RunnerTeam } from '../models/entities/RunnerTeam'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseRunnerTeam } from '../models/responses/ResponseRunnerTeam'; diff --git a/src/controllers/ScanController.ts b/src/controllers/ScanController.ts index 46c7ba1..e5b46fc 100644 --- a/src/controllers/ScanController.ts +++ b/src/controllers/ScanController.ts @@ -5,10 +5,10 @@ import { RunnerNotFoundError } from '../errors/RunnerErrors'; import { ScanIdsNotMatchingError, ScanNotFoundError } from '../errors/ScanErrors'; import { ScanStationNotFoundError } from '../errors/ScanStationErrors'; import ScanAuth from '../middlewares/ScanAuth'; -import { CreateScan } from '../models/actions/CreateScan'; -import { CreateTrackScan } from '../models/actions/CreateTrackScan'; -import { UpdateScan } from '../models/actions/UpdateScan'; -import { UpdateTrackScan } from '../models/actions/UpdateTrackScan'; +import { CreateScan } from '../models/actions/create/CreateScan'; +import { CreateTrackScan } from '../models/actions/create/CreateTrackScan'; +import { UpdateScan } from '../models/actions/update/UpdateScan'; +import { UpdateTrackScan } from '../models/actions/update/UpdateTrackScan'; import { Scan } from '../models/entities/Scan'; import { TrackScan } from '../models/entities/TrackScan'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; diff --git a/src/controllers/ScanStationController.ts b/src/controllers/ScanStationController.ts index df85d0e..2666b64 100644 --- a/src/controllers/ScanStationController.ts +++ b/src/controllers/ScanStationController.ts @@ -3,8 +3,8 @@ import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { ScanStationHasScansError, ScanStationIdsNotMatchingError, ScanStationNotFoundError } from '../errors/ScanStationErrors'; import { TrackNotFoundError } from '../errors/TrackErrors'; -import { CreateScanStation } from '../models/actions/CreateScanStation'; -import { UpdateScanStation } from '../models/actions/UpdateScanStation'; +import { CreateScanStation } from '../models/actions/create/CreateScanStation'; +import { UpdateScanStation } from '../models/actions/update/UpdateScanStation'; import { ScanStation } from '../models/entities/ScanStation'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseScanStation } from '../models/responses/ResponseScanStation'; diff --git a/src/controllers/StatsClientController.ts b/src/controllers/StatsClientController.ts index 1aa46a2..9d9080d 100644 --- a/src/controllers/StatsClientController.ts +++ b/src/controllers/StatsClientController.ts @@ -3,7 +3,7 @@ import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { StatsClientNotFoundError } from '../errors/StatsClientErrors'; import { TrackNotFoundError } from "../errors/TrackErrors"; -import { CreateStatsClient } from '../models/actions/CreateStatsClient'; +import { CreateStatsClient } from '../models/actions/create/CreateStatsClient'; import { StatsClient } from '../models/entities/StatsClient'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseStatsClient } from '../models/responses/ResponseStatsClient'; diff --git a/src/controllers/TrackController.ts b/src/controllers/TrackController.ts index 42feb7c..85416db 100644 --- a/src/controllers/TrackController.ts +++ b/src/controllers/TrackController.ts @@ -2,8 +2,8 @@ import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { TrackHasScanStationsError, TrackIdsNotMatchingError, TrackLapTimeCantBeNegativeError, TrackNotFoundError } from "../errors/TrackErrors"; -import { CreateTrack } from '../models/actions/CreateTrack'; -import { UpdateTrack } from '../models/actions/UpdateTrack'; +import { CreateTrack } from '../models/actions/create/CreateTrack'; +import { UpdateTrack } from '../models/actions/update/UpdateTrack'; import { Track } from '../models/entities/Track'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseTrack } from '../models/responses/ResponseTrack'; diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index c528572..0fbed48 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -3,8 +3,8 @@ import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { UserIdsNotMatchingError, UserNotFoundError } from '../errors/UserErrors'; import { UserGroupNotFoundError } from '../errors/UserGroupErrors'; -import { CreateUser } from '../models/actions/CreateUser'; -import { UpdateUser } from '../models/actions/UpdateUser'; +import { CreateUser } from '../models/actions/create/CreateUser'; +import { UpdateUser } from '../models/actions/update/UpdateUser'; import { User } from '../models/entities/User'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseUser } from '../models/responses/ResponseUser'; diff --git a/src/controllers/UserGroupController.ts b/src/controllers/UserGroupController.ts index 160a99e..f3ae435 100644 --- a/src/controllers/UserGroupController.ts +++ b/src/controllers/UserGroupController.ts @@ -3,7 +3,7 @@ import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { EntityFromBody } from 'typeorm-routing-controllers-extensions'; import { UserGroupIdsNotMatchingError, UserGroupNotFoundError } from '../errors/UserGroupErrors'; -import { CreateUserGroup } from '../models/actions/CreateUserGroup'; +import { CreateUserGroup } from '../models/actions/create/CreateUserGroup'; import { UserGroup } from '../models/entities/UserGroup'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseUserGroup } from '../models/responses/ResponseUserGroup'; diff --git a/src/models/actions/ImportRunner.ts b/src/models/actions/ImportRunner.ts index 3155b0e..b399d90 100644 --- a/src/models/actions/ImportRunner.ts +++ b/src/models/actions/ImportRunner.ts @@ -5,7 +5,7 @@ import { RunnerOrganisationNotFoundError } from '../../errors/RunnerOrganisation import { RunnerGroup } from '../entities/RunnerGroup'; import { RunnerOrganisation } from '../entities/RunnerOrganisation'; import { RunnerTeam } from '../entities/RunnerTeam'; -import { CreateRunner } from './CreateRunner'; +import { CreateRunner } from './create/CreateRunner'; /** * Special class used to import runners from csv files - or json arrays created from csv to be exact. diff --git a/src/models/actions/create/CreateAuth.ts b/src/models/actions/create/CreateAuth.ts index 6b22d7d..e915d1b 100644 --- a/src/models/actions/create/CreateAuth.ts +++ b/src/models/actions/create/CreateAuth.ts @@ -1,11 +1,11 @@ import * as argon2 from "argon2"; import { IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { InvalidCredentialsError, PasswordNeededError, UserDisabledError, UserNotFoundError } from '../../errors/AuthError'; -import { UsernameOrEmailNeededError } from '../../errors/UserErrors'; -import { JwtCreator } from '../../jwtcreator'; -import { User } from '../entities/User'; -import { Auth } from '../responses/ResponseAuth'; +import { InvalidCredentialsError, PasswordNeededError, UserDisabledError, UserNotFoundError } from '../../../errors/AuthError'; +import { UsernameOrEmailNeededError } from '../../../errors/UserErrors'; +import { JwtCreator } from '../../../jwtcreator'; +import { User } from '../../entities/User'; +import { Auth } from '../../responses/ResponseAuth'; /** * This class is used to create auth credentials based on user credentials provided in a json body (post request). diff --git a/src/models/actions/create/CreateDonor.ts b/src/models/actions/create/CreateDonor.ts index 25a631c..2deb10b 100644 --- a/src/models/actions/create/CreateDonor.ts +++ b/src/models/actions/create/CreateDonor.ts @@ -1,6 +1,6 @@ import { IsBoolean, IsOptional } from 'class-validator'; -import { DonorReceiptAddressNeededError } from '../../errors/DonorErrors'; -import { Donor } from '../entities/Donor'; +import { DonorReceiptAddressNeededError } from '../../../errors/DonorErrors'; +import { Donor } from '../../entities/Donor'; import { CreateParticipant } from './CreateParticipant'; /** diff --git a/src/models/actions/create/CreateGroupContact.ts b/src/models/actions/create/CreateGroupContact.ts index 711d14a..fa83bed 100644 --- a/src/models/actions/create/CreateGroupContact.ts +++ b/src/models/actions/create/CreateGroupContact.ts @@ -1,9 +1,9 @@ import { IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { config } from '../../config'; -import { AddressNotFoundError, AddressWrongTypeError } from '../../errors/AddressErrors'; -import { Address } from '../entities/Address'; -import { GroupContact } from '../entities/GroupContact'; +import { config } from '../../../config'; +import { AddressNotFoundError, AddressWrongTypeError } from '../../../errors/AddressErrors'; +import { Address } from '../../entities/Address'; +import { GroupContact } from '../../entities/GroupContact'; /** * This classed is used to create a new Group entity from a json body (post request). diff --git a/src/models/actions/create/CreateParticipant.ts b/src/models/actions/create/CreateParticipant.ts index cba347a..17e7c56 100644 --- a/src/models/actions/create/CreateParticipant.ts +++ b/src/models/actions/create/CreateParticipant.ts @@ -1,8 +1,8 @@ import { IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { config } from '../../config'; -import { AddressNotFoundError, AddressWrongTypeError } from '../../errors/AddressErrors'; -import { Address } from '../entities/Address'; +import { config } from '../../../config'; +import { AddressNotFoundError, AddressWrongTypeError } from '../../../errors/AddressErrors'; +import { Address } from '../../entities/Address'; /** * This classed is used to create a new Participant entity from a json body (post request). diff --git a/src/models/actions/create/CreatePermission.ts b/src/models/actions/create/CreatePermission.ts index 5ee9582..41fddfc 100644 --- a/src/models/actions/create/CreatePermission.ts +++ b/src/models/actions/create/CreatePermission.ts @@ -4,11 +4,11 @@ import { IsNotEmpty } from "class-validator"; import { getConnectionManager } from 'typeorm'; -import { PrincipalNotFoundError } from '../../errors/PrincipalErrors'; -import { Permission } from '../entities/Permission'; -import { Principal } from '../entities/Principal'; -import { PermissionAction } from '../enums/PermissionAction'; -import { PermissionTarget } from '../enums/PermissionTargets'; +import { PrincipalNotFoundError } from '../../../errors/PrincipalErrors'; +import { Permission } from '../../entities/Permission'; +import { Principal } from '../../entities/Principal'; +import { PermissionAction } from '../../enums/PermissionAction'; +import { PermissionTarget } from '../../enums/PermissionTargets'; /** * This classed is used to create a new Permission entity from a json body (post request). diff --git a/src/models/actions/create/CreateResetToken.ts b/src/models/actions/create/CreateResetToken.ts index dcf22f1..81f430a 100644 --- a/src/models/actions/create/CreateResetToken.ts +++ b/src/models/actions/create/CreateResetToken.ts @@ -1,9 +1,9 @@ import { IsEmail, IsOptional, IsString } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { ResetAlreadyRequestedError, UserDisabledError, UserNotFoundError } from '../../errors/AuthError'; -import { UsernameOrEmailNeededError } from '../../errors/UserErrors'; -import { JwtCreator } from '../../jwtcreator'; -import { User } from '../entities/User'; +import { ResetAlreadyRequestedError, UserDisabledError, UserNotFoundError } from '../../../errors/AuthError'; +import { UsernameOrEmailNeededError } from '../../../errors/UserErrors'; +import { JwtCreator } from '../../../jwtcreator'; +import { User } from '../../entities/User'; /** * This calss is used to create password reset tokens for users. diff --git a/src/models/actions/create/CreateRunner.ts b/src/models/actions/create/CreateRunner.ts index ab2cc1f..acd36d4 100644 --- a/src/models/actions/create/CreateRunner.ts +++ b/src/models/actions/create/CreateRunner.ts @@ -1,10 +1,10 @@ import { IsInt } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { RunnerGroupNotFoundError } from '../../errors/RunnerGroupErrors'; -import { RunnerOrganisationWrongTypeError } from '../../errors/RunnerOrganisationErrors'; -import { RunnerTeamNeedsParentError } from '../../errors/RunnerTeamErrors'; -import { Runner } from '../entities/Runner'; -import { RunnerGroup } from '../entities/RunnerGroup'; +import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors'; +import { RunnerOrganisationWrongTypeError } from '../../../errors/RunnerOrganisationErrors'; +import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; +import { Runner } from '../../entities/Runner'; +import { RunnerGroup } from '../../entities/RunnerGroup'; import { CreateParticipant } from './CreateParticipant'; /** diff --git a/src/models/actions/create/CreateRunnerCard.ts b/src/models/actions/create/CreateRunnerCard.ts index 2baf1e9..b661e6f 100644 --- a/src/models/actions/create/CreateRunnerCard.ts +++ b/src/models/actions/create/CreateRunnerCard.ts @@ -1,8 +1,8 @@ import { IsBoolean, IsInt, IsOptional } from 'class-validator'; import { getConnection } from 'typeorm'; -import { RunnerNotFoundError } from '../../errors/RunnerErrors'; -import { Runner } from '../entities/Runner'; -import { RunnerCard } from '../entities/RunnerCard'; +import { RunnerNotFoundError } from '../../../errors/RunnerErrors'; +import { Runner } from '../../entities/Runner'; +import { RunnerCard } from '../../entities/RunnerCard'; /** * This classed is used to create a new RunnerCard entity from a json body (post request). diff --git a/src/models/actions/create/CreateRunnerGroup.ts b/src/models/actions/create/CreateRunnerGroup.ts index 9f4c803..0b62024 100644 --- a/src/models/actions/create/CreateRunnerGroup.ts +++ b/src/models/actions/create/CreateRunnerGroup.ts @@ -1,7 +1,7 @@ import { IsInt, IsNotEmpty, IsOptional, IsString } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { GroupContactNotFoundError, GroupContactWrongTypeError } from '../../errors/GroupContactErrors'; -import { GroupContact } from '../entities/GroupContact'; +import { GroupContactNotFoundError, GroupContactWrongTypeError } from '../../../errors/GroupContactErrors'; +import { GroupContact } from '../../entities/GroupContact'; /** * This classed is used to create a new RunnerGroup entity from a json body (post request). diff --git a/src/models/actions/create/CreateRunnerOrganisation.ts b/src/models/actions/create/CreateRunnerOrganisation.ts index a0733de..426793d 100644 --- a/src/models/actions/create/CreateRunnerOrganisation.ts +++ b/src/models/actions/create/CreateRunnerOrganisation.ts @@ -1,8 +1,8 @@ import { IsInt, IsOptional } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { AddressNotFoundError, AddressWrongTypeError } from '../../errors/AddressErrors'; -import { Address } from '../entities/Address'; -import { RunnerOrganisation } from '../entities/RunnerOrganisation'; +import { AddressNotFoundError, AddressWrongTypeError } from '../../../errors/AddressErrors'; +import { Address } from '../../entities/Address'; +import { RunnerOrganisation } from '../../entities/RunnerOrganisation'; import { CreateRunnerGroup } from './CreateRunnerGroup'; /** diff --git a/src/models/actions/create/CreateRunnerTeam.ts b/src/models/actions/create/CreateRunnerTeam.ts index 30a27b3..a0c955b 100644 --- a/src/models/actions/create/CreateRunnerTeam.ts +++ b/src/models/actions/create/CreateRunnerTeam.ts @@ -1,9 +1,9 @@ import { IsInt, IsNotEmpty } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { RunnerOrganisationNotFoundError, RunnerOrganisationWrongTypeError } from '../../errors/RunnerOrganisationErrors'; -import { RunnerTeamNeedsParentError } from '../../errors/RunnerTeamErrors'; -import { RunnerOrganisation } from '../entities/RunnerOrganisation'; -import { RunnerTeam } from '../entities/RunnerTeam'; +import { RunnerOrganisationNotFoundError, RunnerOrganisationWrongTypeError } from '../../../errors/RunnerOrganisationErrors'; +import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; +import { RunnerOrganisation } from '../../entities/RunnerOrganisation'; +import { RunnerTeam } from '../../entities/RunnerTeam'; import { CreateRunnerGroup } from './CreateRunnerGroup'; /** diff --git a/src/models/actions/create/CreateScan.ts b/src/models/actions/create/CreateScan.ts index e0d0efc..9835924 100644 --- a/src/models/actions/create/CreateScan.ts +++ b/src/models/actions/create/CreateScan.ts @@ -1,8 +1,8 @@ import { IsBoolean, IsInt, IsOptional, IsPositive } from 'class-validator'; import { getConnection } from 'typeorm'; -import { RunnerNotFoundError } from '../../errors/RunnerErrors'; -import { Runner } from '../entities/Runner'; -import { Scan } from '../entities/Scan'; +import { RunnerNotFoundError } from '../../../errors/RunnerErrors'; +import { Runner } from '../../entities/Runner'; +import { Scan } from '../../entities/Scan'; /** * This class is used to create a new Scan entity from a json body (post request). diff --git a/src/models/actions/create/CreateScanStation.ts b/src/models/actions/create/CreateScanStation.ts index 5d93b7c..0804b9f 100644 --- a/src/models/actions/create/CreateScanStation.ts +++ b/src/models/actions/create/CreateScanStation.ts @@ -3,9 +3,9 @@ import { IsBoolean, IsInt, IsOptional, IsPositive, IsString } from 'class-valida import crypto from 'crypto'; import { getConnection } from 'typeorm'; import * as uuid from 'uuid'; -import { TrackNotFoundError } from '../../errors/TrackErrors'; -import { ScanStation } from '../entities/ScanStation'; -import { Track } from '../entities/Track'; +import { TrackNotFoundError } from '../../../errors/TrackErrors'; +import { ScanStation } from '../../entities/ScanStation'; +import { Track } from '../../entities/Track'; /** * This class is used to create a new StatsClient entity from a json body (post request). diff --git a/src/models/actions/create/CreateStatsClient.ts b/src/models/actions/create/CreateStatsClient.ts index 40172e5..d648f3c 100644 --- a/src/models/actions/create/CreateStatsClient.ts +++ b/src/models/actions/create/CreateStatsClient.ts @@ -2,7 +2,7 @@ import * as argon2 from "argon2"; import { IsOptional, IsString } from 'class-validator'; import crypto from 'crypto'; import * as uuid from 'uuid'; -import { StatsClient } from '../entities/StatsClient'; +import { StatsClient } from '../../entities/StatsClient'; /** * This classed is used to create a new StatsClient entity from a json body (post request). diff --git a/src/models/actions/create/CreateTrack.ts b/src/models/actions/create/CreateTrack.ts index fdeae71..7250889 100644 --- a/src/models/actions/create/CreateTrack.ts +++ b/src/models/actions/create/CreateTrack.ts @@ -1,6 +1,6 @@ import { IsInt, IsNotEmpty, IsOptional, IsPositive, IsString } from 'class-validator'; -import { TrackLapTimeCantBeNegativeError } from '../../errors/TrackErrors'; -import { Track } from '../entities/Track'; +import { TrackLapTimeCantBeNegativeError } from '../../../errors/TrackErrors'; +import { Track } from '../../entities/Track'; /** * This classed is used to create a new Track entity from a json body (post request). diff --git a/src/models/actions/create/CreateTrackScan.ts b/src/models/actions/create/CreateTrackScan.ts index 51078c4..49a9611 100644 --- a/src/models/actions/create/CreateTrackScan.ts +++ b/src/models/actions/create/CreateTrackScan.ts @@ -1,11 +1,11 @@ import { IsInt, IsPositive } from 'class-validator'; import { getConnection } from 'typeorm'; -import { RunnerCardNotFoundError } from '../../errors/RunnerCardErrors'; -import { RunnerNotFoundError } from '../../errors/RunnerErrors'; -import { ScanStationNotFoundError } from '../../errors/ScanStationErrors'; -import { RunnerCard } from '../entities/RunnerCard'; -import { ScanStation } from '../entities/ScanStation'; -import { TrackScan } from '../entities/TrackScan'; +import { RunnerCardNotFoundError } from '../../../errors/RunnerCardErrors'; +import { RunnerNotFoundError } from '../../../errors/RunnerErrors'; +import { ScanStationNotFoundError } from '../../../errors/ScanStationErrors'; +import { RunnerCard } from '../../entities/RunnerCard'; +import { ScanStation } from '../../entities/ScanStation'; +import { TrackScan } from '../../entities/TrackScan'; /** * This classed is used to create a new Scan entity from a json body (post request). diff --git a/src/models/actions/create/CreateUser.ts b/src/models/actions/create/CreateUser.ts index 838d1e0..a153750 100644 --- a/src/models/actions/create/CreateUser.ts +++ b/src/models/actions/create/CreateUser.ts @@ -2,11 +2,11 @@ import * as argon2 from "argon2"; import { IsBoolean, IsEmail, IsOptional, IsPhoneNumber, IsString, IsUrl } from 'class-validator'; import { getConnectionManager } from 'typeorm'; import * as uuid from 'uuid'; -import { config } from '../../config'; -import { UsernameOrEmailNeededError } from '../../errors/UserErrors'; -import { UserGroupNotFoundError } from '../../errors/UserGroupErrors'; -import { User } from '../entities/User'; -import { UserGroup } from '../entities/UserGroup'; +import { config } from '../../../config'; +import { UsernameOrEmailNeededError } from '../../../errors/UserErrors'; +import { UserGroupNotFoundError } from '../../../errors/UserGroupErrors'; +import { User } from '../../entities/User'; +import { UserGroup } from '../../entities/UserGroup'; /** * This classed is used to create a new User entity from a json body (post request). diff --git a/src/models/actions/create/CreateUserGroup.ts b/src/models/actions/create/CreateUserGroup.ts index 50ad15d..ec0dad7 100644 --- a/src/models/actions/create/CreateUserGroup.ts +++ b/src/models/actions/create/CreateUserGroup.ts @@ -1,5 +1,5 @@ import { IsOptional, IsString } from 'class-validator'; -import { UserGroup } from '../entities/UserGroup'; +import { UserGroup } from '../../entities/UserGroup'; /** * This classed is used to create a new UserGroup entity from a json body (post request). diff --git a/src/models/actions/update/UpdateDonor.ts b/src/models/actions/update/UpdateDonor.ts index 21b2eb1..4c62c98 100644 --- a/src/models/actions/update/UpdateDonor.ts +++ b/src/models/actions/update/UpdateDonor.ts @@ -1,7 +1,7 @@ import { IsBoolean, IsInt, IsOptional } from 'class-validator'; import { DonorReceiptAddressNeededError } from '../../../errors/DonorErrors'; import { Donor } from '../../entities/Donor'; -import { CreateParticipant } from './CreateParticipant'; +import { CreateParticipant } from '../create/CreateParticipant'; /** * This class is used to update a Donor entity (via put request). diff --git a/src/models/actions/update/UpdatePermission.ts b/src/models/actions/update/UpdatePermission.ts index 5241a1b..8e012b8 100644 --- a/src/models/actions/update/UpdatePermission.ts +++ b/src/models/actions/update/UpdatePermission.ts @@ -1,11 +1,11 @@ import { IsInt, IsNotEmpty, IsObject } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { PermissionNeedsPrincipalError } from '../../errors/PermissionErrors'; -import { PrincipalNotFoundError, PrincipalWrongTypeError } from '../../errors/PrincipalErrors'; -import { Permission } from '../entities/Permission'; -import { Principal } from '../entities/Principal'; -import { PermissionAction } from '../enums/PermissionAction'; -import { PermissionTarget } from '../enums/PermissionTargets'; +import { PermissionNeedsPrincipalError } from '../../../errors/PermissionErrors'; +import { PrincipalNotFoundError, PrincipalWrongTypeError } from '../../../errors/PrincipalErrors'; +import { Permission } from '../../entities/Permission'; +import { Principal } from '../../entities/Principal'; +import { PermissionAction } from '../../enums/PermissionAction'; +import { PermissionTarget } from '../../enums/PermissionTargets'; /** * This class is used to update a Permission entity (via put request). diff --git a/src/models/actions/update/UpdateRunner.ts b/src/models/actions/update/UpdateRunner.ts index abc71e0..79c92b1 100644 --- a/src/models/actions/update/UpdateRunner.ts +++ b/src/models/actions/update/UpdateRunner.ts @@ -1,11 +1,11 @@ import { IsInt, IsObject } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { RunnerGroupNotFoundError } from '../../errors/RunnerGroupErrors'; -import { RunnerOrganisationWrongTypeError } from '../../errors/RunnerOrganisationErrors'; -import { RunnerTeamNeedsParentError } from '../../errors/RunnerTeamErrors'; -import { Runner } from '../entities/Runner'; -import { RunnerGroup } from '../entities/RunnerGroup'; -import { CreateParticipant } from './CreateParticipant'; +import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors'; +import { RunnerOrganisationWrongTypeError } from '../../../errors/RunnerOrganisationErrors'; +import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; +import { Runner } from '../../entities/Runner'; +import { RunnerGroup } from '../../entities/RunnerGroup'; +import { CreateParticipant } from '../create/CreateParticipant'; /** * This class is used to update a Runner entity (via put request). diff --git a/src/models/actions/update/UpdateRunnerCard.ts b/src/models/actions/update/UpdateRunnerCard.ts index 2ee34ab..51f70bf 100644 --- a/src/models/actions/update/UpdateRunnerCard.ts +++ b/src/models/actions/update/UpdateRunnerCard.ts @@ -1,8 +1,8 @@ import { IsBoolean, IsInt, IsOptional, IsPositive } from 'class-validator'; import { getConnection } from 'typeorm'; -import { RunnerNotFoundError } from '../../errors/RunnerErrors'; -import { Runner } from '../entities/Runner'; -import { RunnerCard } from '../entities/RunnerCard'; +import { RunnerNotFoundError } from '../../../errors/RunnerErrors'; +import { Runner } from '../../entities/Runner'; +import { RunnerCard } from '../../entities/RunnerCard'; /** * This class is used to update a RunnerCard entity (via put request). diff --git a/src/models/actions/update/UpdateRunnerOrganisation.ts b/src/models/actions/update/UpdateRunnerOrganisation.ts index 9a2cafa..bdc0d33 100644 --- a/src/models/actions/update/UpdateRunnerOrganisation.ts +++ b/src/models/actions/update/UpdateRunnerOrganisation.ts @@ -1,9 +1,9 @@ import { IsInt, IsOptional } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { AddressNotFoundError } from '../../errors/AddressErrors'; -import { Address } from '../entities/Address'; -import { RunnerOrganisation } from '../entities/RunnerOrganisation'; -import { CreateRunnerGroup } from './CreateRunnerGroup'; +import { AddressNotFoundError } from '../../../errors/AddressErrors'; +import { Address } from '../../entities/Address'; +import { RunnerOrganisation } from '../../entities/RunnerOrganisation'; +import { CreateRunnerGroup } from '../create/CreateRunnerGroup'; /** * This class is used to update a RunnerOrganisation entity (via put request). diff --git a/src/models/actions/update/UpdateRunnerTeam.ts b/src/models/actions/update/UpdateRunnerTeam.ts index 756d7df..8420473 100644 --- a/src/models/actions/update/UpdateRunnerTeam.ts +++ b/src/models/actions/update/UpdateRunnerTeam.ts @@ -1,10 +1,10 @@ import { IsInt, IsNotEmpty, IsObject } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { RunnerOrganisationNotFoundError, RunnerOrganisationWrongTypeError } from '../../errors/RunnerOrganisationErrors'; -import { RunnerTeamNeedsParentError } from '../../errors/RunnerTeamErrors'; -import { RunnerOrganisation } from '../entities/RunnerOrganisation'; -import { RunnerTeam } from '../entities/RunnerTeam'; -import { CreateRunnerGroup } from './CreateRunnerGroup'; +import { RunnerOrganisationNotFoundError, RunnerOrganisationWrongTypeError } from '../../../errors/RunnerOrganisationErrors'; +import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; +import { RunnerOrganisation } from '../../entities/RunnerOrganisation'; +import { RunnerTeam } from '../../entities/RunnerTeam'; +import { CreateRunnerGroup } from '../create/CreateRunnerGroup'; /** * This class is used to update a RunnerTeam entity (via put request). diff --git a/src/models/actions/update/UpdateScan.ts b/src/models/actions/update/UpdateScan.ts index 00b375e..157f8b5 100644 --- a/src/models/actions/update/UpdateScan.ts +++ b/src/models/actions/update/UpdateScan.ts @@ -1,8 +1,8 @@ import { IsBoolean, IsInt, IsOptional, IsPositive } from 'class-validator'; import { getConnection } from 'typeorm'; -import { RunnerNotFoundError } from '../../errors/RunnerErrors'; -import { Runner } from '../entities/Runner'; -import { Scan } from '../entities/Scan'; +import { RunnerNotFoundError } from '../../../errors/RunnerErrors'; +import { Runner } from '../../entities/Runner'; +import { Scan } from '../../entities/Scan'; /** * This class is used to update a Scan entity (via put request) diff --git a/src/models/actions/update/UpdateScanStation.ts b/src/models/actions/update/UpdateScanStation.ts index a8ebc6a..e6121c3 100644 --- a/src/models/actions/update/UpdateScanStation.ts +++ b/src/models/actions/update/UpdateScanStation.ts @@ -1,5 +1,5 @@ import { IsBoolean, IsInt, IsOptional, IsString } from 'class-validator'; -import { ScanStation } from '../entities/ScanStation'; +import { ScanStation } from '../../entities/ScanStation'; /** * This class is used to update a ScanStation entity (via put request) diff --git a/src/models/actions/update/UpdateTrack.ts b/src/models/actions/update/UpdateTrack.ts index bc64d54..a4456cb 100644 --- a/src/models/actions/update/UpdateTrack.ts +++ b/src/models/actions/update/UpdateTrack.ts @@ -1,6 +1,6 @@ import { IsInt, IsNotEmpty, IsOptional, IsPositive, IsString } from 'class-validator'; -import { TrackLapTimeCantBeNegativeError } from '../../errors/TrackErrors'; -import { Track } from '../entities/Track'; +import { TrackLapTimeCantBeNegativeError } from '../../../errors/TrackErrors'; +import { Track } from '../../entities/Track'; /** * This class is used to update a Track entity (via put request). diff --git a/src/models/actions/update/UpdateTrackScan.ts b/src/models/actions/update/UpdateTrackScan.ts index 43c37cd..d5fc8f9 100644 --- a/src/models/actions/update/UpdateTrackScan.ts +++ b/src/models/actions/update/UpdateTrackScan.ts @@ -1,10 +1,10 @@ import { IsBoolean, IsInt, IsOptional } from 'class-validator'; import { getConnection } from 'typeorm'; -import { RunnerNotFoundError } from '../../errors/RunnerErrors'; -import { ScanStationNotFoundError } from '../../errors/ScanStationErrors'; -import { Runner } from '../entities/Runner'; -import { ScanStation } from '../entities/ScanStation'; -import { TrackScan } from '../entities/TrackScan'; +import { RunnerNotFoundError } from '../../../errors/RunnerErrors'; +import { ScanStationNotFoundError } from '../../../errors/ScanStationErrors'; +import { Runner } from '../../entities/Runner'; +import { ScanStation } from '../../entities/ScanStation'; +import { TrackScan } from '../../entities/TrackScan'; /** * This class is used to update a TrackScan entity (via put request) diff --git a/src/models/actions/update/UpdateUser.ts b/src/models/actions/update/UpdateUser.ts index 37e186e..a9ae5fe 100644 --- a/src/models/actions/update/UpdateUser.ts +++ b/src/models/actions/update/UpdateUser.ts @@ -1,11 +1,11 @@ import * as argon2 from "argon2"; import { IsBoolean, IsEmail, IsInt, IsOptional, IsPhoneNumber, IsString, IsUrl } from 'class-validator'; import { getConnectionManager } from 'typeorm'; -import { config } from '../../config'; -import { UsernameOrEmailNeededError } from '../../errors/AuthError'; -import { UserGroupNotFoundError } from '../../errors/UserGroupErrors'; -import { User } from '../entities/User'; -import { UserGroup } from '../entities/UserGroup'; +import { config } from '../../../config'; +import { UsernameOrEmailNeededError } from '../../../errors/AuthError'; +import { UserGroupNotFoundError } from '../../../errors/UserGroupErrors'; +import { User } from '../../entities/User'; +import { UserGroup } from '../../entities/UserGroup'; /** * This class is used to update a User entity (via put request). diff --git a/src/seeds/SeedUsers.ts b/src/seeds/SeedUsers.ts index c393a10..a21db99 100644 --- a/src/seeds/SeedUsers.ts +++ b/src/seeds/SeedUsers.ts @@ -1,8 +1,8 @@ import { Connection } from 'typeorm'; import { Factory, Seeder } from 'typeorm-seeding'; -import { CreatePermission } from '../models/actions/CreatePermission'; -import { CreateUser } from '../models/actions/CreateUser'; -import { CreateUserGroup } from '../models/actions/CreateUserGroup'; +import { CreatePermission } from '../models/actions/create/CreatePermission'; +import { CreateUser } from '../models/actions/create/CreateUser'; +import { CreateUserGroup } from '../models/actions/create/CreateUserGroup'; import { Permission } from '../models/entities/Permission'; import { User } from '../models/entities/User'; import { UserGroup } from '../models/entities/UserGroup'; From e6b9d4f2737a6eeb30e4c14a10675b13f89d62fa Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 16:31:55 +0100 Subject: [PATCH 37/50] Renamed the to>Entity Name>() functiuons to toEntity() ref #76 --- src/controllers/DonorController.ts | 2 +- src/controllers/PermissionController.ts | 2 +- src/controllers/RunnerController.ts | 2 +- src/controllers/RunnerOrganisationController.ts | 2 +- src/controllers/ScanController.ts | 4 ++-- src/controllers/StatsClientController.ts | 2 +- src/controllers/TrackController.ts | 2 +- src/controllers/UserController.ts | 2 +- src/controllers/UserGroupController.ts | 2 +- src/models/actions/create/CreateAddress.ts | 2 +- src/models/actions/create/CreateDonor.ts | 2 +- src/models/actions/create/CreateGroupContact.ts | 2 +- src/models/actions/create/CreatePermission.ts | 2 +- src/models/actions/create/CreateRunner.ts | 2 +- src/models/actions/create/CreateRunnerOrganisation.ts | 2 +- src/models/actions/create/CreateScan.ts | 2 +- src/models/actions/create/CreateStatsClient.ts | 2 +- src/models/actions/create/CreateTrack.ts | 2 +- src/models/actions/create/CreateTrackScan.ts | 2 +- src/models/actions/create/CreateUser.ts | 2 +- src/models/actions/create/CreateUserGroup.ts | 2 +- src/seeds/SeedUsers.ts | 6 +++--- 22 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/controllers/DonorController.ts b/src/controllers/DonorController.ts index 9a13784..5b17c1d 100644 --- a/src/controllers/DonorController.ts +++ b/src/controllers/DonorController.ts @@ -52,7 +52,7 @@ export class DonorController { async post(@Body({ validate: true }) createRunner: CreateDonor) { let donor; try { - donor = await createRunner.toDonor(); + donor = await createRunner.toEntity(); } catch (error) { throw error; } diff --git a/src/controllers/PermissionController.ts b/src/controllers/PermissionController.ts index 9080cac..37085f1 100644 --- a/src/controllers/PermissionController.ts +++ b/src/controllers/PermissionController.ts @@ -58,7 +58,7 @@ export class PermissionController { async post(@Body({ validate: true }) createPermission: CreatePermission) { let permission; try { - permission = await createPermission.toPermission(); + permission = await createPermission.toEntity(); } catch (error) { throw error; } diff --git a/src/controllers/RunnerController.ts b/src/controllers/RunnerController.ts index 494876c..184cc38 100644 --- a/src/controllers/RunnerController.ts +++ b/src/controllers/RunnerController.ts @@ -57,7 +57,7 @@ export class RunnerController { async post(@Body({ validate: true }) createRunner: CreateRunner) { let runner; try { - runner = await createRunner.toRunner(); + runner = await createRunner.toEntity(); } catch (error) { throw error; } diff --git a/src/controllers/RunnerOrganisationController.ts b/src/controllers/RunnerOrganisationController.ts index ac06cbb..4717d3c 100644 --- a/src/controllers/RunnerOrganisationController.ts +++ b/src/controllers/RunnerOrganisationController.ts @@ -55,7 +55,7 @@ export class RunnerOrganisationController { async post(@Body({ validate: true }) createRunnerOrganisation: CreateRunnerOrganisation) { let runnerOrganisation; try { - runnerOrganisation = await createRunnerOrganisation.toRunnerOrganisation(); + runnerOrganisation = await createRunnerOrganisation.toEntity(); } catch (error) { throw error; } diff --git a/src/controllers/ScanController.ts b/src/controllers/ScanController.ts index e5b46fc..e098a21 100644 --- a/src/controllers/ScanController.ts +++ b/src/controllers/ScanController.ts @@ -62,7 +62,7 @@ export class ScanController { @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @OpenAPI({ description: 'Create a new scan (not track scan - use /scans/trackscans instead).
Please rmemember to provide the scan\'s runner\'s id and distance.', security: [{ "ScanApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) async post(@Body({ validate: true }) createScan: CreateScan) { - let scan = await createScan.toScan(); + let scan = await createScan.toEntity(); scan = await this.scanRepository.save(scan); return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse(); } @@ -73,7 +73,7 @@ export class ScanController { @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @OpenAPI({ description: 'Create a new track scan (for "normal" scans use /scans instead).
Please remember that to provide the scan\'s card\'s station\'s id.', security: [{ "ScanApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) async postTrackScans(@Body({ validate: true }) createScan: CreateTrackScan) { - let scan = await createScan.toScan(); + let scan = await createScan.toEntity(); scan = await this.trackScanRepository.save(scan); return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse(); } diff --git a/src/controllers/StatsClientController.ts b/src/controllers/StatsClientController.ts index 9d9080d..d7724c3 100644 --- a/src/controllers/StatsClientController.ts +++ b/src/controllers/StatsClientController.ts @@ -53,7 +53,7 @@ export class StatsClientController { @Body({ validate: true }) client: CreateStatsClient ) { - let newClient = await this.clientRepository.save(await client.toStatsClient()); + let newClient = await this.clientRepository.save(await client.toEntity()); let responseClient = new ResponseStatsClient(newClient); responseClient.key = newClient.cleartextkey; return responseClient; diff --git a/src/controllers/TrackController.ts b/src/controllers/TrackController.ts index 85416db..a47972f 100644 --- a/src/controllers/TrackController.ts +++ b/src/controllers/TrackController.ts @@ -55,7 +55,7 @@ export class TrackController { @Body({ validate: true }) track: CreateTrack ) { - return new ResponseTrack(await this.trackRepository.save(track.toTrack())); + return new ResponseTrack(await this.trackRepository.save(track.toEntity())); } @Put('/:id') diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index 0fbed48..195b66a 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -56,7 +56,7 @@ export class UserController { async post(@Body({ validate: true }) createUser: CreateUser) { let user; try { - user = await createUser.toUser(); + user = await createUser.toEntity(); } catch (error) { throw error; } diff --git a/src/controllers/UserGroupController.ts b/src/controllers/UserGroupController.ts index f3ae435..85426f5 100644 --- a/src/controllers/UserGroupController.ts +++ b/src/controllers/UserGroupController.ts @@ -48,7 +48,7 @@ export class UserGroupController { async post(@Body({ validate: true }) createUserGroup: CreateUserGroup) { let userGroup; try { - userGroup = await createUserGroup.toUserGroup(); + userGroup = await createUserGroup.toEntity(); } catch (error) { throw error; } diff --git a/src/models/actions/create/CreateAddress.ts b/src/models/actions/create/CreateAddress.ts index 365035e..0111736 100644 --- a/src/models/actions/create/CreateAddress.ts +++ b/src/models/actions/create/CreateAddress.ts @@ -56,7 +56,7 @@ export class CreateAddress { /** * Creates a new Address entity from this. */ - public toAddress(): Address { + public toEntity(): Address { let newAddress: Address = new Address(); newAddress.address1 = this.address1; diff --git a/src/models/actions/create/CreateDonor.ts b/src/models/actions/create/CreateDonor.ts index 2deb10b..791461a 100644 --- a/src/models/actions/create/CreateDonor.ts +++ b/src/models/actions/create/CreateDonor.ts @@ -18,7 +18,7 @@ export class CreateDonor extends CreateParticipant { /** * Creates a new Donor entity from this. */ - public async toDonor(): Promise { + public async toEntity(): Promise { let newDonor: Donor = new Donor(); newDonor.firstname = this.firstname; diff --git a/src/models/actions/create/CreateGroupContact.ts b/src/models/actions/create/CreateGroupContact.ts index fa83bed..c6e10a8 100644 --- a/src/models/actions/create/CreateGroupContact.ts +++ b/src/models/actions/create/CreateGroupContact.ts @@ -72,7 +72,7 @@ export class CreateGroupContact { /** * Creates a new Address entity from this. */ - public async toGroupContact(): Promise { + public async toEntity(): Promise { let contact: GroupContact = new GroupContact(); contact.firstname = this.firstname; contact.middlename = this.middlename; diff --git a/src/models/actions/create/CreatePermission.ts b/src/models/actions/create/CreatePermission.ts index 41fddfc..e59a186 100644 --- a/src/models/actions/create/CreatePermission.ts +++ b/src/models/actions/create/CreatePermission.ts @@ -39,7 +39,7 @@ export class CreatePermission { /** * Creates a new Permission entity from this. */ - public async toPermission(): Promise { + public async toEntity(): Promise { let newPermission: Permission = new Permission(); newPermission.principal = await this.getPrincipal(); diff --git a/src/models/actions/create/CreateRunner.ts b/src/models/actions/create/CreateRunner.ts index acd36d4..2286fdf 100644 --- a/src/models/actions/create/CreateRunner.ts +++ b/src/models/actions/create/CreateRunner.ts @@ -21,7 +21,7 @@ export class CreateRunner extends CreateParticipant { /** * Creates a new Runner entity from this. */ - public async toRunner(): Promise { + public async toEntity(): Promise { let newRunner: Runner = new Runner(); newRunner.firstname = this.firstname; diff --git a/src/models/actions/create/CreateRunnerOrganisation.ts b/src/models/actions/create/CreateRunnerOrganisation.ts index 426793d..04edf93 100644 --- a/src/models/actions/create/CreateRunnerOrganisation.ts +++ b/src/models/actions/create/CreateRunnerOrganisation.ts @@ -36,7 +36,7 @@ export class CreateRunnerOrganisation extends CreateRunnerGroup { /** * Creates a new RunnerOrganisation entity from this. */ - public async toRunnerOrganisation(): Promise { + public async toEntity(): Promise { let newRunnerOrganisation: RunnerOrganisation = new RunnerOrganisation(); newRunnerOrganisation.name = this.name; diff --git a/src/models/actions/create/CreateScan.ts b/src/models/actions/create/CreateScan.ts index 9835924..496b8a0 100644 --- a/src/models/actions/create/CreateScan.ts +++ b/src/models/actions/create/CreateScan.ts @@ -36,7 +36,7 @@ export abstract class CreateScan { /** * Creates a new Scan entity from this. */ - public async toScan(): Promise { + public async toEntity(): Promise { let newScan = new Scan(); newScan.distance = this.distance; diff --git a/src/models/actions/create/CreateStatsClient.ts b/src/models/actions/create/CreateStatsClient.ts index d648f3c..0f666fc 100644 --- a/src/models/actions/create/CreateStatsClient.ts +++ b/src/models/actions/create/CreateStatsClient.ts @@ -18,7 +18,7 @@ export class CreateStatsClient { /** * Converts this to a StatsClient entity. */ - public async toStatsClient(): Promise { + public async toEntity(): Promise { let newClient: StatsClient = new StatsClient(); newClient.description = this.description; diff --git a/src/models/actions/create/CreateTrack.ts b/src/models/actions/create/CreateTrack.ts index 7250889..8c0db34 100644 --- a/src/models/actions/create/CreateTrack.ts +++ b/src/models/actions/create/CreateTrack.ts @@ -31,7 +31,7 @@ export class CreateTrack { /** * Creates a new Track entity from this. */ - public toTrack(): Track { + public toEntity(): Track { let newTrack: Track = new Track(); newTrack.name = this.name; diff --git a/src/models/actions/create/CreateTrackScan.ts b/src/models/actions/create/CreateTrackScan.ts index 49a9611..db63cf2 100644 --- a/src/models/actions/create/CreateTrackScan.ts +++ b/src/models/actions/create/CreateTrackScan.ts @@ -30,7 +30,7 @@ export class CreateTrackScan { /** * Creates a new Track entity from this. */ - public async toScan(): Promise { + public async toEntity(): Promise { let newScan: TrackScan = new TrackScan(); newScan.station = await this.getStation(); diff --git a/src/models/actions/create/CreateUser.ts b/src/models/actions/create/CreateUser.ts index a153750..a5f20c2 100644 --- a/src/models/actions/create/CreateUser.ts +++ b/src/models/actions/create/CreateUser.ts @@ -89,7 +89,7 @@ export class CreateUser { /** * Converts this to a User entity. */ - public async toUser(): Promise { + public async toEntity(): Promise { let newUser: User = new User(); if (this.email === undefined && this.username === undefined) { diff --git a/src/models/actions/create/CreateUserGroup.ts b/src/models/actions/create/CreateUserGroup.ts index ec0dad7..aa5a862 100644 --- a/src/models/actions/create/CreateUserGroup.ts +++ b/src/models/actions/create/CreateUserGroup.ts @@ -22,7 +22,7 @@ export class CreateUserGroup { /** * Creates a new UserGroup entity from this. */ - public async toUserGroup(): Promise { + public async toEntity(): Promise { let newUserGroup: UserGroup = new UserGroup(); newUserGroup.name = this.name; diff --git a/src/seeds/SeedUsers.ts b/src/seeds/SeedUsers.ts index a21db99..e70ef84 100644 --- a/src/seeds/SeedUsers.ts +++ b/src/seeds/SeedUsers.ts @@ -24,7 +24,7 @@ export default class SeedUsers implements Seeder { let adminGroup = new CreateUserGroup(); adminGroup.name = "ADMINS"; adminGroup.description = "Have all possible permissions"; - return await connection.getRepository(UserGroup).save(await adminGroup.toUserGroup()); + return await connection.getRepository(UserGroup).save(await adminGroup.toEntity()); } public async createUser(connection: Connection, group: number) { @@ -34,7 +34,7 @@ export default class SeedUsers implements Seeder { initialUser.username = "demo"; initialUser.password = "demo"; initialUser.groups = group; - return await connection.getRepository(User).save(await initialUser.toUser()); + return await connection.getRepository(User).save(await initialUser.toEntity()); } public async createPermissions(connection: Connection, principal: number) { @@ -45,7 +45,7 @@ export default class SeedUsers implements Seeder { permission.target = target; permission.action = action; permission.principal = principal; - await repo.save(await permission.toPermission()); + await repo.save(await permission.toEntity()); } } } From 3f7b0f6563f2446508257d09ca87e119c6383ea8 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 16:35:52 +0100 Subject: [PATCH 38/50] Renamed the update>Entity Name>() functiuons to update() ref #76 --- src/controllers/DonorController.ts | 2 +- src/controllers/PermissionController.ts | 2 +- src/controllers/RunnerController.ts | 2 +- src/controllers/RunnerOrganisationController.ts | 2 +- src/controllers/RunnerTeamController.ts | 2 +- src/controllers/ScanController.ts | 4 ++-- src/controllers/ScanStationController.ts | 2 +- src/controllers/TrackController.ts | 2 +- src/controllers/UserController.ts | 2 +- src/models/actions/update/UpdateDonor.ts | 2 +- src/models/actions/update/UpdatePermission.ts | 2 +- src/models/actions/update/UpdateRunner.ts | 2 +- src/models/actions/update/UpdateRunnerOrganisation.ts | 2 +- src/models/actions/update/UpdateRunnerTeam.ts | 2 +- src/models/actions/update/UpdateScan.ts | 2 +- src/models/actions/update/UpdateScanStation.ts | 2 +- src/models/actions/update/UpdateTrack.ts | 2 +- src/models/actions/update/UpdateTrackScan.ts | 2 +- src/models/actions/update/UpdateUser.ts | 2 +- 19 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/controllers/DonorController.ts b/src/controllers/DonorController.ts index 5b17c1d..f6b8527 100644 --- a/src/controllers/DonorController.ts +++ b/src/controllers/DonorController.ts @@ -78,7 +78,7 @@ export class DonorController { throw new DonorIdsNotMatchingError(); } - await this.donorRepository.save(await donor.updateDonor(oldDonor)); + await this.donorRepository.save(await donor.update(oldDonor)); return new ResponseDonor(await this.donorRepository.findOne({ id: id })); } diff --git a/src/controllers/PermissionController.ts b/src/controllers/PermissionController.ts index 37085f1..e123e81 100644 --- a/src/controllers/PermissionController.ts +++ b/src/controllers/PermissionController.ts @@ -96,7 +96,7 @@ export class PermissionController { return new ResponsePermission(existingPermission); } - await this.permissionRepository.save(await permission.updatePermission(oldPermission)); + await this.permissionRepository.save(await permission.update(oldPermission)); return new ResponsePermission(await this.permissionRepository.findOne({ id: permission.id }, { relations: ['principal'] })); } diff --git a/src/controllers/RunnerController.ts b/src/controllers/RunnerController.ts index 184cc38..2d83a02 100644 --- a/src/controllers/RunnerController.ts +++ b/src/controllers/RunnerController.ts @@ -83,7 +83,7 @@ export class RunnerController { throw new RunnerIdsNotMatchingError(); } - await this.runnerRepository.save(await runner.updateRunner(oldRunner)); + await this.runnerRepository.save(await runner.update(oldRunner)); return new ResponseRunner(await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group', 'scans.track', 'cards'] })); } diff --git a/src/controllers/RunnerOrganisationController.ts b/src/controllers/RunnerOrganisationController.ts index 4717d3c..15c12ff 100644 --- a/src/controllers/RunnerOrganisationController.ts +++ b/src/controllers/RunnerOrganisationController.ts @@ -82,7 +82,7 @@ export class RunnerOrganisationController { throw new RunnerOrganisationIdsNotMatchingError(); } - await this.runnerOrganisationRepository.save(await updateOrganisation.updateRunnerOrganisation(oldRunnerOrganisation)); + await this.runnerOrganisationRepository.save(await updateOrganisation.update(oldRunnerOrganisation)); return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(id, { relations: ['address', 'contact', 'teams'] })); } diff --git a/src/controllers/RunnerTeamController.ts b/src/controllers/RunnerTeamController.ts index 6587a84..d06ccce 100644 --- a/src/controllers/RunnerTeamController.ts +++ b/src/controllers/RunnerTeamController.ts @@ -82,7 +82,7 @@ export class RunnerTeamController { throw new RunnerTeamIdsNotMatchingError(); } - await this.runnerTeamRepository.save(await runnerTeam.updateRunnerTeam(oldRunnerTeam)); + await this.runnerTeamRepository.save(await runnerTeam.update(oldRunnerTeam)); return new ResponseRunnerTeam(await this.runnerTeamRepository.findOne({ id: runnerTeam.id }, { relations: ['parentGroup', 'contact'] })); } diff --git a/src/controllers/ScanController.ts b/src/controllers/ScanController.ts index e098a21..0de844c 100644 --- a/src/controllers/ScanController.ts +++ b/src/controllers/ScanController.ts @@ -96,7 +96,7 @@ export class ScanController { throw new ScanIdsNotMatchingError(); } - await this.scanRepository.save(await scan.updateScan(oldScan)); + await this.scanRepository.save(await scan.update(oldScan)); return (await this.scanRepository.findOne({ id: id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse(); } @@ -119,7 +119,7 @@ export class ScanController { throw new ScanIdsNotMatchingError(); } - await this.trackScanRepository.save(await scan.updateScan(oldScan)); + await this.trackScanRepository.save(await scan.update(oldScan)); return (await this.scanRepository.findOne({ id: id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse(); } diff --git a/src/controllers/ScanStationController.ts b/src/controllers/ScanStationController.ts index 2666b64..80aa6e3 100644 --- a/src/controllers/ScanStationController.ts +++ b/src/controllers/ScanStationController.ts @@ -77,7 +77,7 @@ export class ScanStationController { throw new ScanStationIdsNotMatchingError(); } - await this.stationRepository.save(await station.updateStation(oldStation)); + await this.stationRepository.save(await station.update(oldStation)); return (await this.stationRepository.findOne({ id: id }, { relations: ['track'] })).toResponse(); } diff --git a/src/controllers/TrackController.ts b/src/controllers/TrackController.ts index a47972f..b9f8d30 100644 --- a/src/controllers/TrackController.ts +++ b/src/controllers/TrackController.ts @@ -75,7 +75,7 @@ export class TrackController { if (oldTrack.id != updateTrack.id) { throw new TrackIdsNotMatchingError(); } - await this.trackRepository.save(await updateTrack.updateTrack(oldTrack)); + await this.trackRepository.save(await updateTrack.update(oldTrack)); return new ResponseTrack(await this.trackRepository.findOne({ id: id })); } diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index 195b66a..57083db 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -81,7 +81,7 @@ export class UserController { if (oldUser.id != updateUser.id) { throw new UserIdsNotMatchingError(); } - await this.userRepository.save(await updateUser.updateUser(oldUser)); + await this.userRepository.save(await updateUser.update(oldUser)); return new ResponseUser(await this.userRepository.findOne({ id: id }, { relations: ['permissions', 'groups'] })); } diff --git a/src/models/actions/update/UpdateDonor.ts b/src/models/actions/update/UpdateDonor.ts index 4c62c98..8c77ff1 100644 --- a/src/models/actions/update/UpdateDonor.ts +++ b/src/models/actions/update/UpdateDonor.ts @@ -26,7 +26,7 @@ export class UpdateDonor extends CreateParticipant { /** * Updates a provided Donor entity based on this. */ - public async updateDonor(donor: Donor): Promise { + public async update(donor: Donor): Promise { donor.firstname = this.firstname; donor.middlename = this.middlename; donor.lastname = this.lastname; diff --git a/src/models/actions/update/UpdatePermission.ts b/src/models/actions/update/UpdatePermission.ts index 8e012b8..e591e20 100644 --- a/src/models/actions/update/UpdatePermission.ts +++ b/src/models/actions/update/UpdatePermission.ts @@ -42,7 +42,7 @@ export class UpdatePermission { /** * Updates a provided Permission entity based on this. */ - public async updatePermission(permission: Permission): Promise { + public async update(permission: Permission): Promise { permission.principal = await this.getPrincipal(); permission.target = this.target; permission.action = this.action; diff --git a/src/models/actions/update/UpdateRunner.ts b/src/models/actions/update/UpdateRunner.ts index 79c92b1..29a2423 100644 --- a/src/models/actions/update/UpdateRunner.ts +++ b/src/models/actions/update/UpdateRunner.ts @@ -29,7 +29,7 @@ export class UpdateRunner extends CreateParticipant { /** * Updates a provided Runner entity based on this. */ - public async updateRunner(runner: Runner): Promise { + public async update(runner: Runner): Promise { runner.firstname = this.firstname; runner.middlename = this.middlename; runner.lastname = this.lastname; diff --git a/src/models/actions/update/UpdateRunnerOrganisation.ts b/src/models/actions/update/UpdateRunnerOrganisation.ts index bdc0d33..7270923 100644 --- a/src/models/actions/update/UpdateRunnerOrganisation.ts +++ b/src/models/actions/update/UpdateRunnerOrganisation.ts @@ -41,7 +41,7 @@ export class UpdateRunnerOrganisation extends CreateRunnerGroup { /** * Updates a provided RunnerOrganisation entity based on this. */ - public async updateRunnerOrganisation(organisation: RunnerOrganisation): Promise { + public async update(organisation: RunnerOrganisation): Promise { organisation.name = this.name; organisation.contact = await this.getContact(); diff --git a/src/models/actions/update/UpdateRunnerTeam.ts b/src/models/actions/update/UpdateRunnerTeam.ts index 8420473..d7e435d 100644 --- a/src/models/actions/update/UpdateRunnerTeam.ts +++ b/src/models/actions/update/UpdateRunnerTeam.ts @@ -45,7 +45,7 @@ export class UpdateRunnerTeam extends CreateRunnerGroup { /** * Updates a provided RunnerTeam entity based on this. */ - public async updateRunnerTeam(team: RunnerTeam): Promise { + public async update(team: RunnerTeam): Promise { team.name = this.name; team.parentGroup = await this.getParent(); diff --git a/src/models/actions/update/UpdateScan.ts b/src/models/actions/update/UpdateScan.ts index 157f8b5..a0d6633 100644 --- a/src/models/actions/update/UpdateScan.ts +++ b/src/models/actions/update/UpdateScan.ts @@ -41,7 +41,7 @@ export abstract class UpdateScan { * Update a Scan entity based on this. * @param scan The scan that shall be updated. */ - public async updateScan(scan: Scan): Promise { + public async update(scan: Scan): Promise { scan.distance = this.distance; scan.valid = this.valid; scan.runner = await this.getRunner(); diff --git a/src/models/actions/update/UpdateScanStation.ts b/src/models/actions/update/UpdateScanStation.ts index e6121c3..b7557e3 100644 --- a/src/models/actions/update/UpdateScanStation.ts +++ b/src/models/actions/update/UpdateScanStation.ts @@ -30,7 +30,7 @@ export class UpdateScanStation { * Update a ScanStation entity based on this. * @param station The station that shall be updated. */ - public async updateStation(station: ScanStation): Promise { + public async update(station: ScanStation): Promise { station.description = this.description; station.enabled = this.enabled; diff --git a/src/models/actions/update/UpdateTrack.ts b/src/models/actions/update/UpdateTrack.ts index a4456cb..c9935f5 100644 --- a/src/models/actions/update/UpdateTrack.ts +++ b/src/models/actions/update/UpdateTrack.ts @@ -37,7 +37,7 @@ export class UpdateTrack { * Update a Track entity based on this. * @param track The track that shall be updated. */ - public updateTrack(track: Track): Track { + public update(track: Track): Track { track.name = this.name; track.distance = this.distance; track.minimumLapTime = this.minimumLapTime; diff --git a/src/models/actions/update/UpdateTrackScan.ts b/src/models/actions/update/UpdateTrackScan.ts index d5fc8f9..1280e94 100644 --- a/src/models/actions/update/UpdateTrackScan.ts +++ b/src/models/actions/update/UpdateTrackScan.ts @@ -44,7 +44,7 @@ export abstract class UpdateTrackScan { * Update a TrackScan entity based on this. * @param scan The scan that shall be updated. */ - public async updateScan(scan: TrackScan): Promise { + public async update(scan: TrackScan): Promise { scan.valid = this.valid; if (this.runner) { scan.runner = await this.getRunner(); diff --git a/src/models/actions/update/UpdateUser.ts b/src/models/actions/update/UpdateUser.ts index a9ae5fe..59d95a4 100644 --- a/src/models/actions/update/UpdateUser.ts +++ b/src/models/actions/update/UpdateUser.ts @@ -98,7 +98,7 @@ export class UpdateUser { * Updates a user entity based on this. * @param user The user that shall be updated. */ - public async updateUser(user: User): Promise { + public async update(user: User): Promise { user.email = this.email; user.username = this.username; if ((user.email === undefined || user.email === null) && (user.username === undefined || user.username === null)) { From 3deae2bfeb9f022d3d324bfdd7f0d6d2e9bd39a1 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 16:53:59 +0100 Subject: [PATCH 39/50] Moved all update() and toEntity action model functions to async ref #76 --- src/controllers/RunnerTeamController.ts | 2 +- src/controllers/TrackController.ts | 2 +- src/models/actions/create/CreateAddress.ts | 2 +- src/models/actions/create/CreateRunnerTeam.ts | 2 +- src/models/actions/update/UpdateTrack.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/controllers/RunnerTeamController.ts b/src/controllers/RunnerTeamController.ts index d06ccce..5b97f2b 100644 --- a/src/controllers/RunnerTeamController.ts +++ b/src/controllers/RunnerTeamController.ts @@ -54,7 +54,7 @@ export class RunnerTeamController { async post(@Body({ validate: true }) createRunnerTeam: CreateRunnerTeam) { let runnerTeam; try { - runnerTeam = await createRunnerTeam.toRunnerTeam(); + runnerTeam = await createRunnerTeam.toEntity(); } catch (error) { throw error; } diff --git a/src/controllers/TrackController.ts b/src/controllers/TrackController.ts index b9f8d30..6ea2907 100644 --- a/src/controllers/TrackController.ts +++ b/src/controllers/TrackController.ts @@ -55,7 +55,7 @@ export class TrackController { @Body({ validate: true }) track: CreateTrack ) { - return new ResponseTrack(await this.trackRepository.save(track.toEntity())); + return new ResponseTrack(await this.trackRepository.save(await track.toEntity())); } @Put('/:id') diff --git a/src/models/actions/create/CreateAddress.ts b/src/models/actions/create/CreateAddress.ts index 0111736..c399bb8 100644 --- a/src/models/actions/create/CreateAddress.ts +++ b/src/models/actions/create/CreateAddress.ts @@ -56,7 +56,7 @@ export class CreateAddress { /** * Creates a new Address entity from this. */ - public toEntity(): Address { + public async toEntity(): Promise
{ let newAddress: Address = new Address(); newAddress.address1 = this.address1; diff --git a/src/models/actions/create/CreateRunnerTeam.ts b/src/models/actions/create/CreateRunnerTeam.ts index a0c955b..fc5c310 100644 --- a/src/models/actions/create/CreateRunnerTeam.ts +++ b/src/models/actions/create/CreateRunnerTeam.ts @@ -37,7 +37,7 @@ export class CreateRunnerTeam extends CreateRunnerGroup { /** * Creates a new RunnerTeam entity from this. */ - public async toRunnerTeam(): Promise { + public async toEntity(): Promise { let newRunnerTeam: RunnerTeam = new RunnerTeam(); newRunnerTeam.name = this.name; diff --git a/src/models/actions/update/UpdateTrack.ts b/src/models/actions/update/UpdateTrack.ts index c9935f5..409a356 100644 --- a/src/models/actions/update/UpdateTrack.ts +++ b/src/models/actions/update/UpdateTrack.ts @@ -37,7 +37,7 @@ export class UpdateTrack { * Update a Track entity based on this. * @param track The track that shall be updated. */ - public update(track: Track): Track { + public async update(track: Track): Promise { track.name = this.name; track.distance = this.distance; track.minimumLapTime = this.minimumLapTime; From ac00667465d80745d6e1954df764f8aa977a693f Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 16:54:19 +0100 Subject: [PATCH 40/50] Renamed the auth response call to ResponseAuth ref #76 --- src/controllers/AuthController.ts | 10 +++++----- src/models/responses/ResponseAuth.ts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/controllers/AuthController.ts b/src/controllers/AuthController.ts index 5615de9..507ac38 100644 --- a/src/controllers/AuthController.ts +++ b/src/controllers/AuthController.ts @@ -7,7 +7,7 @@ import { CreateResetToken } from '../models/actions/create/CreateResetToken'; import { HandleLogout } from '../models/actions/HandleLogout'; import { RefreshAuth } from '../models/actions/RefreshAuth'; import { ResetPassword } from '../models/actions/ResetPassword'; -import { Auth } from '../models/responses/ResponseAuth'; +import { ResponseAuth } from '../models/responses/ResponseAuth'; import { Logout } from '../models/responses/ResponseLogout'; @JsonController('/auth') @@ -16,7 +16,7 @@ export class AuthController { } @Post("/login") - @ResponseSchema(Auth) + @ResponseSchema(ResponseAuth) @ResponseSchema(InvalidCredentialsError) @ResponseSchema(UserNotFoundError) @ResponseSchema(UsernameOrEmailNeededError) @@ -60,7 +60,7 @@ export class AuthController { } @Post("/refresh") - @ResponseSchema(Auth) + @ResponseSchema(ResponseAuth) @ResponseSchema(JwtNotProvidedError) @ResponseSchema(IllegalJWTError) @ResponseSchema(UserNotFoundError) @@ -82,7 +82,7 @@ export class AuthController { } @Post("/reset") - @ResponseSchema(Auth) + @ResponseSchema(ResponseAuth) @ResponseSchema(UserNotFoundError) @ResponseSchema(UsernameOrEmailNeededError) @OpenAPI({ description: "Request a password reset token.
This will provide you with a reset token that you can use by posting to /api/auth/reset/{token}." }) @@ -92,7 +92,7 @@ export class AuthController { } @Post("/reset/:token") - @ResponseSchema(Auth) + @ResponseSchema(ResponseAuth) @ResponseSchema(UserNotFoundError) @ResponseSchema(UsernameOrEmailNeededError) @OpenAPI({ description: "Reset a user's utilising a valid password reset token.
This will set the user's password to the one you provided in the body.
To get a reset token post to /api/auth/reset with your username." }) diff --git a/src/models/responses/ResponseAuth.ts b/src/models/responses/ResponseAuth.ts index 5a8aa9e..6948253 100644 --- a/src/models/responses/ResponseAuth.ts +++ b/src/models/responses/ResponseAuth.ts @@ -3,7 +3,7 @@ import { IsInt, IsString } from 'class-validator'; /** * Defines the repsonse auth. */ -export class Auth { +export class ResponseAuth { /** * The access_token - JWT shortterm access token. */ From 01e0d5b94db8d6fc8d0e5f6aa7f83794812d9367 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 16:54:19 +0100 Subject: [PATCH 41/50] Renamed the auth response call to ResponseAuth ref #76 --- src/controllers/AuthController.ts | 10 +++++----- src/models/actions/RefreshAuth.ts | 6 +++--- src/models/actions/create/CreateAuth.ts | 6 +++--- src/models/responses/ResponseAuth.ts | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/controllers/AuthController.ts b/src/controllers/AuthController.ts index 5615de9..507ac38 100644 --- a/src/controllers/AuthController.ts +++ b/src/controllers/AuthController.ts @@ -7,7 +7,7 @@ import { CreateResetToken } from '../models/actions/create/CreateResetToken'; import { HandleLogout } from '../models/actions/HandleLogout'; import { RefreshAuth } from '../models/actions/RefreshAuth'; import { ResetPassword } from '../models/actions/ResetPassword'; -import { Auth } from '../models/responses/ResponseAuth'; +import { ResponseAuth } from '../models/responses/ResponseAuth'; import { Logout } from '../models/responses/ResponseLogout'; @JsonController('/auth') @@ -16,7 +16,7 @@ export class AuthController { } @Post("/login") - @ResponseSchema(Auth) + @ResponseSchema(ResponseAuth) @ResponseSchema(InvalidCredentialsError) @ResponseSchema(UserNotFoundError) @ResponseSchema(UsernameOrEmailNeededError) @@ -60,7 +60,7 @@ export class AuthController { } @Post("/refresh") - @ResponseSchema(Auth) + @ResponseSchema(ResponseAuth) @ResponseSchema(JwtNotProvidedError) @ResponseSchema(IllegalJWTError) @ResponseSchema(UserNotFoundError) @@ -82,7 +82,7 @@ export class AuthController { } @Post("/reset") - @ResponseSchema(Auth) + @ResponseSchema(ResponseAuth) @ResponseSchema(UserNotFoundError) @ResponseSchema(UsernameOrEmailNeededError) @OpenAPI({ description: "Request a password reset token.
This will provide you with a reset token that you can use by posting to /api/auth/reset/{token}." }) @@ -92,7 +92,7 @@ export class AuthController { } @Post("/reset/:token") - @ResponseSchema(Auth) + @ResponseSchema(ResponseAuth) @ResponseSchema(UserNotFoundError) @ResponseSchema(UsernameOrEmailNeededError) @OpenAPI({ description: "Reset a user's utilising a valid password reset token.
This will set the user's password to the one you provided in the body.
To get a reset token post to /api/auth/reset with your username." }) diff --git a/src/models/actions/RefreshAuth.ts b/src/models/actions/RefreshAuth.ts index bcc4fbb..20e8abf 100644 --- a/src/models/actions/RefreshAuth.ts +++ b/src/models/actions/RefreshAuth.ts @@ -5,7 +5,7 @@ import { config } from '../../config'; import { IllegalJWTError, JwtNotProvidedError, RefreshTokenCountInvalidError, UserDisabledError, UserNotFoundError } from '../../errors/AuthError'; import { JwtCreator } from "../../jwtcreator"; import { User } from '../entities/User'; -import { Auth } from '../responses/ResponseAuth'; +import { ResponseAuth } from '../responses/ResponseAuth'; /** * This class is used to create refreshed auth credentials. @@ -24,8 +24,8 @@ export class RefreshAuth { /** * Creates a new auth object based on this. */ - public async toAuth(): Promise { - let newAuth: Auth = new Auth(); + public async toAuth(): Promise { + let newAuth: ResponseAuth = new ResponseAuth(); if (!this.token || this.token === undefined) { throw new JwtNotProvidedError() } diff --git a/src/models/actions/create/CreateAuth.ts b/src/models/actions/create/CreateAuth.ts index e915d1b..d9b96b7 100644 --- a/src/models/actions/create/CreateAuth.ts +++ b/src/models/actions/create/CreateAuth.ts @@ -5,7 +5,7 @@ import { InvalidCredentialsError, PasswordNeededError, UserDisabledError, UserNo import { UsernameOrEmailNeededError } from '../../../errors/UserErrors'; import { JwtCreator } from '../../../jwtcreator'; import { User } from '../../entities/User'; -import { Auth } from '../../responses/ResponseAuth'; +import { ResponseAuth } from '../../responses/ResponseAuth'; /** * This class is used to create auth credentials based on user credentials provided in a json body (post request). @@ -42,8 +42,8 @@ export class CreateAuth { /** * Creates a new auth object based on this. */ - public async toAuth(): Promise { - let newAuth: Auth = new Auth(); + public async toAuth(): Promise { + let newAuth: ResponseAuth = new ResponseAuth(); if (this.email === undefined && this.username === undefined) { throw new UsernameOrEmailNeededError(); diff --git a/src/models/responses/ResponseAuth.ts b/src/models/responses/ResponseAuth.ts index 5a8aa9e..6948253 100644 --- a/src/models/responses/ResponseAuth.ts +++ b/src/models/responses/ResponseAuth.ts @@ -3,7 +3,7 @@ import { IsInt, IsString } from 'class-validator'; /** * Defines the repsonse auth. */ -export class Auth { +export class ResponseAuth { /** * The access_token - JWT shortterm access token. */ From 9355138a8c8322bc98465fcfc7d9691694b3986b Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 16:59:39 +0100 Subject: [PATCH 42/50] App now automagicly displays the current package version as the openapi version ref #76 --- src/config.ts | 3 ++- src/loaders/openapi.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index 8729b6e..43bb2b4 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,7 +7,8 @@ export const config = { development: process.env.NODE_ENV === "production", jwt_secret: process.env.JWT_SECRET || "secretjwtsecret", phone_validation_countrycode: process.env.PHONE_COUNTRYCODE || "ZZ", - postalcode_validation_countrycode: getPostalCodeLocale() + postalcode_validation_countrycode: getPostalCodeLocale(), + package_version: process.env.npm_package_version } let errors = 0 if (typeof config.internal_port !== "number") { diff --git a/src/loaders/openapi.ts b/src/loaders/openapi.ts index 7d8acfe..6f2056c 100644 --- a/src/loaders/openapi.ts +++ b/src/loaders/openapi.ts @@ -3,6 +3,7 @@ import express, { Application } from "express"; import path from 'path'; import { getMetadataArgsStorage } from "routing-controllers"; import { routingControllersToSpec } from "routing-controllers-openapi"; +import { config } from '../config'; /** * Loader for everything openapi related - from creating the schema to serving it via a static route and swaggerUiExpress. @@ -51,7 +52,7 @@ export default async (app: Application) => { info: { description: "The the backend API for the LfK! runner system.", title: "LfK! Backend API", - version: "0.0.8", + version: config.package_version, }, } ); From 172159414b1d4964ee862ad1edc66a7c4c94cccb Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 17:10:25 +0100 Subject: [PATCH 43/50] Unified the openapi generation ref #76 --- scripts/openapi_export.ts | 43 ++------------------------------- src/apispec.ts | 51 +++++++++++++++++++++++++++++++++++++++ src/loaders/openapi.ts | 44 ++------------------------------- 3 files changed, 55 insertions(+), 83 deletions(-) create mode 100644 src/apispec.ts diff --git a/scripts/openapi_export.ts b/scripts/openapi_export.ts index b72a369..83fd879 100644 --- a/scripts/openapi_export.ts +++ b/scripts/openapi_export.ts @@ -3,7 +3,7 @@ import consola from "consola"; import fs from "fs"; import "reflect-metadata"; import { createExpressServer, getMetadataArgsStorage } from "routing-controllers"; -import { routingControllersToSpec } from 'routing-controllers-openapi'; +import { generateSpec } from '../src/apispec'; import { config } from '../src/config'; import authchecker from "../src/middlewares/authchecker"; import { ErrorHandler } from '../src/middlewares/ErrorHandler'; @@ -24,46 +24,7 @@ const schemas = validationMetadatasToSchemas({ }); //Spec creation based on the previously created schemas -const spec = routingControllersToSpec( - storage, - { - routePrefix: "/api" - }, - { - components: { - schemas, - "securitySchemes": { - "AuthToken": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "JWT", - description: "A JWT based access token. Use /api/auth/login or /api/auth/refresh to get one." - }, - "RefreshTokenCookie": { - "type": "apiKey", - "in": "cookie", - "name": "lfk_backend__refresh_token", - description: "A cookie containing a JWT based refreh token. Attention: Doesn't work in swagger-ui. Use /api/auth/login or /api/auth/refresh to get one." - }, - "StatsApiToken": { - "type": "http", - "scheme": "bearer", - description: "Api token that can be obtained by creating a new stats client (post to /api/statsclients). Only valid for obtaining stats." - }, - "StationApiToken": { - "type": "http", - "scheme": "bearer", - description: "Api token that can be obtained by creating a new scan station (post to /api/stations). Only valid for creating scans." - } - } - }, - info: { - description: "The the backend API for the LfK! runner system.", - title: "LfK! Backend API", - version: "0.0.8", - }, - } -); +const spec = generateSpec(storage, schemas); try { fs.writeFileSync("./openapi.json", JSON.stringify(spec), { encoding: "utf-8" }); diff --git a/src/apispec.ts b/src/apispec.ts new file mode 100644 index 0000000..6beb511 --- /dev/null +++ b/src/apispec.ts @@ -0,0 +1,51 @@ +import { MetadataArgsStorage } from 'routing-controllers'; +import { routingControllersToSpec } from 'routing-controllers-openapi'; +import { config } from './config'; + +/** + * This function generates a the openapi spec from route metadata and type schemas. + * @param storage MetadataArgsStorage object generated by routing-controllers. + * @param schemas MetadataArgsStorage object generated by class-validator-jsonschema. + */ +export function generateSpec(storage: MetadataArgsStorage, schemas) { + return routingControllersToSpec( + storage, + { + routePrefix: "/api" + }, + { + components: { + schemas, + "securitySchemes": { + "AuthToken": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT", + description: "A JWT based access token. Use /api/auth/login or /api/auth/refresh to get one." + }, + "RefreshTokenCookie": { + "type": "apiKey", + "in": "cookie", + "name": "lfk_backend__refresh_token", + description: "A cookie containing a JWT based refreh token. Attention: Doesn't work in swagger-ui. Use /api/auth/login or /api/auth/refresh to get one." + }, + "StatsApiToken": { + "type": "http", + "scheme": "bearer", + description: "Api token that can be obtained by creating a new stats client (post to /api/statsclients). Only valid for obtaining stats." + }, + "StationApiToken": { + "type": "http", + "scheme": "bearer", + description: "Api token that can be obtained by creating a new scan station (post to /api/stations). Only valid for creating scans." + } + } + }, + info: { + description: "The the backend API for the LfK! runner system.", + title: "LfK! Backend API", + version: config.package_version, + }, + } + ); +} \ No newline at end of file diff --git a/src/loaders/openapi.ts b/src/loaders/openapi.ts index 6f2056c..0f3a49d 100644 --- a/src/loaders/openapi.ts +++ b/src/loaders/openapi.ts @@ -2,8 +2,7 @@ import { validationMetadatasToSchemas } from "class-validator-jsonschema"; import express, { Application } from "express"; import path from 'path'; import { getMetadataArgsStorage } from "routing-controllers"; -import { routingControllersToSpec } from "routing-controllers-openapi"; -import { config } from '../config'; +import { generateSpec } from '../apispec'; /** * Loader for everything openapi related - from creating the schema to serving it via a static route and swaggerUiExpress. @@ -16,46 +15,7 @@ export default async (app: Application) => { }); //Spec creation based on the previously created schemas - const spec = routingControllersToSpec( - storage, - { - routePrefix: "/api" - }, - { - components: { - schemas, - "securitySchemes": { - "AuthToken": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "JWT", - description: "A JWT based access token. Use /api/auth/login or /api/auth/refresh to get one." - }, - "RefreshTokenCookie": { - "type": "apiKey", - "in": "cookie", - "name": "lfk_backend__refresh_token", - description: "A cookie containing a JWT based refreh token. Attention: Doesn't work in swagger-ui. Use /api/auth/login or /api/auth/refresh to get one." - }, - "StatsApiToken": { - "type": "http", - "scheme": "bearer", - description: "Api token that can be obtained by creating a new stats client (post to /api/statsclients). Only valid for obtaining stats." - }, - "StationApiToken": { - "type": "http", - "scheme": "bearer", - description: "Api token that can be obtained by creating a new scan station (post to /api/stations). Only valid for creating scans." - } - } - }, - info: { - description: "The the backend API for the LfK! runner system.", - title: "LfK! Backend API", - version: config.package_version, - }, - } - ); + const spec = generateSpec(storage, schemas); app.get(["/api/docs/openapi.json", "/api/docs/swagger.json"], (req, res) => { res.json(spec); }); From e4fafd764c138708e0393e0b2cc46dd4e6276239 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 17:14:42 +0100 Subject: [PATCH 44/50] Cleaner implementation of the api version getter ref #76 --- src/apispec.ts | 3 +-- src/config.ts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/apispec.ts b/src/apispec.ts index 6beb511..f0a6d85 100644 --- a/src/apispec.ts +++ b/src/apispec.ts @@ -1,6 +1,5 @@ import { MetadataArgsStorage } from 'routing-controllers'; import { routingControllersToSpec } from 'routing-controllers-openapi'; -import { config } from './config'; /** * This function generates a the openapi spec from route metadata and type schemas. @@ -44,7 +43,7 @@ export function generateSpec(storage: MetadataArgsStorage, schemas) { info: { description: "The the backend API for the LfK! runner system.", title: "LfK! Backend API", - version: config.package_version, + version: process.env.npm_package_version }, } ); diff --git a/src/config.ts b/src/config.ts index 43bb2b4..8729b6e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,8 +7,7 @@ export const config = { development: process.env.NODE_ENV === "production", jwt_secret: process.env.JWT_SECRET || "secretjwtsecret", phone_validation_countrycode: process.env.PHONE_COUNTRYCODE || "ZZ", - postalcode_validation_countrycode: getPostalCodeLocale(), - package_version: process.env.npm_package_version + postalcode_validation_countrycode: getPostalCodeLocale() } let errors = 0 if (typeof config.internal_port !== "number") { From bca979bab5a092d0e266f96b5eca54525d53b0c7 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 17:16:42 +0100 Subject: [PATCH 45/50] Unified remove parameters ref #76 --- src/controllers/StatsClientController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/StatsClientController.ts b/src/controllers/StatsClientController.ts index d7724c3..4716909 100644 --- a/src/controllers/StatsClientController.ts +++ b/src/controllers/StatsClientController.ts @@ -1,4 +1,4 @@ -import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post } from 'routing-controllers'; +import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, QueryParam } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { StatsClientNotFoundError } from '../errors/StatsClientErrors'; @@ -65,7 +65,7 @@ export class StatsClientController { @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @OnUndefined(204) @OpenAPI({ description: "Delete the stats client whose id you provided.
If no client with this id exists it will just return 204(no content)." }) - async remove(@Param("id") id: number) { + async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let client = await this.clientRepository.findOne({ id: id }); if (!client) { return null; } From 1bb98c13d1eef83204506e67381f448b16f542fa Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 17:29:30 +0100 Subject: [PATCH 46/50] Dependency bump ref #76 --- package.json | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 952b62a..b905083 100644 --- a/package.json +++ b/package.json @@ -22,11 +22,11 @@ ], "license": "CC-BY-NC-SA-4.0", "dependencies": { - "argon2": "^0.27.0", + "argon2": "^0.27.1", "body-parser": "^1.19.0", "class-transformer": "^0.3.1", "class-validator": "^0.12.2", - "class-validator-jsonschema": "^2.0.3", + "class-validator-jsonschema": "^2.1.0", "consola": "^2.15.0", "cookie": "^0.4.1", "cookie-parser": "^1.4.5", @@ -39,33 +39,34 @@ "pg": "^8.5.1", "reflect-metadata": "^0.1.13", "routing-controllers": "^0.9.0-alpha.6", - "routing-controllers-openapi": "^2.1.0", + "routing-controllers-openapi": "^2.2.0", "sqlite3": "5.0.0", "typeorm": "^0.2.29", "typeorm-routing-controllers-extensions": "^0.2.0", "typeorm-seeding": "^1.6.1", - "uuid": "^8.3.1", + "uuid": "^8.3.2", "validator": "^13.5.2" }, "devDependencies": { - "@odit/license-exporter": "^0.0.8", - "@types/cors": "^2.8.8", + "@odit/license-exporter": "^0.0.9", + "@types/cors": "^2.8.9", "@types/csvtojson": "^1.1.5", "@types/express": "^4.17.9", "@types/jest": "^26.0.16", "@types/jsonwebtoken": "^8.5.0", - "@types/node": "^14.14.9", + "@types/node": "^14.14.20", "@types/uuid": "^8.3.0", - "axios": "^0.21.0", + "axios": "^0.21.1", "cp-cli": "^2.0.0", "jest": "^26.6.3", - "nodemon": "^2.0.6", - "rimraf": "^2.7.1", - "start-server-and-test": "^1.11.6", + "nodemon": "^2.0.7", + "release-it": "^14.2.2", + "rimraf": "^3.0.2", + "start-server-and-test": "^1.11.7", "ts-jest": "^26.4.4", - "ts-node": "^9.0.0", - "typedoc": "^0.19.2", - "typescript": "^4.1.2" + "ts-node": "^9.1.1", + "typedoc": "^0.20.14", + "typescript": "^4.1.3" }, "scripts": { "dev": "nodemon src/app.ts", @@ -76,7 +77,9 @@ "test:ci": "start-server-and-test dev http://localhost:4010/api/docs/openapi.json test", "seed": "ts-node ./node_modules/typeorm/cli.js schema:sync && ts-node ./node_modules/typeorm-seeding/dist/cli.js seed", "openapi:export": "ts-node scripts/openapi_export.ts", - "licenses:export": "license-exporter --md" + "licenses:export": "license-exporter --md", + "release": "release-it", + "changelog": "npx auto-changelog --commit-limit false --template https://raw.githubusercontent.com/release-it/release-it/master/templates/changelog-compact.hbs" }, "nodemonConfig": { "ignore": [ From dc6ec23cb99efecf1b932b91fcec2bb7d7ba208c Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 17:47:31 +0100 Subject: [PATCH 47/50] Implmented basic release mgnt ref #76 --- package.json | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b905083..44090a9 100644 --- a/package.json +++ b/package.json @@ -78,8 +78,25 @@ "seed": "ts-node ./node_modules/typeorm/cli.js schema:sync && ts-node ./node_modules/typeorm-seeding/dist/cli.js seed", "openapi:export": "ts-node scripts/openapi_export.ts", "licenses:export": "license-exporter --md", - "release": "release-it", - "changelog": "npx auto-changelog --commit-limit false --template https://raw.githubusercontent.com/release-it/release-it/master/templates/changelog-compact.hbs" + "release": "release-it" + }, + "release-it": { + "git": { + "commit": true, + "requireCleanWorkingDir": false, + "requireBranch": "main", + "commitMessage": "🚀RELEASE ${version}", + "push": false, + "tag": true, + "tagName": "v${version}", + "tagAnnotation": "v${version}" + }, + "npm": { + "publish": false + }, + "hooks": { + "after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md" + } }, "nodemonConfig": { "ignore": [ From be4050768e45fb7893d9bf1957095baed646ae92 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 18:01:22 +0100 Subject: [PATCH 48/50] Moded group updateing to a updateusergroup action model ref #76 --- src/controllers/UserGroupController.ts | 15 ++++---- src/models/actions/update/UpdateUserGroup.ts | 39 ++++++++++++++++++++ 2 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 src/models/actions/update/UpdateUserGroup.ts diff --git a/src/controllers/UserGroupController.ts b/src/controllers/UserGroupController.ts index 85426f5..18a901d 100644 --- a/src/controllers/UserGroupController.ts +++ b/src/controllers/UserGroupController.ts @@ -4,6 +4,7 @@ import { getConnectionManager, Repository } from 'typeorm'; import { EntityFromBody } from 'typeorm-routing-controllers-extensions'; import { UserGroupIdsNotMatchingError, UserGroupNotFoundError } from '../errors/UserGroupErrors'; import { CreateUserGroup } from '../models/actions/create/CreateUserGroup'; +import { UpdateUserGroup } from '../models/actions/update/UpdateUserGroup'; import { UserGroup } from '../models/entities/UserGroup'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseUserGroup } from '../models/responses/ResponseUserGroup'; @@ -62,19 +63,19 @@ export class UserGroupController { @ResponseSchema(UserGroupNotFoundError, { statusCode: 404 }) @ResponseSchema(UserGroupIdsNotMatchingError, { statusCode: 406 }) @OpenAPI({ description: "Update the group whose id you provided.
To change the permissions granted to the group please use /api/permissions instead.
Please remember that ids can't be changed." }) - async put(@Param('id') id: number, @EntityFromBody() userGroup: UserGroup) { - let oldUserGroup = await this.userGroupsRepository.findOne({ id: id }, { relations: ["permissions"] }); + async put(@Param('id') id: number, @EntityFromBody() updateGroup: UpdateUserGroup) { + let oldGroup = await this.userGroupsRepository.findOne({ id: id }); - if (!oldUserGroup) { - throw new UserGroupNotFoundError() + if (!oldGroup) { + throw new UserGroupNotFoundError(); } - if (oldUserGroup.id != userGroup.id) { + if (oldGroup.id != updateGroup.id) { throw new UserGroupIdsNotMatchingError(); } + await this.userGroupsRepository.save(await updateGroup.update(oldGroup)); - await this.userGroupsRepository.save(userGroup); - return userGroup; + return (await this.userGroupsRepository.findOne({ id: id }, { relations: ['permissions', 'groups'] })).toResponse(); } @Delete('/:id') diff --git a/src/models/actions/update/UpdateUserGroup.ts b/src/models/actions/update/UpdateUserGroup.ts new file mode 100644 index 0000000..88b559e --- /dev/null +++ b/src/models/actions/update/UpdateUserGroup.ts @@ -0,0 +1,39 @@ +import { IsInt, IsOptional, IsString } from 'class-validator'; +import { UserGroup } from '../../entities/UserGroup'; + +/** + * This class is used to update a UserGroup entity (via put request). + */ +export class UpdateUserGroup { + + /** + * The updated group's id. + * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to). + */ + @IsInt() + id: number; + + /** + * The updated group's name. + */ + @IsString() + name: string; + + /** + * The updated groups's description. + */ + @IsString() + @IsOptional() + description?: string; + + /** + * Updates a group entity based on this. + * @param group The group that shall be updated. + */ + public async update(group: UserGroup): Promise { + group.name = this.name; + group.description = this.description; + + return group; + } +} \ No newline at end of file From 02ae883fa4dd34d3d8032bbe81414c4287f078b9 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 18:09:57 +0100 Subject: [PATCH 49/50] Removed everything comit related from the release-it config ref #76 --- package.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/package.json b/package.json index 44090a9..b7fe5e6 100644 --- a/package.json +++ b/package.json @@ -82,10 +82,8 @@ }, "release-it": { "git": { - "commit": true, "requireCleanWorkingDir": false, "requireBranch": "main", - "commitMessage": "🚀RELEASE ${version}", "push": false, "tag": true, "tagName": "v${version}", @@ -93,9 +91,6 @@ }, "npm": { "publish": false - }, - "hooks": { - "after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md" } }, "nodemonConfig": { From 28cefa792cb24d5a07314b58454145a61a64b8d4 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sun, 10 Jan 2021 18:13:08 +0100 Subject: [PATCH 50/50] Version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b7fe5e6..a6f868c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@odit/lfk-backend", - "version": "0.0.10", + "version": "0.0.11", "main": "src/app.ts", "repository": "https://git.odit.services/lfk/backend", "author": {