From 857de9ffcc637ab5e9761e8e5cc00067d4d21745 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Thu, 7 Jan 2021 17:29:22 +0100 Subject: [PATCH] Added Creation class for ScanSatations ref #67 --- src/models/actions/CreateScanStation.ts | 53 +++++++++++++++++++++++++ src/models/entities/ScanStation.ts | 19 ++++++--- 2 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 src/models/actions/CreateScanStation.ts diff --git a/src/models/actions/CreateScanStation.ts b/src/models/actions/CreateScanStation.ts new file mode 100644 index 0000000..fd1d8ad --- /dev/null +++ b/src/models/actions/CreateScanStation.ts @@ -0,0 +1,53 @@ +import * as argon2 from "argon2"; +import { IsInt, IsOptional, IsPositive, IsString } from 'class-validator'; +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'; + +/** + * This classed is used to create a new StatsClient entity from a json body (post request). + */ +export class CreateStatsClient { + /** + * The new client's description. + */ + @IsString() + @IsOptional() + description?: string; + + /** + * The scan's associated track. + * This is used to determine the scan's distance. + */ + @IsInt() + @IsPositive() + track: number; + + /** + * Converts this to a ScanStation entity. + */ + public async toEntity(): Promise { + let newStation: ScanStation = new ScanStation(); + + newStation.description = this.description; + newStation.track = await this.getTrack(); + + let newUUID = uuid.v4().toUpperCase(); + newStation.prefix = crypto.createHash("sha3-512").update(newUUID).digest('hex').substring(0, 7).toUpperCase(); + newStation.key = await argon2.hash(newStation.prefix + "." + newUUID); + newStation.cleartextkey = newStation.prefix + "." + newUUID; + + return newStation; + } + + public async getTrack(): Promise { + const track = await getConnection().getRepository(Track).findOne({ id: this.track }); + if (!track) { + throw new TrackNotFoundError(); + } + return track; + } +} \ No newline at end of file diff --git a/src/models/entities/ScanStation.ts b/src/models/entities/ScanStation.ts index 20c5f05..e9c03d2 100644 --- a/src/models/entities/ScanStation.ts +++ b/src/models/entities/ScanStation.ts @@ -1,5 +1,4 @@ import { - IsBoolean, IsInt, IsNotEmpty, IsOptional, @@ -39,6 +38,14 @@ export class ScanStation { @ManyToOne(() => Track, track => track.stations, { nullable: false }) track: Track; + /** + * The client's api key prefix. + * This is used identitfy a client by it's api key. + */ + @Column({ unique: true }) + @IsString() + prefix: string; + /** * The station's api key. * This is used to authorize a station against the api (not implemented yet). @@ -49,12 +56,12 @@ export class ScanStation { key: string; /** - * Is the station enabled (for fraud and setup reasons)? - * Default: true + * The client's api key in plain text. + * This will only be used to display the full key on creation and updates. */ - @Column() - @IsBoolean() - enabled: boolean = true; + @IsString() + @IsOptional() + cleartextkey?: string; /** * Used to link track scans to a scan station.