From 6aafe4a6ae7d253ab39220e551c52ae067cc481a Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Mon, 29 Mar 2021 16:43:52 +0000 Subject: [PATCH 1/7] =?UTF-8?q?=F0=9F=A7=BENew=20changelog=20file=20versio?= =?UTF-8?q?n=20[CI=20SKIP]=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea6d19a..058ed8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. Dates are d #### [v0.9.2](https://git.odit.services/lfk/backend/compare/v0.9.1...v0.9.2) +- Merge pull request 'Release 0.9.2' (#183) from dev into main [`bdeeb03`](https://git.odit.services/lfk/backend/commit/bdeeb036459c2a2131e843d8a5a6b338e0ba46ea) +- 🧾New changelog file version [CI SKIP] [skip ci] [`675c876`](https://git.odit.services/lfk/backend/commit/675c8762e8e4cf28d2f334d5ab2e1cb6b594e33c) - Fixed bug in return creation [`6c9b91d`](https://git.odit.services/lfk/backend/commit/6c9b91d75a0d08fc4ab0e72c7a09bd0133566368) - 🧾New changelog file version [CI SKIP] [skip ci] [`8c00aef`](https://git.odit.services/lfk/backend/commit/8c00aefd6ce3723d9f83d1c94e6491d5d597391f) - 🚀Bumped version to v0.9.2 [`89e3924`](https://git.odit.services/lfk/backend/commit/89e392473c52a3f328545699a0f4df89be33ba89) From f5433076b01c743ed9af085fccadb8f1edc26419 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Thu, 1 Apr 2021 18:23:15 +0200 Subject: [PATCH 2/7] Added locale to mail related runner endpoints ref #84 --- src/controllers/RunnerSelfServiceController.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/controllers/RunnerSelfServiceController.ts b/src/controllers/RunnerSelfServiceController.ts index 8f5509e..d8b96df 100644 --- a/src/controllers/RunnerSelfServiceController.ts +++ b/src/controllers/RunnerSelfServiceController.ts @@ -119,8 +119,8 @@ export class RunnerSelfServiceController { @Post('/runners/forgot') @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @OnUndefined(ResponseEmpty) - @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) { + @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).', parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) + async requestNewToken(@QueryParam('mail') mail: string, @QueryParam("locale") locale: string = "en") { if (!mail) { throw new RunnerNotFoundError(); } @@ -131,7 +131,7 @@ export class RunnerSelfServiceController { const token = JwtCreator.createSelfService(runner); try { - await Mailer.sendSelfserviceForgottenMail(runner.email, token, "en") + await Mailer.sendSelfserviceForgottenMail(runner.email, token, locale) } catch (error) { throw new MailSendingError(); } @@ -145,8 +145,8 @@ export class RunnerSelfServiceController { @Post('/runners/register') @ResponseSchema(ResponseSelfServiceRunner) @ResponseSchema(RunnerEmailNeededError, { statusCode: 406 }) - @OpenAPI({ description: 'Create a new selfservice runner in the citizen org.
This endpoint shoud be used to allow "everyday citizen" to register themselves.
You have to provide a mail address, b/c the future we\'ll implement email verification.' }) - async registerRunner(@Body({ validate: true }) createRunner: CreateSelfServiceCitizenRunner) { + @OpenAPI({ description: 'Create a new selfservice runner in the citizen org.
This endpoint shoud be used to allow "everyday citizen" to register themselves.
You have to provide a mail address, b/c the future we\'ll implement email verification.', parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) + async registerRunner(@Body({ validate: true }) createRunner: CreateSelfServiceCitizenRunner, @QueryParam("locale") locale: string = "en") { let runner = await createRunner.toEntity(); runner = await this.runnerRepository.save(runner); @@ -154,7 +154,7 @@ export class RunnerSelfServiceController { response.token = JwtCreator.createSelfService(runner); try { - await Mailer.sendSelfserviceWelcomeMail(runner.email, response.token, "en") + await Mailer.sendSelfserviceWelcomeMail(runner.email, response.token, locale) } catch (error) { throw new MailSendingError(); } @@ -165,8 +165,8 @@ export class RunnerSelfServiceController { @Post('/runners/register/:token') @ResponseSchema(ResponseSelfServiceRunner) @ResponseSchema(RunnerOrganizationNotFoundError, { statusCode: 404 }) - @OpenAPI({ description: 'Create a new selfservice runner in a provided org.
The orgs get provided and authorized via api tokens that can be optained via the /organizations endpoint.' }) - async registerOrganizationRunner(@Param('token') token: string, @Body({ validate: true }) createRunner: CreateSelfServiceRunner) { + @OpenAPI({ description: 'Create a new selfservice runner in a provided org.
The orgs get provided and authorized via api tokens that can be optained via the /organizations endpoint.', parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) + async registerOrganizationRunner(@Param('token') token: string, @Body({ validate: true }) createRunner: CreateSelfServiceRunner, @QueryParam("locale") locale: string = "en") { const org = await this.getOrgansisation(token); let runner = await createRunner.toEntity(org); @@ -176,7 +176,7 @@ export class RunnerSelfServiceController { response.token = JwtCreator.createSelfService(runner); try { - await Mailer.sendSelfserviceWelcomeMail(runner.email, response.token, "en") + await Mailer.sendSelfserviceWelcomeMail(runner.email, response.token, locale) } catch (error) { throw new MailSendingError(); } From 7af883f27198206af542bcaff4686221d3788e87 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Thu, 1 Apr 2021 18:23:15 +0200 Subject: [PATCH 3/7] Added locale to mail related runner endpoints ref #184 --- src/controllers/RunnerSelfServiceController.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/controllers/RunnerSelfServiceController.ts b/src/controllers/RunnerSelfServiceController.ts index 8f5509e..d8b96df 100644 --- a/src/controllers/RunnerSelfServiceController.ts +++ b/src/controllers/RunnerSelfServiceController.ts @@ -119,8 +119,8 @@ export class RunnerSelfServiceController { @Post('/runners/forgot') @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @OnUndefined(ResponseEmpty) - @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) { + @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).', parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) + async requestNewToken(@QueryParam('mail') mail: string, @QueryParam("locale") locale: string = "en") { if (!mail) { throw new RunnerNotFoundError(); } @@ -131,7 +131,7 @@ export class RunnerSelfServiceController { const token = JwtCreator.createSelfService(runner); try { - await Mailer.sendSelfserviceForgottenMail(runner.email, token, "en") + await Mailer.sendSelfserviceForgottenMail(runner.email, token, locale) } catch (error) { throw new MailSendingError(); } @@ -145,8 +145,8 @@ export class RunnerSelfServiceController { @Post('/runners/register') @ResponseSchema(ResponseSelfServiceRunner) @ResponseSchema(RunnerEmailNeededError, { statusCode: 406 }) - @OpenAPI({ description: 'Create a new selfservice runner in the citizen org.
This endpoint shoud be used to allow "everyday citizen" to register themselves.
You have to provide a mail address, b/c the future we\'ll implement email verification.' }) - async registerRunner(@Body({ validate: true }) createRunner: CreateSelfServiceCitizenRunner) { + @OpenAPI({ description: 'Create a new selfservice runner in the citizen org.
This endpoint shoud be used to allow "everyday citizen" to register themselves.
You have to provide a mail address, b/c the future we\'ll implement email verification.', parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) + async registerRunner(@Body({ validate: true }) createRunner: CreateSelfServiceCitizenRunner, @QueryParam("locale") locale: string = "en") { let runner = await createRunner.toEntity(); runner = await this.runnerRepository.save(runner); @@ -154,7 +154,7 @@ export class RunnerSelfServiceController { response.token = JwtCreator.createSelfService(runner); try { - await Mailer.sendSelfserviceWelcomeMail(runner.email, response.token, "en") + await Mailer.sendSelfserviceWelcomeMail(runner.email, response.token, locale) } catch (error) { throw new MailSendingError(); } @@ -165,8 +165,8 @@ export class RunnerSelfServiceController { @Post('/runners/register/:token') @ResponseSchema(ResponseSelfServiceRunner) @ResponseSchema(RunnerOrganizationNotFoundError, { statusCode: 404 }) - @OpenAPI({ description: 'Create a new selfservice runner in a provided org.
The orgs get provided and authorized via api tokens that can be optained via the /organizations endpoint.' }) - async registerOrganizationRunner(@Param('token') token: string, @Body({ validate: true }) createRunner: CreateSelfServiceRunner) { + @OpenAPI({ description: 'Create a new selfservice runner in a provided org.
The orgs get provided and authorized via api tokens that can be optained via the /organizations endpoint.', parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) + async registerOrganizationRunner(@Param('token') token: string, @Body({ validate: true }) createRunner: CreateSelfServiceRunner, @QueryParam("locale") locale: string = "en") { const org = await this.getOrgansisation(token); let runner = await createRunner.toEntity(org); @@ -176,7 +176,7 @@ export class RunnerSelfServiceController { response.token = JwtCreator.createSelfService(runner); try { - await Mailer.sendSelfserviceWelcomeMail(runner.email, response.token, "en") + await Mailer.sendSelfserviceWelcomeMail(runner.email, response.token, locale) } catch (error) { throw new MailSendingError(); } From 1be073a4fa39f0332a46f567ee6af10a9137844c Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Thu, 1 Apr 2021 18:25:09 +0200 Subject: [PATCH 4/7] Added locale to mail related user endpoints ref #184 --- src/controllers/AuthController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/AuthController.ts b/src/controllers/AuthController.ts index eebbd79..be55ee7 100644 --- a/src/controllers/AuthController.ts +++ b/src/controllers/AuthController.ts @@ -87,7 +87,7 @@ export class AuthController { @ResponseSchema(UserNotFoundError, { statusCode: 404 }) @ResponseSchema(UsernameOrEmailNeededError, { statusCode: 406 }) @ResponseSchema(MailSendingError, { statusCode: 500 }) - @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}." }) + @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}.", parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) async getResetToken(@Body({ validate: true }) passwordReset: CreateResetToken, @QueryParam("locale") locale: string = "en") { const reset_token: string = await passwordReset.toResetToken(); await Mailer.sendResetMail(passwordReset.email, reset_token, locale); From 5fb355f450f19e96d3671b1a46e94d564495942b Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Thu, 1 Apr 2021 16:30:20 +0000 Subject: [PATCH 5/7] =?UTF-8?q?=F0=9F=A7=BENew=20changelog=20file=20versio?= =?UTF-8?q?n=20[CI=20SKIP]=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 058ed8b..9755623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,18 @@ All notable changes to this project will be documented in this file. Dates are displayed in UTC. +#### [v0.9.2](https://git.odit.services/lfk/backend/compare/v0.9.2...v0.9.2) + +- Merge pull request 'Mail locales feature/184-mail_locales' (#185) from feature/184-mail_locales into dev [`33c13de`](https://git.odit.services/lfk/backend/commit/33c13de32c68a3d9e87e4fd9ad12a815ed8c9fde) +- Added locale to mail related runner endpoints [`7af883f`](https://git.odit.services/lfk/backend/commit/7af883f27198206af542bcaff4686221d3788e87) +- Added locale to mail related runner endpoints [`f543307`](https://git.odit.services/lfk/backend/commit/f5433076b01c743ed9af085fccadb8f1edc26419) +- Added locale to mail related user endpoints [`1be073a`](https://git.odit.services/lfk/backend/commit/1be073a4fa39f0332a46f567ee6af10a9137844c) +- 🧾New changelog file version [CI SKIP] [skip ci] [`6aafe4a`](https://git.odit.services/lfk/backend/commit/6aafe4a6ae7d253ab39220e551c52ae067cc481a) + #### [v0.9.2](https://git.odit.services/lfk/backend/compare/v0.9.1...v0.9.2) +> 29 March 2021 + - Merge pull request 'Release 0.9.2' (#183) from dev into main [`bdeeb03`](https://git.odit.services/lfk/backend/commit/bdeeb036459c2a2131e843d8a5a6b338e0ba46ea) - 🧾New changelog file version [CI SKIP] [skip ci] [`675c876`](https://git.odit.services/lfk/backend/commit/675c8762e8e4cf28d2f334d5ab2e1cb6b594e33c) - Fixed bug in return creation [`6c9b91d`](https://git.odit.services/lfk/backend/commit/6c9b91d75a0d08fc4ab0e72c7a09bd0133566368) From dc3071f7d2be298f0bb02d86ec67ed1125cd3b49 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Thu, 1 Apr 2021 18:30:30 +0200 Subject: [PATCH 6/7] =?UTF-8?q?=F0=9F=9A=80Bumped=20version=20to=20v0.10.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- .../RunnerSelfServiceController.ts | 454 +++++++++--------- 2 files changed, 228 insertions(+), 228 deletions(-) diff --git a/package.json b/package.json index 754a604..a3a6521 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@odit/lfk-backend", - "version": "0.9.2", + "version": "0.10.0", "main": "src/app.ts", "repository": "https://git.odit.services/lfk/backend", "author": { diff --git a/src/controllers/RunnerSelfServiceController.ts b/src/controllers/RunnerSelfServiceController.ts index d8b96df..afa9379 100644 --- a/src/controllers/RunnerSelfServiceController.ts +++ b/src/controllers/RunnerSelfServiceController.ts @@ -1,228 +1,228 @@ -import { Request } from "express"; -import * as jwt from "jsonwebtoken"; -import { Body, Delete, Get, JsonController, OnUndefined, Param, Post, QueryParam, Req, UseBefore } from 'routing-controllers'; -import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; -import { getConnectionManager, Repository } from 'typeorm'; -import { config } from '../config'; -import { InvalidCredentialsError, JwtNotProvidedError } from '../errors/AuthError'; -import { MailSendingError } from '../errors/MailErrors'; -import { RunnerEmailNeededError, RunnerHasDistanceDonationsError, RunnerNotFoundError, RunnerSelfserviceTimeoutError } from '../errors/RunnerErrors'; -import { RunnerOrganizationNotFoundError } from '../errors/RunnerOrganizationErrors'; -import { ScanStationNotFoundError } from '../errors/ScanStationErrors'; -import { JwtCreator } from '../jwtcreator'; -import { Mailer } from '../mailer'; -import ScanAuth from '../middlewares/ScanAuth'; -import { CreateSelfServiceCitizenRunner } from '../models/actions/create/CreateSelfServiceCitizenRunner'; -import { CreateSelfServiceRunner } from '../models/actions/create/CreateSelfServiceRunner'; -import { Runner } from '../models/entities/Runner'; -import { RunnerGroup } from '../models/entities/RunnerGroup'; -import { RunnerOrganization } from '../models/entities/RunnerOrganization'; -import { ScanStation } from '../models/entities/ScanStation'; -import { ResponseEmpty } from '../models/responses/ResponseEmpty'; -import { ResponseScanStation } from '../models/responses/ResponseScanStation'; -import { ResponseSelfServiceOrganisation } from '../models/responses/ResponseSelfServiceOrganisation'; -import { ResponseSelfServiceRunner } from '../models/responses/ResponseSelfServiceRunner'; -import { ResponseSelfServiceScan } from '../models/responses/ResponseSelfServiceScan'; -import { DonationController } from './DonationController'; -import { RunnerCardController } from './RunnerCardController'; -import { ScanController } from './ScanController'; - -@JsonController() -export class RunnerSelfServiceController { - private runnerRepository: Repository; - private orgRepository: Repository; - private stationRepository: Repository; - - /** - * Gets the repository of this controller's model/entity. - */ - constructor() { - this.runnerRepository = getConnectionManager().get().getRepository(Runner); - this.orgRepository = getConnectionManager().get().getRepository(RunnerOrganization); - this.stationRepository = getConnectionManager().get().getRepository(ScanStation); - } - - @Get('/runners/me/:jwt') - @ResponseSchema(ResponseSelfServiceRunner) - @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) - @OnUndefined(RunnerNotFoundError) - @OpenAPI({ description: 'Lists all information about yourself.
Please provide your runner jwt(that code we gave you during registration) for auth.
If you lost your jwt/personalized link please use the forgot endpoint.' }) - async get(@Param('jwt') token: string) { - return (new ResponseSelfServiceRunner(await this.getRunner(token))); - } - - @Delete('/runners/me/:jwt') - @ResponseSchema(ResponseSelfServiceRunner) - @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) - @OnUndefined(RunnerNotFoundError) - @OpenAPI({ description: 'Deletes all information about yourself.
Please provide your runner jwt(that code we gave you during registration) for auth.
If you lost your jwt/personalized link please use the forgot endpoint.' }) - async remove(@Param('jwt') token: string, @QueryParam("force") force: boolean) { - const responseRunner = await this.getRunner(token); - let runner = await this.runnerRepository.findOne({ id: responseRunner.id }); - - if (!runner) { return null; } - if (!runner) { - throw new RunnerNotFoundError(); - } - - const runnerDonations = (await this.runnerRepository.findOne({ id: runner.id }, { relations: ["distanceDonations"] })).distanceDonations; - if (runnerDonations.length > 0 && !force) { - throw new RunnerHasDistanceDonationsError(); - } - const donationController = new DonationController(); - for (let donation of runnerDonations) { - await donationController.remove(donation.id, force); - } - - const runnerCards = (await this.runnerRepository.findOne({ id: runner.id }, { relations: ["cards"] })).cards; - const cardController = new RunnerCardController; - for (let card of runnerCards) { - await cardController.remove(card.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 ResponseSelfServiceRunner(responseRunner); - } - - @Get('/runners/me/:jwt/scans') - @ResponseSchema(ResponseSelfServiceScan, { isArray: true }) - @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) - @OnUndefined(RunnerNotFoundError) - @OpenAPI({ description: 'Lists all your (runner) scans.
Please provide your runner jwt(that code we gave you during registration) for auth.
If you lost your jwt/personalized link please contact support.' }) - async getScans(@Param('jwt') token: string) { - const scans = (await this.getRunner(token)).scans; - let responseScans = new Array() - for (let scan of scans) { - responseScans.push(new ResponseSelfServiceScan(scan)); - } - return responseScans; - } - - @Get('/stations/me') - @UseBefore(ScanAuth) - @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: [{ "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(); } - return scan.toResponse(); - } - - @Post('/runners/forgot') - @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) - @OnUndefined(ResponseEmpty) - @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).', parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) - async requestNewToken(@QueryParam('mail') mail: string, @QueryParam("locale") locale: string = "en") { - if (!mail) { - throw new RunnerNotFoundError(); - } - 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 RunnerSelfserviceTimeoutError(); } - const token = JwtCreator.createSelfService(runner); - - try { - await Mailer.sendSelfserviceForgottenMail(runner.email, token, locale) - } catch (error) { - throw new MailSendingError(); - } - - runner.resetRequestedTimestamp = Math.floor(Date.now() / 1000); - await this.runnerRepository.save(runner); - - return { token }; - } - - @Post('/runners/register') - @ResponseSchema(ResponseSelfServiceRunner) - @ResponseSchema(RunnerEmailNeededError, { statusCode: 406 }) - @OpenAPI({ description: 'Create a new selfservice runner in the citizen org.
This endpoint shoud be used to allow "everyday citizen" to register themselves.
You have to provide a mail address, b/c the future we\'ll implement email verification.', parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) - async registerRunner(@Body({ validate: true }) createRunner: CreateSelfServiceCitizenRunner, @QueryParam("locale") locale: string = "en") { - let runner = await createRunner.toEntity(); - - 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, locale) - } catch (error) { - throw new MailSendingError(); - } - - return response; - } - - @Post('/runners/register/:token') - @ResponseSchema(ResponseSelfServiceRunner) - @ResponseSchema(RunnerOrganizationNotFoundError, { statusCode: 404 }) - @OpenAPI({ description: 'Create a new selfservice runner in a provided org.
The orgs get provided and authorized via api tokens that can be optained via the /organizations endpoint.', parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) - async registerOrganizationRunner(@Param('token') token: string, @Body({ validate: true }) createRunner: CreateSelfServiceRunner, @QueryParam("locale") locale: string = "en") { - const org = await this.getOrgansisation(token); - - let runner = await createRunner.toEntity(org); - 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, locale) - } catch (error) { - throw new MailSendingError(); - } - - return response; - } - - @Get('/organizations/selfservice/:token') - @ResponseSchema(ResponseSelfServiceOrganisation, { isArray: false }) - @ResponseSchema(RunnerOrganizationNotFoundError, { statusCode: 404 }) - @OpenAPI({ description: 'Get the basic info and teams for a org.' }) - async getSelfserviceOrg(@Param('token') token: string) { - const orgid = (await this.getOrgansisation(token)).id; - const org = await this.orgRepository.findOne({ id: orgid }, { relations: ['teams'] }) - - return new ResponseSelfServiceOrganisation(org); - } - - /** - * Get's a runner by a provided jwt token. - * @param token The runner jwt provided by the runner to identitfy themselves. - */ - private async getRunner(token: string): Promise { - if (token == "") { throw new JwtNotProvidedError(); } - let jwtPayload = undefined - try { - jwtPayload = jwt.verify(token, config.jwt_secret); - } catch (error) { - throw new InvalidCredentialsError(); - } - - const runner = await this.runnerRepository.findOne({ id: jwtPayload["id"] }, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards', 'distanceDonations', 'distanceDonations.donor', 'distanceDonations.runner', 'distanceDonations.runner.scans', 'distanceDonations.runner.scans.track'] }); - if (!runner) { throw new RunnerNotFoundError() } - return runner; - } - - /** - * Get's a runner org by a provided registration api key. - * @param token The organization's registration api token. - */ - private async getOrgansisation(token: string): Promise { - token = Buffer.from(token, 'base64').toString('utf8'); - - const organization = await this.orgRepository.findOne({ key: token }); - if (!organization) { throw new RunnerOrganizationNotFoundError; } - - return organization; - } +import { Request } from "express"; +import * as jwt from "jsonwebtoken"; +import { Body, Delete, Get, JsonController, OnUndefined, Param, Post, QueryParam, Req, UseBefore } from 'routing-controllers'; +import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; +import { getConnectionManager, Repository } from 'typeorm'; +import { config } from '../config'; +import { InvalidCredentialsError, JwtNotProvidedError } from '../errors/AuthError'; +import { MailSendingError } from '../errors/MailErrors'; +import { RunnerEmailNeededError, RunnerHasDistanceDonationsError, RunnerNotFoundError, RunnerSelfserviceTimeoutError } from '../errors/RunnerErrors'; +import { RunnerOrganizationNotFoundError } from '../errors/RunnerOrganizationErrors'; +import { ScanStationNotFoundError } from '../errors/ScanStationErrors'; +import { JwtCreator } from '../jwtcreator'; +import { Mailer } from '../mailer'; +import ScanAuth from '../middlewares/ScanAuth'; +import { CreateSelfServiceCitizenRunner } from '../models/actions/create/CreateSelfServiceCitizenRunner'; +import { CreateSelfServiceRunner } from '../models/actions/create/CreateSelfServiceRunner'; +import { Runner } from '../models/entities/Runner'; +import { RunnerGroup } from '../models/entities/RunnerGroup'; +import { RunnerOrganization } from '../models/entities/RunnerOrganization'; +import { ScanStation } from '../models/entities/ScanStation'; +import { ResponseEmpty } from '../models/responses/ResponseEmpty'; +import { ResponseScanStation } from '../models/responses/ResponseScanStation'; +import { ResponseSelfServiceOrganisation } from '../models/responses/ResponseSelfServiceOrganisation'; +import { ResponseSelfServiceRunner } from '../models/responses/ResponseSelfServiceRunner'; +import { ResponseSelfServiceScan } from '../models/responses/ResponseSelfServiceScan'; +import { DonationController } from './DonationController'; +import { RunnerCardController } from './RunnerCardController'; +import { ScanController } from './ScanController'; + +@JsonController() +export class RunnerSelfServiceController { + private runnerRepository: Repository; + private orgRepository: Repository; + private stationRepository: Repository; + + /** + * Gets the repository of this controller's model/entity. + */ + constructor() { + this.runnerRepository = getConnectionManager().get().getRepository(Runner); + this.orgRepository = getConnectionManager().get().getRepository(RunnerOrganization); + this.stationRepository = getConnectionManager().get().getRepository(ScanStation); + } + + @Get('/runners/me/:jwt') + @ResponseSchema(ResponseSelfServiceRunner) + @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) + @OnUndefined(RunnerNotFoundError) + @OpenAPI({ description: 'Lists all information about yourself.
Please provide your runner jwt(that code we gave you during registration) for auth.
If you lost your jwt/personalized link please use the forgot endpoint.' }) + async get(@Param('jwt') token: string) { + return (new ResponseSelfServiceRunner(await this.getRunner(token))); + } + + @Delete('/runners/me/:jwt') + @ResponseSchema(ResponseSelfServiceRunner) + @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) + @OnUndefined(RunnerNotFoundError) + @OpenAPI({ description: 'Deletes all information about yourself.
Please provide your runner jwt(that code we gave you during registration) for auth.
If you lost your jwt/personalized link please use the forgot endpoint.' }) + async remove(@Param('jwt') token: string, @QueryParam("force") force: boolean) { + const responseRunner = await this.getRunner(token); + let runner = await this.runnerRepository.findOne({ id: responseRunner.id }); + + if (!runner) { return null; } + if (!runner) { + throw new RunnerNotFoundError(); + } + + const runnerDonations = (await this.runnerRepository.findOne({ id: runner.id }, { relations: ["distanceDonations"] })).distanceDonations; + if (runnerDonations.length > 0 && !force) { + throw new RunnerHasDistanceDonationsError(); + } + const donationController = new DonationController(); + for (let donation of runnerDonations) { + await donationController.remove(donation.id, force); + } + + const runnerCards = (await this.runnerRepository.findOne({ id: runner.id }, { relations: ["cards"] })).cards; + const cardController = new RunnerCardController; + for (let card of runnerCards) { + await cardController.remove(card.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 ResponseSelfServiceRunner(responseRunner); + } + + @Get('/runners/me/:jwt/scans') + @ResponseSchema(ResponseSelfServiceScan, { isArray: true }) + @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) + @OnUndefined(RunnerNotFoundError) + @OpenAPI({ description: 'Lists all your (runner) scans.
Please provide your runner jwt(that code we gave you during registration) for auth.
If you lost your jwt/personalized link please contact support.' }) + async getScans(@Param('jwt') token: string) { + const scans = (await this.getRunner(token)).scans; + let responseScans = new Array() + for (let scan of scans) { + responseScans.push(new ResponseSelfServiceScan(scan)); + } + return responseScans; + } + + @Get('/stations/me') + @UseBefore(ScanAuth) + @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: [{ "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(); } + return scan.toResponse(); + } + + @Post('/runners/forgot') + @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) + @OnUndefined(ResponseEmpty) + @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).', parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) + async requestNewToken(@QueryParam('mail') mail: string, @QueryParam("locale") locale: string = "en") { + if (!mail) { + throw new RunnerNotFoundError(); + } + 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 RunnerSelfserviceTimeoutError(); } + const token = JwtCreator.createSelfService(runner); + + try { + await Mailer.sendSelfserviceForgottenMail(runner.email, token, locale) + } catch (error) { + throw new MailSendingError(); + } + + runner.resetRequestedTimestamp = Math.floor(Date.now() / 1000); + await this.runnerRepository.save(runner); + + return { token }; + } + + @Post('/runners/register') + @ResponseSchema(ResponseSelfServiceRunner) + @ResponseSchema(RunnerEmailNeededError, { statusCode: 406 }) + @OpenAPI({ description: 'Create a new selfservice runner in the citizen org.
This endpoint shoud be used to allow "everyday citizen" to register themselves.
You have to provide a mail address, b/c the future we\'ll implement email verification.', parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) + async registerRunner(@Body({ validate: true }) createRunner: CreateSelfServiceCitizenRunner, @QueryParam("locale") locale: string = "en") { + let runner = await createRunner.toEntity(); + + 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, locale) + } catch (error) { + throw new MailSendingError(); + } + + return response; + } + + @Post('/runners/register/:token') + @ResponseSchema(ResponseSelfServiceRunner) + @ResponseSchema(RunnerOrganizationNotFoundError, { statusCode: 404 }) + @OpenAPI({ description: 'Create a new selfservice runner in a provided org.
The orgs get provided and authorized via api tokens that can be optained via the /organizations endpoint.', parameters: [{ in: "query", name: "locale", schema: { type: "string", enum: ["de", "en"] } }] }) + async registerOrganizationRunner(@Param('token') token: string, @Body({ validate: true }) createRunner: CreateSelfServiceRunner, @QueryParam("locale") locale: string = "en") { + const org = await this.getOrgansisation(token); + + let runner = await createRunner.toEntity(org); + 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, locale) + } catch (error) { + throw new MailSendingError(); + } + + return response; + } + + @Get('/organizations/selfservice/:token') + @ResponseSchema(ResponseSelfServiceOrganisation, { isArray: false }) + @ResponseSchema(RunnerOrganizationNotFoundError, { statusCode: 404 }) + @OpenAPI({ description: 'Get the basic info and teams for a org.' }) + async getSelfserviceOrg(@Param('token') token: string) { + const orgid = (await this.getOrgansisation(token)).id; + const org = await this.orgRepository.findOne({ id: orgid }, { relations: ['teams'] }) + + return new ResponseSelfServiceOrganisation(org); + } + + /** + * Get's a runner by a provided jwt token. + * @param token The runner jwt provided by the runner to identitfy themselves. + */ + private async getRunner(token: string): Promise { + if (token == "") { throw new JwtNotProvidedError(); } + let jwtPayload = undefined + try { + jwtPayload = jwt.verify(token, config.jwt_secret); + } catch (error) { + throw new InvalidCredentialsError(); + } + + const runner = await this.runnerRepository.findOne({ id: jwtPayload["id"] }, { relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards', 'distanceDonations', 'distanceDonations.donor', 'distanceDonations.runner', 'distanceDonations.runner.scans', 'distanceDonations.runner.scans.track'] }); + if (!runner) { throw new RunnerNotFoundError() } + return runner; + } + + /** + * Get's a runner org by a provided registration api key. + * @param token The organization's registration api token. + */ + private async getOrgansisation(token: string): Promise { + token = Buffer.from(token, 'base64').toString('utf8'); + + const organization = await this.orgRepository.findOne({ key: token }); + if (!organization) { throw new RunnerOrganizationNotFoundError; } + + return organization; + } } \ No newline at end of file From 114c246aceba566cc0dd6daab51a77b951b031cc Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Thu, 1 Apr 2021 16:31:25 +0000 Subject: [PATCH 7/7] =?UTF-8?q?=F0=9F=A7=BENew=20changelog=20file=20versio?= =?UTF-8?q?n=20[CI=20SKIP]=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9755623..7a849b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,10 @@ All notable changes to this project will be documented in this file. Dates are displayed in UTC. -#### [v0.9.2](https://git.odit.services/lfk/backend/compare/v0.9.2...v0.9.2) +#### [v0.10.0](https://git.odit.services/lfk/backend/compare/v0.9.2...v0.10.0) +- 🚀Bumped version to v0.10.0 [`dc3071f`](https://git.odit.services/lfk/backend/commit/dc3071f7d2be298f0bb02d86ec67ed1125cd3b49) +- 🧾New changelog file version [CI SKIP] [skip ci] [`5fb355f`](https://git.odit.services/lfk/backend/commit/5fb355f450f19e96d3671b1a46e94d564495942b) - Merge pull request 'Mail locales feature/184-mail_locales' (#185) from feature/184-mail_locales into dev [`33c13de`](https://git.odit.services/lfk/backend/commit/33c13de32c68a3d9e87e4fd9ad12a815ed8c9fde) - Added locale to mail related runner endpoints [`7af883f`](https://git.odit.services/lfk/backend/commit/7af883f27198206af542bcaff4686221d3788e87) - Added locale to mail related runner endpoints [`f543307`](https://git.odit.services/lfk/backend/commit/f5433076b01c743ed9af085fccadb8f1edc26419)