diff --git a/src/controllers/RunnerSelfServiceController.ts b/src/controllers/RunnerSelfServiceController.ts index 878cf1b..03e0ec3 100644 --- a/src/controllers/RunnerSelfServiceController.ts +++ b/src/controllers/RunnerSelfServiceController.ts @@ -67,7 +67,7 @@ export class RunnerSelfServiceController { @ResponseSchema(ResponseScanStation) @ResponseSchema(ScanStationNotFoundError, { statusCode: 404 }) @OnUndefined(ScanStationNotFoundError) - @OpenAPI({ description: 'Lists basic information about the station whose token got provided.
This includes it\'s associated track.', security: [{ "ScanApiToken": [] }] }) + @OpenAPI({ description: 'Lists basic information about the station whose token got provided.
This includes it\'s associated track.', security: [{ "StationApiToken": [] }] }) async getStationMe(@Req() req: Request) { let scan = await this.stationRepository.findOne({ id: parseInt(req.headers["station_id"].toString()) }, { relations: ['track'] }) if (!scan) { throw new ScanStationNotFoundError(); } @@ -77,7 +77,7 @@ export class RunnerSelfServiceController { @Post('/runners/forgot') @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @OnUndefined(ResponseEmpty) - @OpenAPI({ description: 'TODO' }) + @OpenAPI({ description: 'Use this endpoint to reuqest a new selfservice token/link to be sent to your mail address (rate limited to one mail every 24hrs).' }) async requestNewToken(@QueryParam('mail') mail: string) { if (!mail) { throw new RunnerNotFoundError(); diff --git a/src/controllers/ScanController.ts b/src/controllers/ScanController.ts index b223689..210cde1 100644 --- a/src/controllers/ScanController.ts +++ b/src/controllers/ScanController.ts @@ -1,4 +1,5 @@ -import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam, UseBefore } from 'routing-controllers'; +import { Request } from "express"; +import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam, Req, UseBefore } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { RunnerNotFoundError } from '../errors/RunnerErrors'; @@ -14,7 +15,6 @@ import { TrackScan } from '../models/entities/TrackScan'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseScan } from '../models/responses/ResponseScan'; import { ResponseTrackScan } from '../models/responses/ResponseTrackScan'; - @JsonController('/scans') @OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class ScanController { @@ -60,7 +60,7 @@ export class ScanController { @UseBefore(ScanAuth) @ResponseSchema(ResponseScan) @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": [] }] }) + @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: [{ "StationApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) async post(@Body({ validate: true }) createScan: CreateScan) { let scan = await createScan.toEntity(); scan = await this.scanRepository.save(scan); @@ -71,8 +71,12 @@ export class ScanController { @UseBefore(ScanAuth) @ResponseSchema(ResponseTrackScan) @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) { + @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: [{ "StationApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) + async postTrackScans(@Body({ validate: true }) createScan: CreateTrackScan, @Req() req: Request) { + const station_id = req.headers["station_id"]; + if (station_id) { + createScan.station = parseInt(station_id.toString()); + } 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.group', 'runner.scans.track', 'card', 'station'] })).toResponse(); diff --git a/src/models/actions/create/CreateTrackScan.ts b/src/models/actions/create/CreateTrackScan.ts index 578497f..80ad4d6 100644 --- a/src/models/actions/create/CreateTrackScan.ts +++ b/src/models/actions/create/CreateTrackScan.ts @@ -1,4 +1,5 @@ -import { IsInt, IsPositive } from 'class-validator'; +import { IsInt, IsOptional, IsPositive } from 'class-validator'; +import { BadRequestError } from 'routing-controllers'; import { getConnection } from 'typeorm'; import { RunnerCardNotFoundError } from '../../../errors/RunnerCardErrors'; import { RunnerNotFoundError } from '../../../errors/RunnerErrors'; @@ -22,10 +23,12 @@ export class CreateTrackScan { /** * The scanning station's id that created the scan. * Mainly used for logging and traceing back scans (or errors). + * You don't have to provide the station if you're authenticateing via a scanstation token (The server takes care of it for you). */ @IsInt() @IsPositive() - station: number; + @IsOptional() + station?: number; /** * Creates a new Track entity from this. @@ -44,12 +47,15 @@ export class CreateTrackScan { } newScan.timestamp = Math.round(new Date().getTime() / 1000); - newScan.lapTime = await this.getLaptime(newScan) - newScan.valid = await this.validateScan(newScan); + newScan = await this.validateScan(newScan); return newScan; } + /** + * Get's a runnerCard entity via the provided id. + * @returns The runnerCard whom's id you provided. + */ public async getCard(): Promise { const track = await getConnection().getRepository(RunnerCard).findOne({ id: this.card }, { relations: ["runner"] }); if (!track) { @@ -58,7 +64,14 @@ export class CreateTrackScan { return track; } + /** + * Get's a scanstation entity via the provided id. + * @returns The scanstation whom's id you provided. + */ public async getStation(): Promise { + if (!this.station) { + throw new BadRequestError("You are missing the station's id!") + } const station = await getConnection().getRepository(ScanStation).findOne({ id: this.station }, { relations: ["track"] }); if (!station) { throw new ScanStationNotFoundError(); @@ -66,15 +79,22 @@ export class CreateTrackScan { return station; } - public validateScan(scan: TrackScan): boolean { - return (scan.lapTime > scan.track.minimumLapTime); - } - - public async getLaptime(scan: TrackScan): Promise { + /** + * Validates the scan and sets it's lap time; + * @param scan The scan you want to validate + * @returns The validated scan with it's laptime set. + */ + public async validateScan(scan: TrackScan): Promise { const scans = await getConnection().getRepository(TrackScan).find({ where: { runner: scan.runner, valid: true }, relations: ["track"] }); - if (scans.length == 0) { return 0; } - - const newestScan = scans[scans.length - 1]; - return (scan.timestamp - newestScan.timestamp); + if (scans.length == 0) { + scan.lapTime = 0; + scan.valid = true; + } + else { + const newestScan = scans[scans.length - 1]; + scan.lapTime = scan.timestamp - newestScan.timestamp; + scan.valid = (scan.lapTime > scan.track.minimumLapTime); + } + return scan; } } \ No newline at end of file