From 3bbfab926035cb158c967535e88793416a563404 Mon Sep 17 00:00:00 2001 From: Valentin Kaelin Date: Mon, 5 Oct 2020 19:49:03 +0200 Subject: [PATCH] refactor: use validator for summoner/basic endpoint --- .../Controllers/Http/SummonersController.ts | 23 +++----- .../app/Repositories/MatchRepository.ts | 20 +++++-- .../app/Validators/SummonerBasicValidator.ts | 55 +++++++++++++++++++ 3 files changed, 76 insertions(+), 22 deletions(-) create mode 100644 server-new/app/Validators/SummonerBasicValidator.ts diff --git a/server-new/app/Controllers/Http/SummonersController.ts b/server-new/app/Controllers/Http/SummonersController.ts index be41827..6ceccbd 100644 --- a/server-new/app/Controllers/Http/SummonersController.ts +++ b/server-new/app/Controllers/Http/SummonersController.ts @@ -4,10 +4,15 @@ import MatchRepository from 'App/Repositories/MatchRepository' import Jax from 'App/Services/Jax' import MatchService from 'App/Services/MatchService' import SummonerService from 'App/Services/SummonerService' +import SummonerBasicValidator from 'App/Validators/SummonerBasicValidator' export default class SummonersController { + /** + * Get all played seasons for a summoner + * @param puuid of the summoner + */ private async getSeasons (puuid: string) { - let seasons = await MatchRepository.seasons(puuid) + const seasons = await MatchRepository.seasons(puuid) return seasons.length ? seasons.map(s => s._id) : [10] } @@ -17,15 +22,7 @@ export default class SummonersController { */ public async basic ({ request, response }: HttpContextContract) { console.time('all') - const summoner = request.input('summoner') - const region = request.input('region') - console.log(summoner, region) - - const regexSummonerName = new RegExp('^[0-9\\p{L} _\\.]+$', 'u') - if (!regexSummonerName.exec(summoner)) { - return response.json(null) - } - + const { summoner, region} = await request.validate(SummonerBasicValidator) const finalJSON:any = {} try { @@ -38,11 +35,6 @@ export default class SummonersController { finalJSON.account = account // Summoner in DB - // const summonerDB = await Summoner.findOrCreate( - // { puuid: account.puuid }, - // { puuid: account.puuid } - // ) - let summonerDB = await Summoner.findOne({ puuid: account.puuid }) if(!summonerDB) { summonerDB = await Summoner.create({ puuid: account.puuid }) @@ -67,7 +59,6 @@ export default class SummonersController { finalJSON.ranked = await SummonerService.getRanked(account, region) // SAVE IN DB - // await summonerDB.save() await summonerDB.save() } catch (error) { console.log('username not found') diff --git a/server-new/app/Repositories/MatchRepository.ts b/server-new/app/Repositories/MatchRepository.ts index fc6c4cc..fdb2913 100644 --- a/server-new/app/Repositories/MatchRepository.ts +++ b/server-new/app/Repositories/MatchRepository.ts @@ -1,17 +1,26 @@ import mongodb from '@ioc:Mongodb/Database' +import { Collection } from 'mongodb' class MatchRepository { private season?: number + private collection: Collection constructor () { - // TODO: keep matches collection in the repo instance + this.getCollection() + } + + /** + * Get MongoDB matches collection + */ + private async getCollection () { + this.collection = await mongodb.connection().collection('matches') } /** * Basic matchParams used in a lot of requests * @param puuid of the summoner */ - private _matchParams (puuid: string) { + private matchParams (puuid: string) { return { summoner_puuid: puuid, result: { $not: { $eq: 'Remake' } }, @@ -19,18 +28,17 @@ class MatchRepository { season: this.season ? this.season : { $exists: true }, } } + /** * Get Summoner's played seasons * @param puuid of the summoner */ public async seasons (puuid: string) { this.season = undefined - const matchesCollections = await mongodb.connection().collection('matches') - - return matchesCollections.aggregate([ + return this.collection.aggregate([ { $match: { - ...this._matchParams(puuid), + ...this.matchParams(puuid), }, }, { diff --git a/server-new/app/Validators/SummonerBasicValidator.ts b/server-new/app/Validators/SummonerBasicValidator.ts new file mode 100644 index 0000000..82abb43 --- /dev/null +++ b/server-new/app/Validators/SummonerBasicValidator.ts @@ -0,0 +1,55 @@ +import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' +import { rules, schema } from '@ioc:Adonis/Core/Validator' + +export default class SummonerBasicValidator { + constructor (private ctx: HttpContextContract) { + } + + /** + * Defining a schema to validate the "shape", "type", "formatting" and "integrity" of data. + * + * For example: + * 1. The username must be of data type string. But then also, it should + * not contain special characters or numbers. + * ``` + * schema.string({}, [ rules.alpha() ]) + * ``` + * + * 2. The email must be of data type string, formatted as a valid + * email. But also, not used by any other user. + * ``` + * schema.string({}, [ + * rules.email(), + * rules.unique({ table: 'users', column: 'email' }), + * ]) + * ``` + */ + public schema = schema.create({ + summoner: schema.string({}, [ + rules.regex(/^[0-9\p{L} _\.]+$/u), + ]), + region: schema.string(), + }) + + /** + * The `schema` first gets compiled to a reusable function and then that compiled + * function validates the data at runtime. + * + * Since, compiling the schema is an expensive operation, you must always cache it by + * defining a unique cache key. The simplest way is to use the current request route + * key, which is a combination of the route pattern and HTTP method. + */ + public cacheKey = this.ctx.routeKey + + /** + * Custom messages for validation failures. You can make use of dot notation `(.)` + * for targeting nested fields and array expressions `(*)` for targeting all + * children of an array. For example: + * + * { + * 'profile.username.required': 'Username is required', + * 'scores.*.number': 'Define scores as valid numbers' + * } + */ + public messages = {} +}