From 66d6023335c7a9d1a145c4189b610940ef5a525a Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:15:27 +0100 Subject: [PATCH 01/18] Added last reset requested timestamp to runners ref #154 --- src/models/entities/Runner.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/models/entities/Runner.ts b/src/models/entities/Runner.ts index ad16eae..87ef38d 100644 --- a/src/models/entities/Runner.ts +++ b/src/models/entities/Runner.ts @@ -1,5 +1,5 @@ -import { IsInt, IsNotEmpty } from "class-validator"; -import { ChildEntity, ManyToOne, OneToMany } from "typeorm"; +import { IsInt, IsNotEmpty, IsOptional, IsString } from "class-validator"; +import { ChildEntity, Column, ManyToOne, OneToMany } from "typeorm"; import { ResponseRunner } from '../responses/ResponseRunner'; import { DistanceDonation } from "./DistanceDonation"; import { Participant } from "./Participant"; @@ -43,6 +43,15 @@ export class Runner extends Participant { @OneToMany(() => Scan, scan => scan.runner, { nullable: true }) scans: Scan[]; + /** + * The last time the runner requested a selfservice link. + * Used to prevent spamming of the selfservice link forgotten route. + */ + @Column({ nullable: true, unique: false }) + @IsString() + @IsOptional() + resetRequestedTimestamp?: number; + /** * Returns all valid scans associated with this runner. * This is implemented here to avoid duplicate code in other files. From d7099717c2eee8aaf1b580345717cc5acc06dbd2 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:23:01 +0100 Subject: [PATCH 02/18] Created basic endpoint for user forgotten mails ref #154 --- .../RunnerSelfServiceController.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/controllers/RunnerSelfServiceController.ts b/src/controllers/RunnerSelfServiceController.ts index 8b1f30c..9264555 100644 --- a/src/controllers/RunnerSelfServiceController.ts +++ b/src/controllers/RunnerSelfServiceController.ts @@ -1,5 +1,5 @@ import * as jwt from "jsonwebtoken"; -import { Body, Get, JsonController, OnUndefined, Param, Post } from 'routing-controllers'; +import { Body, Get, JsonController, OnUndefined, Param, Post, QueryParam } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { config } from '../config'; @@ -12,6 +12,7 @@ import { CreateSelfServiceRunner } from '../models/actions/create/CreateSelfServ import { Runner } from '../models/entities/Runner'; import { RunnerGroup } from '../models/entities/RunnerGroup'; import { RunnerOrganization } from '../models/entities/RunnerOrganization'; +import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseSelfServiceOrganisation } from '../models/responses/ResponseSelfServiceOrganisation'; import { ResponseSelfServiceRunner } from '../models/responses/ResponseSelfServiceRunner'; import { ResponseSelfServiceScan } from '../models/responses/ResponseSelfServiceScan'; @@ -53,6 +54,23 @@ export class RunnerSelfServiceController { return responseScans; } + @Post('/runners/me/forgot') + @ResponseSchema(ResponseSelfServiceRunner, { isArray: true }) + @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) + @OnUndefined(ResponseEmpty) + @OpenAPI({ description: 'TODO' }) + async requestNewToken(@QueryParam('mail') mail: string) { + const runner = await this.runnerRepository.findOne({ email: mail }); + if (runner.resetRequestedTimestamp > (Math.floor(Date.now() / 1000) - 15 * 60)) { throw new Error("timeout!") } + const token = JwtCreator.createSelfService(runner); + try { + //await Mailer.sendForgottenMail(); + } catch (error) { + throw new Error("Mail fucked up"); + } + return { token }; + } + @Post('/runners/register') @ResponseSchema(ResponseSelfServiceRunner) @ResponseSchema(RunnerEmailNeededError, { statusCode: 406 }) From ffcd45e5724fccdec9b1dbc48f1320525dcd7288 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:24:43 +0100 Subject: [PATCH 03/18] Updated request timeout ref #154 --- src/controllers/RunnerSelfServiceController.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/controllers/RunnerSelfServiceController.ts b/src/controllers/RunnerSelfServiceController.ts index 9264555..8caeb6b 100644 --- a/src/controllers/RunnerSelfServiceController.ts +++ b/src/controllers/RunnerSelfServiceController.ts @@ -61,13 +61,18 @@ export class RunnerSelfServiceController { @OpenAPI({ description: 'TODO' }) async requestNewToken(@QueryParam('mail') mail: string) { const runner = await this.runnerRepository.findOne({ email: mail }); - if (runner.resetRequestedTimestamp > (Math.floor(Date.now() / 1000) - 15 * 60)) { throw new Error("timeout!") } + if (runner.resetRequestedTimestamp > (Math.floor(Date.now() / 1000) - 60 * 60 * 24)) { throw new Error("timeout!") } const token = JwtCreator.createSelfService(runner); + try { //await Mailer.sendForgottenMail(); } catch (error) { throw new Error("Mail fucked up"); } + + runner.resetRequestedTimestamp = Math.floor(Date.now() / 1000); + await this.runnerRepository.save(runner); + return { token }; } From e7f0cb45c9ac3aa06e2a57786aa1cc51c9d66598 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:29:44 +0100 Subject: [PATCH 04/18] Added not found error logic ref #154 --- src/controllers/RunnerSelfServiceController.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controllers/RunnerSelfServiceController.ts b/src/controllers/RunnerSelfServiceController.ts index 8caeb6b..8e72c3e 100644 --- a/src/controllers/RunnerSelfServiceController.ts +++ b/src/controllers/RunnerSelfServiceController.ts @@ -55,12 +55,13 @@ export class RunnerSelfServiceController { } @Post('/runners/me/forgot') - @ResponseSchema(ResponseSelfServiceRunner, { isArray: true }) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @OnUndefined(ResponseEmpty) @OpenAPI({ description: 'TODO' }) async requestNewToken(@QueryParam('mail') mail: string) { const runner = await this.runnerRepository.findOne({ email: mail }); + if (!runner) { throw new RunnerNotFoundError(); } + if (runner.resetRequestedTimestamp > (Math.floor(Date.now() / 1000) - 60 * 60 * 24)) { throw new Error("timeout!") } const token = JwtCreator.createSelfService(runner); From e26b7d4923777a3013368e29c122709de7e1d9da Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:32:36 +0100 Subject: [PATCH 05/18] Implemented the "real" errors ref #154 --- src/controllers/RunnerSelfServiceController.ts | 7 ++++--- src/errors/RunnerErrors.ts | 11 +++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/controllers/RunnerSelfServiceController.ts b/src/controllers/RunnerSelfServiceController.ts index 8e72c3e..b441cb0 100644 --- a/src/controllers/RunnerSelfServiceController.ts +++ b/src/controllers/RunnerSelfServiceController.ts @@ -4,7 +4,8 @@ import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { getConnectionManager, Repository } from 'typeorm'; import { config } from '../config'; import { InvalidCredentialsError, JwtNotProvidedError } from '../errors/AuthError'; -import { RunnerEmailNeededError, RunnerNotFoundError } from '../errors/RunnerErrors'; +import { MailSendingError } from '../errors/MailErrors'; +import { RunnerEmailNeededError, RunnerNotFoundError, RunnerSelfserviceTimeoutError } from '../errors/RunnerErrors'; import { RunnerOrganizationNotFoundError } from '../errors/RunnerOrganizationErrors'; import { JwtCreator } from '../jwtcreator'; import { CreateSelfServiceCitizenRunner } from '../models/actions/create/CreateSelfServiceCitizenRunner'; @@ -62,13 +63,13 @@ export class RunnerSelfServiceController { const runner = await this.runnerRepository.findOne({ email: mail }); if (!runner) { throw new RunnerNotFoundError(); } - if (runner.resetRequestedTimestamp > (Math.floor(Date.now() / 1000) - 60 * 60 * 24)) { throw new Error("timeout!") } + if (runner.resetRequestedTimestamp > (Math.floor(Date.now() / 1000) - 60 * 60 * 24)) { throw new RunnerSelfserviceTimeoutError(); } const token = JwtCreator.createSelfService(runner); try { //await Mailer.sendForgottenMail(); } catch (error) { - throw new Error("Mail fucked up"); + throw new MailSendingError(); } runner.resetRequestedTimestamp = Math.floor(Date.now() / 1000); diff --git a/src/errors/RunnerErrors.ts b/src/errors/RunnerErrors.ts index 7be9048..f5eea84 100644 --- a/src/errors/RunnerErrors.ts +++ b/src/errors/RunnerErrors.ts @@ -46,6 +46,17 @@ export class RunnerEmailNeededError extends NotAcceptableError { message = "Citizenrunners have to provide an email address for verification and contacting." } +/** + * Error to throw when a runner already requested a new selfservice link in the last 24hrs. + */ +export class RunnerSelfserviceTimeoutError extends NotAcceptableError { + @IsString() + name = "RunnerSelfserviceTimeoutError" + + @IsString() + message = "You can only reqest a new token every 24hrs." +} + /** * Error to throw when a runner still has distance donations associated. */ From 83765136ccacd82ba6a8f9fb43eed78191ee0aa5 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:36:12 +0100 Subject: [PATCH 06/18] Added mailer functions ref #154 --- src/mailer.ts | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/mailer.ts b/src/mailer.ts index 33d7f24..4d1753a 100644 --- a/src/mailer.ts +++ b/src/mailer.ts @@ -25,4 +25,36 @@ export class Mailer { throw new MailSendingError(); } } + + /** + * Function for sending a runner selfservice welcome mail. + * @param to_address The address the mail will be sent to. Should always get pulled from a runner object. + * @param token The requested selfservice token - will be combined with the app_url to generate a selfservice profile link. + */ + public static async sendSelfserviceWelcomeMail(to_address: string, token: string, locale: string = "en") { + try { + await axios.post(`${Mailer.base}/registration?locale=${locale}&key=${Mailer.key}`, { + address: to_address, + selfserviceToken: token + }); + } catch (error) { + throw new MailSendingError(); + } + } + + /** + * Function for sending a runner selfservice link forgotten mail. + * @param to_address The address the mail will be sent to. Should always get pulled from a runner object. + * @param token The requested selfservice token - will be combined with the app_url to generate a selfservice profile link. + */ + public static async sendSelfserviceForgottenMail(to_address: string, token: string, locale: string = "en") { + try { + await axios.post(`${Mailer.base}/registration_forgot?locale=${locale}&key=${Mailer.key}`, { + address: to_address, + selfserviceToken: token + }); + } catch (error) { + throw new MailSendingError(); + } + } } From a3437475caf6b435ae4bdf6d48aeb7da7d43b25f Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:38:37 +0100 Subject: [PATCH 07/18] Runner controller now uses the Mailer functions ref #154 --- src/controllers/RunnerSelfServiceController.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/controllers/RunnerSelfServiceController.ts b/src/controllers/RunnerSelfServiceController.ts index b441cb0..f73098f 100644 --- a/src/controllers/RunnerSelfServiceController.ts +++ b/src/controllers/RunnerSelfServiceController.ts @@ -8,6 +8,7 @@ import { MailSendingError } from '../errors/MailErrors'; import { RunnerEmailNeededError, RunnerNotFoundError, RunnerSelfserviceTimeoutError } from '../errors/RunnerErrors'; import { RunnerOrganizationNotFoundError } from '../errors/RunnerOrganizationErrors'; import { JwtCreator } from '../jwtcreator'; +import { Mailer } from '../mailer'; import { CreateSelfServiceCitizenRunner } from '../models/actions/create/CreateSelfServiceCitizenRunner'; import { CreateSelfServiceRunner } from '../models/actions/create/CreateSelfServiceRunner'; import { Runner } from '../models/entities/Runner'; @@ -67,7 +68,7 @@ export class RunnerSelfServiceController { const token = JwtCreator.createSelfService(runner); try { - //await Mailer.sendForgottenMail(); + await Mailer.sendSelfserviceForgottenMail(runner.email, token, "en") } catch (error) { throw new MailSendingError(); } @@ -88,6 +89,13 @@ export class RunnerSelfServiceController { runner = await this.runnerRepository.save(runner); let response = new ResponseSelfServiceRunner(await this.runnerRepository.findOne(runner, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards', 'distanceDonations', 'distanceDonations.donor', 'distanceDonations.runner', 'distanceDonations.runner.scans', 'distanceDonations.runner.scans.track'] })); response.token = JwtCreator.createSelfService(runner); + + try { + await Mailer.sendSelfserviceWelcomeMail(runner.email, response.token, "en") + } catch (error) { + throw new MailSendingError(); + } + return response; } @@ -103,6 +111,13 @@ export class RunnerSelfServiceController { let response = new ResponseSelfServiceRunner(await this.runnerRepository.findOne(runner, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards', 'distanceDonations', 'distanceDonations.donor', 'distanceDonations.runner', 'distanceDonations.runner.scans', 'distanceDonations.runner.scans.track'] })); response.token = JwtCreator.createSelfService(runner); + + try { + await Mailer.sendSelfserviceWelcomeMail(runner.email, response.token, "en") + } catch (error) { + throw new MailSendingError(); + } + return response; } From 3f372123fd2e1fae467e9cb20985de1eeb9f6a57 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:41:10 +0100 Subject: [PATCH 08/18] Added testing env check ref #154 --- scripts/create_testenv.ts | 2 +- src/config.ts | 2 ++ src/mailer.ts | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/create_testenv.ts b/scripts/create_testenv.ts index da08dea..ed18169 100644 --- a/scripts/create_testenv.ts +++ b/scripts/create_testenv.ts @@ -10,7 +10,7 @@ DB_PORT=bla DB_USER=bla DB_PASSWORD=bla DB_NAME=./test.sqlite -NODE_ENV=dev +NODE_ENV=test POSTALCODE_COUNTRYCODE=DE SEED_TEST_DATA=true MAILER_URL=https://dev.lauf-fuer-kaya.de/mailer diff --git a/src/config.ts b/src/config.ts index 08af1ac..bb6f2c5 100644 --- a/src/config.ts +++ b/src/config.ts @@ -6,6 +6,7 @@ configDotenv(); export const config = { internal_port: parseInt(process.env.APP_PORT) || 4010, development: process.env.NODE_ENV === "production", + testing: process.env.NODE_ENV === "test", jwt_secret: process.env.JWT_SECRET || "secretjwtsecret", phone_validation_countrycode: getPhoneCodeLocale(), postalcode_validation_countrycode: getPostalCodeLocale(), @@ -27,6 +28,7 @@ if (typeof config.development !== "boolean") { if (config.mailer_url == "" || config.mailer_key == "") { errors++; } +console.log(config.testing) function getPhoneCodeLocale(): CountryCode { return (process.env.PHONE_COUNTRYCODE as CountryCode); } diff --git a/src/mailer.ts b/src/mailer.ts index 4d1753a..9782244 100644 --- a/src/mailer.ts +++ b/src/mailer.ts @@ -9,6 +9,7 @@ import { MailSendingError } from './errors/MailErrors'; export class Mailer { public static base: string = config.mailer_url; public static key: string = config.mailer_key; + public static testing: boolean = config.testing; /** * Function for sending a password reset mail. From cedc1750c21ad256c3337f293f06e894e2c2ef9f Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:42:10 +0100 Subject: [PATCH 09/18] Added readme description for testing env ref #154 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b2ba341..06a44b1 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ yarn docs | DB_USER | String | N/A | The user for accessing the db | DB_PASSWORD | String | N/A | The user's password for accessing the db | DB_NAME | String | N/A | The db's name -| NODE_ENV | String | dev | The apps env - influences debug info. +| NODE_ENV | String | dev | The apps env - influences debug info. Also when the env is set to "test", mailing errors get ignored. | POSTALCODE_COUNTRYCODE | String/CountryCode | N/A | The countrycode used to validate address's postal codes | PHONE_COUNTRYCODE | String/CountryCode | null (international) | The countrycode used to validate phone numers | SEED_TEST_DATA | Boolean | False | If you want the app to seed some example data set this to true From 6bb3ae8ba992bd6c4d5809d75a264c710999cdcf Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:44:10 +0100 Subject: [PATCH 10/18] Mailer now ignores mailing erros when env is set to test ref #154 --- src/config.ts | 4 +++- src/mailer.ts | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index bb6f2c5..3c4c843 100644 --- a/src/config.ts +++ b/src/config.ts @@ -28,7 +28,9 @@ if (typeof config.development !== "boolean") { if (config.mailer_url == "" || config.mailer_key == "") { errors++; } -console.log(config.testing) +if (config.testing) { + console.log("Discovered testing env. Ignoring all mailing errors!") +} function getPhoneCodeLocale(): CountryCode { return (process.env.PHONE_COUNTRYCODE as CountryCode); } diff --git a/src/mailer.ts b/src/mailer.ts index 9782244..fae23d1 100644 --- a/src/mailer.ts +++ b/src/mailer.ts @@ -23,6 +23,7 @@ export class Mailer { resetKey: token }); } catch (error) { + if (Mailer.testing) { return true; } throw new MailSendingError(); } } @@ -39,6 +40,7 @@ export class Mailer { selfserviceToken: token }); } catch (error) { + if (Mailer.testing) { return true; } throw new MailSendingError(); } } @@ -55,6 +57,7 @@ export class Mailer { selfserviceToken: token }); } catch (error) { + if (Mailer.testing) { return true; } throw new MailSendingError(); } } From 92920273bec409563d1e38ea27f4d30f893598e8 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:51:07 +0100 Subject: [PATCH 11/18] Adjusted tests for the new testing env ref #154 --- src/config.ts | 3 --- src/tests/auth/auth_reset.spec.ts | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/config.ts b/src/config.ts index 3c4c843..28b687e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -28,9 +28,6 @@ if (typeof config.development !== "boolean") { if (config.mailer_url == "" || config.mailer_key == "") { errors++; } -if (config.testing) { - console.log("Discovered testing env. Ignoring all mailing errors!") -} function getPhoneCodeLocale(): CountryCode { return (process.env.PHONE_COUNTRYCODE as CountryCode); } diff --git a/src/tests/auth/auth_reset.spec.ts b/src/tests/auth/auth_reset.spec.ts index 64aa790..59da15a 100644 --- a/src/tests/auth/auth_reset.spec.ts +++ b/src/tests/auth/auth_reset.spec.ts @@ -38,7 +38,7 @@ describe('POST /api/auth/reset valid', () => { it('valid reset token request should return 200 (500 w/o correct auth)', async () => { const res1 = await axios.post(base + '/api/auth/reset', { email: "demo_reset1@dev.lauf-fuer-kaya.de" }, axios_config); reset_token = res1.data.resetToken; - expect(res1.status).toEqual(500); + expect(res1.status).toEqual(200); }); }); // --------------- From c01233b4d663aefece26dbb86f8b6bcd5c916325 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:51:24 +0100 Subject: [PATCH 12/18] Added console logging when a testing env get's discovered ref #154 --- src/app.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app.ts b/src/app.ts index 6e814b3..9bb6803 100644 --- a/src/app.ts +++ b/src/app.ts @@ -20,6 +20,9 @@ const app = createExpressServer({ async function main() { await loaders(app); + if (config.testing) { + consola.info("🛠[config]: Discovered testing env. Mailing errors will get ignored!") + } app.listen(config.internal_port, () => { consola.success( `⚡️[server]: Server is running at http://localhost:${config.internal_port}` From e5dab3469c3cef6298fc8deb1192a38f7d18406b Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:56:34 +0100 Subject: [PATCH 13/18] Changed endpoint url to avoid conflicts ref #154 --- src/controllers/RunnerSelfServiceController.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/controllers/RunnerSelfServiceController.ts b/src/controllers/RunnerSelfServiceController.ts index f73098f..28f7493 100644 --- a/src/controllers/RunnerSelfServiceController.ts +++ b/src/controllers/RunnerSelfServiceController.ts @@ -56,11 +56,14 @@ export class RunnerSelfServiceController { return responseScans; } - @Post('/runners/me/forgot') + @Post('/runners/forgot') @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @OnUndefined(ResponseEmpty) @OpenAPI({ description: 'TODO' }) async requestNewToken(@QueryParam('mail') mail: string) { + if (!mail) { + throw new RunnerNotFoundError(); + } const runner = await this.runnerRepository.findOne({ email: mail }); if (!runner) { throw new RunnerNotFoundError(); } From a95a9b4ec4a3012a91f6f622cfb9f5bff3376344 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:56:55 +0100 Subject: [PATCH 14/18] Added first selfservice forgotten test ref #154 --- .../selfservice/selfservice_forgotten.spec.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/tests/selfservice/selfservice_forgotten.spec.ts diff --git a/src/tests/selfservice/selfservice_forgotten.spec.ts b/src/tests/selfservice/selfservice_forgotten.spec.ts new file mode 100644 index 0000000..f148490 --- /dev/null +++ b/src/tests/selfservice/selfservice_forgotten.spec.ts @@ -0,0 +1,22 @@ +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/runners/me/forgot invalid should return fail', () => { + it('get without mail return 404', async () => { + const res = await axios.get(base + '/api/runners/forgot', axios_config); + expect(res.status).toEqual(404); + expect(res.headers['content-type']).toContain("application/json"); + }); From 1d762f56628eff47f4e1a910c7152bd0158283bd Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 13:57:25 +0100 Subject: [PATCH 15/18] Renamed test ref #154 --- .../selfservice/{selfservice_org.ts => selfservice_org.spec.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/tests/selfservice/{selfservice_org.ts => selfservice_org.spec.ts} (100%) diff --git a/src/tests/selfservice/selfservice_org.ts b/src/tests/selfservice/selfservice_org.spec.ts similarity index 100% rename from src/tests/selfservice/selfservice_org.ts rename to src/tests/selfservice/selfservice_org.spec.ts From 08957d4dc2951cfeec56a54680c2ae4ef1525ab2 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 14:02:58 +0100 Subject: [PATCH 16/18] Updated to new responsetype ref #154 --- src/tests/selfservice/selfservice_org.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/selfservice/selfservice_org.spec.ts b/src/tests/selfservice/selfservice_org.spec.ts index f269285..f718fac 100644 --- a/src/tests/selfservice/selfservice_org.spec.ts +++ b/src/tests/selfservice/selfservice_org.spec.ts @@ -49,6 +49,6 @@ describe('get valid org w/teams', () => { expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json"); expect(res.data.name).toEqual(added_org.name); - expect(res.data.teams[0]).toEqual({ name: added_team.name, id: added_team.id }); + expect(res.data.teams[0]).toEqual({ name: added_team.name, id: added_team.id, responseType: "SELFSERVICETEAM" }); }); }); \ No newline at end of file From d0a7e34de8095fca282adefff01fa5f72e7cdba3 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 14:08:39 +0100 Subject: [PATCH 17/18] Added all "negative" tests ref #154 --- .../selfservice/selfservice_forgotten.spec.ts | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/tests/selfservice/selfservice_forgotten.spec.ts b/src/tests/selfservice/selfservice_forgotten.spec.ts index f148490..ef365cf 100644 --- a/src/tests/selfservice/selfservice_forgotten.spec.ts +++ b/src/tests/selfservice/selfservice_forgotten.spec.ts @@ -14,9 +14,39 @@ beforeAll(async () => { }; }); -describe('GET /api/runners/me/forgot invalid should return fail', () => { +describe('POST /api/runners/me/forgot invalid syntax/mail should return fail', () => { it('get without mail return 404', async () => { - const res = await axios.get(base + '/api/runners/forgot', axios_config); + const res = await axios.post(base + '/api/runners/forgot', null, axios_config); expect(res.status).toEqual(404); expect(res.headers['content-type']).toContain("application/json"); }); + it('get without bs mail return 404', async () => { + const res = await axios.post(base + '/api/runners/forgot?mail=asdasdasdasdasd@tester.test.dev.lauf-fuer-kaya.de', null, axios_config); + expect(res.status).toEqual(404); + expect(res.headers['content-type']).toContain("application/json"); + }); +}); +describe('POST /api/runners/me/forgot 2 times within timeout should return fail', () => { + let added_runner; + it('registering as citizen should return 200', async () => { + const res = await axios.post(base + '/api/runners/register', { + "firstname": "string", + "middlename": "string", + "lastname": "string", + "email": "citizen420@dev.lauf-fuer-kaya.de" + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + added_runner = res.data; + }); + it('post with valid mail should return 200', async () => { + const res = await axios.post(base + '/api/runners/forgot?mail=' + added_runner.email, null, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + }); + it('2nd post with valid mail should return 400', async () => { + const res = await axios.post(base + '/api/runners/forgot?mail=' + added_runner.email, null, axios_config); + expect(res.status).toEqual(400); + expect(res.headers['content-type']).toContain("application/json"); + }); +}); From bf1ec976e3732b6ac052a55a51ee2ee18a8b1d3d Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Sat, 6 Mar 2021 14:12:46 +0100 Subject: [PATCH 18/18] Added selfservice forgott positive tests ref #154 --- .../selfservice/selfservice_forgotten.spec.ts | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/tests/selfservice/selfservice_forgotten.spec.ts b/src/tests/selfservice/selfservice_forgotten.spec.ts index ef365cf..8f11d48 100644 --- a/src/tests/selfservice/selfservice_forgotten.spec.ts +++ b/src/tests/selfservice/selfservice_forgotten.spec.ts @@ -14,7 +14,7 @@ beforeAll(async () => { }; }); -describe('POST /api/runners/me/forgot invalid syntax/mail should return fail', () => { +describe('POST /api/runners/me/forgot invalid syntax/mail should fail', () => { it('get without mail return 404', async () => { const res = await axios.post(base + '/api/runners/forgot', null, axios_config); expect(res.status).toEqual(404); @@ -26,7 +26,8 @@ describe('POST /api/runners/me/forgot invalid syntax/mail should return fail', ( expect(res.headers['content-type']).toContain("application/json"); }); }); -describe('POST /api/runners/me/forgot 2 times within timeout should return fail', () => { +// --------------- +describe('POST /api/runners/me/forgot 2 times within timeout should fail', () => { let added_runner; it('registering as citizen should return 200', async () => { const res = await axios.post(base + '/api/runners/register', { @@ -44,9 +45,37 @@ describe('POST /api/runners/me/forgot 2 times within timeout should return fail' expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json"); }); - it('2nd post with valid mail should return 400', async () => { + it('2nd post with valid mail should return 406', async () => { const res = await axios.post(base + '/api/runners/forgot?mail=' + added_runner.email, null, axios_config); - expect(res.status).toEqual(400); + expect(res.status).toEqual(406); + expect(res.headers['content-type']).toContain("application/json"); + }); +}); + +// --------------- +describe('POST /api/runners/me/forgot valid should return 200', () => { + let added_runner; + let new_token; + it('registering as citizen should return 200', async () => { + const res = await axios.post(base + '/api/runners/register', { + "firstname": "string", + "middlename": "string", + "lastname": "string", + "email": "citizen69@dev.lauf-fuer-kaya.de" + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + added_runner = res.data; + }); + it('post with valid mail should return 200', async () => { + const res = await axios.post(base + '/api/runners/forgot?mail=' + added_runner.email, null, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json"); + new_token = res.data.token; + }); + it('get infos with valid jwt should return 200', async () => { + const res = await axios.get(base + '/api/runners/me/' + new_token, axios_config); + expect(res.status).toEqual(200); expect(res.headers['content-type']).toContain("application/json"); }); });