diff --git a/.drone.yml b/.drone.yml
index 204f6c3..db1b1e7 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -9,7 +9,6 @@ steps:
commands:
- git clone $DRONE_REMOTE_URL .
- git checkout $DRONE_SOURCE_BRANCH
- - mv .env.ci .env
- name: run tests
image: node:latest
commands:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f837d42..2b0a0d4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,8 +2,58 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
+#### [v0.4.0](https://git.odit.services/lfk/backend/compare/v0.3.1...v0.4.0)
+
+- Added test mail templates [`8270029`](https://git.odit.services/lfk/backend/commit/827002989ee6e3f0d776b5b55b8fb6d65f10c898)
+- 🧾New changelog file version [CI SKIP] [skip ci] [`09b24aa`](https://git.odit.services/lfk/backend/commit/09b24aa6094a980debf4428a1c32583cdb7b606f)
+- Table fix [`1f0c842`](https://git.odit.services/lfk/backend/commit/1f0c842d9e086456f1ae0f6908e474258a04beb4)
+- 🧾New changelog file version [CI SKIP] [skip ci] [`fea4857`](https://git.odit.services/lfk/backend/commit/fea485768570eb5de2bbd2783e339794a67db2de)
+- 🧾New changelog file version [CI SKIP] [skip ci] [`e07f258`](https://git.odit.services/lfk/backend/commit/e07f258a315898d1183c311e7fcd8f65a415504c)
+- 🚀Bumped version to v0.4.0 [`e5f4f6e`](https://git.odit.services/lfk/backend/commit/e5f4f6ee590e0885d6eef9151ce7eb76578b70ca)
+- Merge pull request 'Implemented testmail endpoint feature/124-testmail' (#130) from feature/124-testmail into dev [`f9e75d0`](https://git.odit.services/lfk/backend/commit/f9e75d06b8ee8ff79f60fb384cb2c35ccf19811d)
+- Merge pull request 'Email Basics feature/118-emails' (#128) from feature/118-emails into dev [`348e6cd`](https://git.odit.services/lfk/backend/commit/348e6cdec7411345953243edfb5322a17ad7614d)
+- Merge pull request 'Mail+Env documentation feature/123-mail_documentation' (#129) from feature/123-mail_documentation into dev [`61bbeb0`](https://git.odit.services/lfk/backend/commit/61bbeb0d8f3fd6bfafb65bd11eb4c076a27b4a53)
+- Added pw reset template provided by @philipp [`c116338`](https://git.odit.services/lfk/backend/commit/c116338cd74cf726362f8fa0ae5eea7ec9fabac4)
+- Implemented automatic ci env generation [`536de2a`](https://git.odit.services/lfk/backend/commit/536de2a3199b1befed54b6fe520a2e3fcefe0d90)
+- Implemented a basic mailer with reset link sending [`6379753`](https://git.odit.services/lfk/backend/commit/637975305f1adf9bf505507790638cf1e229cfb1)
+- Implemented the test-mail endpoint via a new mailcontroller [`54ed313`](https://git.odit.services/lfk/backend/commit/54ed313342a72b029b9545bc5ea193e3f0c2166d)
+- Added documentation for the env vars [`13ccab5`](https://git.odit.services/lfk/backend/commit/13ccab5e289d0a629cefb7fe281a85a46058ae97)
+- Added comments [`9bd7636`](https://git.odit.services/lfk/backend/commit/9bd7636a23b5a9662ea2b965d2a2407727a188fb)
+- Added test mail sending test [`ae74b39`](https://git.odit.services/lfk/backend/commit/ae74b3963fddb847aed4a828031b93b26cf551db)
+- Password reset now enforces email [`979d36e`](https://git.odit.services/lfk/backend/commit/979d36ea9147dc575e9e989f6833388828285176)
+- Implementes mail sending on pw reset request [`e26744b`](https://git.odit.services/lfk/backend/commit/e26744b7925d32d65ef4cc3911651758cfc9274f)
+- Added a txt variant of the pw-reset mail [`d3647e3`](https://git.odit.services/lfk/backend/commit/d3647e339990d989dbca4d91aa8c3fe5789dd24a)
+- Changed order [`583a4bc`](https://git.odit.services/lfk/backend/commit/583a4bc0dd0de8026bb2eb6a9b0c31f59344e813)
+- Translated the pw reset mail to english [`5cade25`](https://git.odit.services/lfk/backend/commit/5cade25eeb137eb5890b3fd450646acfbdff2e8b)
+- The auth tests now use mail to identify the user [`c43334b`](https://git.odit.services/lfk/backend/commit/c43334bf96901bfd5116301ff7cf4b2ae1dfcbd3)
+- Added a test mail sending function [`b94179e`](https://git.odit.services/lfk/backend/commit/b94179e3caaf4be0654ca3372f57a490fb32e208)
+- Added the first mail error [`c418603`](https://git.odit.services/lfk/backend/commit/c4186034233a296b5971fbef16e7ef6809fbac51)
+- Now also sending txt mail body [`b92f633`](https://git.odit.services/lfk/backend/commit/b92f633d68604636cecc5e9fdd0d6990b9cb83fe)
+- Removed tests working directly with the old pw-reset response [`d02e9de`](https://git.odit.services/lfk/backend/commit/d02e9dec5637aedefdf2ed3cd2c6d73216b6464b)
+- Added the basics about mail templates to the readme [`b5018eb`](https://git.odit.services/lfk/backend/commit/b5018eb11492884db9f4ec969c767c3cce53f105)
+- Cleaned up the replacements [`389e423`](https://git.odit.services/lfk/backend/commit/389e423850d68a5fe440b62413a6c662353ac9c6)
+- Added mail env vars [`d7ea928`](https://git.odit.services/lfk/backend/commit/d7ea928714f94814695cbd2815c8730df58033f6)
+- Added a barebones class for handleing mail stuff [`cf012c0`](https://git.odit.services/lfk/backend/commit/cf012c0b7efffb81b03497a04b0fdad0423c72f7)
+- Added a Mail permisssion target [`ad4b903`](https://git.odit.services/lfk/backend/commit/ad4b903c258820f14df28d56b12e099075ca7d78)
+- Added env vars [`470703c`](https://git.odit.services/lfk/backend/commit/470703c4de954da94726879becd57986b59e1f69)
+- 🧾New changelog file version [CI SKIP] [skip ci] [`2071c4d`](https://git.odit.services/lfk/backend/commit/2071c4db33bbb9fd41ef650b409cac789732225f)
+- Added a hint to ethereal.email [`53fcff7`](https://git.odit.services/lfk/backend/commit/53fcff77d00fc2b205ada0bcee7bdfe83d94a9f4)
+- Fixed missing app_url protocol [`46af786`](https://git.odit.services/lfk/backend/commit/46af7865165bbfb97ed3e6cdfef15dfb72add611)
+- Removed the duplicate env copy/create from ci tests [`08e6e59`](https://git.odit.services/lfk/backend/commit/08e6e5965544906f5033f2080166bddc37cc30c7)
+- Removed bs console.log [`71c4caa`](https://git.odit.services/lfk/backend/commit/71c4caae8ba67e253d893409b3c5c3a39b08060a)
+- Added nodemailer types [`78d2ac3`](https://git.odit.services/lfk/backend/commit/78d2ac3027f7109161ee36e9b3dda628a7039468)
+- Added nodemailer dependecy [`908ac4f`](https://git.odit.services/lfk/backend/commit/908ac4f1ce9d78749268353c668e67b57eae6f94)
+- Fixed wrong file location [`b4c117b`](https://git.odit.services/lfk/backend/commit/b4c117b7dc326d212598b6e720d0a422134e383d)
+- Renamed the template [`fb77f4d`](https://git.odit.services/lfk/backend/commit/fb77f4d798550fdb6fe6b2c8a81198db0328f71e)
+- Added a folder for the mail templates [`6b0155f`](https://git.odit.services/lfk/backend/commit/6b0155f01464f5ef73ab679b9e3219743e9db66b)
+- Added a folder for the mail templates [`33890b5`](https://git.odit.services/lfk/backend/commit/33890b544b77272ab1c4797e91375d24568eae58)
+
#### [v0.3.1](https://git.odit.services/lfk/backend/compare/v0.3.0...v0.3.1)
+> 27 January 2021
+
+- Merge pull request 'Alpha Release 0.3.1' (#127) from dev into main [`20f960e`](https://git.odit.services/lfk/backend/commit/20f960ed6700fe58c0556895e6485d26c4a4f5e2)
+- 🧾New changelog file version [CI SKIP] [skip ci] [`e6fe8fc`](https://git.odit.services/lfk/backend/commit/e6fe8fcd587751392970d3ee412559b4c1d60f21)
- Merge pull request 'new advanced endpoints feature/125-team_runner' (#126) from feature/125-team_runner into dev [`870fd47`](https://git.odit.services/lfk/backend/commit/870fd47c83389345d7b24a15df6a4e61e930d140)
- Added get runners by team test [`69417e9`](https://git.odit.services/lfk/backend/commit/69417e93c081422561db1e211b12f32e539010ce)
- 🧾New changelog file version [CI SKIP] [skip ci] [`71898d5`](https://git.odit.services/lfk/backend/commit/71898d576c2620d2f2e2b4336e62f1d04a443201)
diff --git a/README.md b/README.md
index 985a69f..8d538ea 100644
--- a/README.md
+++ b/README.md
@@ -35,11 +35,41 @@ yarn test:watch
yarn test:ci
```
+### Use your own mail templates
+> You use your own mail templates by replacing the default ones we provided (either in-code or by mounting them into the /app/static/mail_templates folder).
+
+The mail templates always come in a .html and a .txt variant to provide compatability with legacy mail clients.
+Currently the following templates exist:
+* pw-reset.(html/txt)
+
### Generate Docs
```bash
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).
+
+| Name | Type | Default | Description
+| - | - | - | -
+| APP_PORT | Number | 4010 | The port the backend server listens on. Is optional.
+| DB_TYPE | String | N/A | The type of the db u want to use. It has to be supported by typeorm. Possible: `sqlite`, `mysql`, `postgresql`
+| DB_HOST | String | N/A | The db's host's ip-address/fqdn or file path for sqlite
+| DB_PORT | String | N/A | The db's port
+| 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.
+| 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
+
## Recommended Editor
[Visual Studio Code](https://code.visualstudio.com/)
diff --git a/package.json b/package.json
index 8e0ba5c..0436bee 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@odit/lfk-backend",
- "version": "0.3.1",
+ "version": "0.4.0",
"main": "src/app.ts",
"repository": "https://git.odit.services/lfk/backend",
"author": {
@@ -37,6 +37,7 @@
"jsonwebtoken": "^8.5.1",
"libphonenumber-js": "^1.9.7",
"mysql": "^2.18.1",
+ "nodemailer": "^6.4.17",
"pg": "^8.5.1",
"reflect-metadata": "^0.1.13",
"routing-controllers": "^0.9.0-alpha.6",
@@ -56,6 +57,7 @@
"@types/jest": "^26.0.16",
"@types/jsonwebtoken": "^8.5.0",
"@types/node": "^14.14.20",
+ "@types/nodemailer": "^6.4.0",
"@types/uuid": "^8.3.0",
"axios": "^0.21.1",
"cp-cli": "^2.0.0",
@@ -75,7 +77,9 @@
"docs": "typedoc --out docs src",
"test": "jest",
"test:watch": "jest --watchAll",
- "test:ci": "start-server-and-test dev http://localhost:4010/api/docs/openapi.json test",
+ "test:ci:generate_env": "ts-node scripts/create_testenv.ts",
+ "test:ci:run": "start-server-and-test dev http://localhost:4010/api/docs/openapi.json test",
+ "test:ci": "npm run test:ci:generate_env && npm run test:ci:run",
"seed": "ts-node ./node_modules/typeorm/cli.js schema:sync && ts-node ./node_modules/typeorm-seeding/dist/cli.js seed",
"openapi:export": "ts-node scripts/openapi_export.ts",
"licenses:export": "license-exporter --md",
diff --git a/scripts/create_testenv.ts b/scripts/create_testenv.ts
new file mode 100644
index 0000000..1fa6c8c
--- /dev/null
+++ b/scripts/create_testenv.ts
@@ -0,0 +1,37 @@
+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 = `
+APP_PORT=4010
+DB_TYPE=sqlite
+DB_HOST=bla
+DB_PORT=bla
+DB_USER=bla
+DB_PASSWORD=bla
+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");
+ }
+
+});
+
diff --git a/src/config.ts b/src/config.ts
index 3bdcd27..d2840da 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -10,7 +10,13 @@ export const config = {
phone_validation_countrycode: getPhoneCodeLocale(),
postalcode_validation_countrycode: getPostalCodeLocale(),
version: process.env.VERSION || require('../package.json').version,
- seedTestData: getDataSeeding()
+ seedTestData: getDataSeeding(),
+ app_url: process.env.APP_URL || "http://localhost:4010",
+ 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
}
let errors = 0
if (typeof config.internal_port !== "number") {
diff --git a/src/controllers/AuthController.ts b/src/controllers/AuthController.ts
index 507ac38..3545422 100644
--- a/src/controllers/AuthController.ts
+++ b/src/controllers/AuthController.ts
@@ -2,17 +2,23 @@ import { Body, CookieParam, JsonController, Param, Post, Req, Res } from 'routin
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
import { IllegalJWTError, InvalidCredentialsError, JwtNotProvidedError, PasswordNeededError, RefreshTokenCountInvalidError, UsernameOrEmailNeededError } from '../errors/AuthError';
import { UserNotFoundError } from '../errors/UserErrors';
+import { Mailer } from '../mailer';
import { CreateAuth } from '../models/actions/create/CreateAuth';
import { CreateResetToken } from '../models/actions/create/CreateResetToken';
import { HandleLogout } from '../models/actions/HandleLogout';
import { RefreshAuth } from '../models/actions/RefreshAuth';
import { ResetPassword } from '../models/actions/ResetPassword';
import { ResponseAuth } from '../models/responses/ResponseAuth';
+import { ResponseEmpty } from '../models/responses/ResponseEmpty';
import { Logout } from '../models/responses/ResponseLogout';
@JsonController('/auth')
export class AuthController {
+
+ private mailer: Mailer;
+
constructor() {
+ this.mailer = new Mailer();
}
@Post("/login")
@@ -82,13 +88,14 @@ export class AuthController {
}
@Post("/reset")
- @ResponseSchema(ResponseAuth)
- @ResponseSchema(UserNotFoundError)
- @ResponseSchema(UsernameOrEmailNeededError)
+ @ResponseSchema(ResponseEmpty, { statusCode: 200 })
+ @ResponseSchema(UserNotFoundError, { statusCode: 404 })
+ @ResponseSchema(UsernameOrEmailNeededError, { statusCode: 406 })
@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) {
- //This really shouldn't just get returned, but sent via mail or sth like that. But for dev only this is fine.
- return { "resetToken": await passwordReset.toResetToken() };
+ const reset_token: String = await passwordReset.toResetToken();
+ await this.mailer.sendResetMail(passwordReset.email, reset_token);
+ return new ResponseEmpty();
}
@Post("/reset/:token")
diff --git a/src/controllers/MailController.ts b/src/controllers/MailController.ts
new file mode 100644
index 0000000..94ff599
--- /dev/null
+++ b/src/controllers/MailController.ts
@@ -0,0 +1,26 @@
+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/errors/MailErrors.ts b/src/errors/MailErrors.ts
new file mode 100644
index 0000000..7772ca9
--- /dev/null
+++ b/src/errors/MailErrors.ts
@@ -0,0 +1,12 @@
+import { IsString } from 'class-validator'
+
+/**
+ * Error to throw when a permission couldn't be found.
+ */
+export class MailServerConfigError extends Error {
+ @IsString()
+ name = "MailServerConfigError"
+
+ @IsString()
+ message = "The SMTP server you provided couldn't be reached!"
+}
\ No newline at end of file
diff --git a/src/mailer.ts b/src/mailer.ts
new file mode 100644
index 0000000..d52e540
--- /dev/null
+++ b/src/mailer.ts
@@ -0,0 +1,79 @@
+import fs from "fs";
+import nodemailer from 'nodemailer';
+import { MailOptions } from 'nodemailer/lib/json-transport';
+import Mail from 'nodemailer/lib/mailer';
+import { config } from './config';
+import { MailServerConfigError } from './errors/MailErrors';
+
+/**
+ * This class is responsible for all things mail sending.
+ * This uses the mail emplates from src/static/mail_templates
+ */
+export class Mailer {
+ private transport: Mail;
+
+ /**
+ * 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.
+ * @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/${token}`
+ 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);
+ }
+}
diff --git a/src/models/actions/create/CreateResetToken.ts b/src/models/actions/create/CreateResetToken.ts
index 81f430a..8194fe4 100644
--- a/src/models/actions/create/CreateResetToken.ts
+++ b/src/models/actions/create/CreateResetToken.ts
@@ -1,39 +1,33 @@
-import { IsEmail, IsOptional, IsString } from 'class-validator';
+import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
import { getConnectionManager } from 'typeorm';
import { ResetAlreadyRequestedError, UserDisabledError, UserNotFoundError } from '../../../errors/AuthError';
-import { UsernameOrEmailNeededError } from '../../../errors/UserErrors';
+import { UserEmailNeededError } from '../../../errors/UserErrors';
import { JwtCreator } from '../../../jwtcreator';
import { User } from '../../entities/User';
/**
- * This calss is used to create password reset tokens for users.
+ * This class is used to create password reset tokens for users.
* These password reset token can be used to set a new password for the user for the next 15mins.
*/
export class CreateResetToken {
- /**
- * The username of the user that wants to reset their password.
- */
- @IsOptional()
- @IsString()
- username?: string;
/**
* The email address of the user that wants to reset their password.
*/
- @IsOptional()
+ @IsNotEmpty()
@IsEmail()
@IsString()
- email?: string;
+ email: string;
/**
* Create a password reset token based on this.
*/
public async toResetToken(): Promise {
- if (this.email === undefined && this.username === undefined) {
- throw new UsernameOrEmailNeededError();
+ if (!this.email) {
+ throw new UserEmailNeededError();
}
- let found_user = await getConnectionManager().get().getRepository(User).findOne({ where: [{ username: this.username }, { email: this.email }] });
+ let found_user = await getConnectionManager().get().getRepository(User).findOne({ where: [{ email: this.email }] });
if (!found_user) { throw new UserNotFoundError(); }
if (found_user.enabled == false) { throw new UserDisabledError(); }
if (found_user.resetRequestedTimestamp > (Math.floor(Date.now() / 1000) - 15 * 60)) { throw new ResetAlreadyRequestedError(); }
diff --git a/src/models/enums/PermissionTargets.ts b/src/models/enums/PermissionTargets.ts
index 4bb9c1c..249ec2f 100644
--- a/src/models/enums/PermissionTargets.ts
+++ b/src/models/enums/PermissionTargets.ts
@@ -15,5 +15,6 @@ export enum PermissionTarget {
STATION = 'STATION',
CARD = 'CARD',
DONATION = 'DONATION',
- CONTACT = 'CONTACT'
+ CONTACT = 'CONTACT',
+ MAIL = 'MAIL'
}
\ No newline at end of file
diff --git a/src/static/mail_templates/.gitkeep b/src/static/mail_templates/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/src/static/mail_templates/pw-reset.html b/src/static/mail_templates/pw-reset.html
new file mode 100644
index 0000000..7f672b8
--- /dev/null
+++ b/src/static/mail_templates/pw-reset.html
@@ -0,0 +1,384 @@
+
+
+
+
+ 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.