diff --git a/backend/.eslintrc.js b/backend/.eslintrc.js
index 0007fd125..e853c8bf6 100644
--- a/backend/.eslintrc.js
+++ b/backend/.eslintrc.js
@@ -25,10 +25,12 @@ module.exports = {
},
node: true,
},
+ // the parser cannot handle the split sodium import
+ 'import/ignore': ['sodium-native'],
},
rules: {
'no-console': 'error',
- camelcase: ['error', { allow: ['FederationClient_*'] }],
+ camelcase: ['error', { allow: ['FederationClient_*', 'crypto_*', 'randombytes_random'] }],
'no-debugger': 'error',
'prettier/prettier': [
'error',
@@ -58,7 +60,10 @@ module.exports = {
'import/no-dynamic-require': 'error',
'import/no-internal-modules': 'off',
'import/no-relative-packages': 'error',
- 'import/no-relative-parent-imports': ['error', { ignore: ['@/*', 'random-bigint'] }],
+ 'import/no-relative-parent-imports': [
+ 'error',
+ { ignore: ['@/*', 'random-bigint', 'sodium-native'] },
+ ],
'import/no-self-import': 'error',
'import/no-unresolved': 'error',
'import/no-useless-path-segments': 'error',
diff --git a/backend/@types/sodium-native/index.d.ts b/backend/@types/sodium-native/index.d.ts
new file mode 100644
index 000000000..773d85ee5
--- /dev/null
+++ b/backend/@types/sodium-native/index.d.ts
@@ -0,0 +1,8 @@
+// eslint-disable-next-line import/no-unresolved
+export * from '@/node_modules/@types/sodium-native'
+
+declare module 'sodium-native' {
+ export function crypto_hash_sha512_init(state: Buffer, key?: Buffer, outlen?: Buffer): void
+ export function crypto_hash_sha512_update(state: Buffer, input: Buffer): void
+ export function crypto_hash_sha512_final(state: Buffer, out: Buffer): void
+}
diff --git a/backend/package.json b/backend/package.json
index 68ec89ec0..10d58f8ed 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -55,6 +55,7 @@
"@types/lodash.clonedeep": "^4.5.6",
"@types/node": "^16.10.3",
"@types/nodemailer": "^6.4.4",
+ "@types/sodium-native": "^2.3.5",
"@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
diff --git a/backend/src/emails/__snapshots__/sendEmailVariants.test.ts.snap b/backend/src/emails/__snapshots__/sendEmailVariants.test.ts.snap
new file mode 100644
index 000000000..5a443b2bf
--- /dev/null
+++ b/backend/src/emails/__snapshots__/sendEmailVariants.test.ts.snap
@@ -0,0 +1,1521 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`sendEmailVariants sendAccountActivationEmail result has the correct html as snapshot 1`] = `
+"
+
+
+
+
+
+
+
+
+
+
+
+
Email Verification
+
+
Hello Peter Lustig,
+
Your email address has just been registered with Gradido.
+
+
+
Complete registration
+
Please click here to complete the registration and activate your Gradido account.
Activate account
+
Or copy the link into your browser window.
http://localhost/checkEmail/6627633878930542284
+
+ Request new valid link
+ The link has a validity of 23 hours and 30 minutes.
+If the validity of the link has already expired, you can have a new link sent to you here.
New link
+
+
+
+
Kind regards,
your Gradido team
+
+
+
+
+
+
+"
+`;
+
+exports[`sendEmailVariants sendAccountMultiRegistrationEmail calls "sendEmailTranslated" result has the correct html as snapshot 1`] = `
+"
+
+
+
+
+
+
+
+
+
+
+
+
Try To Register Again With Your Email
+
+
Hello Peter Lustig,
+
Your email address has just been used again to register an account with Gradido.
However, an account already exists for your email address.
+
+
+
+
Reset password
+
If you have forgotten your password, please click here.
reset
+
Or copy the link into your browser window.
http://localhost/forgot-password
+
Contact support
+
If you did not try to register again, please contact our support:
support@supportmail.com
+
+
+
Kind regards,
your Gradido team
+
+
+
+
+
+
+"
+`;
+
+exports[`sendEmailVariants sendAddedContributionMessageEmail result has the correct html as snapshot 1`] = `
+"
+
+
+
+
+
+
+
+
+
+
+
+
Message about your common good contribution
+
+
Hello Peter Lustig,
+
You have received a message from Bibi Bloxberg regarding your common good contribution “My contribution.”.
+
+
+
Read and reply to message
+
To view and reply to the message, go to the “Creation” menu in your Gradido account and click on the “My contributions” tab.
To account
+
Please do not reply to this email.
+
+
+
Kind regards,
your Gradido team
+
+
+
+
+
+
+"
+`;
+
+exports[`sendEmailVariants sendContributionConfirmedEmail result has the correct html as snapshot 1`] = `
+"
+
+
+
+
+
+
+
+
+
+
+
+
Your contribution to the common good was confirmed
+
+
Hello Peter Lustig,
+
Your common good contribution “My contribution.” has just been approved by Bibi Bloxberg. Your Gradido account has been credited with 23.54 GDD.
+
+
+
Contribution details
+
To see your common good contributions and related messages, go to the “Creation” menu in your Gradido account and click on the “My contributions” tab.
To account
+
Or copy the link into your browser window.
https://gdd.gradido.net/community/contributions
+
Please do not reply to this email.
+
+
+
Kind regards,
your Gradido team
+
+
+
+
+
+
+"
+`;
+
+exports[`sendEmailVariants sendContributionDeletedEmail result has the correct html as snapshot 1`] = `
+"
+
+
+
+
+
+
+
+
+
+
+
+
Your common good contribution was deleted
+
+
Hello Peter Lustig,
+
Your common good contribution “My contribution.” was deleted by Bibi Bloxberg.
+
+
+
Contribution details
+
To see your common good contributions and related messages, go to the “Creation” menu in your Gradido account and click on the “My contributions” tab.
To account
+
Or copy the link into your browser window.
https://gdd.gradido.net/community/contributions
+
Please do not reply to this email.
+
+
+
Kind regards,
your Gradido team
+
+
+
+
+
+
+"
+`;
+
+exports[`sendEmailVariants sendContributionDeniedEmail result has the correct html as snapshot 1`] = `
+"
+
+
+
+
+
+
+
+
+
+
+
+
Your common good contribution was rejected
+
+
Hello Peter Lustig,
+
Your common good contribution “My contribution.” was rejected by Bibi Bloxberg.
+
+
+
Contribution details
+
To see your common good contributions and related messages, go to the “Creation” menu in your Gradido account and click on the “My contributions” tab.
To account
+
Or copy the link into your browser window.
https://gdd.gradido.net/community/contributions
+
Please do not reply to this email.
+
+
+
Kind regards,
your Gradido team
+
+
+
+
+
+
+"
+`;
+
+exports[`sendEmailVariants sendResetPasswordEmail result has the correct html as snapshot 1`] = `
+"
+
+
+
+
+
+
+
+
+
+
+
+
Reset password
+
+
Hello Peter Lustig,
+
You, or someone else, requested a password reset for this account.
+
+
+
Reset password
+
If it was you, please click here.
reset
+
Or copy the link into your browser window.
http://localhost/reset-password/3762660021544901417
+
+ Request new valid link
+ The link has a validity of 23 hours and 30 minutes.
+If the validity of the link has already expired, you can have a new link sent to you here.
New link
+
+
+
+
Kind regards,
your Gradido team
+
+
+
+
+
+
+"
+`;
+
+exports[`sendEmailVariants sendTransactionLinkRedeemedEmail result has the correct html as snapshot 1`] = `
+"
+
+
+
+
+
+
+
+
+
+
+
+
Bibi Bloxberg has redeemed your Gradido link
+
+
Hello Peter Lustig,
+
Bibi Bloxberg (bibi@bloxberg.de) has just redeemed your link.
+
+
+
Transaction details
+
Amount: 17.65 GDD
Message: You deserve it! 🙏🏼
You can find transaction details in your Gradido account.
+
To account
+
Please do not reply to this email.
+
+
+
Kind regards,
your Gradido team
+
+
+
+
+
+
+"
+`;
+
+exports[`sendEmailVariants sendTransactionReceivedEmail result has the correct html as snapshot 1`] = `
+"
+
+
+
+
+
+
+
+
+
+
+
+
Bibi Bloxberg has sent you 37.40 Gradido
+
+
Hello Peter Lustig,
+
You have just received 37.40 GDD from Bibi Bloxberg (bibi@bloxberg.de).
+
+
+
Transaction details
+
You can find transaction details in your Gradido account.
To account
+
Please do not reply to this email.
+
+
+
Kind regards,
your Gradido team
+
+
+
+
+
+
+"
+`;
diff --git a/backend/src/emails/sendEmailTranslated.test.ts b/backend/src/emails/sendEmailTranslated.test.ts
index 3f1dd1061..b6ec0fbb5 100644
--- a/backend/src/emails/sendEmailTranslated.test.ts
+++ b/backend/src/emails/sendEmailTranslated.test.ts
@@ -94,11 +94,11 @@ describe('sendEmailTranslated', () => {
originalMessage: expect.objectContaining({
to: 'receiver@mail.org',
cc: 'support@gradido.net',
- from: 'Gradido (do not answer) ',
- attachments: [],
- subject: 'Gradido: Try To Register Again With Your Email',
- html: expect.stringContaining('Gradido: Try To Register Again With Your Email'),
- text: expect.stringContaining('GRADIDO: TRY TO REGISTER AGAIN WITH YOUR EMAIL'),
+ from: 'Gradido (emails.general.doNotAnswer) ',
+ attachments: expect.any(Array),
+ subject: 'Try To Register Again With Your Email',
+ html: expect.stringContaining('Try To Register Again With Your Email'),
+ text: expect.stringContaining('TRY TO REGISTER AGAIN WITH YOUR EMAIL'),
}),
})
})
@@ -142,11 +142,11 @@ describe('sendEmailTranslated', () => {
originalMessage: expect.objectContaining({
to: CONFIG.EMAIL_TEST_RECEIVER,
cc: 'support@gradido.net',
- from: `Gradido (do not answer) <${CONFIG.EMAIL_SENDER}>`,
- attachments: [],
- subject: 'Gradido: Try To Register Again With Your Email',
- html: expect.stringContaining('Gradido: Try To Register Again With Your Email'),
- text: expect.stringContaining('GRADIDO: TRY TO REGISTER AGAIN WITH YOUR EMAIL'),
+ from: `Gradido (emails.general.doNotAnswer) <${CONFIG.EMAIL_SENDER}>`,
+ attachments: expect.any(Array),
+ subject: 'Try To Register Again With Your Email',
+ html: expect.stringContaining('Try To Register Again With Your Email'),
+ text: expect.stringContaining('TRY TO REGISTER AGAIN WITH YOUR EMAIL'),
}),
})
})
diff --git a/backend/src/emails/sendEmailTranslated.ts b/backend/src/emails/sendEmailTranslated.ts
index 879d17656..acef8a11f 100644
--- a/backend/src/emails/sendEmailTranslated.ts
+++ b/backend/src/emails/sendEmailTranslated.ts
@@ -70,7 +70,36 @@ export const sendEmailTranslated = async ({
const resultSend = await email
.send({
template: path.join(__dirname, 'templates', template),
- message: receiver,
+ message: {
+ ...receiver,
+ attachments: [
+ {
+ filename: 'gradido-header.jpeg',
+ path: path.join(__dirname, 'templates/includes/gradido-header.jpeg'),
+ cid: 'gradidoheader',
+ },
+ {
+ filename: 'facebook-icon.png',
+ path: path.join(__dirname, 'templates/includes/facebook-icon.png'),
+ cid: 'facebookicon',
+ },
+ {
+ filename: 'telegram-icon.png',
+ path: path.join(__dirname, 'templates/includes/telegram-icon.png'),
+ cid: 'telegramicon',
+ },
+ {
+ filename: 'twitter-icon.png',
+ path: path.join(__dirname, 'templates/includes/twitter-icon.png'),
+ cid: 'twittericon',
+ },
+ {
+ filename: 'youtube-icon.png',
+ path: path.join(__dirname, 'templates/includes/youtube-icon.png'),
+ cid: 'youtubeicon',
+ },
+ ],
+ },
locals, // the 'locale' in here seems not to be used by 'email-template', because it doesn't work if the language isn't set before by 'i18n.setLocale'
})
.catch((error: unknown) => {
diff --git a/backend/src/emails/sendEmailVariants.test.ts b/backend/src/emails/sendEmailVariants.test.ts
index 76e96f129..3340a361d 100644
--- a/backend/src/emails/sendEmailVariants.test.ts
+++ b/backend/src/emails/sendEmailVariants.test.ts
@@ -34,11 +34,9 @@ let testEnv: {
beforeAll(async () => {
testEnv = await testEnvironment(logger, localization)
con = testEnv.con
- // await cleanDB()
})
afterAll(async () => {
- // await cleanDB()
await con.close()
})
@@ -87,8 +85,10 @@ describe('sendEmailVariants', () => {
},
})
})
+ })
- it('has expected result', () => {
+ describe('result', () => {
+ it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
@@ -97,37 +97,17 @@ describe('sendEmailVariants', () => {
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig ',
- from: 'Gradido (do not answer) ',
- attachments: [],
- subject: 'Gradido: Message about your common good contribution',
+ from: 'Gradido (emails.general.doNotAnswer) ',
+ attachments: expect.any(Array),
+ subject: 'Message about your common good contribution',
html: expect.any(String),
- text: expect.stringContaining('GRADIDO: MESSAGE ABOUT YOUR COMMON GOOD CONTRIBUTION'),
+ text: expect.stringContaining('MESSAGE ABOUT YOUR COMMON GOOD CONTRIBUTION'),
}),
})
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain(
- 'Gradido: Message about your common good contribution',
- )
- expect(result.originalMessage.html).toContain(
- '>Gradido: Message about your common good contribution',
- )
- expect(result.originalMessage.html).toContain('Hello Peter Lustig')
- expect(result.originalMessage.html).toContain(
- 'you have received a message from Bibi Bloxberg regarding your common good contribution “My contribution.”.',
- )
- expect(result.originalMessage.html).toContain(
- 'To view and reply to the message, go to the “Creation” menu in your Gradido account and click on the “My contributions” tab!',
- )
- expect(result.originalMessage.html).toContain(
- `Link to your account: ${CONFIG.EMAIL_LINK_OVERVIEW}`,
- )
- expect(result.originalMessage.html).toContain('Please do not reply to this email!')
- expect(result.originalMessage.html).toContain('Kind regards,
your Gradido team')
- expect(result.originalMessage.html).toContain('—————')
- expect(result.originalMessage.html).toContain(
- '
Gradido-Akademie
Institut für Wirtschaftsbionik
Pfarrweg 2
74653 Künzelsau
Deutschland
support@supportmail.com
http://localhost/',
- )
+ })
+
+ it('has the correct html as snapshot', () => {
+ expect(result.originalMessage.html).toMatchSnapshot()
})
})
})
@@ -163,8 +143,10 @@ describe('sendEmailVariants', () => {
},
})
})
+ })
- it('has expected result', () => {
+ describe('result', () => {
+ it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
@@ -173,41 +155,17 @@ describe('sendEmailVariants', () => {
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig ',
- from: 'Gradido (do not answer) ',
- attachments: [],
- subject: 'Gradido: Email Verification',
+ from: 'Gradido (emails.general.doNotAnswer) ',
+ attachments: expect.any(Array),
+ subject: 'Email Verification',
html: expect.any(String),
- text: expect.stringContaining('GRADIDO: EMAIL VERIFICATION'),
+ text: expect.stringContaining('EMAIL VERIFICATION'),
}),
})
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain('Gradido: Email Verification')
- expect(result.originalMessage.html).toContain('>Gradido: Email Verification')
- expect(result.originalMessage.html).toContain('Hello Peter Lustig')
- expect(result.originalMessage.html).toContain(
- 'Your email address has just been registered with Gradido.',
- )
- expect(result.originalMessage.html).toContain(
- 'Please click on this link to complete the registration and activate your Gradido account:',
- )
- expect(result.originalMessage.html).toContain(
- 'http://localhost/checkEmail/6627633878930542284',
- )
- expect(result.originalMessage.html).toContain(
- 'or copy the link above into your browser window.',
- )
- expect(result.originalMessage.html).toContain(
- 'The link has a validity of 23 hours and 30 minutes. If the validity of the link has already expired, you can have a new link sent to you here:',
- )
- expect(result.originalMessage.html).toContain(
- `${CONFIG.EMAIL_LINK_FORGOTPASSWORD}`,
- )
- expect(result.originalMessage.html).toContain('Kind regards,
your Gradido team')
- expect(result.originalMessage.html).toContain('—————')
- expect(result.originalMessage.html).toContain(
- '
Gradido-Akademie
Institut für Wirtschaftsbionik
Pfarrweg 2
74653 Künzelsau
Deutschland
support@supportmail.com
http://localhost/',
- )
+ })
+
+ it('has the correct html as snapshot', () => {
+ expect(result.originalMessage.html).toMatchSnapshot()
})
})
})
@@ -240,54 +198,28 @@ describe('sendEmailVariants', () => {
})
})
- it('has expected result', () => {
- expect(result).toMatchObject({
- envelope: {
- from: 'info@gradido.net',
- to: ['peter@lustig.de'],
- },
- message: expect.any(String),
- originalMessage: expect.objectContaining({
- to: 'Peter Lustig ',
- from: 'Gradido (do not answer) ',
- attachments: [],
- subject: 'Gradido: Try To Register Again With Your Email',
- html: expect.any(String),
- text: expect.stringContaining('GRADIDO: TRY TO REGISTER AGAIN WITH YOUR EMAIL'),
- }),
+ describe('result', () => {
+ it('is the expected object', () => {
+ expect(result).toMatchObject({
+ envelope: {
+ from: 'info@gradido.net',
+ to: ['peter@lustig.de'],
+ },
+ message: expect.any(String),
+ originalMessage: expect.objectContaining({
+ to: 'Peter Lustig ',
+ from: 'Gradido (emails.general.doNotAnswer) ',
+ attachments: expect.any(Array),
+ subject: 'Try To Register Again With Your Email',
+ html: expect.any(String),
+ text: expect.stringContaining('TRY TO REGISTER AGAIN WITH YOUR EMAIL'),
+ }),
+ })
+ })
+
+ it('has the correct html as snapshot', () => {
+ expect(result.originalMessage.html).toMatchSnapshot()
})
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain(
- 'Gradido: Try To Register Again With Your Email',
- )
- expect(result.originalMessage.html).toContain(
- '>Gradido: Try To Register Again With Your Email',
- )
- expect(result.originalMessage.html).toContain('Hello Peter Lustig')
- expect(result.originalMessage.html).toContain(
- 'Your email address has just been used again to register an account with Gradido.',
- )
- expect(result.originalMessage.html).toContain(
- 'However, an account already exists for your email address.',
- )
- expect(result.originalMessage.html).toContain(
- 'Please click on the following link if you have forgotten your password:',
- )
- expect(result.originalMessage.html).toContain(
- `${CONFIG.EMAIL_LINK_FORGOTPASSWORD}`,
- )
- expect(result.originalMessage.html).toContain(
- 'or copy the link above into your browser window.',
- )
- expect(result.originalMessage.html).toContain(
- 'If you are not the one who tried to register again, please contact our support:
support@supportmail.com',
- )
- expect(result.originalMessage.html).toContain('Kind regards,
your Gradido team')
- expect(result.originalMessage.html).toContain('—————')
- expect(result.originalMessage.html).toContain(
- '
Gradido-Akademie
Institut für Wirtschaftsbionik
Pfarrweg 2
74653 Künzelsau
Deutschland
support@supportmail.com
http://localhost/',
- )
})
})
})
@@ -327,8 +259,10 @@ describe('sendEmailVariants', () => {
},
})
})
+ })
- it('has expected result', () => {
+ describe('result', () => {
+ it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
@@ -337,37 +271,17 @@ describe('sendEmailVariants', () => {
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig ',
- from: 'Gradido (do not answer) ',
- attachments: [],
- subject: 'Gradido: Your contribution to the common good was confirmed',
+ from: 'Gradido (emails.general.doNotAnswer) ',
+ attachments: expect.any(Array),
+ subject: 'Your contribution to the common good was confirmed',
html: expect.any(String),
- text: expect.stringContaining(
- 'GRADIDO: YOUR CONTRIBUTION TO THE COMMON GOOD WAS CONFIRMED',
- ),
+ text: expect.stringContaining('YOUR CONTRIBUTION TO THE COMMON GOOD WAS CONFIRMED'),
}),
})
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain(
- 'Gradido: Your contribution to the common good was confirmed',
- )
- expect(result.originalMessage.html).toContain(
- '>Gradido: Your contribution to the common good was confirmed',
- )
- expect(result.originalMessage.html).toContain('Hello Peter Lustig')
- expect(result.originalMessage.html).toContain(
- 'Your public good contribution “My contribution.” has just been confirmed by Bibi Bloxberg and credited to your Gradido account.',
- )
- expect(result.originalMessage.html).toContain('Amount: 23.54 GDD')
- expect(result.originalMessage.html).toContain(
- `Link to your account: ${CONFIG.EMAIL_LINK_OVERVIEW}`,
- )
- expect(result.originalMessage.html).toContain('Please do not reply to this email!')
- expect(result.originalMessage.html).toContain('Kind regards,
your Gradido team')
- expect(result.originalMessage.html).toContain('—————')
- expect(result.originalMessage.html).toContain(
- '
Gradido-Akademie
Institut für Wirtschaftsbionik
Pfarrweg 2
74653 Künzelsau
Deutschland
support@supportmail.com
http://localhost/',
- )
+ })
+
+ it('has the correct html as snapshot', () => {
+ expect(result.originalMessage.html).toMatchSnapshot()
})
})
})
@@ -405,7 +319,9 @@ describe('sendEmailVariants', () => {
},
})
})
+ })
+ describe('result', () => {
it('has expected result', () => {
expect(result).toMatchObject({
envelope: {
@@ -415,37 +331,17 @@ describe('sendEmailVariants', () => {
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig ',
- from: 'Gradido (do not answer) ',
- attachments: [],
- subject: 'Gradido: Your common good contribution was rejected',
+ from: 'Gradido (emails.general.doNotAnswer) ',
+ attachments: expect.any(Array),
+ subject: 'Your common good contribution was rejected',
html: expect.any(String),
- text: expect.stringContaining('GRADIDO: YOUR COMMON GOOD CONTRIBUTION WAS REJECTED'),
+ text: expect.stringContaining('YOUR COMMON GOOD CONTRIBUTION WAS REJECTED'),
}),
})
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain(
- 'Gradido: Your common good contribution was rejected',
- )
- expect(result.originalMessage.html).toContain(
- '>Gradido: Your common good contribution was rejected',
- )
- expect(result.originalMessage.html).toContain('Hello Peter Lustig')
- expect(result.originalMessage.html).toContain(
- 'Your public good contribution “My contribution.” was rejected by Bibi Bloxberg.',
- )
- expect(result.originalMessage.html).toContain(
- 'To see your common good contributions and related messages, go to the “Creation” menu in your Gradido account and click on the “My contributions” tab!',
- )
- expect(result.originalMessage.html).toContain(
- `Link to your account: ${CONFIG.EMAIL_LINK_OVERVIEW}`,
- )
- expect(result.originalMessage.html).toContain('Please do not reply to this email!')
- expect(result.originalMessage.html).toContain('Kind regards,
your Gradido team')
- expect(result.originalMessage.html).toContain('—————')
- expect(result.originalMessage.html).toContain(
- '
Gradido-Akademie
Institut für Wirtschaftsbionik
Pfarrweg 2
74653 Künzelsau
Deutschland
support@supportmail.com
http://localhost/',
- )
+ })
+
+ it('has the correct html as snapshot', () => {
+ expect(result.originalMessage.html).toMatchSnapshot()
})
})
})
@@ -483,8 +379,10 @@ describe('sendEmailVariants', () => {
},
})
})
+ })
- it('has expected result', () => {
+ describe('result', () => {
+ it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
@@ -493,37 +391,17 @@ describe('sendEmailVariants', () => {
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig ',
- from: 'Gradido (do not answer) ',
- attachments: [],
- subject: 'Gradido: Your common good contribution was deleted',
+ from: 'Gradido (emails.general.doNotAnswer) ',
+ attachments: expect.any(Array),
+ subject: 'Your common good contribution was deleted',
html: expect.any(String),
- text: expect.stringContaining('GRADIDO: YOUR COMMON GOOD CONTRIBUTION WAS DELETED'),
+ text: expect.stringContaining('YOUR COMMON GOOD CONTRIBUTION WAS DELETED'),
}),
})
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain(
- 'Gradido: Your common good contribution was deleted',
- )
- expect(result.originalMessage.html).toContain(
- '>Gradido: Your common good contribution was deleted',
- )
- expect(result.originalMessage.html).toContain('Hello Peter Lustig')
- expect(result.originalMessage.html).toContain(
- 'Your public good contribution “My contribution.” was deleted by Bibi Bloxberg.',
- )
- expect(result.originalMessage.html).toContain(
- 'To see your common good contributions and related messages, go to the “Creation” menu in your Gradido account and click on the “My contributions” tab!',
- )
- expect(result.originalMessage.html).toContain(
- `Link to your account: ${CONFIG.EMAIL_LINK_OVERVIEW}`,
- )
- expect(result.originalMessage.html).toContain('Please do not reply to this email!')
- expect(result.originalMessage.html).toContain('Kind regards,
your Gradido team')
- expect(result.originalMessage.html).toContain('—————')
- expect(result.originalMessage.html).toContain(
- '
Gradido-Akademie
Institut für Wirtschaftsbionik
Pfarrweg 2
74653 Künzelsau
Deutschland
support@supportmail.com
http://localhost/',
- )
+ })
+
+ it('has the correct html as snapshot', () => {
+ expect(result.originalMessage.html).toMatchSnapshot()
})
})
})
@@ -559,8 +437,10 @@ describe('sendEmailVariants', () => {
},
})
})
+ })
- it('has expected result', () => {
+ describe('result', () => {
+ it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
@@ -569,39 +449,17 @@ describe('sendEmailVariants', () => {
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig ',
- from: 'Gradido (do not answer) ',
- attachments: [],
- subject: 'Gradido: Reset password',
+ from: 'Gradido (emails.general.doNotAnswer) ',
+ attachments: expect.any(Array),
+ subject: 'Reset password',
html: expect.any(String),
- text: expect.stringContaining('GRADIDO: RESET PASSWORD'),
+ text: expect.stringContaining('RESET PASSWORD'),
}),
})
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain('Gradido: Reset password')
- expect(result.originalMessage.html).toContain('>Gradido: Reset password')
- expect(result.originalMessage.html).toContain('Hello Peter Lustig')
- expect(result.originalMessage.html).toContain(
- 'You, or someone else, requested a password reset for this account.',
- )
- expect(result.originalMessage.html).toContain('If it was you, please click on the link:')
- expect(result.originalMessage.html).toContain(
- 'http://localhost/reset-password/3762660021544901417',
- )
- expect(result.originalMessage.html).toContain(
- 'or copy the link above into your browser window.',
- )
- expect(result.originalMessage.html).toContain(
- 'The link has a validity of 23 hours and 30 minutes. If the validity of the link has already expired, you can have a new link sent to you here:',
- )
- expect(result.originalMessage.html).toContain(
- `${CONFIG.EMAIL_LINK_FORGOTPASSWORD}`,
- )
- expect(result.originalMessage.html).toContain('Kind regards,
your Gradido team')
- expect(result.originalMessage.html).toContain('—————')
- expect(result.originalMessage.html).toContain(
- '
Gradido-Akademie
Institut für Wirtschaftsbionik
Pfarrweg 2
74653 Künzelsau
Deutschland
support@supportmail.com
http://localhost/',
- )
+ })
+
+ it('has the correct html as snapshot', () => {
+ expect(result.originalMessage.html).toMatchSnapshot()
})
})
})
@@ -643,8 +501,10 @@ describe('sendEmailVariants', () => {
},
})
})
+ })
- it('has expected result', () => {
+ describe('result', () => {
+ it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
@@ -653,36 +513,17 @@ describe('sendEmailVariants', () => {
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig ',
- from: 'Gradido (do not answer) ',
- attachments: [],
- subject: 'Gradido: Bibi Bloxberg has redeemed your Gradido link',
+ from: 'Gradido (emails.general.doNotAnswer) ',
+ attachments: expect.any(Array),
+ subject: 'Bibi Bloxberg has redeemed your Gradido link',
html: expect.any(String),
text: expect.stringContaining('BIBI BLOXBERG HAS REDEEMED YOUR GRADIDO LINK'),
}),
})
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain(
- 'Gradido: Bibi Bloxberg has redeemed your Gradido link',
- )
- expect(result.originalMessage.html).toContain(
- '>Gradido: Bibi Bloxberg has redeemed your Gradido link',
- )
- expect(result.originalMessage.html).toContain('Hello Peter Lustig')
- expect(result.originalMessage.html).toContain(
- 'Bibi Bloxberg (bibi@bloxberg.de) has just redeemed your link.',
- )
- expect(result.originalMessage.html).toContain('Amount: 17.65 GDD')
- expect(result.originalMessage.html).toContain('Message: You deserve it! 🙏🏼')
- expect(result.originalMessage.html).toContain(
- `You can find transaction details in your Gradido account: ${CONFIG.EMAIL_LINK_OVERVIEW}`,
- )
- expect(result.originalMessage.html).toContain('Please do not reply to this email!')
- expect(result.originalMessage.html).toContain('Kind regards,
your Gradido team')
- expect(result.originalMessage.html).toContain('—————')
- expect(result.originalMessage.html).toContain(
- '
Gradido-Akademie
Institut für Wirtschaftsbionik
Pfarrweg 2
74653 Künzelsau
Deutschland
support@supportmail.com
http://localhost/',
- )
+ })
+
+ it('has the correct html as snapshot', () => {
+ expect(result.originalMessage.html).toMatchSnapshot()
})
})
})
@@ -722,8 +563,10 @@ describe('sendEmailVariants', () => {
},
})
})
+ })
- it('has expected result', () => {
+ describe('result', () => {
+ it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
@@ -732,34 +575,17 @@ describe('sendEmailVariants', () => {
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig ',
- from: 'Gradido (do not answer) ',
- attachments: [],
- subject: 'Gradido: Bibi Bloxberg has sent you 37.40 Gradido',
+ from: 'Gradido (emails.general.doNotAnswer) ',
+ attachments: expect.any(Array),
+ subject: 'Bibi Bloxberg has sent you 37.40 Gradido',
html: expect.any(String),
- text: expect.stringContaining('GRADIDO: BIBI BLOXBERG HAS SENT YOU 37.40 GRADIDO'),
+ text: expect.stringContaining('BIBI BLOXBERG HAS SENT YOU 37.40 GRADIDO'),
}),
})
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain('')
- expect(result.originalMessage.html).toContain(
- 'Gradido: Bibi Bloxberg has sent you 37.40 Gradido',
- )
- expect(result.originalMessage.html).toContain(
- '>Gradido: Bibi Bloxberg has sent you 37.40 Gradido',
- )
- expect(result.originalMessage.html).toContain('Hello Peter Lustig')
- expect(result.originalMessage.html).toContain(
- 'You have just received 37.40 GDD from Bibi Bloxberg (bibi@bloxberg.de).',
- )
- expect(result.originalMessage.html).toContain(
- `You can find transaction details in your Gradido account: ${CONFIG.EMAIL_LINK_OVERVIEW}`,
- )
- expect(result.originalMessage.html).toContain('Please do not reply to this email!')
- expect(result.originalMessage.html).toContain('Kind regards,
your Gradido team')
- expect(result.originalMessage.html).toContain('—————')
- expect(result.originalMessage.html).toContain(
- '
Gradido-Akademie
Institut für Wirtschaftsbionik
Pfarrweg 2
74653 Künzelsau
Deutschland
support@supportmail.com
http://localhost/',
- )
+ })
+
+ it('has the correct html as snapshot', () => {
+ expect(result.originalMessage.html).toMatchSnapshot()
})
})
})
diff --git a/backend/src/emails/templates/accountActivation/html.pug b/backend/src/emails/templates/accountActivation/html.pug
index 6075fa8a8..027dcbc63 100644
--- a/backend/src/emails/templates/accountActivation/html.pug
+++ b/backend/src/emails/templates/accountActivation/html.pug
@@ -1,20 +1,16 @@
-doctype html
-html(lang=locale)
- head
- title= t('emails.accountActivation.subject')
- body
- h1(style='margin-bottom: 24px;')= t('emails.accountActivation.subject')
- #container.col
- include ../hello.pug
- p= t('emails.accountActivation.emailRegistered')
- p
- = t('emails.accountActivation.pleaseClickLink')
- br
- a(href=activationLink) #{activationLink}
- br
- = t('emails.general.orCopyLink')
- p
- = t('emails.accountActivation.duration', { hours: timeDurationObject.hours, minutes: timeDurationObject.minutes })
- br
- a(href=resendLink) #{resendLink}
- include ../greatingFormularImprint.pug
+extend ../layout.pug
+
+block content
+ h2= t('emails.accountActivation.title')
+ .text-block
+ include ../includes/salutation.pug
+ p= t('emails.accountActivation.emailRegistered')
+ .content
+ h2= t('emails.general.completeRegistration')
+ div(class="p_content")= t('emails.accountActivation.pleaseClickLink')
+ a.button-3(href=activationLink) #{t('emails.accountActivation.activateAccount')}
+ div(class="p_content")= t('emails.general.orCopyLink')
+
+ a.clink(href=activationLink) #{activationLink}
+
+ include ../includes/requestNewLink.pug
diff --git a/backend/src/emails/templates/accountMultiRegistration/html.pug b/backend/src/emails/templates/accountMultiRegistration/html.pug
index f8570422c..4d568261b 100644
--- a/backend/src/emails/templates/accountMultiRegistration/html.pug
+++ b/backend/src/emails/templates/accountMultiRegistration/html.pug
@@ -1,23 +1,22 @@
-doctype html
-html(lang=locale)
- head
- title= t('emails.accountMultiRegistration.subject')
- body
- h1(style='margin-bottom: 24px;')= t('emails.accountMultiRegistration.subject')
- #container.col
- include ../hello.pug
- p
- = t('emails.accountMultiRegistration.emailReused')
- br
- = t('emails.accountMultiRegistration.emailExists')
- p
- = t('emails.accountMultiRegistration.onForgottenPasswordClickLink')
- br
- a(href=resendLink) #{resendLink}
- br
- = t('emails.accountMultiRegistration.onForgottenPasswordCopyLink')
- p
- = t('emails.accountMultiRegistration.ifYouAreNotTheOne')
- br
- a(href='mailto:' + supportEmail)= supportEmail
- include ../greatingFormularImprint.pug
+extend ../layout.pug
+
+block content
+ h2= t('emails.accountMultiRegistration.title')
+ .text-block
+ include ../includes/salutation.pug
+ p
+ = t('emails.accountMultiRegistration.emailReused')
+ br
+ = t('emails.accountMultiRegistration.emailExists')
+ .content
+ h2= t('emails.resetPassword.title')
+ div(class="p_content")= t('emails.accountMultiRegistration.onForgottenPasswordClickLink')
+ a.button-3(href=resendLink) #{t('emails.general.reset')}
+ div(class="p_content")= t('emails.general.orCopyLink')
+
+ a.clink(href=resendLink) #{resendLink}
+
+ h2(style="color: red")= t('emails.accountMultiRegistration.contactSupport')
+ div(class="p_content")= t('emails.accountMultiRegistration.ifYouAreNotTheOne')
+
+ a.clink(href='mailto:' + supportEmail)= supportEmail
diff --git a/backend/src/emails/templates/addedContributionMessage/html.pug b/backend/src/emails/templates/addedContributionMessage/html.pug
index e7410c0f0..b09d2c0f0 100644
--- a/backend/src/emails/templates/addedContributionMessage/html.pug
+++ b/backend/src/emails/templates/addedContributionMessage/html.pug
@@ -1,16 +1,14 @@
-doctype html
-html(lang=locale)
- head
- title= t('emails.addedContributionMessage.subject')
- body
- h1(style='margin-bottom: 24px;')= t('emails.addedContributionMessage.subject')
- #container.col
- include ../hello.pug
- p= t('emails.addedContributionMessage.commonGoodContributionMessage', { senderFirstName, senderLastName, contributionMemo })
- p= t('emails.addedContributionMessage.toSeeAndAnswerMessage')
- p
- = t('emails.general.linkToYourAccount')
- = " "
- a(href=overviewURL) #{overviewURL}
- p= t('emails.general.pleaseDoNotReply')
- include ../greatingFormularImprint.pug
+extend ../layout.pug
+
+block content
+ h2= t('emails.addedContributionMessage.title')
+ .text-block
+ include ../includes/salutation.pug
+ p= t('emails.addedContributionMessage.commonGoodContributionMessage', { senderFirstName, senderLastName, contributionMemo })
+ .content
+ h2= t('emails.addedContributionMessage.readMessage')
+ div(class="p_content")= t('emails.addedContributionMessage.toSeeAndAnswerMessage')
+
+ a.button-3(href="https://gdd.gradido.net/community/contribution") #{t('emails.general.toAccount')}
+
+ include ../includes/doNotReply.pug
diff --git a/backend/src/emails/templates/contributionConfirmed/html.pug b/backend/src/emails/templates/contributionConfirmed/html.pug
index 4ff17ffd4..310993d97 100644
--- a/backend/src/emails/templates/contributionConfirmed/html.pug
+++ b/backend/src/emails/templates/contributionConfirmed/html.pug
@@ -1,16 +1,10 @@
-doctype html
-html(lang=locale)
- head
- title= t('emails.contributionConfirmed.subject')
- body
- h1(style='margin-bottom: 24px;')= t('emails.contributionConfirmed.subject')
- #container.col
- include ../hello.pug
- p= t('emails.contributionConfirmed.commonGoodContributionConfirmed', { senderFirstName, senderLastName, contributionMemo })
- p= t('emails.general.amountGDD', { amountGDD: contributionAmount })
- p
- = t('emails.general.linkToYourAccount')
- = " "
- a(href=overviewURL) #{overviewURL}
- p= t('emails.general.pleaseDoNotReply')
- include ../greatingFormularImprint.pug
+extend ../layout.pug
+
+block content
+ h2= t('emails.contributionConfirmed.title')
+ .text-block
+ include ../includes/salutation.pug
+ p= t('emails.contributionConfirmed.commonGoodContributionConfirmed', { contributionMemo, senderFirstName, senderLastName, amountGDD: contributionAmount })
+ .content
+ include ../includes/contributionDetailsCTA.pug
+ include ../includes/doNotReply.pug
\ No newline at end of file
diff --git a/backend/src/emails/templates/contributionDeleted/html.pug b/backend/src/emails/templates/contributionDeleted/html.pug
index d6b3ea207..daf54227d 100644
--- a/backend/src/emails/templates/contributionDeleted/html.pug
+++ b/backend/src/emails/templates/contributionDeleted/html.pug
@@ -1,16 +1,10 @@
-doctype html
-html(lang=locale)
- head
- title= t('emails.contributionDeleted.subject')
- body
- h1(style='margin-bottom: 24px;')= t('emails.contributionDeleted.subject')
- #container.col
- include ../hello.pug
- p= t('emails.contributionDeleted.commonGoodContributionDeleted', { senderFirstName, senderLastName, contributionMemo })
- p= t('emails.contributionDeleted.toSeeContributionsAndMessages')
- p
- = t('emails.general.linkToYourAccount')
- = " "
- a(href=overviewURL) #{overviewURL}
- p= t('emails.general.pleaseDoNotReply')
- include ../greatingFormularImprint.pug
+extend ../layout.pug
+
+block content
+ h2= t('emails.contributionDeleted.title')
+ .text-block
+ include ../includes/salutation.pug
+ p= t('emails.contributionDeleted.commonGoodContributionDeleted', { contributionMemo, senderFirstName, senderLastName })
+ .content
+ include ../includes/contributionDetailsCTA.pug
+ include ../includes/doNotReply.pug
diff --git a/backend/src/emails/templates/contributionDenied/html.pug b/backend/src/emails/templates/contributionDenied/html.pug
index a324374a7..d30653acd 100644
--- a/backend/src/emails/templates/contributionDenied/html.pug
+++ b/backend/src/emails/templates/contributionDenied/html.pug
@@ -1,16 +1,10 @@
-doctype html
-html(lang=locale)
- head
- title= t('emails.contributionDenied.subject')
- body
- h1(style='margin-bottom: 24px;')= t('emails.contributionDenied.subject')
- #container.col
- include ../hello.pug
- p= t('emails.contributionDenied.commonGoodContributionDenied', { senderFirstName, senderLastName, contributionMemo })
- p= t('emails.contributionDenied.toSeeContributionsAndMessages')
- p
- = t('emails.general.linkToYourAccount')
- = " "
- a(href=overviewURL) #{overviewURL}
- p= t('emails.general.pleaseDoNotReply')
- include ../greatingFormularImprint.pug
+extend ../layout.pug
+
+block content
+ h2= t('emails.contributionDenied.title')
+ .text-block
+ include ../includes/salutation.pug
+ p= t('emails.contributionDenied.commonGoodContributionDenied', { contributionMemo, senderFirstName, senderLastName })
+ .content
+ include ../includes/contributionDetailsCTA.pug
+ include ../includes/doNotReply.pug
diff --git a/backend/src/emails/templates/greatingFormularImprint.pug b/backend/src/emails/templates/greatingFormularImprint.pug
deleted file mode 100644
index d7d8c3a14..000000000
--- a/backend/src/emails/templates/greatingFormularImprint.pug
+++ /dev/null
@@ -1,16 +0,0 @@
-p(style='margin-top: 24px;')
- = t('emails.general.sincerelyYours')
- br
- = t('emails.general.yourGradidoTeam')
-p(style='margin-top: 24px;')= '—————'
-p(style='margin-top: 24px;')
- if t('general.imprintImageURL').length > 0
- div(style='position: relative; left: -22px;')
- img(src=t('general.imprintImageURL'), width='200', alt=t('general.imprintImageAlt'))
- br
- each line in t('general.imprint').split(/\n/)
- = line
- br
- a(href='mailto:' + supportEmail)= supportEmail
- br
- a(href=communityURL)= communityURL
diff --git a/backend/src/emails/templates/includes/contributionDetailsCTA.pug b/backend/src/emails/templates/includes/contributionDetailsCTA.pug
new file mode 100644
index 000000000..c2209014f
--- /dev/null
+++ b/backend/src/emails/templates/includes/contributionDetailsCTA.pug
@@ -0,0 +1,7 @@
+//-
+h2= t('emails.general.contributionDetails')
+div(class="p_content")= t('emails.contribution.toSeeContributionsAndMessages')
+a.button-3(href="https://gdd.gradido.net/community/contributions") #{t('emails.general.toAccount')}
+div(class="p_content")= t('emails.general.orCopyLink')
+
+a.clink(href="https://gdd.gradido.net/community/contributions") https://gdd.gradido.net/community/contributions
\ No newline at end of file
diff --git a/backend/src/emails/templates/includes/doNotReply.pug b/backend/src/emails/templates/includes/doNotReply.pug
new file mode 100644
index 000000000..506a5d0db
--- /dev/null
+++ b/backend/src/emails/templates/includes/doNotReply.pug
@@ -0,0 +1 @@
+div(class="p_content")= t('emails.general.pleaseDoNotReply')
\ No newline at end of file
diff --git a/backend/src/emails/templates/includes/email.css b/backend/src/emails/templates/includes/email.css
new file mode 100644
index 000000000..5110c3882
--- /dev/null
+++ b/backend/src/emails/templates/includes/email.css
@@ -0,0 +1,216 @@
+/* vietnamese */
+/* @font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 100;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_c6Dpp_k.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+} */
+/* latin-ext */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 100;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_cqDpp_k.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 100;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_fKDp.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* vietnamese */
+/* @font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 200;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_c6Dpp_k.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+} */
+/* latin-ext */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 200;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_cqDpp_k.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 200;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_fKDp.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* vietnamese */
+/* @font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 300;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_c6Dpp_k.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+} */
+/* latin-ext */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 300;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_cqDpp_k.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 300;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_fKDp.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* vietnamese */
+/* @font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_c6Dpp_k.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+} */
+/* latin-ext */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_cqDpp_k.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_fKDp.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* vietnamese */
+/* @font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 500;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_c6Dpp_k.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+} */
+/* latin-ext */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 500;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_cqDpp_k.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 500;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_fKDp.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* vietnamese */
+/* @font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 600;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_c6Dpp_k.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+} */
+/* latin-ext */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 600;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_cqDpp_k.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 600;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_fKDp.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* vietnamese */
+/* @font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_c6Dpp_k.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+} */
+/* latin-ext */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_cqDpp_k.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 700;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_fKDp.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* vietnamese */
+/* @font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 800;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_c6Dpp_k.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+} */
+/* latin-ext */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 800;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_cqDpp_k.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 800;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_fKDp.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* vietnamese */
+/* @font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 900;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_c6Dpp_k.woff2) format('woff2');
+ unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+} */
+/* latin-ext */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 900;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_cqDpp_k.woff2) format('woff2');
+ unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+ font-family: 'Work Sans';
+ font-style: normal;
+ font-weight: 900;
+ src: url(https://fonts.gstatic.com/s/worksans/v18/QGYsz_wNahGAdqQ43Rh_fKDp.woff2) format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
diff --git a/backend/src/emails/templates/includes/facebook-icon.png b/backend/src/emails/templates/includes/facebook-icon.png
new file mode 100644
index 000000000..1d880cf3e
Binary files /dev/null and b/backend/src/emails/templates/includes/facebook-icon.png differ
diff --git a/backend/src/emails/templates/includes/footer.pug b/backend/src/emails/templates/includes/footer.pug
new file mode 100644
index 000000000..3ae63e32e
--- /dev/null
+++ b/backend/src/emails/templates/includes/footer.pug
@@ -0,0 +1,73 @@
+footer
+ .w-container(class="footer_01")
+ .socialmedia
+ a.slink(
+ target="_blank"
+ href="https://www.facebook.com/groups/Gradido/"
+ )
+ img.bi-facebook(
+ alt="facebook"
+ loading="lazy"
+ src="cid:facebookicon"
+ )
+ a.slink(
+ target="_blank"
+ href="https://t.me/GradidoGruppe"
+ )
+ img.bi-telegram(
+ alt="Telegram"
+ loading="lazy"
+ src="cid:telegramicon"
+ )
+ a.slink(
+ target="_blank"
+ href="https://twitter.com/gradido"
+ )
+ img.bi-twitter(
+ alt="Twitter"
+ loading="lazy"
+ src="cid:twittericon"
+ )
+ a.slink(
+ target="_blank"
+ href="https://www.youtube.com/c/GradidoNet"
+ )
+ img.bi-youtube(
+ alt="youtube"
+ loading="lazy"
+ src="cid:youtubeicon"
+ )
+ .line
+ .footer
+ div(class="footer_p1")= t("emails.footer.contactOurSupport")
+ div(class="footer_p2")= t("emails.footer.supportEmail")
+ img.image(
+ alt="Gradido Logo"
+ src="https://gdd.gradido.net/img/brand/green.png"
+ )
+ div
+ a(
+ class="terms_of_use"
+ href="https://gradido.net/de/impressum/"
+ target="_blank"
+ )= t("emails.footer.imprint")
+ br
+ a(
+ class="terms_of_use"
+ href="https://gradido.net/de/datenschutz/"
+ target="_blank"
+ )= t("emails.footer.privacyPolicy")
+ div(class="footer_p1")
+ | Gradido-Akademie
+ br
+ | Institut für Wirtschaftsbionik
+ br
+ | Pfarrweg 2
+ br
+ | 74653 Künzelsau
+ br
+ | Deutschland
+ br
+ br
+ br
+
diff --git a/backend/src/emails/templates/includes/gradido-header.jpeg b/backend/src/emails/templates/includes/gradido-header.jpeg
new file mode 100644
index 000000000..38a5c3a80
Binary files /dev/null and b/backend/src/emails/templates/includes/gradido-header.jpeg differ
diff --git a/backend/src/emails/templates/includes/greeting.pug b/backend/src/emails/templates/includes/greeting.pug
new file mode 100644
index 000000000..6693e23ca
--- /dev/null
+++ b/backend/src/emails/templates/includes/greeting.pug
@@ -0,0 +1,6 @@
+//- This sets the greeting at the end of every e-mail
+.text-block
+ p
+ = t('emails.general.sincerelyYours')
+ br
+ = t('emails.general.yourGradidoTeam')
\ No newline at end of file
diff --git a/backend/src/emails/templates/includes/header.pug b/backend/src/emails/templates/includes/header.pug
new file mode 100644
index 000000000..3160d3e2b
--- /dev/null
+++ b/backend/src/emails/templates/includes/header.pug
@@ -0,0 +1,13 @@
+header
+ .head
+ //- TODO
+ //- when https://gdd.gradido.net/img/gradido-email-header.jpg is on production,
+ //- replace this URL by https://gdd.gradido.net/img/brand/gradido-email-header.png
+ img.head-logo(
+ alt="Gradido Logo"
+ loading="lazy"
+ src="cid:gradidoheader"
+ )
+
+
+
diff --git a/backend/src/emails/templates/includes/requestNewLink.pug b/backend/src/emails/templates/includes/requestNewLink.pug
new file mode 100644
index 000000000..8baa3d6df
--- /dev/null
+++ b/backend/src/emails/templates/includes/requestNewLink.pug
@@ -0,0 +1,10 @@
+//-
+requestNewLink
+ h2= t('emails.general.requestNewLink')
+
+ if timeDurationObject.minutes == 0
+ div(class="p_content")= t('emails.general.linkValidity', { hours: timeDurationObject.hours })
+ else
+ div(class="p_content")= t('emails.general.linkValidityWithMinutes', { hours: timeDurationObject.hours, minutes: timeDurationObject.minutes })
+
+ a.button-4(href=resendLink) #{t('emails.general.newLink')}
\ No newline at end of file
diff --git a/backend/src/emails/templates/hello.pug b/backend/src/emails/templates/includes/salutation.pug
similarity index 100%
rename from backend/src/emails/templates/hello.pug
rename to backend/src/emails/templates/includes/salutation.pug
diff --git a/backend/src/emails/templates/includes/telegram-icon.png b/backend/src/emails/templates/includes/telegram-icon.png
new file mode 100644
index 000000000..4c36ff661
Binary files /dev/null and b/backend/src/emails/templates/includes/telegram-icon.png differ
diff --git a/backend/src/emails/templates/includes/twitter-icon.png b/backend/src/emails/templates/includes/twitter-icon.png
new file mode 100644
index 000000000..fffb9b599
Binary files /dev/null and b/backend/src/emails/templates/includes/twitter-icon.png differ
diff --git a/backend/src/emails/templates/includes/webflow.css b/backend/src/emails/templates/includes/webflow.css
new file mode 100644
index 000000000..02e7fc4e0
--- /dev/null
+++ b/backend/src/emails/templates/includes/webflow.css
@@ -0,0 +1,136 @@
+body{
+ display: block;
+ font-family: "Work Sans", sans-serif;
+ font-size: 17px;
+ text-align: center;
+ text-align: -webkit-center;
+ justify-content: center;
+ padding: 0px;
+ margin: 0px;
+}
+
+h2 {
+ margin-top: 15px;
+ color: #383838;
+}
+
+.container {
+ max-width: 680px;
+ margin: 0 auto;
+ display: block;
+}
+
+.head-logo {
+ width: 100%;
+ height: auto;
+}
+
+.text-block {
+ margin-top: 20px;
+ color: #9ca0a8;
+}
+
+.content {
+ display: block;
+ width: 78%;
+ margin: 40px 1% 40px 1%;
+ padding: 20px 10% 40px 10%;
+ border-radius: 24px;
+ background-image: linear-gradient(180deg, #f5f5f5, #f5f5f5);
+}
+
+.p_content{
+ margin: 15px 0 15px 0;
+ line-height: 26px;
+ color: #9ca0a8;
+}
+
+.clink {
+ line-break: anywhere;
+ margin-bottom: 40px;
+}
+
+.button-3,
+.button-4 {
+ display: inline-block;
+ padding: 9px 15px;
+ color: white;
+ border: 0;
+ line-height: inherit;
+ text-decoration: none;
+ cursor: pointer;
+ border-radius: 20px;
+ background-image: radial-gradient(circle farthest-corner at 0% 0%, #f9cd69, #c58d38);
+ box-shadow: 16px 13px 35px 0 rgba(56, 56, 56, 0.3);
+ margin: 25px 0 25px 0;
+ width: 50%;
+}
+
+.button-4 {
+ background-image: radial-gradient(circle farthest-corner at 0% 0%, #616161, #c2c2c2);
+}
+
+.socialmedia {
+ display: flex;
+ margin-top: 40px;
+ max-width: 600px;
+
+}
+.slink{
+ width: 150px;
+}
+
+.footer {
+ padding-bottom: 20px;
+}
+
+.footer_p1 {
+ margin-top: 30px;
+ color: #9ca0a8;
+ margin-bottom: 30px;
+}
+
+.footer_p2 {
+ color: #383838;
+ font-weight: bold;
+}
+
+
+.image {
+ width: 200px;
+ margin-top: 30px;
+ margin-bottom: 30px;
+}
+
+.div-block {
+ display: table;
+ margin-top: 20px;
+ margin-bottom: 40px;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+}
+
+.terms_of_use {
+ color: #9ca0a8;
+}
+
+.text-block-3 {
+ color: #9ca0a8;
+ margin-bottom: 30px;
+}
+
+.line_image,
+.line {
+ width: 100%;
+ height: 13px;
+ margin-top: 40px;
+}
+
+.line_image {
+ background-image: linear-gradient(90deg, #c58d38, #c58d38 0%, #f3cd7c 35%, #dbb056 54%, #eec05f 63%, #cc9d3d);
+}
+
+.line {
+ background-image: linear-gradient(90deg, #c58d38, #f3cd7c 40%, #dbb056 55%, #eec05f 71%, #cc9d3d);
+}
diff --git a/backend/src/emails/templates/includes/youtube-icon.png b/backend/src/emails/templates/includes/youtube-icon.png
new file mode 100644
index 000000000..d135ba625
Binary files /dev/null and b/backend/src/emails/templates/includes/youtube-icon.png differ
diff --git a/backend/src/emails/templates/layout.pug b/backend/src/emails/templates/layout.pug
new file mode 100644
index 000000000..0995b2647
--- /dev/null
+++ b/backend/src/emails/templates/layout.pug
@@ -0,0 +1,26 @@
+doctype html
+html(lang=locale)
+ head
+ meta(
+ content="multipart/html; charset=UTF-8"
+ http-equiv="content-type"
+ )
+ meta(
+ name="viewport"
+ content="width=device-width, initial-scale=1"
+ )
+ style.
+ .wf-force-outline-none[tabindex="-1"]:focus{outline:none;}
+ style
+ include includes/email.css
+ include includes/webflow.css
+
+ body
+ div.container
+ include includes/header.pug
+
+ .wrapper
+ block content
+ include includes/greeting.pug
+
+ include includes/footer.pug
diff --git a/backend/src/emails/templates/resetPassword/html.pug b/backend/src/emails/templates/resetPassword/html.pug
index 53ffbcd04..4d4ed3f50 100644
--- a/backend/src/emails/templates/resetPassword/html.pug
+++ b/backend/src/emails/templates/resetPassword/html.pug
@@ -1,20 +1,16 @@
-doctype html
-html(lang=locale)
- head
- title= t('emails.resetPassword.subject')
- body
- h1(style='margin-bottom: 24px;')= t('emails.resetPassword.subject')
- #container.col
- include ../hello.pug
- p= t('emails.resetPassword.youOrSomeoneResetPassword')
- p
- = t('emails.resetPassword.pleaseClickLink')
- br
- a(href=resetLink) #{resetLink}
- br
- = t('emails.general.orCopyLink')
- p
- = t('emails.resetPassword.duration', { hours: timeDurationObject.hours, minutes: timeDurationObject.minutes })
- br
- a(href=resendLink) #{resendLink}
- include ../greatingFormularImprint.pug
+extends ../layout.pug
+
+block content
+ h2= t('emails.resetPassword.title')
+ .text-block
+ include ../includes/salutation.pug
+ p= t('emails.resetPassword.youOrSomeoneResetPassword')
+ .content
+ h2= t('emails.resetPassword.title')
+ div(class="p_content")= t('emails.resetPassword.pleaseClickLink')
+ a.button-3(href=resetLink) #{t('emails.general.reset')}
+ div(class="p_content")= t('emails.general.orCopyLink')
+
+ a.clink(href=resetLink) #{resetLink}
+
+ include ../includes/requestNewLink.pug
diff --git a/backend/src/emails/templates/transactionLinkRedeemed/html.pug b/backend/src/emails/templates/transactionLinkRedeemed/html.pug
index 30146e27f..598a18337 100644
--- a/backend/src/emails/templates/transactionLinkRedeemed/html.pug
+++ b/backend/src/emails/templates/transactionLinkRedeemed/html.pug
@@ -1,19 +1,18 @@
-doctype html
-html(lang=locale)
- head
- title= t('emails.transactionLinkRedeemed.subject', { senderFirstName, senderLastName })
- body
- h1(style='margin-bottom: 24px;')= t('emails.transactionLinkRedeemed.subject', { senderFirstName, senderLastName })
- #container.col
- include ../hello.pug
- p= t('emails.transactionLinkRedeemed.hasRedeemedYourLink', { senderFirstName, senderLastName, senderEmail })
- p
- = t('emails.general.amountGDD', { amountGDD: transactionAmount })
- br
- = t('emails.transactionLinkRedeemed.memo', { transactionMemo })
- p
- = t('emails.general.detailsYouFindOnLinkToYourAccount')
- = " "
- a(href=overviewURL) #{overviewURL}
- p= t('emails.general.pleaseDoNotReply')
- include ../greatingFormularImprint.pug
+extend ../layout.pug
+
+block content
+ h2= t('emails.transactionLinkRedeemed.title', { senderFirstName, senderLastName })
+ .text-block
+ include ../includes/salutation.pug
+ p= t('emails.transactionLinkRedeemed.hasRedeemedYourLink', { senderFirstName, senderLastName, senderEmail })
+ .content
+ h2= t('emails.general.transactionDetails')
+ div(class="p_content")= t('emails.general.amountGDD', { amountGDD: transactionAmount })
+ br
+ = t('emails.transactionLinkRedeemed.memo', { transactionMemo })
+ br
+ = t('emails.general.detailsYouFindOnLinkToYourAccount')
+
+ a.button-3(href="https://gdd.gradido.net/transactions") #{t('emails.general.toAccount')}
+
+ include ../includes/doNotReply.pug
diff --git a/backend/src/emails/templates/transactionReceived/html.pug b/backend/src/emails/templates/transactionReceived/html.pug
index e6807f539..abf468dd0 100644
--- a/backend/src/emails/templates/transactionReceived/html.pug
+++ b/backend/src/emails/templates/transactionReceived/html.pug
@@ -1,15 +1,15 @@
-doctype html
-html(lang=locale)
- head
- title= t('emails.transactionReceived.subject', { senderFirstName, senderLastName, transactionAmount })
- body
- h1(style='margin-bottom: 24px;')= t('emails.transactionReceived.subject', { senderFirstName, senderLastName, transactionAmount })
- #container.col
- include ../hello.pug
- p= t('emails.transactionReceived.haveReceivedAmountGDDFrom', { transactionAmount, senderFirstName, senderLastName, senderEmail })
- p
- = t('emails.general.detailsYouFindOnLinkToYourAccount')
- = " "
- a(href=overviewURL) #{overviewURL}
- p= t('emails.general.pleaseDoNotReply')
- include ../greatingFormularImprint.pug
+extend ../layout.pug
+
+block content
+ h2= t('emails.transactionReceived.title', { senderFirstName, senderLastName, transactionAmount })
+ .text-block
+ include ../includes/salutation.pug
+ p= t('emails.transactionReceived.haveReceivedAmountGDDFrom', { transactionAmount, senderFirstName, senderLastName, senderEmail })
+ .content
+ h2= t('emails.general.transactionDetails')
+ div(class="p_content")= t('emails.general.detailsYouFindOnLinkToYourAccount')
+
+ a.button-3(href="https://gdd.gradido.net/transactions") #{t('emails.general.toAccount')}
+
+ include ../includes/doNotReply.pug
+
diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts
index 9934c93de..a61bbfd32 100644
--- a/backend/src/graphql/resolver/UserResolver.ts
+++ b/backend/src/graphql/resolver/UserResolver.ts
@@ -71,15 +71,13 @@ import { hasElopageBuys } from '@/util/hasElopageBuys'
import { getTimeDurationObject, printTimeDuration } from '@/util/time'
import random from 'random-bigint'
+import { randombytes_random } from 'sodium-native'
import { FULL_CREATION_AVAILABLE } from './const/const'
import { getUserCreations } from './util/creations'
import { findUserByIdentifier } from './util/findUserByIdentifier'
import { validateAlias } from './util/validateAlias'
-// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-commonjs
-const sodium = require('sodium-native')
-
const LANGUAGES = ['de', 'en', 'es', 'fr', 'nl']
const DEFAULT_LANGUAGE = 'de'
const isLanguage = (language: string): boolean => {
@@ -237,7 +235,7 @@ export class UserResolver {
// TODO: this is unsecure, but the current implementation of the login server. This way it can be queried if the user with given EMail is existent.
const user = new User(communityDbUser)
- user.id = sodium.randombytes_random() % (2048 * 16) // TODO: for a better faking derive id from email so that it will be always the same id when the same email comes in?
+ user.id = randombytes_random() % (2048 * 16) // TODO: for a better faking derive id from email so that it will be always the same id when the same email comes in?
user.gradidoID = uuidv4()
user.firstName = firstName
user.lastName = lastName
diff --git a/backend/src/locales/de.json b/backend/src/locales/de.json
index 4dc90def2..349c5089e 100644
--- a/backend/src/locales/de.json
+++ b/backend/src/locales/de.json
@@ -1,69 +1,92 @@
{
"emails": {
"accountActivation": {
- "duration": "Der Link hat eine Gültigkeit von {hours} Stunden und {minutes} Minuten. Sollte die Gültigkeit des Links bereits abgelaufen sein, kannst du dir hier einen neuen Link schicken lassen:",
+ "activateAccount": "Konto aktivieren",
"emailRegistered": "deine E-Mail-Adresse wurde soeben bei Gradido registriert.",
- "pleaseClickLink": "Klicke bitte auf diesen Link, um die Registrierung abzuschließen und dein Gradido-Konto zu aktivieren:",
- "subject": "Gradido: E-Mail Überprüfung"
+ "pleaseClickLink": "Klicke bitte hier, um die Registrierung abzuschließen und dein Gradido-Konto zu aktivieren.",
+ "subject": "E-Mail Überprüfung",
+ "title": "E-Mail Überprüfung"
},
"accountMultiRegistration": {
+ "contactSupport": "Support kontaktieren",
"emailExists": "Es existiert jedoch zu deiner E-Mail-Adresse schon ein Konto.",
"emailReused": "deine E-Mail-Adresse wurde soeben erneut benutzt, um bei Gradido ein Konto zu registrieren.",
- "ifYouAreNotTheOne": "Wenn du nicht derjenige bist, der versucht hat sich erneut zu registrieren, wende dich bitte an unseren Support:",
- "onForgottenPasswordClickLink": "Klicke bitte auf den folgenden Link, falls du dein Passwort vergessen haben solltest:",
- "onForgottenPasswordCopyLink": "oder kopiere den obigen Link in dein Browserfenster.",
- "subject": "Gradido: Erneuter Registrierungsversuch mit deiner E-Mail"
+ "ifYouAreNotTheOne": "Wenn du nicht versucht hast dich erneut zu registrieren, wende dich bitte an unseren Support:",
+ "onForgottenPasswordClickLink": "Solltest du dein Passwort vergessen haben, klicke bitte hier.",
+ "subject": "Erneuter Registrierungsversuch mit deiner E-Mail",
+ "title": "Erneuter Registrierungsversuch mit deiner E-Mail"
},
"addedContributionMessage": {
"commonGoodContributionMessage": "du hast zu deinem Gemeinwohl-Beitrag „{contributionMemo}“ eine Nachricht von {senderFirstName} {senderLastName} erhalten.",
- "subject": "Gradido: Nachricht zu deinem Gemeinwohl-Beitrag",
- "toSeeAndAnswerMessage": "Um die Nachricht zu sehen und darauf zu antworten, gehe in deinem Gradido-Konto ins Menü „Schöpfen“ auf den Tab „Meine Beiträge“!"
+ "readMessage": "Nachricht lesen und beantworten",
+ "subject": "Nachricht zu deinem Gemeinwohl-Beitrag",
+ "title": "Nachricht zu deinem Gemeinwohl-Beitrag",
+ "toSeeAndAnswerMessage": "Um die Nachricht zu sehen und darauf zu antworten, gehe in deinem Gradido-Konto ins Menü „Schöpfen“ auf den Tab „Meine Beiträge“."
+ },
+ "contribution": {
+ "toSeeContributionsAndMessages": "Um deine Gemeinwohl-Beiträge und dazugehörige Nachrichten zu sehen, gehe in deinem Gradido-Konto ins Menü „Schöpfen“ auf den Tab „Meine Beiträge“."
},
"contributionConfirmed": {
- "commonGoodContributionConfirmed": "dein Gemeinwohl-Beitrag „{contributionMemo}“ wurde soeben von {senderFirstName} {senderLastName} bestätigt und in deinem Gradido-Konto gutgeschrieben.",
- "subject": "Gradido: Dein Gemeinwohl-Beitrag wurde bestätigt"
+ "commonGoodContributionConfirmed": "dein Gemeinwohl-Beitrag „{contributionMemo}“ wurde soeben von {senderFirstName} {senderLastName} bestätigt. Es wurden deinem Gradido-Konto {amountGDD} GDD gutgeschrieben.",
+ "subject": "Dein Gemeinwohl-Beitrag wurde bestätigt",
+ "title": "Dein Gemeinwohl-Beitrag wurde bestätigt"
},
"contributionDeleted": {
"commonGoodContributionDeleted": "dein Gemeinwohl-Beitrag „{contributionMemo}“ wurde von {senderFirstName} {senderLastName} gelöscht.",
- "subject": "Gradido: Dein Gemeinwohl-Beitrag wurde gelöscht",
- "toSeeContributionsAndMessages": "Um deine Gemeinwohl-Beiträge und dazugehörige Nachrichten zu sehen, gehe in deinem Gradido-Konto ins Menü „Schöpfen“ auf den Tab „Meine Beiträge“!"
+ "subject": "Dein Gemeinwohl-Beitrag wurde gelöscht",
+ "title": "Dein Gemeinwohl-Beitrag wurde gelöscht"
},
"contributionDenied": {
"commonGoodContributionDenied": "dein Gemeinwohl-Beitrag „{contributionMemo}“ wurde von {senderFirstName} {senderLastName} abgelehnt.",
- "subject": "Gradido: Dein Gemeinwohl-Beitrag wurde abgelehnt",
- "toSeeContributionsAndMessages": "Um deine Gemeinwohl-Beiträge und dazugehörige Nachrichten zu sehen, gehe in deinem Gradido-Konto ins Menü „Schöpfen“ auf den Tab „Meine Beiträge“!"
+ "subject": "Dein Gemeinwohl-Beitrag wurde abgelehnt",
+ "title": "Dein Gemeinwohl-Beitrag wurde abgelehnt"
+ },
+ "footer": {
+ "contactOurSupport": "Bei weiteren Fragen kontaktiere bitte unseren Support.",
+ "imprint": "Impressum",
+ "imprintAddress": "Gradido-Akademie\nInstitut für Wirtschaftsbionik\nPfarrweg 2\n74653 Künzelsau\nDeutschland",
+ "imprintImageAlt": "Gradido-Akademie Logo",
+ "privacyPolicy": "Datenschutzerklärung",
+ "supportEmail": "support@gradido.net"
},
"general": {
"amountGDD": "Betrag: {amountGDD} GDD",
- "detailsYouFindOnLinkToYourAccount": "Details zur Transaktion findest du in deinem Gradido-Konto:",
- "doNotAnswer": "nicht antworten",
+ "completeRegistration": "Registrierung abschließen",
+ "contribution": "Gemeinwohl-Beitrag: {contributionMemo}",
+ "contributionDetails": "Beitragsdetails",
+ "detailsYouFindOnLinkToYourAccount": "Details zur Transaktion findest du in deinem Gradido-Konto.",
"helloName": "Hallo {firstName} {lastName},",
- "linkToYourAccount": "Link zu deinem Konto:",
- "orCopyLink": "oder kopiere den obigen Link in dein Browserfenster.",
- "pleaseDoNotReply": "Bitte antworte nicht auf diese E-Mail!",
+ "linkValidity": "Der Link hat eine Gültigkeit von {hours} Stunden.\nSollte die Gültigkeit des Links bereits abgelaufen sein, kannst du dir hier einen neuen Link schicken lassen.",
+ "linkValidityWithMinutes": "Der Link hat eine Gültigkeit von {hours} Stunden und {minutes} Minuten.\nSollte die Gültigkeit des Links bereits abgelaufen sein, kannst du dir hier einen neuen Link schicken lassen.",
+ "newLink": "Neuer Link",
+ "orCopyLink": "Oder kopiere den Link in dein Browserfenster.",
+ "pleaseDoNotReply": "Bitte antworte nicht auf diese E-Mail.",
+ "requestNewLink": "Neuen gültigen Link anfordern",
+ "reset": "zurücksetzen",
"sincerelyYours": "Liebe Grüße",
+ "toAccount": "Zum Konto",
+ "transactionDetails": "Transaktionsdetails",
"yourGradidoTeam": "dein Gradido-Team"
},
"resetPassword": {
- "duration": "Der Link hat eine Gültigkeit von {hours} Stunden und {minutes} Minuten. Sollte die Gültigkeit des Links bereits abgelaufen sein, kannst du dir hier einen neuen Link schicken lassen:",
- "pleaseClickLink": "Wenn du es warst, klicke bitte auf den Link:",
- "subject": "Gradido: Passwort zurücksetzen",
- "youOrSomeoneResetPassword": "du, oder jemand anderes, hast für dieses Konto ein Zurücksetzen des Passworts angefordert."
+ "pleaseClickLink": "Wenn du es warst, klicke bitte hier.",
+ "subject": "Passwort zurücksetzen",
+ "title": "Passwort zurücksetzen",
+ "youOrSomeoneResetPassword": "du oder jemand anderes, hast für dieses Konto ein Zurücksetzen des Passworts angefordert."
},
"transactionLinkRedeemed": {
"hasRedeemedYourLink": "{senderFirstName} {senderLastName} ({senderEmail}) hat soeben deinen Link eingelöst.",
"memo": "Nachricht: {transactionMemo}",
- "subject": "Gradido: {senderFirstName} {senderLastName} hat deinen Gradido-Link eingelöst"
+ "subject": "{senderFirstName} {senderLastName} hat deinen Gradido-Link eingelöst",
+ "title": "{senderFirstName} {senderLastName} hat deinen Gradido-Link eingelöst"
},
"transactionReceived": {
"haveReceivedAmountGDDFrom": "du hast soeben {transactionAmount} GDD von {senderFirstName} {senderLastName} ({senderEmail}) erhalten.",
- "subject": "Gradido: {senderFirstName} {senderLastName} hat dir {transactionAmount} Gradido gesendet"
+ "subject": "{senderFirstName} {senderLastName} hat dir {transactionAmount} Gradido gesendet",
+ "title": "{senderFirstName} {senderLastName} hat dir {transactionAmount} Gradido gesendet"
}
},
"general": {
- "decimalSeparator": ",",
- "imprint": "Gradido-Akademie\nInstitut für Wirtschaftsbionik\nPfarrweg 2\n74653 Künzelsau\nDeutschland",
- "imprintImageAlt": "Gradido-Akademie Logo",
- "imprintImageURL": "https://gdd.gradido.net/img/brand/green.png"
+ "decimalSeparator": ","
}
}
diff --git a/backend/src/locales/en.json b/backend/src/locales/en.json
index 74c5739bc..cf4bbef47 100644
--- a/backend/src/locales/en.json
+++ b/backend/src/locales/en.json
@@ -1,69 +1,92 @@
{
"emails": {
"accountActivation": {
- "duration": "The link has a validity of {hours} hours and {minutes} minutes. If the validity of the link has already expired, you can have a new link sent to you here:",
+ "activateAccount": "Activate account",
"emailRegistered": "Your email address has just been registered with Gradido.",
- "pleaseClickLink": "Please click on this link to complete the registration and activate your Gradido account:",
- "subject": "Gradido: Email Verification"
+ "pleaseClickLink": "Please click here to complete the registration and activate your Gradido account.",
+ "subject": "Email Verification",
+ "title": "Email Verification"
},
"accountMultiRegistration": {
+ "contactSupport": "Contact support",
"emailExists": "However, an account already exists for your email address.",
"emailReused": "Your email address has just been used again to register an account with Gradido.",
- "ifYouAreNotTheOne": "If you are not the one who tried to register again, please contact our support:",
- "onForgottenPasswordClickLink": "Please click on the following link if you have forgotten your password:",
- "onForgottenPasswordCopyLink": "or copy the link above into your browser window.",
- "subject": "Gradido: Try To Register Again With Your Email"
+ "ifYouAreNotTheOne": "If you did not try to register again, please contact our support:",
+ "onForgottenPasswordClickLink": "If you have forgotten your password, please click here.",
+ "subject": "Try To Register Again With Your Email",
+ "title": "Try To Register Again With Your Email"
},
"addedContributionMessage": {
- "commonGoodContributionMessage": "you have received a message from {senderFirstName} {senderLastName} regarding your common good contribution “{contributionMemo}”.",
- "subject": "Gradido: Message about your common good contribution",
- "toSeeAndAnswerMessage": "To view and reply to the message, go to the “Creation” menu in your Gradido account and click on the “My contributions” tab!"
+ "commonGoodContributionMessage": "You have received a message from {senderFirstName} {senderLastName} regarding your common good contribution “{contributionMemo}”.",
+ "readMessage": "Read and reply to message",
+ "subject": "Message about your common good contribution",
+ "title": "Message about your common good contribution",
+ "toSeeAndAnswerMessage": "To view and reply to the message, go to the “Creation” menu in your Gradido account and click on the “My contributions” tab."
+ },
+ "contribution": {
+ "toSeeContributionsAndMessages": "To see your common good contributions and related messages, go to the “Creation” menu in your Gradido account and click on the “My contributions” tab."
},
"contributionConfirmed": {
- "commonGoodContributionConfirmed": "Your public good contribution “{contributionMemo}” has just been confirmed by {senderFirstName} {senderLastName} and credited to your Gradido account.",
- "subject": "Gradido: Your contribution to the common good was confirmed"
+ "commonGoodContributionConfirmed": "Your common good contribution “{contributionMemo}” has just been approved by {senderFirstName} {senderLastName}. Your Gradido account has been credited with {amountGDD} GDD.",
+ "subject": "Your contribution to the common good was confirmed",
+ "title": "Your contribution to the common good was confirmed"
},
"contributionDeleted": {
- "commonGoodContributionDeleted": "Your public good contribution “{contributionMemo}” was deleted by {senderFirstName} {senderLastName}.",
- "subject": "Gradido: Your common good contribution was deleted",
- "toSeeContributionsAndMessages": "To see your common good contributions and related messages, go to the “Creation” menu in your Gradido account and click on the “My contributions” tab!"
+ "commonGoodContributionDeleted": "Your common good contribution “{contributionMemo}” was deleted by {senderFirstName} {senderLastName}.",
+ "subject": "Your common good contribution was deleted",
+ "title": "Your common good contribution was deleted"
},
"contributionDenied": {
- "commonGoodContributionDenied": "Your public good contribution “{contributionMemo}” was rejected by {senderFirstName} {senderLastName}.",
- "subject": "Gradido: Your common good contribution was rejected",
- "toSeeContributionsAndMessages": "To see your common good contributions and related messages, go to the “Creation” menu in your Gradido account and click on the “My contributions” tab!"
+ "commonGoodContributionDenied": "Your common good contribution “{contributionMemo}” was rejected by {senderFirstName} {senderLastName}.",
+ "subject": "Your common good contribution was rejected",
+ "title": "Your common good contribution was rejected"
+ },
+ "footer": {
+ "contactOurSupport": "If you have any further questions, please contact our support.",
+ "imprint": "Impressum",
+ "imprintAddress": "Gradido-Akademie\nInstitut für Wirtschaftsbionik\nPfarrweg 2\n74653 Künzelsau\nDeutschland",
+ "imprintImageAlt": "Gradido-Akademie Logo",
+ "privacyPolicy": "Privacy Policy",
+ "supportEmail": "support@gradido.net"
},
"general": {
"amountGDD": "Amount: {amountGDD} GDD",
- "detailsYouFindOnLinkToYourAccount": "You can find transaction details in your Gradido account:",
- "doNotAnswer": "do not answer",
- "helloName": "Hello {firstName} {lastName}",
- "linkToYourAccount": "Link to your account:",
- "orCopyLink": "or copy the link above into your browser window.",
- "pleaseDoNotReply": "Please do not reply to this email!",
+ "completeRegistration": "Complete registration",
+ "contribution": "Contribution: : {contributionMemo}",
+ "contributionDetails": "Contribution details",
+ "detailsYouFindOnLinkToYourAccount": "You can find transaction details in your Gradido account.",
+ "helloName": "Hello {firstName} {lastName},",
+ "linkValidity": "The link has a validity of {hours} hours.\nIf the validity of the link has already expired, you can have a new link sent to you here.",
+ "linkValidityWithMinutes": "The link has a validity of {hours} hours and {minutes} minutes.\nIf the validity of the link has already expired, you can have a new link sent to you here.",
+ "newLink": "New link",
+ "orCopyLink": "Or copy the link into your browser window.",
+ "pleaseDoNotReply": "Please do not reply to this email.",
+ "requestNewLink": "Request new valid link",
+ "reset": "reset",
"sincerelyYours": "Kind regards,",
+ "toAccount": "To account",
+ "transactionDetails": "Transaction details",
"yourGradidoTeam": "your Gradido team"
},
"resetPassword": {
- "duration": "The link has a validity of {hours} hours and {minutes} minutes. If the validity of the link has already expired, you can have a new link sent to you here:",
- "pleaseClickLink": "If it was you, please click on the link:",
- "subject": "Gradido: Reset password",
+ "pleaseClickLink": "If it was you, please click here.",
+ "subject": "Reset password",
+ "title": "Reset password",
"youOrSomeoneResetPassword": "You, or someone else, requested a password reset for this account."
},
"transactionLinkRedeemed": {
"hasRedeemedYourLink": "{senderFirstName} {senderLastName} ({senderEmail}) has just redeemed your link.",
"memo": "Message: {transactionMemo}",
- "subject": "Gradido: {senderFirstName} {senderLastName} has redeemed your Gradido link"
+ "subject": "{senderFirstName} {senderLastName} has redeemed your Gradido link",
+ "title": "{senderFirstName} {senderLastName} has redeemed your Gradido link"
},
"transactionReceived": {
"haveReceivedAmountGDDFrom": "You have just received {transactionAmount} GDD from {senderFirstName} {senderLastName} ({senderEmail}).",
- "subject": "Gradido: {senderFirstName} {senderLastName} has sent you {transactionAmount} Gradido"
+ "subject": "{senderFirstName} {senderLastName} has sent you {transactionAmount} Gradido",
+ "title": "{senderFirstName} {senderLastName} has sent you {transactionAmount} Gradido"
}
},
"general": {
- "decimalSeparator": ".",
- "imprint": "Gradido-Akademie\nInstitut für Wirtschaftsbionik\nPfarrweg 2\n74653 Künzelsau\nDeutschland",
- "imprintImageAlt": "Gradido-Akademie Logo",
- "imprintImageURL": "https://gdd.gradido.net/img/brand/green.png"
+ "decimalSeparator": "."
}
}
diff --git a/backend/src/password/EncryptorUtils.ts b/backend/src/password/EncryptorUtils.ts
index 827fc9547..64dcb2289 100644
--- a/backend/src/password/EncryptorUtils.ts
+++ b/backend/src/password/EncryptorUtils.ts
@@ -10,8 +10,19 @@ import { CONFIG } from '@/config'
import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
-// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-commonjs
-const sodium = require('sodium-native')
+import {
+ crypto_shorthash_KEYBYTES,
+ crypto_box_SEEDBYTES,
+ crypto_hash_sha512_init,
+ crypto_hash_sha512_update,
+ crypto_hash_sha512_final,
+ crypto_hash_sha512_BYTES,
+ crypto_hash_sha512_STATEBYTES,
+ crypto_shorthash_BYTES,
+ crypto_pwhash_SALTBYTES,
+ crypto_pwhash,
+ crypto_shorthash,
+} from 'sodium-native'
// We will reuse this for changePassword
export const isValidPassword = (password: string): boolean => {
@@ -22,36 +33,36 @@ export const SecretKeyCryptographyCreateKey = (salt: string, password: string):
logger.trace('SecretKeyCryptographyCreateKey...')
const configLoginAppSecret = Buffer.from(CONFIG.LOGIN_APP_SECRET, 'hex')
const configLoginServerKey = Buffer.from(CONFIG.LOGIN_SERVER_KEY, 'hex')
- if (configLoginServerKey.length !== sodium.crypto_shorthash_KEYBYTES) {
+ if (configLoginServerKey.length !== crypto_shorthash_KEYBYTES) {
throw new LogError(
'ServerKey has an invalid size',
configLoginServerKey.length,
- sodium.crypto_shorthash_KEYBYTES,
+ crypto_shorthash_KEYBYTES,
)
}
- const state = Buffer.alloc(sodium.crypto_hash_sha512_STATEBYTES)
- sodium.crypto_hash_sha512_init(state)
- sodium.crypto_hash_sha512_update(state, Buffer.from(salt))
- sodium.crypto_hash_sha512_update(state, configLoginAppSecret)
- const hash = Buffer.alloc(sodium.crypto_hash_sha512_BYTES)
- sodium.crypto_hash_sha512_final(state, hash)
+ const state = Buffer.alloc(crypto_hash_sha512_STATEBYTES)
+ crypto_hash_sha512_init(state)
+ crypto_hash_sha512_update(state, Buffer.from(salt))
+ crypto_hash_sha512_update(state, configLoginAppSecret)
+ const hash = Buffer.alloc(crypto_hash_sha512_BYTES)
+ crypto_hash_sha512_final(state, hash)
- const encryptionKey = Buffer.alloc(sodium.crypto_box_SEEDBYTES)
+ const encryptionKey = Buffer.alloc(crypto_box_SEEDBYTES)
const opsLimit = 10
const memLimit = 33554432
const algo = 2
- sodium.crypto_pwhash(
+ crypto_pwhash(
encryptionKey,
Buffer.from(password),
- hash.slice(0, sodium.crypto_pwhash_SALTBYTES),
+ hash.slice(0, crypto_pwhash_SALTBYTES),
opsLimit,
memLimit,
algo,
)
- const encryptionKeyHash = Buffer.alloc(sodium.crypto_shorthash_BYTES)
- sodium.crypto_shorthash(encryptionKeyHash, encryptionKey, configLoginServerKey)
+ const encryptionKeyHash = Buffer.alloc(crypto_shorthash_BYTES)
+ crypto_shorthash(encryptionKeyHash, encryptionKey, configLoginServerKey)
return [encryptionKeyHash, encryptionKey]
}
diff --git a/backend/yarn.lock b/backend/yarn.lock
index 4d070934b..24537fc57 100644
--- a/backend/yarn.lock
+++ b/backend/yarn.lock
@@ -1181,6 +1181,13 @@
"@types/mime" "^1"
"@types/node" "*"
+"@types/sodium-native@^2.3.5":
+ version "2.3.5"
+ resolved "https://registry.yarnpkg.com/@types/sodium-native/-/sodium-native-2.3.5.tgz#5d2681e7b6b67bcbdc63cfb133e303ec9e942e43"
+ integrity sha512-a3DAIpW8+36XAY8aIR36JBQQsfOabxHuJwx11DL/PTvnbwEWPAXW66b8QbMi0r2vUnkOfREsketxdvjBmQxqDQ==
+ dependencies:
+ "@types/node" "*"
+
"@types/stack-utils@^2.0.0":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
@@ -3645,7 +3652,7 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0:
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
"gradido-database@file:../database":
- version "1.20.0"
+ version "1.21.0"
dependencies:
"@types/uuid" "^8.3.4"
cross-env "^7.0.3"
diff --git a/database/.eslintrc.js b/database/.eslintrc.js
index f0d1ae1e3..1547b6867 100644
--- a/database/.eslintrc.js
+++ b/database/.eslintrc.js
@@ -101,43 +101,43 @@ module.exports = {
// ],
'import/prefer-default-export': 'off',
// n
- // 'n/handle-callback-err': 'error',
- // 'n/no-callback-literal': 'error',
- // 'n/no-exports-assign': 'error',
+ 'n/handle-callback-err': 'error',
+ 'n/no-callback-literal': 'error',
+ 'n/no-exports-assign': 'error',
// 'n/no-extraneous-import': 'error',
- // 'n/no-extraneous-require': 'error',
- // 'n/no-hide-core-modules': 'error',
- // 'n/no-missing-import': 'off', // not compatible with typescript
- // 'n/no-missing-require': 'error',
- // 'n/no-new-require': 'error',
- // 'n/no-path-concat': 'error',
+ 'n/no-extraneous-require': 'error',
+ 'n/no-hide-core-modules': 'error',
+ 'n/no-missing-import': 'off', // not compatible with typescript
+ 'n/no-missing-require': 'error',
+ 'n/no-new-require': 'error',
+ 'n/no-path-concat': 'error',
// 'n/no-process-exit': 'error',
- // 'n/no-unpublished-bin': 'error',
- // 'n/no-unpublished-import': 'off', // TODO need to exclude seeds
- // 'n/no-unpublished-require': 'error',
- // 'n/no-unsupported-features': ['error', { ignores: ['modules'] }],
- // 'n/no-unsupported-features/es-builtins': 'error',
- // 'n/no-unsupported-features/es-syntax': 'error',
- // 'n/no-unsupported-features/node-builtins': 'error',
- // 'n/process-exit-as-throw': 'error',
- // 'n/shebang': 'error',
- // 'n/callback-return': 'error',
- // 'n/exports-style': 'error',
- // 'n/file-extension-in-import': 'off',
- // 'n/global-require': 'error',
- // 'n/no-mixed-requires': 'error',
- // 'n/no-process-env': 'error',
- // 'n/no-restricted-import': 'error',
- // 'n/no-restricted-require': 'error',
+ 'n/no-unpublished-bin': 'error',
+ 'n/no-unpublished-import': 'off', // TODO need to exclude seeds
+ 'n/no-unpublished-require': 'error',
+ 'n/no-unsupported-features': ['error', { ignores: ['modules'] }],
+ 'n/no-unsupported-features/es-builtins': 'error',
+ 'n/no-unsupported-features/es-syntax': 'error',
+ 'n/no-unsupported-features/node-builtins': 'error',
+ 'n/process-exit-as-throw': 'error',
+ 'n/shebang': 'error',
+ 'n/callback-return': 'error',
+ 'n/exports-style': 'error',
+ 'n/file-extension-in-import': 'off',
+ 'n/global-require': 'error',
+ 'n/no-mixed-requires': 'error',
+ 'n/no-process-env': 'error',
+ 'n/no-restricted-import': 'error',
+ 'n/no-restricted-require': 'error',
// 'n/no-sync': 'error',
- // 'n/prefer-global/buffer': 'error',
- // 'n/prefer-global/console': 'error',
- // 'n/prefer-global/process': 'error',
- // 'n/prefer-global/text-decoder': 'error',
- // 'n/prefer-global/text-encoder': 'error',
- // 'n/prefer-global/url': 'error',
- // 'n/prefer-global/url-search-params': 'error',
- // 'n/prefer-promises/dns': 'error',
+ 'n/prefer-global/buffer': 'error',
+ 'n/prefer-global/console': 'error',
+ 'n/prefer-global/process': 'error',
+ 'n/prefer-global/text-decoder': 'error',
+ 'n/prefer-global/text-encoder': 'error',
+ 'n/prefer-global/url': 'error',
+ 'n/prefer-global/url-search-params': 'error',
+ 'n/prefer-promises/dns': 'error',
// 'n/prefer-promises/fs': 'error',
// promise
// 'promise/catch-or-return': 'error',
diff --git a/database/package.json b/database/package.json
index 65b76ca14..abc69d21d 100644
--- a/database/package.json
+++ b/database/package.json
@@ -48,5 +48,8 @@
"ts-mysql-migrate": "^1.0.2",
"typeorm": "^0.2.38",
"uuid": "^8.3.2"
+ },
+ "engines": {
+ "node": ">=14"
}
}
diff --git a/database/src/config/index.ts b/database/src/config/index.ts
index 4840f3f86..0fc8cf9c5 100644
--- a/database/src/config/index.ts
+++ b/database/src/config/index.ts
@@ -1,4 +1,4 @@
-// ATTENTION: DO NOT PUT ANY SECRETS IN HERE (or the .env)
+/* eslint-disable n/no-process-env */
import dotenv from 'dotenv'
diff --git a/frontend/public/img/brand/gradido-email-header.png b/frontend/public/img/brand/gradido-email-header.png
new file mode 100644
index 000000000..b7fa83b92
Binary files /dev/null and b/frontend/public/img/brand/gradido-email-header.png differ