diff --git a/CHANGELOG.md b/CHANGELOG.md
index 208f0ee..e65ea03 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,11 +2,46 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
+#### [v0.5.0](https://git.odit.services/lfk/backend/compare/v0.4.6...v0.5.0)
+
+- Removed mail templates [`c2fdfee`](https://git.odit.services/lfk/backend/commit/c2fdfeed4f5fc454b02bc4b198965889c173bbaa)
+- Removed mail config [`0342757`](https://git.odit.services/lfk/backend/commit/0342757d929b12635c88e74f17495df656865b1a)
+- Added selfservice scan response class [`6074ac5`](https://git.odit.services/lfk/backend/commit/6074ac5b3a8e43fd98394c1fb70c6e1dea8fcd5e)
+- Removed old mailer code [`0fcc729`](https://git.odit.services/lfk/backend/commit/0fcc729b56430f0fdb56242857aa1d883d5a4866)
+- Added the new mailer code [`1551a44`](https://git.odit.services/lfk/backend/commit/1551a444babc025cde6e894c66d2be2c84ab26da)
+- Removed (now useless) mail controller [`485c247`](https://git.odit.services/lfk/backend/commit/485c247cd3305c4c4422d5582b1d61cc7af84989)
+- Trackscans now have a laptime that get's calculated on creation [`aa83373`](https://git.odit.services/lfk/backend/commit/aa833736d32993b1656abeeb02a4f8b021ec6252)
+- Removed useless functions and updated comments [`ada6798`](https://git.odit.services/lfk/backend/commit/ada679823cda8bc31d45c0ff6905f3d270cfd729)
+- Added new selfservice scans endpoint [`771a205`](https://git.odit.services/lfk/backend/commit/771a205fe634fc5c07e794b3245c59483ff14bd8)
+- Updated mail errors [`f289afd`](https://git.odit.services/lfk/backend/commit/f289afd8bc47f6eae9f12f765322b2db974ba918)
+- Laptime is now a part of the response [`a2c97a1`](https://git.odit.services/lfk/backend/commit/a2c97a11a3dc82543076e3844f20d1218943bbf9)
+- Updated readme env section [`db58a28`](https://git.odit.services/lfk/backend/commit/db58a280b3792b768eb2b1c82a76d9a9836978b1)
+- Added locale to pw reset endpoint [`a5d2a6e`](https://git.odit.services/lfk/backend/commit/a5d2a6ecd31dc9c186d4201aef5c52e34cbef3b5)
+- Now using mailer as static funtion [`9a1678a`](https://git.odit.services/lfk/backend/commit/9a1678acf0929dab9f84bd2c6a961b52e36172ce)
+- Updated readme env section [`149f3a8`](https://git.odit.services/lfk/backend/commit/149f3a83b2e9d59bfbf36c7ea9e27bc7f514856d)
+- Now checking for mails being set [`bb9bad6`](https://git.odit.services/lfk/backend/commit/bb9bad6d90370e768d4baffaae23ec756cc8353b)
+- Updated auth reset test for new mailer [`ae7d617`](https://git.odit.services/lfk/backend/commit/ae7d6176902699f82ea127194908ee360233e7b4)
+- Added scans returns 200 test [`82c65b6`](https://git.odit.services/lfk/backend/commit/82c65b632cdf44165b083494702b836c74e46a41)
+- 🚀Bumped version to v0.4.7 [`f1d85cf`](https://git.odit.services/lfk/backend/commit/f1d85cfb855c2aae581ade69751b3969ce38f020)
+- Added new mailer settings to config [`ddea02d`](https://git.odit.services/lfk/backend/commit/ddea02db574cc348685558f3fa3ecc84adbd6b65)
+- 🧾New changelog file version [CI SKIP] [skip ci] [`be397c8`](https://git.odit.services/lfk/backend/commit/be397c8899d5b4406c17e8f9951555c54f852901)
+- 🚀Bumped version to v0.5.0 [`3f2a2d2`](https://git.odit.services/lfk/backend/commit/3f2a2d292979c7f8162d92465b60b220f2634e7a)
+- Merge pull request 'Features for the new selfservice feature/151-selfservice_scans_mails' (#152) from feature/151-selfservice_scans_mails into dev [`15356c1`](https://git.odit.services/lfk/backend/commit/15356c1030988d03e3739f3ffe770669789759f2)
+- Now generateing bs mailer config in test env [`bf6b701`](https://git.odit.services/lfk/backend/commit/bf6b70106eb735d9ad6f6ad89f09194680af5ae1)
+- Promoted axios to dependency [`a9e06c9`](https://git.odit.services/lfk/backend/commit/a9e06c905537b6da24706389e304e825a33a28ad)
+- Removed nodemailer from backend [`5833f42`](https://git.odit.services/lfk/backend/commit/5833f4218f9a4c97b69021814df92470a1816917)
+- Added another resonse type [`030b225`](https://git.odit.services/lfk/backend/commit/030b2255d42aab21d8974fc3a7235285934d53b7)
+- Added new selfservice response type [`f7f6df4`](https://git.odit.services/lfk/backend/commit/f7f6df41ff74708482db3ea2db717ffb562131c0)
+
#### [v0.4.6](https://git.odit.services/lfk/backend/compare/v0.4.5...v0.4.6)
-- Merge pull request 'Fixed wrong body acceptance type' (#150) from bugfix/146-usergroup_update into dev [`d870b2f`](https://git.odit.services/lfk/backend/commit/d870b2fd01b11b1732fcbb6feecaf6a6155fa702)
+> 26 February 2021
+
+- Merge pull request 'Alpha Release 0.4.6' (#148) from dev into main [`dd3c927`](https://git.odit.services/lfk/backend/commit/dd3c9275d60cb5bb1a40fbe91f666f17a8e0c8d3)
- Added tests for the new org selfservice endpoints [`28ef139`](https://git.odit.services/lfk/backend/commit/28ef139a70e0c063982b2eb9167b7abe41db1621)
- Added selfservice org response model [`ba3b5ee`](https://git.odit.services/lfk/backend/commit/ba3b5eeefc45f9bd94aef24f9f509f6835f5ea7c)
+- 🧾New changelog file version [CI SKIP] [skip ci] [`764b7ff`](https://git.odit.services/lfk/backend/commit/764b7ffe00086248e1f1cccb265ca920a568c0a0)
+- Merge pull request 'Fixed wrong body acceptance type' (#150) from bugfix/146-usergroup_update into dev [`d870b2f`](https://git.odit.services/lfk/backend/commit/d870b2fd01b11b1732fcbb6feecaf6a6155fa702)
- Added selfservice team response model [`ba396e0`](https://git.odit.services/lfk/backend/commit/ba396e0eba15647b3004437a5a9949c7a69e828d)
- 📖New license file version [CI SKIP] [skip ci] [`bce8811`](https://git.odit.services/lfk/backend/commit/bce8811925e7f77c64fc507d55335ac45b0e5572)
- 📖New license file version [CI SKIP] [skip ci] [`b1fced7`](https://git.odit.services/lfk/backend/commit/b1fced77640b6c26438331474f368f2b0708b672)
diff --git a/README.md b/README.md
index 51b2d70..b2ba341 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@ yarn docs
## ENV Vars
> You can provide them via .env file or docker env vars.
-> You can use the `test:ci:generate_env` package script to generate a example env (uses [ethereal.email](https://ethereal.email) as the mailserver).
+> You can use the `test:ci:generate_env` package script to generate a example env (uses bs data as test server and ignores the errors).
| Name | Type | Default | Description
| - | - | - | -
@@ -64,11 +64,8 @@ yarn docs
| 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
-| MAIL_SERVER | String | N/A | The smtp server's ip-address/fqdn
-| MAIL_PORT | String | N/A | The smtp server's port
-| MAIL_USER | String | N/A | The username for sending mails
-| MAIL_PASSWORD | String | N/A | The user's password for sending mails
-| MAIL_FROM | String | N/A | The from-address for sending mails
+| MAILER_URL | String(Url) | N/A | The mailer's base url (no trailing slash)
+| MAILER_KEY | String | N/A | The mailer's api key.
| IMPRINT_URL | String(Url) | /imprint | The link to a imprint page for the system (Defaults to the frontend's imprint)
| PRIVACY_URL | String(Url) | /privacy | The link to a privacy page for the system (Defaults to the frontend's privacy page)
diff --git a/package.json b/package.json
index b2c115d..5f6a7d9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@odit/lfk-backend",
- "version": "0.4.6",
+ "version": "0.5.0",
"main": "src/app.ts",
"repository": "https://git.odit.services/lfk/backend",
"author": {
@@ -24,6 +24,7 @@
"dependencies": {
"@odit/class-validator-jsonschema": "2.1.1",
"argon2": "^0.27.1",
+ "axios": "^0.21.1",
"body-parser": "^1.19.0",
"class-transformer": "0.3.1",
"class-validator": "^0.13.1",
@@ -37,7 +38,6 @@
"jsonwebtoken": "^8.5.1",
"libphonenumber-js": "^1.9.9",
"mysql": "^2.18.1",
- "nodemailer": "^6.4.17",
"pg": "^8.5.1",
"reflect-metadata": "^0.1.13",
"routing-controllers": "0.9.0-alpha.6",
@@ -57,9 +57,7 @@
"@types/jest": "^26.0.20",
"@types/jsonwebtoken": "^8.5.0",
"@types/node": "^14.14.22",
- "@types/nodemailer": "^6.4.0",
"@types/uuid": "^8.3.0",
- "axios": "^0.21.1",
"cp-cli": "^2.0.0",
"jest": "^26.6.3",
"nodemon": "^2.0.7",
@@ -104,4 +102,4 @@
"docs/*"
]
}
-}
\ No newline at end of file
+}
diff --git a/scripts/create_testenv.ts b/scripts/create_testenv.ts
index 1fa6c8c..da08dea 100644
--- a/scripts/create_testenv.ts
+++ b/scripts/create_testenv.ts
@@ -1,15 +1,8 @@
import consola from "consola";
import fs from "fs";
-import nodemailer from "nodemailer";
-nodemailer.createTestAccount((err, account) => {
- if (err) {
- console.error('Failed to create a testing account. ' + err.message);
- return process.exit(1);
- }
-
- const env = `
+const env = `
APP_PORT=4010
DB_TYPE=sqlite
DB_HOST=bla
@@ -20,18 +13,12 @@ DB_NAME=./test.sqlite
NODE_ENV=dev
POSTALCODE_COUNTRYCODE=DE
SEED_TEST_DATA=true
-MAIL_SERVER=${account.smtp.host}
-MAIL_PORT=${account.smtp.port}
-MAIL_USER=${account.user}
-MAIL_PASSWORD=${account.pass}
-MAIL_FROM=${account.user}`
-
- try {
- fs.writeFileSync("./.env", env, { encoding: "utf-8" });
- consola.success("Exported ci env to .env");
- } catch (error) {
- consola.error("Couldn't export the ci env");
- }
-
-});
+MAILER_URL=https://dev.lauf-fuer-kaya.de/mailer
+MAILER_KEY=asdasd`;
+try {
+ fs.writeFileSync("./.env", env, { encoding: "utf-8" });
+ consola.success("Exported ci env to .env");
+} catch (error) {
+ consola.error("Couldn't export the ci env");
+}
\ No newline at end of file
diff --git a/src/config.ts b/src/config.ts
index 8dbffca..08af1ac 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -12,13 +12,10 @@ export const config = {
version: process.env.VERSION || require('../package.json').version,
seedTestData: getDataSeeding(),
app_url: process.env.APP_URL || "http://localhost:8080",
- mail_server: process.env.MAIL_SERVER,
- mail_port: Number(process.env.MAIL_PORT) || 25,
- mail_user: process.env.MAIL_USER,
- mail_password: process.env.MAIL_PASSWORD,
- mail_from: process.env.MAIL_FROM,
privacy_url: process.env.PRIVACY_URL || "/privacy",
- imprint_url: process.env.IMPRINT_URL || "/imprint"
+ imprint_url: process.env.IMPRINT_URL || "/imprint",
+ mailer_url: process.env.MAILER_URL || "",
+ mailer_key: process.env.MAILER_KEY || ""
}
let errors = 0
if (typeof config.internal_port !== "number") {
@@ -27,6 +24,9 @@ if (typeof config.internal_port !== "number") {
if (typeof config.development !== "boolean") {
errors++
}
+if (config.mailer_url == "" || config.mailer_key == "") {
+ errors++;
+}
function getPhoneCodeLocale(): CountryCode {
return (process.env.PHONE_COUNTRYCODE as CountryCode);
}
diff --git a/src/controllers/AuthController.ts b/src/controllers/AuthController.ts
index de5ed39..eebbd79 100644
--- a/src/controllers/AuthController.ts
+++ b/src/controllers/AuthController.ts
@@ -1,6 +1,7 @@
-import { Body, CookieParam, JsonController, Param, Post, Req, Res } from 'routing-controllers';
+import { Body, CookieParam, JsonController, Param, Post, QueryParam, Req, Res } from 'routing-controllers';
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
import { IllegalJWTError, InvalidCredentialsError, JwtNotProvidedError, PasswordNeededError, RefreshTokenCountInvalidError, UsernameOrEmailNeededError } from '../errors/AuthError';
+import { MailSendingError } from '../errors/MailErrors';
import { UserNotFoundError } from '../errors/UserErrors';
import { Mailer } from '../mailer';
import { CreateAuth } from '../models/actions/create/CreateAuth';
@@ -15,12 +16,6 @@ import { Logout } from '../models/responses/ResponseLogout';
@JsonController('/auth')
export class AuthController {
- private mailer: Mailer;
-
- constructor() {
- this.mailer = new Mailer();
- }
-
@Post("/login")
@ResponseSchema(ResponseAuth)
@ResponseSchema(InvalidCredentialsError)
@@ -91,10 +86,11 @@ export class AuthController {
@ResponseSchema(ResponseEmpty, { statusCode: 200 })
@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}." })
- async getResetToken(@Body({ validate: true }) passwordReset: CreateResetToken) {
+ async getResetToken(@Body({ validate: true }) passwordReset: CreateResetToken, @QueryParam("locale") locale: string = "en") {
const reset_token: string = await passwordReset.toResetToken();
- await this.mailer.sendResetMail(passwordReset.email, reset_token);
+ await Mailer.sendResetMail(passwordReset.email, reset_token, locale);
return new ResponseEmpty();
}
diff --git a/src/controllers/MailController.ts b/src/controllers/MailController.ts
deleted file mode 100644
index 94ff599..0000000
--- a/src/controllers/MailController.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Authorized, JsonController, Post } from 'routing-controllers';
-import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
-import { config } from '../config';
-import { Mailer } from '../mailer';
-import { ResponseEmpty } from '../models/responses/ResponseEmpty';
-
-
-@JsonController('/mails')
-@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
-export class MailController {
-
- private mailer: Mailer;
-
- constructor() {
- this.mailer = new Mailer();
- }
-
- @Post('/test')
- @Authorized(["MAIL:CREATE"])
- @ResponseSchema(ResponseEmpty, { statusCode: 200 })
- @OpenAPI({ description: 'Sends a test email to the configured from-address.' })
- async get() {
- await this.mailer.sendTestMail(config.mail_from);
- return new ResponseEmpty();
- }
-}
\ No newline at end of file
diff --git a/src/controllers/RunnerSelfServiceController.ts b/src/controllers/RunnerSelfServiceController.ts
index 324f9c1..8b1f30c 100644
--- a/src/controllers/RunnerSelfServiceController.ts
+++ b/src/controllers/RunnerSelfServiceController.ts
@@ -14,6 +14,7 @@ import { RunnerGroup } from '../models/entities/RunnerGroup';
import { RunnerOrganization } from '../models/entities/RunnerOrganization';
import { ResponseSelfServiceOrganisation } from '../models/responses/ResponseSelfServiceOrganisation';
import { ResponseSelfServiceRunner } from '../models/responses/ResponseSelfServiceRunner';
+import { ResponseSelfServiceScan } from '../models/responses/ResponseSelfServiceScan';
@JsonController()
@@ -38,6 +39,20 @@ export class RunnerSelfServiceController {
return (new ResponseSelfServiceRunner(await this.getRunner(token)));
}
+ @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;
+ }
+
@Post('/runners/register')
@ResponseSchema(ResponseSelfServiceRunner)
@ResponseSchema(RunnerEmailNeededError, { statusCode: 406 })
diff --git a/src/errors/MailErrors.ts b/src/errors/MailErrors.ts
index 7772ca9..1bde0ba 100644
--- a/src/errors/MailErrors.ts
+++ b/src/errors/MailErrors.ts
@@ -1,12 +1,17 @@
-import { IsString } from 'class-validator'
+import { IsString } from 'class-validator';
+import { InternalServerError } from 'routing-controllers';
/**
* Error to throw when a permission couldn't be found.
*/
-export class MailServerConfigError extends Error {
+export class MailSendingError extends InternalServerError {
@IsString()
- name = "MailServerConfigError"
+ name = "MailSendingError"
@IsString()
- message = "The SMTP server you provided couldn't be reached!"
+ message = "We had a problem sending the mail!"
+
+ constructor() {
+ super("We had a problem sending the mail!");
+ }
}
\ No newline at end of file
diff --git a/src/mailer.ts b/src/mailer.ts
index d1f31c2..33d7f24 100644
--- a/src/mailer.ts
+++ b/src/mailer.ts
@@ -1,79 +1,28 @@
-import fs from "fs";
-import nodemailer from 'nodemailer';
-import { MailOptions } from 'nodemailer/lib/json-transport';
-import Mail from 'nodemailer/lib/mailer';
+import axios from 'axios';
import { config } from './config';
-import { MailServerConfigError } from './errors/MailErrors';
+import { MailSendingError } from './errors/MailErrors';
/**
* This class is responsible for all things mail sending.
- * This uses the mail emplates from src/static/mail_templates
+ * This uses axios to communicate with the mailer api (https://git.odit.services/lfk/mailer).
*/
export class Mailer {
- private transport: Mail;
+ public static base: string = config.mailer_url;
+ public static key: string = config.mailer_key;
/**
- * The class's default constructor.
- * Creates the transporter and tests the connection.
- */
- constructor() {
- this.transport = nodemailer.createTransport({
- host: config.mail_server,
- port: config.mail_port,
- auth: {
- user: config.mail_user,
- pass: config.mail_password
- }
- });
-
- this.transport.verify(function (error, success) {
- if (error) {
- throw new MailServerConfigError();
- }
- });
- }
-
- /**
- * Function for sending a test mail from the test mail template.
+ * Function for sending a password reset mail.
* @param to_address The address the mail will be sent to. Should always get pulled from a user object.
* @param token The requested password reset token - will be combined with the app_url to generate a password reset link.
*/
- public async sendResetMail(to_address: string, token: string) {
- const reset_link = `${config.app_url}/reset/${(Buffer.from(token)).toString("base64")}`
- const body_html = fs.readFileSync(__dirname + '/static/mail_templates/pw-reset.html', { encoding: 'utf8' }).replace("{{reset_link}}", reset_link).replace("{{recipient_mail}}", to_address).replace("{{copyright_owner}}", "LfK!").replace("{{link_imprint}}", `${config.app_url}/imprint`).replace("{{link_privacy}}", `${config.app_url}/privacy`);
- const body_txt = fs.readFileSync(__dirname + '/static/mail_templates/pw-reset.html', { encoding: 'utf8' }).replace("{{reset_link}}", reset_link).replace("{{recipient_mail}}", to_address).replace("{{copyright_owner}}", "LfK!").replace("{{link_imprint}}", `${config.app_url}/imprint`).replace("{{link_privacy}}", `${config.app_url}/privacy`);
-
- const mail: MailOptions = {
- to: to_address,
- subject: "LfK! Password Reset",
- text: body_txt,
- html: body_html
- };
- await this.sendMail(mail);
- }
-
- /**
- * Function for sending a test mail from the test mail template.
- * @param to_address The address the test mail will be sent to - this is the configured from-address by default.
- */
- public async sendTestMail(to_address: string = config.mail_from) {
- const body_html = fs.readFileSync(__dirname + '/static/mail_templates/test.html', { encoding: 'utf8' }).replace("{{recipient_mail}}", to_address).replace("{{copyright_owner}}", "LfK!").replace("{{link_imprint}}", `${config.app_url}/imprint`).replace("{{link_privacy}}", `${config.app_url}/privacy`);
- const body_txt = fs.readFileSync(__dirname + '/static/mail_templates/test.txt', { encoding: 'utf8' }).replace("{{recipient_mail}}", to_address).replace("{{copyright_owner}}", "LfK!").replace("{{link_imprint}}", `${config.app_url}/imprint`).replace("{{link_privacy}}", `${config.app_url}/privacy`);
- const mail: MailOptions = {
- to: to_address,
- subject: "LfK! Test Mail",
- text: body_txt,
- html: body_html
- };
- await this.sendMail(mail);
- }
-
- /**
- * Wrapper function for sending a mail via this object's transporter.
- * @param mail MailOptions object containing the
- */
- public async sendMail(mail: MailOptions) {
- mail.from = config.mail_from;
- await this.transport.sendMail(mail);
+ public static async sendResetMail(to_address: string, token: string, locale: string = "en") {
+ try {
+ await axios.post(`${Mailer.base}/reset?locale=${locale}&key=${Mailer.key}`, {
+ address: to_address,
+ resetKey: token
+ });
+ } catch (error) {
+ throw new MailSendingError();
+ }
}
}
diff --git a/src/models/actions/create/CreateTrackScan.ts b/src/models/actions/create/CreateTrackScan.ts
index 89ccb5b..578497f 100644
--- a/src/models/actions/create/CreateTrackScan.ts
+++ b/src/models/actions/create/CreateTrackScan.ts
@@ -44,6 +44,7 @@ export class CreateTrackScan {
}
newScan.timestamp = Math.round(new Date().getTime() / 1000);
+ newScan.lapTime = await this.getLaptime(newScan)
newScan.valid = await this.validateScan(newScan);
return newScan;
@@ -65,15 +66,15 @@ export class CreateTrackScan {
return station;
}
- public async validateScan(scan: TrackScan): Promise {
+ public validateScan(scan: TrackScan): boolean {
+ return (scan.lapTime > scan.track.minimumLapTime);
+ }
+
+ public async getLaptime(scan: TrackScan): Promise {
const scans = await getConnection().getRepository(TrackScan).find({ where: { runner: scan.runner, valid: true }, relations: ["track"] });
- if (scans.length == 0) { return true; }
+ if (scans.length == 0) { return 0; }
const newestScan = scans[scans.length - 1];
- if ((scan.timestamp - newestScan.timestamp) > scan.track.minimumLapTime) {
- return true;
- }
-
- return false;
+ return (scan.timestamp - newestScan.timestamp);
}
}
\ No newline at end of file
diff --git a/src/models/entities/TrackScan.ts b/src/models/entities/TrackScan.ts
index cd8049a..17983f3 100644
--- a/src/models/entities/TrackScan.ts
+++ b/src/models/entities/TrackScan.ts
@@ -2,6 +2,8 @@ import {
IsInt,
IsNotEmpty,
+ IsNumber,
+
IsPositive
} from "class-validator";
import { ChildEntity, Column, ManyToOne } from "typeorm";
@@ -59,6 +61,14 @@ export class TrackScan extends Scan {
@IsInt()
timestamp: number;
+ /**
+ * The scan's lap time.
+ * This simply get's calculated from the last lap time;
+ */
+ @Column()
+ @IsNumber()
+ lapTime: number;
+
/**
* Turns this entity into it's response class.
*/
diff --git a/src/models/enums/ResponseObjectType.ts b/src/models/enums/ResponseObjectType.ts
index a25ebd4..c7fc527 100644
--- a/src/models/enums/ResponseObjectType.ts
+++ b/src/models/enums/ResponseObjectType.ts
@@ -21,6 +21,8 @@ export enum ResponseObjectType {
SCANSTATION = 'SCANSTATION',
SELFSERVICEDONATION = 'SELFSERVICEDONATION',
SELFSERVICERUNNER = 'SELFSERVICRUNNER',
+ SELFSERVICESCAN = 'SELFSERVICESCAN',
+ SELFSERVICETRACKSCAN = 'SELFSERVICETRACKSCAN',
SELFSERVICETEAM = 'SELFSERVICETEAM',
SELFSERVICEORGANIZATION = 'SELFSERVICEORGANIZATION',
STATS = 'STATS',
diff --git a/src/models/responses/ResponseSelfServiceScan.ts b/src/models/responses/ResponseSelfServiceScan.ts
new file mode 100644
index 0000000..65b90de
--- /dev/null
+++ b/src/models/responses/ResponseSelfServiceScan.ts
@@ -0,0 +1,57 @@
+import { IsBoolean, IsInt, IsNotEmpty, IsPositive } from "class-validator";
+import { Scan } from '../entities/Scan';
+import { TrackScan } from '../entities/TrackScan';
+import { ResponseObjectType } from '../enums/ResponseObjectType';
+import { IResponse } from './IResponse';
+
+/**
+ * Defines the scan selfservice response.
+*/
+export class ResponseSelfServiceScan implements IResponse {
+ /**
+ * The responseType.
+ * This contains the type of class/entity this response contains.
+ */
+ responseType: ResponseObjectType = ResponseObjectType.SELFSERVICESCAN;
+
+ /**
+ * The scans's id (for sorting).
+ */
+ @IsInt()
+ id: number;
+
+ /**
+ * Is the scan valid (for fraud reasons).
+ * The determination of validity will work differently for every child class.
+ */
+ @IsBoolean()
+ valid: boolean = true;
+
+ /**
+ * The scans's length/distance in meters.
+ */
+ @IsInt()
+ @IsPositive()
+ distance: number;
+
+ /**
+ * The scans's lap time (0 if non is availdable).
+ */
+ @IsInt()
+ @IsNotEmpty()
+ lapTime: number = 0;
+
+ /**
+ * Creates a ResponseScan object from a scan.
+ * @param scan The scan the response shall be build for.
+ */
+ public constructor(scan: Scan | TrackScan) {
+ this.id = scan.id;
+ this.distance = scan.distance;
+ this.valid = scan.valid;
+ if (scan instanceof TrackScan) {
+ this.lapTime = scan.lapTime;
+ this.responseType = ResponseObjectType.SELFSERVICETRACKSCAN;
+ }
+ }
+}
diff --git a/src/models/responses/ResponseTrackScan.ts b/src/models/responses/ResponseTrackScan.ts
index ffd9ceb..9bbc6f3 100644
--- a/src/models/responses/ResponseTrackScan.ts
+++ b/src/models/responses/ResponseTrackScan.ts
@@ -1,4 +1,4 @@
-import { IsDateString, IsNotEmpty } from "class-validator";
+import { IsDateString, IsNotEmpty, IsNumber } from "class-validator";
import { TrackScan } from '../entities/TrackScan';
import { ResponseObjectType } from '../enums/ResponseObjectType';
import { IResponse } from './IResponse';
@@ -42,6 +42,13 @@ export class ResponseTrackScan extends ResponseScan implements IResponse {
@IsNotEmpty()
timestamp: number;
+ /**
+ * The scan's lap time.
+ * This simply get's calculated from the last lap time;
+ */
+ @IsNumber()
+ lapTime: number;
+
/**
* Creates a ResponseTrackScan object from a scan.
* @param scan The trackSscan the response shall be build for.
@@ -53,5 +60,6 @@ export class ResponseTrackScan extends ResponseScan implements IResponse {
if (scan.station) { scan.station.toResponse(); }
this.timestamp = scan.timestamp;
this.distance = scan.distance;
+ this.lapTime = scan.lapTime;
}
}
diff --git a/src/static/mail_templates/.gitkeep b/src/static/mail_templates/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/src/static/mail_templates/pw-reset.html b/src/static/mail_templates/pw-reset.html
deleted file mode 100644
index 7f672b8..0000000
--- a/src/static/mail_templates/pw-reset.html
+++ /dev/null
@@ -1,384 +0,0 @@
-
-
-
-
- LfK! - Passwort zurücksetzen
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- LfK! - Password reset
-
-
-
-
-
-
-
-
-
-
-
-
LfK!
-
-
-
-
-
Password reset
-
A password reset for your account got requested. If you didn't request the reset please ignore this mail. Your password won't be changed until you click the reset link below and set a new one.