diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts
index e50f96dd2..658c7e97c 100644
--- a/backend/src/config/index.ts
+++ b/backend/src/config/index.ts
@@ -1,8 +1,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
-/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+
/* eslint-disable n/no-process-env */
import { config } from 'dotenv'
+// eslint-disable-next-line import/no-namespace
+import * as SMTPTransport from 'nodemailer/lib/smtp-pool'
import emails from './emails'
import metadata from './metadata'
@@ -13,16 +15,17 @@ config()
// Use Cypress env or process.env
// eslint-disable-next-line @typescript-eslint/no-explicit-any
declare let Cypress: any | undefined
-const env = typeof Cypress !== 'undefined' ? Cypress.env() : process.env
+const env = (typeof Cypress !== 'undefined' ? Cypress.env() : process.env) as typeof process.env
const environment = {
- NODE_ENV: env.NODE_ENV || process.env.NODE_ENV,
+ NODE_ENV: env.NODE_ENV ?? process.env.NODE_ENV,
DEBUG: env.NODE_ENV !== 'production' && env.DEBUG,
TEST: env.NODE_ENV === 'test',
PRODUCTION: env.NODE_ENV === 'production',
// used for staging enviroments if 'PRODUCTION=true' and 'PRODUCTION_DB_CLEAN_ALLOW=true'
PRODUCTION_DB_CLEAN_ALLOW: env.PRODUCTION_DB_CLEAN_ALLOW === 'true' || false, // default = false
- DISABLED_MIDDLEWARES: ['test', 'development'].includes(env.NODE_ENV as string)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ DISABLED_MIDDLEWARES: ['test', 'development'].includes(env.NODE_ENV!)
? (env.DISABLED_MIDDLEWARES?.split(',') ?? [])
: [],
SEND_MAIL: env.NODE_ENV !== 'test',
@@ -35,32 +38,51 @@ const required = {
}
const server = {
- CLIENT_URI: env.CLIENT_URI || 'http://localhost:3000',
- GRAPHQL_URI: env.GRAPHQL_URI || 'http://localhost:4000',
- JWT_EXPIRES: env.JWT_EXPIRES || '2y',
+ CLIENT_URI: env.CLIENT_URI ?? 'http://localhost:3000',
+ GRAPHQL_URI: env.GRAPHQL_URI ?? 'http://localhost:4000',
+ JWT_EXPIRES: env.JWT_EXPIRES ?? '2y',
}
-const hasDKIMData = env.SMTP_DKIM_DOMAINNAME && env.SMTP_DKIM_KEYSELECTOR && env.SMTP_DKIM_PRIVATKEY
+const SMTP_HOST = env.SMTP_HOST
+const SMTP_PORT = (env.SMTP_PORT && parseInt(env.SMTP_PORT)) || undefined
+const SMTP_IGNORE_TLS = env.SMTP_IGNORE_TLS !== 'false' // default = true
+const SMTP_SECURE = env.SMTP_SECURE === 'true'
+const SMTP_USERNAME = env.SMTP_USERNAME
+const SMTP_PASSWORD = env.SMTP_PASSWORD
+const SMTP_DKIM_DOMAINNAME = env.SMTP_DKIM_DOMAINNAME
+const SMTP_DKIM_KEYSELECTOR = env.SMTP_DKIM_KEYSELECTOR
+// PEM format = https://docs.progress.com/bundle/datadirect-hybrid-data-pipeline-installation-46/page/PEM-file-format.html
+const SMTP_DKIM_PRIVATKEY = env.SMTP_DKIM_PRIVATKEY?.replace(/\\n/g, '\n') // replace all "\n" in .env string by real line break
+const SMTP_MAX_CONNECTIONS = (env.SMTP_MAX_CONNECTIONS && parseInt(env.SMTP_MAX_CONNECTIONS)) || 5
+const SMTP_MAX_MESSAGES = (env.SMTP_MAX_MESSAGES && parseInt(env.SMTP_MAX_MESSAGES)) || 100
-const smtp = {
- SMTP_HOST: env.SMTP_HOST,
- SMTP_PORT: env.SMTP_PORT,
- SMTP_IGNORE_TLS: env.SMTP_IGNORE_TLS !== 'false', // default = true
- SMTP_SECURE: env.SMTP_SECURE === 'true',
- SMTP_USERNAME: env.SMTP_USERNAME,
- SMTP_PASSWORD: env.SMTP_PASSWORD,
- SMTP_DKIM_DOMAINNAME: hasDKIMData && env.SMTP_DKIM_DOMAINNAME,
- SMTP_DKIM_KEYSELECTOR: hasDKIMData && env.SMTP_DKIM_KEYSELECTOR,
- // PEM format: https://docs.progress.com/bundle/datadirect-hybrid-data-pipeline-installation-46/page/PEM-file-format.html
- SMTP_DKIM_PRIVATKEY: hasDKIMData && env.SMTP_DKIM_PRIVATKEY.replace(/\\n/g, '\n'), // replace all "\n" in .env string by real line break
- SMTP_MAX_CONNECTIONS: env.SMTP_MAX_CONNECTIONS || 5,
- SMTP_MAX_MESSAGES: env.SMTP_MAX_MESSAGES || 100,
+const nodemailerTransportOptions: SMTPTransport.Options = {
+ host: SMTP_HOST,
+ port: SMTP_PORT,
+ ignoreTLS: SMTP_IGNORE_TLS,
+ secure: SMTP_SECURE, // true for 465, false for other ports
+ pool: true,
+ maxConnections: SMTP_MAX_CONNECTIONS,
+ maxMessages: SMTP_MAX_MESSAGES,
+}
+if (SMTP_USERNAME && SMTP_PASSWORD) {
+ nodemailerTransportOptions.auth = {
+ user: SMTP_USERNAME,
+ pass: SMTP_PASSWORD,
+ }
+}
+if (SMTP_DKIM_DOMAINNAME && SMTP_DKIM_KEYSELECTOR && SMTP_DKIM_PRIVATKEY) {
+ nodemailerTransportOptions.dkim = {
+ domainName: SMTP_DKIM_DOMAINNAME,
+ keySelector: SMTP_DKIM_KEYSELECTOR,
+ privateKey: SMTP_DKIM_PRIVATKEY,
+ }
}
const neo4j = {
- NEO4J_URI: env.NEO4J_URI || 'bolt://localhost:7687',
- NEO4J_USERNAME: env.NEO4J_USERNAME || 'neo4j',
- NEO4J_PASSWORD: env.NEO4J_PASSWORD || 'neo4j',
+ NEO4J_URI: env.NEO4J_URI ?? 'bolt://localhost:7687',
+ NEO4J_USERNAME: env.NEO4J_USERNAME ?? 'neo4j',
+ NEO4J_PASSWORD: env.NEO4J_PASSWORD ?? 'neo4j',
}
const sentry = {
@@ -70,7 +92,7 @@ const sentry = {
const redis = {
REDIS_DOMAIN: env.REDIS_DOMAIN,
- REDIS_PORT: env.REDIS_PORT,
+ REDIS_PORT: (env.REDIS_PORT && parseInt(env.REDIS_PORT)) || undefined,
REDIS_PASSWORD: env.REDIS_PASSWORD,
}
@@ -110,10 +132,11 @@ export default {
...environment,
...server,
...required,
- ...smtp,
...neo4j,
...sentry,
...redis,
...s3,
...options,
}
+
+export { nodemailerTransportOptions }
diff --git a/backend/src/context/pubsub.ts b/backend/src/context/pubsub.ts
index 003347b16..3d99bba6d 100644
--- a/backend/src/context/pubsub.ts
+++ b/backend/src/context/pubsub.ts
@@ -1,4 +1,3 @@
-/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { RedisPubSub } from 'graphql-redis-subscriptions'
import { PubSub } from 'graphql-subscriptions'
import Redis from 'ioredis'
@@ -6,14 +5,15 @@ import Redis from 'ioredis'
import CONFIG from '@config/index'
export default () => {
- if (!CONFIG.REDIS_DOMAIN || CONFIG.REDIS_PORT || CONFIG.REDIS_PASSWORD) {
+ const { REDIS_DOMAIN, REDIS_PORT, REDIS_PASSWORD } = CONFIG
+ if (!(REDIS_DOMAIN && REDIS_PORT && REDIS_PASSWORD)) {
return new PubSub()
}
const options = {
- host: CONFIG.REDIS_DOMAIN,
- port: CONFIG.REDIS_PORT,
- password: CONFIG.REDIS_PASSWORD,
+ host: REDIS_DOMAIN,
+ port: REDIS_PORT,
+ password: REDIS_PASSWORD,
retryStrategy: (times) => {
return Math.min(times * 50, 2000)
},
diff --git a/backend/src/db/migrations-examples/20200312140328-bulk_upload_to_s3.ts b/backend/src/db/migrations-examples/20200312140328-bulk_upload_to_s3.ts
deleted file mode 100644
index 0307a2e6e..000000000
--- a/backend/src/db/migrations-examples/20200312140328-bulk_upload_to_s3.ts
+++ /dev/null
@@ -1,117 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unsafe-argument */
-/* eslint-disable @typescript-eslint/no-unsafe-return */
-/* eslint-disable @typescript-eslint/no-unsafe-call */
-/* eslint-disable @typescript-eslint/no-unsafe-member-access */
-/* eslint-disable @typescript-eslint/no-unsafe-assignment */
-/* eslint-disable security/detect-non-literal-fs-filename */
-import https from 'https'
-import { existsSync, createReadStream } from 'node:fs'
-import path from 'node:path'
-
-import { S3 } from 'aws-sdk'
-import mime from 'mime-types'
-
-import s3Configs from '@config/index'
-import { getDriver } from '@db/neo4j'
-
-export const description = `
-Upload all image files to a S3 compatible object storage in order to reduce
-load on our backend.
-`
-
-export async function up(next) {
- const driver = getDriver()
- const session = driver.session()
- const transaction = session.beginTransaction()
- const agent = new https.Agent({
- maxSockets: 5,
- })
-
- const {
- AWS_ENDPOINT: endpoint,
- AWS_REGION: region,
- AWS_BUCKET: Bucket,
- S3_CONFIGURED,
- } = s3Configs
-
- if (!S3_CONFIGURED) {
- // eslint-disable-next-line no-console
- console.log('No S3 given, cannot upload image files')
- return
- }
-
- const s3 = new S3({ region, endpoint, httpOptions: { agent } })
- try {
- // Implement your migration here.
- const { records } = await transaction.run('MATCH (image:Image) RETURN image.url as url')
- let urls = records.map((r) => r.get('url'))
- urls = urls.filter((url) => url.startsWith('/uploads'))
- const locations = await Promise.all(
- urls
- .map((url) => {
- return async () => {
- const { pathname } = new URL(url, 'http://example.org')
- const fileLocation = path.join(__dirname, `../../../public/${pathname}`)
- const s3Location = `original${pathname}`
- // eslint-disable-next-line n/no-sync
- if (existsSync(fileLocation)) {
- const mimeType = mime.lookup(fileLocation)
- const params = {
- Bucket,
- Key: s3Location,
- ACL: 'public-read',
- ContentType: mimeType || 'image/jpeg',
- Body: createReadStream(fileLocation),
- }
-
- const data = await s3.upload(params).promise()
- const { Location: spacesUrl } = data
-
- const updatedRecord = await transaction.run(
- 'MATCH (image:Image {url: $url}) SET image.url = $spacesUrl RETURN image.url as url',
- { url, spacesUrl },
- )
- const [updatedUrl] = updatedRecord.records.map((record) => record.get('url'))
- return updatedUrl
- }
- }
- })
- .map((p) => p()),
- )
- // eslint-disable-next-line no-console
- console.log('this is locations', locations)
- await transaction.commit()
- next()
- } catch (error) {
- // eslint-disable-next-line no-console
- console.log(error)
- await transaction.rollback()
- // eslint-disable-next-line no-console
- console.log('rolled back')
- throw new Error(error)
- } finally {
- await session.close()
- }
-}
-
-export async function down(next) {
- const driver = getDriver()
- const session = driver.session()
- const transaction = session.beginTransaction()
-
- try {
- // Implement your migration here.
- await transaction.run(``)
- await transaction.commit()
- next()
- // eslint-disable-next-line no-catch-all/no-catch-all
- } catch (error) {
- // eslint-disable-next-line no-console
- console.log(error)
- await transaction.rollback()
- // eslint-disable-next-line no-console
- console.log('rolled back')
- } finally {
- await session.close()
- }
-}
diff --git a/backend/src/db/neo4j.ts b/backend/src/db/neo4j.ts
index 5d084099a..ecaef68b5 100644
--- a/backend/src/db/neo4j.ts
+++ b/backend/src/db/neo4j.ts
@@ -1,6 +1,3 @@
-/* eslint-disable @typescript-eslint/no-unsafe-argument */
-
-/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable import/no-named-as-default-member */
import neo4j, { Driver } from 'neo4j-driver'
import Neode from 'neode'
diff --git a/backend/src/emails/sendEmail.ts b/backend/src/emails/sendEmail.ts
index 7b7ea76b3..8e5d8e83c 100644
--- a/backend/src/emails/sendEmail.ts
+++ b/backend/src/emails/sendEmail.ts
@@ -7,17 +7,14 @@ import path from 'node:path'
import Email from 'email-templates'
import { createTransport } from 'nodemailer'
+
// import type Email as EmailType from '@types/email-templates'
-import CONFIG from '@config/index'
+import CONFIG, { nodemailerTransportOptions } from '@config/index'
import logosWebapp from '@config/logos'
import metadata from '@config/metadata'
import { UserDbProperties } from '@db/types/User'
-const hasAuthData = CONFIG.SMTP_USERNAME && CONFIG.SMTP_PASSWORD
-const hasDKIMData =
- CONFIG.SMTP_DKIM_DOMAINNAME && CONFIG.SMTP_DKIM_KEYSELECTOR && CONFIG.SMTP_DKIM_PRIVATKEY
-
const welcomeImageUrl = new URL(logosWebapp.LOGO_WELCOME_PATH, CONFIG.CLIENT_URI)
const settingsUrl = new URL('/settings/notifications', CONFIG.CLIENT_URI)
@@ -31,24 +28,7 @@ const defaultParams = {
renderSettingsUrl: true,
}
-export const transport = createTransport({
- host: CONFIG.SMTP_HOST,
- port: CONFIG.SMTP_PORT,
- ignoreTLS: CONFIG.SMTP_IGNORE_TLS,
- secure: CONFIG.SMTP_SECURE, // true for 465, false for other ports
- pool: true,
- maxConnections: CONFIG.SMTP_MAX_CONNECTIONS,
- maxMessages: CONFIG.SMTP_MAX_MESSAGES,
- auth: hasAuthData && {
- user: CONFIG.SMTP_USERNAME,
- pass: CONFIG.SMTP_PASSWORD,
- },
- dkim: hasDKIMData && {
- domainName: CONFIG.SMTP_DKIM_DOMAINNAME,
- keySelector: CONFIG.SMTP_DKIM_KEYSELECTOR,
- privateKey: CONFIG.SMTP_DKIM_PRIVATKEY,
- },
-})
+const transport = createTransport(nodemailerTransportOptions)
const email = new Email({
message: {
diff --git a/backend/src/graphql/resolvers/images/images.ts b/backend/src/graphql/resolvers/images/images.ts
index 2e76a7889..217d26553 100644
--- a/backend/src/graphql/resolvers/images/images.ts
+++ b/backend/src/graphql/resolvers/images/images.ts
@@ -138,6 +138,9 @@ const s3Upload = async ({ createReadStream, uniqueFilename, mimetype }) => {
const s3 = new S3({ region, endpoint })
const s3Location = `original/${uniqueFilename}`
+ if (!Bucket) {
+ throw new Error('AWS_BUCKET is undefined')
+ }
const params = {
Bucket,
Key: s3Location,
@@ -160,6 +163,9 @@ const s3Delete = async (url) => {
const s3 = new S3({ region, endpoint })
let { pathname } = new URL(url, 'http://example.org') // dummy domain to avoid invalid URL error
pathname = pathname.substring(1) // remove first character '/'
+ if (!Bucket) {
+ throw new Error('AWS_BUCKET is undefined')
+ }
const params = {
Bucket,
Key: pathname,
diff --git a/backend/src/index.ts b/backend/src/index.ts
index 3da4ec7ae..612141733 100644
--- a/backend/src/index.ts
+++ b/backend/src/index.ts
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
-/* eslint-disable @typescript-eslint/no-unsafe-argument */
+
import CONFIG from './config'
import createServer from './server'
diff --git a/backend/src/middleware/helpers/email/sendMail.ts b/backend/src/middleware/helpers/email/sendMail.ts
deleted file mode 100644
index fc50107fb..000000000
--- a/backend/src/middleware/helpers/email/sendMail.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-/* eslint-disable @typescript-eslint/require-await */
-/* eslint-disable @typescript-eslint/no-unsafe-argument */
-/* eslint-disable @typescript-eslint/restrict-plus-operands */
-/* eslint-disable @typescript-eslint/no-unsafe-call */
-/* eslint-disable @typescript-eslint/no-unsafe-member-access */
-/* eslint-disable @typescript-eslint/no-unsafe-assignment */
-import { createTransport } from 'nodemailer'
-import { htmlToText } from 'nodemailer-html-to-text'
-
-import CONFIG from '@config/index'
-import { cleanHtml } from '@middleware/helpers/cleanHtml'
-
-const hasEmailConfig = CONFIG.SMTP_HOST && CONFIG.SMTP_PORT
-const hasAuthData = CONFIG.SMTP_USERNAME && CONFIG.SMTP_PASSWORD
-const hasDKIMData =
- CONFIG.SMTP_DKIM_DOMAINNAME && CONFIG.SMTP_DKIM_KEYSELECTOR && CONFIG.SMTP_DKIM_PRIVATKEY
-
-const transporter = createTransport({
- host: CONFIG.SMTP_HOST,
- port: CONFIG.SMTP_PORT,
- ignoreTLS: CONFIG.SMTP_IGNORE_TLS,
- secure: CONFIG.SMTP_SECURE, // true for 465, false for other ports
- pool: true,
- maxConnections: CONFIG.SMTP_MAX_CONNECTIONS,
- maxMessages: CONFIG.SMTP_MAX_MESSAGES,
- auth: hasAuthData && {
- user: CONFIG.SMTP_USERNAME,
- pass: CONFIG.SMTP_PASSWORD,
- },
- dkim: hasDKIMData && {
- domainName: CONFIG.SMTP_DKIM_DOMAINNAME,
- keySelector: CONFIG.SMTP_DKIM_KEYSELECTOR,
- privateKey: CONFIG.SMTP_DKIM_PRIVATKEY,
- },
-})
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-function
-let sendMailCallback: any = async () => {}
-if (!hasEmailConfig) {
- if (!CONFIG.TEST) {
- // eslint-disable-next-line no-console
- console.log('Warning: Middlewares will not try to send mails.')
- // TODO: disable e-mail logging on database seeding?
- // TODO: implement general logging like 'log4js', see Gradido project: https://github.com/gradido/gradido/blob/master/backend/log4js-config.json
- sendMailCallback = async (templateArgs) => {
- // eslint-disable-next-line no-console
- console.log('--- Log Unsend E-Mail ---')
- // eslint-disable-next-line no-console
- console.log('To: ' + templateArgs.to)
- // eslint-disable-next-line no-console
- console.log('From: ' + templateArgs.from)
- // eslint-disable-next-line no-console
- console.log('Subject: ' + templateArgs.subject)
- // eslint-disable-next-line no-console
- console.log('Content:')
- // eslint-disable-next-line no-console
- console.log(
- cleanHtml(templateArgs.html, 'dummyKey', {
- allowedTags: ['a'],
- allowedAttributes: { a: ['href'] },
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- } as any).replace(/&/g, '&'),
- )
- }
- }
-} else {
- sendMailCallback = async (templateArgs) => {
- transporter.use(
- 'compile',
- htmlToText({
- ignoreImage: true,
- wordwrap: false,
- }),
- )
-
- await transporter.sendMail(templateArgs)
- }
-}
-
-export const sendMail = sendMailCallback
diff --git a/backend/src/middleware/helpers/email/templateBuilder.spec.ts b/backend/src/middleware/helpers/email/templateBuilder.spec.ts
deleted file mode 100644
index 85608b55a..000000000
--- a/backend/src/middleware/helpers/email/templateBuilder.spec.ts
+++ /dev/null
@@ -1,283 +0,0 @@
-/* eslint-disable @typescript-eslint/require-await */
-/* eslint-disable @typescript-eslint/no-unsafe-return */
-/* eslint-disable @typescript-eslint/no-unsafe-call */
-/* eslint-disable @typescript-eslint/no-unsafe-member-access */
-/* eslint-disable @typescript-eslint/no-unsafe-assignment */
-/* eslint-disable @typescript-eslint/no-unsafe-argument */
-import CONFIG from '@config/index'
-import logosWebapp from '@config/logos'
-
-import {
- signupTemplate,
- emailVerificationTemplate,
- resetPasswordTemplate,
- wrongAccountTemplate,
- notificationTemplate,
- chatMessageTemplate,
-} from './templateBuilder'
-
-const englishHint = 'English version below!'
-const welcomeImageUrl = new URL(logosWebapp.LOGO_WELCOME_PATH, CONFIG.CLIENT_URI)
-const supportUrl = CONFIG.SUPPORT_URL.toString()
-let actionUrl, name, settingsUrl
-
-const signupTemplateData = () => ({
- email: 'test@example.org',
- variables: {
- nonce: '12345',
- inviteCode: 'AAAAAA',
- },
-})
-const emailVerificationTemplateData = () => ({
- email: 'test@example.org',
- variables: {
- nonce: '12345',
- name: 'Mr Example',
- },
-})
-const resetPasswordTemplateData = () => ({
- email: 'test@example.org',
- variables: {
- nonce: '12345',
- name: 'Mr Example',
- },
-})
-const chatMessageTemplateData = {
- email: 'test@example.org',
- variables: {
- senderUser: {
- name: 'Sender',
- },
- recipientUser: {
- name: 'Recipient',
- },
- },
-}
-const wrongAccountTemplateData = () => ({
- email: 'test@example.org',
- variables: {},
-})
-const notificationTemplateData = (locale) => ({
- email: 'test@example.org',
- variables: {
- notification: {
- to: { name: 'Mr Example', locale },
- },
- },
-})
-const textsStandard = [
- {
- templPropName: 'from',
- isContaining: false,
- text: CONFIG.EMAIL_DEFAULT_SENDER,
- },
- {
- templPropName: 'to',
- isContaining: false,
- text: 'test@example.org',
- },
- // is contained in html
- welcomeImageUrl.toString(),
- CONFIG.ORGANIZATION_URL,
- CONFIG.APPLICATION_NAME,
-]
-const testEmailData = (emailTemplate, templateBuilder, templateData, texts) => {
- if (!emailTemplate) {
- emailTemplate = templateBuilder(templateData)
- }
- texts.forEach((element) => {
- if (typeof element === 'object') {
- if (element.isContaining) {
- expect(emailTemplate[element.templPropName]).toEqual(expect.stringContaining(element.text))
- } else {
- expect(emailTemplate[element.templPropName]).toEqual(element.text)
- }
- } else {
- expect(emailTemplate.html).toEqual(expect.stringContaining(element))
- }
- })
- return emailTemplate
-}
-
-describe('templateBuilder', () => {
- describe('signupTemplate', () => {
- describe('multi language', () => {
- it('e-mail is build with all data', () => {
- const subject = `Willkommen, Bienvenue, Welcome to ${CONFIG.APPLICATION_NAME}!`
- const actionUrl = new URL('/registration', CONFIG.CLIENT_URI).toString()
- const theSignupTemplateData = signupTemplateData()
- const enContent = "Thank you for joining our cause – it's awesome to have you on board."
- const deContent =
- 'Danke, dass Du dich angemeldet hast – wir freuen uns, Dich dabei zu haben.'
- testEmailData(null, signupTemplate, theSignupTemplateData, [
- ...textsStandard,
- {
- templPropName: 'subject',
- isContaining: false,
- text: subject,
- },
- englishHint,
- actionUrl,
- theSignupTemplateData.variables.nonce,
- theSignupTemplateData.variables.inviteCode,
- enContent,
- deContent,
- supportUrl,
- ])
- })
- })
- })
-
- describe('emailVerificationTemplate', () => {
- describe('multi language', () => {
- it('e-mail is build with all data', () => {
- const subject = 'Neue E-Mail Adresse | New E-Mail Address'
- const actionUrl = new URL('/settings/my-email-address/verify', CONFIG.CLIENT_URI).toString()
- const theEmailVerificationTemplateData = emailVerificationTemplateData()
- const enContent = 'So, you want to change your e-mail? No problem!'
- const deContent = 'Du möchtest also deine E-Mail ändern? Kein Problem!'
- testEmailData(null, emailVerificationTemplate, theEmailVerificationTemplateData, [
- ...textsStandard,
- {
- templPropName: 'subject',
- isContaining: false,
- text: subject,
- },
- englishHint,
- actionUrl,
- theEmailVerificationTemplateData.variables.nonce,
- theEmailVerificationTemplateData.variables.name,
- enContent,
- deContent,
- supportUrl,
- ])
- })
- })
- })
-
- describe('resetPasswordTemplate', () => {
- describe('multi language', () => {
- it('e-mail is build with all data', () => {
- const subject = 'Neues Passwort | Reset Password'
- const actionUrl = new URL('/password-reset/change-password', CONFIG.CLIENT_URI).toString()
- const theResetPasswordTemplateData = resetPasswordTemplateData()
- const enContent = 'So, you forgot your password? No problem!'
- const deContent = 'Du hast also dein Passwort vergessen? Kein Problem!'
- testEmailData(null, resetPasswordTemplate, theResetPasswordTemplateData, [
- ...textsStandard,
- {
- templPropName: 'subject',
- isContaining: false,
- text: subject,
- },
- englishHint,
- actionUrl,
- theResetPasswordTemplateData.variables.nonce,
- theResetPasswordTemplateData.variables.name,
- enContent,
- deContent,
- supportUrl,
- ])
- })
- })
- })
-
- describe('chatMessageTemplate', () => {
- describe('multi language', () => {
- it('e-mail is build with all data', () => {
- const subject = `Neue Chat-Nachricht | New chat message - ${chatMessageTemplateData.variables.senderUser.name}`
- const actionUrl = new URL('/chat', CONFIG.CLIENT_URI).toString()
- const enContent = `You have received a new chat message from ${chatMessageTemplateData.variables.senderUser.name} .`
- const deContent = `Du hast eine neue Chat-Nachricht von ${chatMessageTemplateData.variables.senderUser.name} erhalten.`
- testEmailData(null, chatMessageTemplate, chatMessageTemplateData, [
- ...textsStandard,
- {
- templPropName: 'subject',
- isContaining: false,
- text: subject,
- },
- englishHint,
- actionUrl,
- chatMessageTemplateData.variables.senderUser,
- chatMessageTemplateData.variables.recipientUser,
- enContent,
- deContent,
- supportUrl,
- ])
- })
- })
- })
-
- describe('wrongAccountTemplate', () => {
- describe('multi language', () => {
- it('e-mail is build with all data', () => {
- const subject = 'Falsche Mailadresse? | Wrong E-mail?'
- const actionUrl = new URL('/password-reset/request', CONFIG.CLIENT_URI).toString()
- const theWrongAccountTemplateData = wrongAccountTemplateData()
- const enContent =
- "You requested a password reset but unfortunately we couldn't find an account associated with your e-mail address."
- const deContent =
- 'Du hast bei uns ein neues Passwort angefordert – leider haben wir aber keinen Account mit Deiner E-Mailadresse gefunden.'
- testEmailData(null, wrongAccountTemplate, theWrongAccountTemplateData, [
- ...textsStandard,
- {
- templPropName: 'subject',
- isContaining: false,
- text: subject,
- },
- englishHint,
- actionUrl,
- enContent,
- deContent,
- supportUrl,
- ])
- })
- })
- })
-
- describe('notificationTemplate', () => {
- beforeEach(() => {
- actionUrl = new URL('/notifications', CONFIG.CLIENT_URI).toString()
- name = notificationTemplateData('en').variables.notification.to.name
- settingsUrl = new URL('/settings/notifications', CONFIG.CLIENT_URI)
- })
-
- describe('en', () => {
- it('e-mail is build with all data', () => {
- const subject = `${CONFIG.APPLICATION_NAME} – Notification`
- const content = 'You received at least one notification. Click on this button to view them:'
- testEmailData(null, notificationTemplate, notificationTemplateData('en'), [
- ...textsStandard,
- {
- templPropName: 'subject',
- isContaining: false,
- text: subject,
- },
- actionUrl,
- name,
- content,
- settingsUrl,
- ])
- })
- })
-
- describe('de', () => {
- it('e-mail is build with all data', async () => {
- const subject = `${CONFIG.APPLICATION_NAME} – Benachrichtigung`
- const content = `Du hast mindestens eine Benachrichtigung erhalten. Klick auf diesen Button, um sie anzusehen:`
- testEmailData(null, notificationTemplate, notificationTemplateData('de'), [
- ...textsStandard,
- {
- templPropName: 'subject',
- isContaining: false,
- text: subject,
- },
- actionUrl,
- name,
- content,
- settingsUrl,
- ])
- })
- })
- })
-})
diff --git a/backend/src/middleware/helpers/email/templateBuilder.ts b/backend/src/middleware/helpers/email/templateBuilder.ts
deleted file mode 100644
index ffceb49f6..000000000
--- a/backend/src/middleware/helpers/email/templateBuilder.ts
+++ /dev/null
@@ -1,140 +0,0 @@
-/* eslint-disable @typescript-eslint/restrict-template-expressions */
-/* eslint-disable @typescript-eslint/no-unsafe-call */
-/* eslint-disable @typescript-eslint/no-unsafe-member-access */
-/* eslint-disable @typescript-eslint/no-unsafe-argument */
-/* eslint-disable @typescript-eslint/no-unsafe-assignment */
-/* eslint-disable import/no-namespace */
-import mustache from 'mustache'
-
-import CONFIG from '@config/index'
-import logosWebapp from '@config/logos'
-import metadata from '@config/metadata'
-
-import * as templates from './templates'
-import * as templatesDE from './templates/de'
-import * as templatesEN from './templates/en'
-
-const from = CONFIG.EMAIL_DEFAULT_SENDER
-const welcomeImageUrl = new URL(logosWebapp.LOGO_WELCOME_PATH, CONFIG.CLIENT_URI)
-
-const defaultParams = {
- welcomeImageUrl,
- APPLICATION_NAME: CONFIG.APPLICATION_NAME,
- ORGANIZATION_NAME: metadata.ORGANIZATION_NAME,
- ORGANIZATION_URL: CONFIG.ORGANIZATION_URL,
- supportUrl: CONFIG.SUPPORT_URL,
-}
-const englishHint = 'English version below!'
-
-export const signupTemplate = ({ email, variables: { nonce, inviteCode = null } }) => {
- const subject = `Willkommen, Bienvenue, Welcome to ${CONFIG.APPLICATION_NAME}!`
- // dev format example: http://localhost:3000/registration?method=invite-mail&email=huss%40pjannto.com&nonce=64853
- const actionUrl = new URL('/registration', CONFIG.CLIENT_URI)
- actionUrl.searchParams.set('email', email)
- actionUrl.searchParams.set('nonce', nonce)
- if (inviteCode) {
- actionUrl.searchParams.set('inviteCode', inviteCode)
- actionUrl.searchParams.set('method', 'invite-code')
- } else {
- actionUrl.searchParams.set('method', 'invite-mail')
- }
- const renderParams = { ...defaultParams, englishHint, actionUrl, nonce, subject }
-
- return {
- from,
- to: email,
- subject,
- html: mustache.render(templates.layout, renderParams, { content: templates.signup }),
- }
-}
-
-export const emailVerificationTemplate = ({ email, variables: { nonce, name } }) => {
- const subject = 'Neue E-Mail Adresse | New E-Mail Address'
- const actionUrl = new URL('/settings/my-email-address/verify', CONFIG.CLIENT_URI)
- actionUrl.searchParams.set('email', email)
- actionUrl.searchParams.set('nonce', nonce)
- const renderParams = { ...defaultParams, englishHint, actionUrl, name, nonce, subject }
-
- return {
- from,
- to: email,
- subject,
- html: mustache.render(templates.layout, renderParams, { content: templates.emailVerification }),
- }
-}
-
-export const resetPasswordTemplate = ({ email, variables: { nonce, name } }) => {
- const subject = 'Neues Passwort | Reset Password'
- const actionUrl = new URL('/password-reset/change-password', CONFIG.CLIENT_URI)
- actionUrl.searchParams.set('nonce', nonce)
- actionUrl.searchParams.set('email', email)
- const renderParams = { ...defaultParams, englishHint, actionUrl, name, nonce, subject }
-
- return {
- from,
- to: email,
- subject,
- html: mustache.render(templates.layout, renderParams, { content: templates.passwordReset }),
- }
-}
-
-export const chatMessageTemplate = ({ email, variables: { senderUser, recipientUser } }) => {
- const subject = `Neue Chat-Nachricht | New chat message - ${senderUser.name}`
- const actionUrl = new URL('/chat', CONFIG.CLIENT_URI)
- const renderParams = {
- ...defaultParams,
- subject,
- englishHint,
- actionUrl,
- senderUser,
- recipientUser,
- }
-
- return {
- from,
- to: email,
- subject,
- html: mustache.render(templates.layout, renderParams, { content: templates.chatMessage }),
- }
-}
-
-export const wrongAccountTemplate = ({ email, _variables = {} }) => {
- const subject = 'Falsche Mailadresse? | Wrong E-mail?'
- const actionUrl = new URL('/password-reset/request', CONFIG.CLIENT_URI)
- const renderParams = { ...defaultParams, englishHint, actionUrl }
-
- return {
- from,
- to: email,
- subject,
- html: mustache.render(templates.layout, renderParams, { content: templates.wrongAccount }),
- }
-}
-
-export const notificationTemplate = ({ email, variables: { notification } }) => {
- const actionUrl = new URL('/notifications', CONFIG.CLIENT_URI)
- const settingsUrl = new URL('/settings/notifications', CONFIG.CLIENT_URI)
- const renderParams = { ...defaultParams, name: notification.to.name, settingsUrl, actionUrl }
- let content
- switch (notification.to.locale) {
- case 'de':
- content = templatesDE.notification
- break
- case 'en':
- content = templatesEN.notification
- break
-
- default:
- content = templatesEN.notification
- break
- }
- const subjectUnrendered = content.split('\n')[0].split('"')[1]
- const subject = mustache.render(subjectUnrendered, renderParams, {})
-
- return {
- from,
- to: email,
- subject,
- html: mustache.render(templates.layout, renderParams, { content }),
- }
-}
diff --git a/backend/src/middleware/helpers/email/templates/chatMessage.html b/backend/src/middleware/helpers/email/templates/chatMessage.html
deleted file mode 100644
index 49fc69bf2..000000000
--- a/backend/src/middleware/helpers/email/templates/chatMessage.html
+++ /dev/null
@@ -1,105 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Hallo {{ recipientUser.name }}!
- Du hast eine neue Chat-Nachricht von {{ senderUser.name }} erhalten.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Hello {{ recipientUser.name }}!
- You have received a new chat message from {{ senderUser.name }} .
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/backend/src/middleware/helpers/email/templates/de/index.ts b/backend/src/middleware/helpers/email/templates/de/index.ts
deleted file mode 100644
index 4aa323b9f..000000000
--- a/backend/src/middleware/helpers/email/templates/de/index.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unsafe-argument */
-/* eslint-disable security/detect-non-literal-fs-filename */
-import fs from 'node:fs'
-import path from 'node:path'
-
-// eslint-disable-next-line n/no-sync
-const readFile = (fileName) => fs.readFileSync(path.join(__dirname, fileName), 'utf-8')
-
-export const notification = readFile('./notification.html')
diff --git a/backend/src/middleware/helpers/email/templates/de/notification.html b/backend/src/middleware/helpers/email/templates/de/notification.html
deleted file mode 100644
index a54943310..000000000
--- a/backend/src/middleware/helpers/email/templates/de/notification.html
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Hallo {{ name }},
- Du hast mindestens eine Benachrichtigung erhalten. Klick auf diesen Button, um sie anzusehen:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/backend/src/middleware/helpers/email/templates/emailVerification.html b/backend/src/middleware/helpers/email/templates/emailVerification.html
deleted file mode 100644
index 35ce27e5a..000000000
--- a/backend/src/middleware/helpers/email/templates/emailVerification.html
+++ /dev/null
@@ -1,186 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Hallo {{ name }}!
- Du möchtest also deine E-Mail ändern? Kein Problem! Mit Klick auf diesen Button
- kannst Du Deine neue E-Mail Adresse bestätigen:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Falls Du deine E-Mail Adresse doch nicht ändern möchtest, kannst du diese Nachricht
- einfach ignorieren. Melde Dich gerne bei
- unserem Support Team , wenn du noch Fragen hast!
-
-
-
-
-
-
-
-
-
-
-
-
-
- Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in
- Dein Browserfenster kopieren: {{{ nonce }}}
- Bis bald bei {{{APPLICATION_NAME}}} !
- – Dein {{APPLICATION_NAME}} Team
-
-
-
-
- –––––––––––––––––––––––––––––––––––––––––––––––
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Hello {{ name }}!
- So, you want to change your e-mail? No problem! Just click the button below to verify
- your new address:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- If you don't want to change your e-mail address feel free to ignore this message. You
- can
- also contact our
- support team if you have any questions!
-
-
-
-
-
-
-
-
-
-
-
-
-
- If the above button doesn't work you can also copy the following code into your
- browser window: {{{ nonce }}}
- See you soon on {{{APPLICATION_NAME}}} !
- – The {{APPLICATION_NAME}} Team
-
-
-
-
-
-
-
-
-
diff --git a/backend/src/middleware/helpers/email/templates/en/index.ts b/backend/src/middleware/helpers/email/templates/en/index.ts
deleted file mode 100644
index 4aa323b9f..000000000
--- a/backend/src/middleware/helpers/email/templates/en/index.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unsafe-argument */
-/* eslint-disable security/detect-non-literal-fs-filename */
-import fs from 'node:fs'
-import path from 'node:path'
-
-// eslint-disable-next-line n/no-sync
-const readFile = (fileName) => fs.readFileSync(path.join(__dirname, fileName), 'utf-8')
-
-export const notification = readFile('./notification.html')
diff --git a/backend/src/middleware/helpers/email/templates/en/notification.html b/backend/src/middleware/helpers/email/templates/en/notification.html
deleted file mode 100644
index 168b21864..000000000
--- a/backend/src/middleware/helpers/email/templates/en/notification.html
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Hello {{ name }},
- You received at least one notification. Click on this button to view them:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/backend/src/middleware/helpers/email/templates/index.ts b/backend/src/middleware/helpers/email/templates/index.ts
deleted file mode 100644
index 9a64192ce..000000000
--- a/backend/src/middleware/helpers/email/templates/index.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unsafe-argument */
-/* eslint-disable security/detect-non-literal-fs-filename */
-import fs from 'node:fs'
-import path from 'node:path'
-
-// eslint-disable-next-line n/no-sync
-const readFile = (fileName) => fs.readFileSync(path.join(__dirname, fileName), 'utf-8')
-
-export const signup = readFile('./signup.html')
-export const passwordReset = readFile('./resetPassword.html')
-export const wrongAccount = readFile('./wrongAccount.html')
-export const emailVerification = readFile('./emailVerification.html')
-export const chatMessage = readFile('./chatMessage.html')
-
-export const layout = readFile('./layout.html')
diff --git a/backend/src/middleware/helpers/email/templates/layout.html b/backend/src/middleware/helpers/email/templates/layout.html
deleted file mode 100644
index 0c68d6309..000000000
--- a/backend/src/middleware/helpers/email/templates/layout.html
+++ /dev/null
@@ -1,197 +0,0 @@
-
-
-
-
-
-
-
-
-
- {{ subject }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{englishHint}}
-
- {{> content}}
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/backend/src/middleware/helpers/email/templates/resetPassword.html b/backend/src/middleware/helpers/email/templates/resetPassword.html
deleted file mode 100644
index 43c45455e..000000000
--- a/backend/src/middleware/helpers/email/templates/resetPassword.html
+++ /dev/null
@@ -1,185 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Hallo {{ name }}!
- Du hast also dein Passwort vergessen? Kein Problem! Mit Klick auf diesen Button
- kannst Du innerhalb der nächsten 24 Stunden Dein Passwort zurücksetzen:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Falls Du kein neues Passwort angefordert hast, kannst Du diese E-Mail einfach
- ignorieren. Wenn Du noch Fragen hast, melde Dich gerne bei
- unserem Support Team !
-
-
-
-
-
-
-
-
-
-
-
-
-
- Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in
- Dein Browserfenster kopieren: {{{ nonce }}}
- Bis bald bei {{APPLICATION_NAME}} !
- – Dein {{APPLICATION_NAME}} Team
-
-
-
-
- –––––––––––––––––––––––––––––––––––––––––––––––
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Hello {{ name }}!
- So, you forgot your password? No problem! Just click the button below to reset
- it within the next 24 hours:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- If you didn't request a new password feel free to ignore this e-mail. You can
- also contact our
- support team if you have any questions!
-
-
-
-
-
-
-
-
-
-
-
-
-
- If the above button doesn't work you can also copy the following code into your
- browser window: {{{ nonce }}}
- See you soon on {{APPLICATION_NAME}} !
- – The {{APPLICATION_NAME}} Team
-
-
-
-
-
-
-
-
-
diff --git a/backend/src/middleware/helpers/email/templates/signup.html b/backend/src/middleware/helpers/email/templates/signup.html
deleted file mode 100644
index 4bf17fd61..000000000
--- a/backend/src/middleware/helpers/email/templates/signup.html
+++ /dev/null
@@ -1,214 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Willkommen bei {{APPLICATION_NAME}}!
- Danke, dass Du dich angemeldet hast – wir freuen uns, Dich dabei zu haben. Jetzt
- fehlt nur noch eine Kleinigkeit, bevor wir gemeinsam die Welt verbessern können ... Bitte bestätige
- Deine E-Mail Adresse:
-
-
-
-
-
-
-
-
-
-
-
- –––––––––––––––––––––––––––––––––––––––––––––––
-
-
-
-
-
-
-
-
-
-
-
-
-
- Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in Dein Browserfenster kopieren: {{{ nonce }}}
- Das funktioniert allerdings nur, wenn du Dich über unsere Website registriert hast.
- Falls Du Dich nicht selbst bei {{APPLICATION_NAME}} angemeldet hast, schau doch mal vorbei!
- Wir sind ein gemeinnütziges Aktionsnetzwerk – von Menschen für Menschen.
- PS: Wenn Du keinen Account bei uns möchtest, kannst Du diese
- E-Mail einfach ignorieren. ;)
-
-
-
-
- –––––––––––––––––––––––––––––––––––––––––––––––
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Welcome to {{APPLICATION_NAME}}!
- Thank you for joining our cause – it's awesome to have you on board. There's
- just one tiny step missing before we can start shaping the world together ... Please confirm your
- e-mail address by clicking the button below:
-
-
-
-
-
-
-
-
-
-
-
- –––––––––––––––––––––––––––––––––––––––––––––––
-
-
-
-
-
-
-
-
-
-
-
-
-
- If the above button doesn't work, you can also copy the following code into your browser window: {{{ nonce }}}
- However, this only works if you have registered through our website.
- If you didn't sign up for {{APPLICATION_NAME}} we recommend you to check it out!
- It's a social network from people for people who want to connect and change the world together.
- PS: If you ignore this e-mail we will not create an account
- for
- you. ;)
-
-
-
-
- –––––––––––––––––––––––––––––––––––––––––––––––
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/backend/src/middleware/helpers/email/templates/wrongAccount.html b/backend/src/middleware/helpers/email/templates/wrongAccount.html
deleted file mode 100644
index e8f71e9ea..000000000
--- a/backend/src/middleware/helpers/email/templates/wrongAccount.html
+++ /dev/null
@@ -1,185 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Hallo!
- Du hast bei uns ein neues Passwort angefordert – leider haben wir aber keinen Account mit Deiner E-Mailadresse gefunden.
- Kann es sein, dass Du mit einer anderen Adresse bei uns
- angemeldet bist?
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Wenn Du noch keinen Account bei {{APPLICATION_NAME}} hast oder Dein Password gar nicht ändern willst,
- kannst Du diese E-Mail einfach ignorieren!
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Hello!
- You requested a password reset but unfortunately we couldn't find an account associated with your e-mail address.
- Did you maybe use another one when you signed up?
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- If you don't have an account at {{APPLICATION_NAME}} yet or if you didn't want to reset your password,
- please ignore this e-mail.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/backend/src/middleware/index.ts b/backend/src/middleware/index.ts
index 896e5b33b..cc3af6bfc 100644
--- a/backend/src/middleware/index.ts
+++ b/backend/src/middleware/index.ts
@@ -1,7 +1,5 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
-/* eslint-disable @typescript-eslint/restrict-template-expressions */
-/* eslint-disable @typescript-eslint/no-unsafe-call */
-/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { applyMiddleware, IMiddleware } from 'graphql-middleware'
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index e0f91c358..ae77abd5e 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -30,6 +30,8 @@ services:
environment:
- NODE_ENV="development"
- DEBUG=true
+ - SMTP_PORT=1025
+ - SMTP_HOST=mailserver
volumes:
- ./backend:/app