diff --git a/admin/src/graphql/searchUsers.js b/admin/src/graphql/searchUsers.js index 3e33fe96b..15fb8da32 100644 --- a/admin/src/graphql/searchUsers.js +++ b/admin/src/graphql/searchUsers.js @@ -1,12 +1,19 @@ import gql from 'graphql-tag' export const searchUsers = gql` - query ($searchText: String!, $currentPage: Int, $pageSize: Int, $filters: SearchUsersFilters) { + query ( + $query: String! + $filters: SearchUsersFilters + $currentPage: Int = 0 + $pageSize: Int = 25 + $order: Order = ASC + ) { searchUsers( - searchText: $searchText + query: $query + filters: $filters currentPage: $currentPage pageSize: $pageSize - filters: $filters + order: $order ) { userCount userList { diff --git a/admin/src/pages/UserSearch.spec.js b/admin/src/pages/UserSearch.spec.js index 0d145cb89..1f9b0ce6e 100644 --- a/admin/src/pages/UserSearch.spec.js +++ b/admin/src/pages/UserSearch.spec.js @@ -10,11 +10,20 @@ const apolloQueryMock = jest.fn().mockResolvedValue({ userCount: 4, userList: [ { - userId: 1, - firstName: 'Bibi', - lastName: 'Bloxberg', - email: 'bibi@bloxberg.de', - creation: [200, 400, 600], + userId: 4, + firstName: 'New', + lastName: 'User', + email: 'new@user.ch', + creation: [1000, 1000, 1000], + emailChecked: false, + deletedAt: null, + }, + { + userId: 3, + firstName: 'Peter', + lastName: 'Lustig', + email: 'peter@lustig.de', + creation: [0, 0, 0], emailChecked: true, deletedAt: null, }, @@ -28,23 +37,14 @@ const apolloQueryMock = jest.fn().mockResolvedValue({ deletedAt: new Date(), }, { - userId: 3, - firstName: 'Peter', - lastName: 'Lustig', - email: 'peter@lustig.de', - creation: [0, 0, 0], + userId: 1, + firstName: 'Bibi', + lastName: 'Bloxberg', + email: 'bibi@bloxberg.de', + creation: [200, 400, 600], emailChecked: true, deletedAt: null, }, - { - userId: 4, - firstName: 'New', - lastName: 'User', - email: 'new@user.ch', - creation: [1000, 1000, 1000], - emailChecked: false, - deletedAt: null, - }, ], }, }, @@ -79,9 +79,10 @@ describe('UserSearch', () => { expect(apolloQueryMock).toBeCalledWith( expect.objectContaining({ variables: { - searchText: '', + query: '', currentPage: 1, pageSize: 25, + order: 'DESC', filters: { byActivated: null, byDeleted: null, @@ -100,9 +101,10 @@ describe('UserSearch', () => { expect(apolloQueryMock).toBeCalledWith( expect.objectContaining({ variables: { - searchText: '', + query: '', currentPage: 1, pageSize: 25, + order: 'DESC', filters: { byActivated: false, byDeleted: null, @@ -122,9 +124,10 @@ describe('UserSearch', () => { expect(apolloQueryMock).toBeCalledWith( expect.objectContaining({ variables: { - searchText: '', + query: '', currentPage: 1, pageSize: 25, + order: 'DESC', filters: { byActivated: null, byDeleted: true, @@ -144,9 +147,10 @@ describe('UserSearch', () => { expect(apolloQueryMock).toBeCalledWith( expect.objectContaining({ variables: { - searchText: '', + query: '', currentPage: 2, pageSize: 25, + order: 'DESC', filters: { byActivated: null, byDeleted: null, @@ -166,9 +170,10 @@ describe('UserSearch', () => { expect(apolloQueryMock).toBeCalledWith( expect.objectContaining({ variables: { - searchText: 'search string', + query: 'search string', currentPage: 1, pageSize: 25, + order: 'DESC', filters: { byActivated: null, byDeleted: null, @@ -185,9 +190,10 @@ describe('UserSearch', () => { expect(apolloQueryMock).toBeCalledWith( expect.objectContaining({ variables: { - searchText: '', + query: '', currentPage: 1, pageSize: 25, + order: 'DESC', filters: { byActivated: null, byDeleted: null, diff --git a/admin/src/pages/UserSearch.vue b/admin/src/pages/UserSearch.vue index 8f24181ee..d4e4083c2 100644 --- a/admin/src/pages/UserSearch.vue +++ b/admin/src/pages/UserSearch.vue @@ -49,7 +49,7 @@ pills size="lg" v-model="currentPage" - per-page="perPage" + :per-page="perPage" :total-rows="rows" align="center" :hide-ellipsis="true" @@ -97,10 +97,11 @@ export default { .query({ query: searchUsers, variables: { - searchText: this.criteria, + query: this.criteria, + filters: this.filters, currentPage: this.currentPage, pageSize: this.perPage, - filters: this.filters, + order: 'DESC', }, fetchPolicy: 'no-cache', }) 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/config/index.ts b/backend/src/config/index.ts index 8d1ed8ae6..70830359f 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -12,7 +12,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0066-x-community-sendcoins-transactions_table', + DB_VERSION: '0067-private_key_in_community_table', DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info 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`] = ` +" + + + + + + + + +
+
+
\\"Gradido
+
+
+

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`] = ` +" + + + + + + + + +
+
+
\\"Gradido
+
+
+

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`] = ` +" + + + + + + + + +
+
+
\\"Gradido
+
+
+

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`] = ` +" + + + + + + + + +
+
+
\\"Gradido
+
+
+

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`] = ` +" + + + + + + + + +
+
+
\\"Gradido
+
+
+

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`] = ` +" + + + + + + + + +
+
+
\\"Gradido
+
+
+

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`] = ` +" + + + + + + + + +
+
+
\\"Gradido
+
+
+

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`] = ` +" + + + + + + + + +
+
+
\\"Gradido
+
+
+

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`] = ` +" + + + + + + + + +
+
+
\\"Gradido
+
+
+

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 Logo

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 Logo

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 Logo

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 Logo

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 Logo

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 Logo

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 Logo

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 Logo

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 Logo

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/arg/SearchUsersArgs.ts b/backend/src/graphql/arg/SearchUsersArgs.ts deleted file mode 100644 index 0ebc442c3..000000000 --- a/backend/src/graphql/arg/SearchUsersArgs.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ArgsType, Field, Int } from 'type-graphql' - -import { SearchUsersFilters } from '@arg/SearchUsersFilters' - -@ArgsType() -export class SearchUsersArgs { - @Field(() => String) - searchText: string - - @Field(() => Int, { nullable: true }) - // eslint-disable-next-line type-graphql/invalid-nullable-input-type - currentPage?: number - - @Field(() => Int, { nullable: true }) - // eslint-disable-next-line type-graphql/invalid-nullable-input-type - pageSize?: number - - // eslint-disable-next-line type-graphql/wrong-decorator-signature - @Field(() => SearchUsersFilters, { nullable: true, defaultValue: null }) - filters?: SearchUsersFilters | null -} diff --git a/backend/src/graphql/model/KlickTipp.ts b/backend/src/graphql/model/KlickTipp.ts index 059c7874d..356ed391f 100644 --- a/backend/src/graphql/model/KlickTipp.ts +++ b/backend/src/graphql/model/KlickTipp.ts @@ -1,12 +1,9 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import { ObjectType, Field } from 'type-graphql' @ObjectType() export class KlickTipp { - constructor(json: any) { - this.newsletterState = json.status === 'Subscribed' + constructor(newsletterState: boolean) { + this.newsletterState = newsletterState } @Field(() => Boolean) diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts index 25787490f..0384b64c5 100644 --- a/backend/src/graphql/resolver/UserResolver.test.ts +++ b/backend/src/graphql/resolver/UserResolver.test.ts @@ -2110,7 +2110,7 @@ describe('UserResolver', () => { describe('search users', () => { const variablesWithoutTextAndFilters = { - searchText: '', + query: '', currentPage: 1, pageSize: 25, filters: null, diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 9934c93de..9df6b861b 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -8,22 +8,12 @@ import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink' import { User as DbUser } from '@entity/User' import { UserContact as DbUserContact } from '@entity/UserContact' import i18n from 'i18n' -import { - Resolver, - Query, - Args, - Arg, - Authorized, - Ctx, - UseMiddleware, - Mutation, - Int, -} from 'type-graphql' +import { Resolver, Query, Args, Arg, Authorized, Ctx, Mutation, Int } from 'type-graphql' import { v4 as uuidv4 } from 'uuid' import { CreateUserArgs } from '@arg/CreateUserArgs' import { Paginated } from '@arg/Paginated' -import { SearchUsersArgs } from '@arg/SearchUsersArgs' +import { SearchUsersFilters } from '@arg/SearchUsersFilters' import { UnsecureLoginArgs } from '@arg/UnsecureLoginArgs' import { UpdateUserInfosArgs } from '@arg/UpdateUserInfosArgs' import { OptInType } from '@enum/OptInType' @@ -60,7 +50,6 @@ import { EVENT_ADMIN_USER_DELETE, EVENT_ADMIN_USER_UNDELETE, } from '@/event/Events' -import { klicktippNewsletterStateMiddleware } from '@/middleware/klicktippMiddleware' import { isValidPassword } from '@/password/EncryptorUtils' import { encryptPassword, verifyPassword } from '@/password/PasswordEncryptor' import { Context, getUser, getClientTimezoneOffset } from '@/server/context' @@ -71,15 +60,14 @@ 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 { getKlicktippState } from './util/getKlicktippState' 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 => { @@ -122,7 +110,6 @@ const newGradidoID = async (): Promise => { export class UserResolver { @Authorized([RIGHTS.VERIFY_LOGIN]) @Query(() => User) - @UseMiddleware(klicktippNewsletterStateMiddleware) async verifyLogin(@Ctx() context: Context): Promise { logger.info('verifyLogin...') // TODO refactor and do not have duplicate code with login(see below) @@ -132,12 +119,12 @@ export class UserResolver { user.hasElopage = await this.hasElopage(context) logger.debug(`verifyLogin... successful: ${user.firstName}.${user.lastName}`) + user.klickTipp = await getKlicktippState(userEntity.emailContact.email) return user } @Authorized([RIGHTS.LOGIN]) @Mutation(() => User) - @UseMiddleware(klicktippNewsletterStateMiddleware) async login( @Args() { email, password, publisherId }: UnsecureLoginArgs, @Ctx() context: Context, @@ -183,6 +170,7 @@ export class UserResolver { dbUser.publisherId = publisherId await DbUser.save(dbUser) } + user.klickTipp = await getKlicktippState(dbUser.emailContact.email) context.setHeaders.push({ key: 'token', @@ -237,7 +225,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 @@ -640,8 +628,11 @@ export class UserResolver { @Authorized([RIGHTS.SEARCH_USERS]) @Query(() => SearchUsersResult) async searchUsers( + @Arg('query', () => String) query: string, + @Arg('filters', () => SearchUsersFilters, { nullable: true }) + filters: SearchUsersFilters | null | undefined, @Args() - { searchText, currentPage = 1, pageSize = 25, filters }: SearchUsersArgs, + { currentPage = 1, pageSize = 25, order = Order.ASC }: Paginated, @Ctx() context: Context, ): Promise { const clientTimezoneOffset = getClientTimezoneOffset(context) @@ -659,15 +650,16 @@ export class UserResolver { userFields.map((fieldName) => { return 'user.' + fieldName }), - searchText, + query, filters ?? null, currentPage, pageSize, + order, ) if (users.length === 0) { return { - userCount: 0, + userCount: count, userList: [], } } diff --git a/backend/src/graphql/resolver/util/getKlicktippState.ts b/backend/src/graphql/resolver/util/getKlicktippState.ts new file mode 100644 index 000000000..728f565ff --- /dev/null +++ b/backend/src/graphql/resolver/util/getKlicktippState.ts @@ -0,0 +1,19 @@ +/* eslint-disable @typescript-eslint/no-unsafe-return */ +import { KlickTipp } from '@model/KlickTipp' + +import { getKlickTippUser } from '@/apis/KlicktippController' +import { klickTippLogger as logger } from '@/server/logger' + +export const getKlicktippState = async (email: string): Promise => { + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const klickTippUser = await getKlickTippUser(email) + if (klickTippUser) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + return new KlickTipp(klickTippUser.status === 'Subscribed') + } + } catch (err) { + logger.error('There is no klicktipp user for email', email, err) + } + return new KlickTipp(false) +} 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/middleware/klicktippMiddleware.ts b/backend/src/middleware/klicktippMiddleware.ts deleted file mode 100644 index 038bd3dd3..000000000 --- a/backend/src/middleware/klicktippMiddleware.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-return */ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ -/* eslint-disable @typescript-eslint/restrict-template-expressions */ -/* eslint-disable @typescript-eslint/no-unsafe-argument */ -import { MiddlewareFn } from 'type-graphql' - -import { KlickTipp } from '@model/KlickTipp' - -import { getKlickTippUser } from '@/apis/KlicktippController' -import { klickTippLogger as logger } from '@/server/logger' - -export const klicktippNewsletterStateMiddleware: MiddlewareFn = async ( - /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ - { root, args, context, info }, - next, -) => { - // eslint-disable-next-line n/callback-return - const result = await next() - let klickTipp = new KlickTipp({ status: 'Unsubscribed' }) - try { - const klickTippUser = await getKlickTippUser(result.email) - if (klickTippUser) { - klickTipp = new KlickTipp(klickTippUser) - } - } catch (err) { - logger.error(`There is no user for (email='${result.email}') ${err}`) - } - result.klickTipp = klickTipp - return result -} 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/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index ce7efbfc3..a964cdb3a 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -69,12 +69,19 @@ export const sendResetPasswordEmail = gql` ` export const searchUsers = gql` - query ($searchText: String!, $currentPage: Int, $pageSize: Int, $filters: SearchUsersFilters) { + query ( + $query: String! + $filters: SearchUsersFilters + $currentPage: Int = 1 + $pageSize: Int = 25 + $order: Order = ASC + ) { searchUsers( - searchText: $searchText + query: $query + filters: $filters currentPage: $currentPage pageSize: $pageSize - filters: $filters + order: $order ) { userCount userList { diff --git a/backend/src/typeorm/repository/User.ts b/backend/src/typeorm/repository/User.ts index 53273102d..f54859f41 100644 --- a/backend/src/typeorm/repository/User.ts +++ b/backend/src/typeorm/repository/User.ts @@ -1,7 +1,8 @@ import { Brackets, EntityRepository, IsNull, Not, Repository } from '@dbTools/typeorm' import { User as DbUser } from '@entity/User' -import { SearchUsersFilters } from '@/graphql/arg/SearchUsersFilters' +import { SearchUsersFilters } from '@arg/SearchUsersFilters' +import { Order } from '@enum/Order' @EntityRepository(DbUser) export class UserRepository extends Repository { @@ -11,6 +12,7 @@ export class UserRepository extends Repository { filters: SearchUsersFilters | null, currentPage: number, pageSize: number, + order = Order.ASC, ): Promise<[DbUser[], number]> { const query = this.createQueryBuilder('user') .select(select) @@ -46,6 +48,7 @@ export class UserRepository extends Repository { } return query + .orderBy({ 'user.id': order }) .take(pageSize) .skip((currentPage - 1) * pageSize) .getManyAndCount() 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 587506ecc..6f1db58ff 100644 --- a/database/.eslintrc.js +++ b/database/.eslintrc.js @@ -10,10 +10,10 @@ module.exports = { 'standard', 'eslint:recommended', 'plugin:prettier/recommended', - // 'plugin:import/recommended', - // 'plugin:import/typescript', + 'plugin:import/recommended', + 'plugin:import/typescript', // 'plugin:security/recommended', - // 'plugin:@eslint-community/eslint-comments/recommended', + 'plugin:@eslint-community/eslint-comments/recommended', ], settings: { 'import/parsers': { @@ -37,107 +37,107 @@ module.exports = { }, ], // import - // 'import/export': 'error', - // 'import/no-deprecated': 'error', - // 'import/no-empty-named-blocks': 'error', + 'import/export': 'error', + 'import/no-deprecated': 'error', + 'import/no-empty-named-blocks': 'error', // 'import/no-extraneous-dependencies': 'error', - // 'import/no-mutable-exports': 'error', - // 'import/no-unused-modules': 'error', - // 'import/no-named-as-default': 'error', - // 'import/no-named-as-default-member': 'error', - // 'import/no-amd': 'error', - // 'import/no-commonjs': 'error', - // 'import/no-import-module-exports': 'error', - // 'import/no-nodejs-modules': 'off', - // 'import/unambiguous': 'error', - // 'import/default': 'error', - // 'import/named': 'error', - // 'import/namespace': 'error', - // 'import/no-absolute-path': 'error', + 'import/no-mutable-exports': 'error', + 'import/no-unused-modules': 'error', + 'import/no-named-as-default': 'error', + 'import/no-named-as-default-member': 'error', + 'import/no-amd': 'error', + 'import/no-commonjs': 'error', + 'import/no-import-module-exports': 'error', + 'import/no-nodejs-modules': 'off', + 'import/unambiguous': 'error', + 'import/default': 'error', + 'import/named': 'error', + 'import/namespace': 'error', + 'import/no-absolute-path': 'error', // 'import/no-cycle': 'error', - // 'import/no-dynamic-require': 'error', - // 'import/no-internal-modules': 'off', - // 'import/no-relative-packages': 'error', + 'import/no-dynamic-require': 'error', + 'import/no-internal-modules': 'off', + 'import/no-relative-packages': 'error', // 'import/no-relative-parent-imports': ['error', { ignore: ['@/*'] }], - // 'import/no-self-import': 'error', - // 'import/no-unresolved': 'error', - // 'import/no-useless-path-segments': 'error', - // 'import/no-webpack-loader-syntax': 'error', - // 'import/consistent-type-specifier-style': 'error', - // 'import/exports-last': 'off', - // 'import/extensions': 'error', - // 'import/first': 'error', - // 'import/group-exports': 'off', - // 'import/newline-after-import': 'error', - // 'import/no-anonymous-default-export': 'error', - // 'import/no-default-export': 'error', - // 'import/no-duplicates': 'error', - // 'import/no-named-default': 'error', - // 'import/no-namespace': 'error', - // 'import/no-unassigned-import': 'error', + 'import/no-self-import': 'error', + 'import/no-unresolved': 'error', + 'import/no-useless-path-segments': 'error', + 'import/no-webpack-loader-syntax': 'error', + 'import/consistent-type-specifier-style': 'error', + 'import/exports-last': 'off', + 'import/extensions': 'error', + 'import/first': 'error', + 'import/group-exports': 'off', + 'import/newline-after-import': 'error', + 'import/no-anonymous-default-export': 'error', + 'import/no-default-export': 'error', + 'import/no-duplicates': 'error', + 'import/no-named-default': 'error', + 'import/no-namespace': 'error', + 'import/no-unassigned-import': 'error', // 'import/order': [ - // 'error', - // { - // groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'], - // 'newlines-between': 'always', - // pathGroups: [ - // { - // pattern: '@?*/**', - // group: 'external', - // position: 'after', - // }, - // { - // pattern: '@/**', - // group: 'external', - // position: 'after', - // }, - // ], - // alphabetize: { - // order: 'asc' /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */, - // caseInsensitive: true /* ignore case. Options: [true, false] */, + // 'error', + // { + // groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'], + // 'newlines-between': 'always', + // pathGroups: [ + // { + // pattern: '@?*/**', + // group: 'external', + // position: 'after', + // }, + // { + // pattern: '@/**', + // group: 'external', + // position: 'after', + // }, + // ], + // alphabetize: { + // order: 'asc' /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */, + // caseInsensitive: true /* ignore case. Options: [true, false] */, // }, // distinctGroup: true, // }, // ], - // 'import/prefer-default-export': 'off', + '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', @@ -155,10 +155,10 @@ module.exports = { // 'promise/prefer-await-to-callbacks': 'error', // 'promise/no-multiple-resolved': 'error', // eslint comments - // '@eslint-community/eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }], - // '@eslint-community/eslint-comments/no-restricted-disable': 'error', - // '@eslint-community/eslint-comments/no-use': 'off', - // '@eslint-community/eslint-comments/require-description': 'off', + '@eslint-community/eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }], + '@eslint-community/eslint-comments/no-restricted-disable': 'error', + '@eslint-community/eslint-comments/no-use': 'off', + '@eslint-community/eslint-comments/require-description': 'off', }, overrides: [ // only for ts files diff --git a/database/entity/0002-add_settings/User.ts b/database/entity/0002-add_settings/User.ts index 4f333fd50..c26602cd5 100644 --- a/database/entity/0002-add_settings/User.ts +++ b/database/entity/0002-add_settings/User.ts @@ -1,5 +1,5 @@ import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm' -import { UserSetting } from '../0002-add_settings/UserSetting' +import { UserSetting } from './UserSetting' // Moriz: I do not like the idea of having two user tables @Entity('state_users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' }) diff --git a/database/entity/0028-decimal_types/Transaction.ts b/database/entity/0028-decimal_types/Transaction.ts index 9352e6335..6c08fe3c0 100644 --- a/database/entity/0028-decimal_types/Transaction.ts +++ b/database/entity/0028-decimal_types/Transaction.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' diff --git a/database/entity/0029-clean_transaction_table/Transaction.ts b/database/entity/0029-clean_transaction_table/Transaction.ts index 5931c153f..f253b9d58 100644 --- a/database/entity/0029-clean_transaction_table/Transaction.ts +++ b/database/entity/0029-clean_transaction_table/Transaction.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' diff --git a/database/entity/0030-transaction_link/TransactionLink.ts b/database/entity/0030-transaction_link/TransactionLink.ts index 177f23561..59179c3be 100644 --- a/database/entity/0030-transaction_link/TransactionLink.ts +++ b/database/entity/0030-transaction_link/TransactionLink.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, DeleteDateColumn } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' diff --git a/database/entity/0031-remove_sendEmail_from_transaction_link/TransactionLink.ts b/database/entity/0031-remove_sendEmail_from_transaction_link/TransactionLink.ts index 9cd42258a..6c8edf30f 100644 --- a/database/entity/0031-remove_sendEmail_from_transaction_link/TransactionLink.ts +++ b/database/entity/0031-remove_sendEmail_from_transaction_link/TransactionLink.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, DeleteDateColumn } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' diff --git a/database/entity/0032-add-transaction-link-to-transaction/Transaction.ts b/database/entity/0032-add-transaction-link-to-transaction/Transaction.ts index 398fa03db..e9e206e14 100644 --- a/database/entity/0032-add-transaction-link-to-transaction/Transaction.ts +++ b/database/entity/0032-add-transaction-link-to-transaction/Transaction.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' diff --git a/database/entity/0035-admin_pending_creations_decimal/AdminPendingCreation.ts b/database/entity/0035-admin_pending_creations_decimal/AdminPendingCreation.ts index 3cd83a3a5..f2d0d1386 100644 --- a/database/entity/0035-admin_pending_creations_decimal/AdminPendingCreation.ts +++ b/database/entity/0035-admin_pending_creations_decimal/AdminPendingCreation.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' diff --git a/database/entity/0036-unique_previous_in_transactions/Transaction.ts b/database/entity/0036-unique_previous_in_transactions/Transaction.ts index 3b6baf47a..2f2899429 100644 --- a/database/entity/0036-unique_previous_in_transactions/Transaction.ts +++ b/database/entity/0036-unique_previous_in_transactions/Transaction.ts @@ -1,5 +1,5 @@ /* eslint-disable no-use-before-define */ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' import { Contribution } from '../Contribution' diff --git a/database/entity/0038-add_contribution_links_table/ContributionLink.ts b/database/entity/0038-add_contribution_links_table/ContributionLink.ts index 496f57d71..3d79e84fd 100644 --- a/database/entity/0038-add_contribution_links_table/ContributionLink.ts +++ b/database/entity/0038-add_contribution_links_table/ContributionLink.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, DeleteDateColumn } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' diff --git a/database/entity/0039-contributions_table/Contribution.ts b/database/entity/0039-contributions_table/Contribution.ts index b5e6ac0e0..7b0abd29a 100644 --- a/database/entity/0039-contributions_table/Contribution.ts +++ b/database/entity/0039-contributions_table/Contribution.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Column, diff --git a/database/entity/0043-add_event_protocol_table/EventProtocol.ts b/database/entity/0043-add_event_protocol_table/EventProtocol.ts index 72470d2ed..13eebcce5 100644 --- a/database/entity/0043-add_event_protocol_table/EventProtocol.ts +++ b/database/entity/0043-add_event_protocol_table/EventProtocol.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' diff --git a/database/entity/0045-add_denied_type_and_status_to_contributions/Contribution.ts b/database/entity/0045-add_denied_type_and_status_to_contributions/Contribution.ts index c376ae53e..21300fd4d 100644 --- a/database/entity/0045-add_denied_type_and_status_to_contributions/Contribution.ts +++ b/database/entity/0045-add_denied_type_and_status_to_contributions/Contribution.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Column, diff --git a/database/entity/0047-messages_tables/Contribution.ts b/database/entity/0047-messages_tables/Contribution.ts index 1ba31bb88..323bf91b6 100644 --- a/database/entity/0047-messages_tables/Contribution.ts +++ b/database/entity/0047-messages_tables/Contribution.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Column, diff --git a/database/entity/0050-add_messageId_to_event_protocol/EventProtocol.ts b/database/entity/0050-add_messageId_to_event_protocol/EventProtocol.ts index e457cc0a3..ca7d27069 100644 --- a/database/entity/0050-add_messageId_to_event_protocol/EventProtocol.ts +++ b/database/entity/0050-add_messageId_to_event_protocol/EventProtocol.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' diff --git a/database/entity/0051-add_delete_by_to_contributions/Contribution.ts b/database/entity/0051-add_delete_by_to_contributions/Contribution.ts index 32c6f32a3..8e8d0d172 100644 --- a/database/entity/0051-add_delete_by_to_contributions/Contribution.ts +++ b/database/entity/0051-add_delete_by_to_contributions/Contribution.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Column, diff --git a/database/entity/0052-add_updated_at_to_contributions/Contribution.ts b/database/entity/0052-add_updated_at_to_contributions/Contribution.ts index 4676c14af..941e9da38 100644 --- a/database/entity/0052-add_updated_at_to_contributions/Contribution.ts +++ b/database/entity/0052-add_updated_at_to_contributions/Contribution.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Column, diff --git a/database/entity/0061-event_refactoring/Event.ts b/database/entity/0061-event_refactoring/Event.ts index ab75c2d94..a2fbf0adf 100644 --- a/database/entity/0061-event_refactoring/Event.ts +++ b/database/entity/0061-event_refactoring/Event.ts @@ -2,7 +2,7 @@ import { Contribution } from '../Contribution' import { ContributionMessage } from '../ContributionMessage' import { User } from '../User' import { Transaction } from '../Transaction' -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Entity, diff --git a/database/entity/0063-event_link_fields/Event.ts b/database/entity/0063-event_link_fields/Event.ts index dc7fa776c..40f1ea7c0 100644 --- a/database/entity/0063-event_link_fields/Event.ts +++ b/database/entity/0063-event_link_fields/Event.ts @@ -2,7 +2,7 @@ import { Contribution } from '../Contribution' import { ContributionMessage } from '../ContributionMessage' import { User } from '../User' import { Transaction } from '../Transaction' -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Entity, diff --git a/database/entity/0066-x-community-sendcoins-transactions_table/Transaction.ts b/database/entity/0066-x-community-sendcoins-transactions_table/Transaction.ts index 319bd81de..105972310 100644 --- a/database/entity/0066-x-community-sendcoins-transactions_table/Transaction.ts +++ b/database/entity/0066-x-community-sendcoins-transactions_table/Transaction.ts @@ -1,5 +1,5 @@ /* eslint-disable no-use-before-define */ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' import { Contribution } from '../Contribution' diff --git a/database/entity/0067-private_key_in_community_table/Community.ts b/database/entity/0067-private_key_in_community_table/Community.ts new file mode 100644 index 000000000..dcb55c875 --- /dev/null +++ b/database/entity/0067-private_key_in_community_table/Community.ts @@ -0,0 +1,63 @@ +import { + BaseEntity, + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, +} from 'typeorm' + +@Entity('communities') +export class Community extends BaseEntity { + @PrimaryGeneratedColumn('increment', { unsigned: true }) + id: number + + @Column({ name: 'foreign', type: 'bool', nullable: false, default: true }) + foreign: boolean + + @Column({ name: 'url', length: 255, nullable: false }) + url: string + + @Column({ name: 'public_key', type: 'binary', length: 64, nullable: false }) + publicKey: Buffer + + @Column({ name: 'private_key', type: 'binary', length: 64, nullable: true }) + privateKey: Buffer | null + + @Column({ + name: 'community_uuid', + type: 'char', + length: 36, + nullable: true, + collation: 'utf8mb4_unicode_ci', + }) + communityUuid: string | null + + @Column({ name: 'authenticated_at', type: 'datetime', nullable: true }) + authenticatedAt: Date | null + + @Column({ name: 'name', type: 'varchar', length: 40, nullable: true }) + name: string | null + + @Column({ name: 'description', type: 'varchar', length: 255, nullable: true }) + description: string | null + + @CreateDateColumn({ name: 'creation_date', type: 'datetime', nullable: true }) + creationDate: Date | null + + @CreateDateColumn({ + name: 'created_at', + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP(3)', + nullable: false, + }) + createdAt: Date + + @UpdateDateColumn({ + name: 'updated_at', + type: 'datetime', + onUpdate: 'CURRENT_TIMESTAMP(3)', + nullable: true, + }) + updatedAt: Date | null +} diff --git a/database/entity/Community.ts b/database/entity/Community.ts index ee08323b6..5df0f70fe 100644 --- a/database/entity/Community.ts +++ b/database/entity/Community.ts @@ -1 +1 @@ -export { Community } from './0065-refactor_communities_table/Community' +export { Community } from './0067-private_key_in_community_table/Community' diff --git a/database/migrations/0028-decimal_types.ts b/database/migrations/0028-decimal_types.ts index e79d120a8..742a370ba 100644 --- a/database/migrations/0028-decimal_types.ts +++ b/database/migrations/0028-decimal_types.ts @@ -20,9 +20,8 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable no-unused-vars */ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' // Set precision value Decimal.set({ @@ -41,11 +40,13 @@ interface Decay { duration: number | null } +/* eslint-disable no-unused-vars */ export enum TransactionTypeId { CREATION = 1, SEND = 2, RECEIVE = 3, } +/* eslint-enable no-unused-vars */ function decayFormula(value: Decimal, seconds: number): Decimal { return value.mul(new Decimal('0.99999997803504048973201202316767079413460520837376').pow(seconds)) diff --git a/database/migrations/0054-recalculate_balance_and_decay.ts b/database/migrations/0054-recalculate_balance_and_decay.ts index b2add3a58..7c567c36a 100644 --- a/database/migrations/0054-recalculate_balance_and_decay.ts +++ b/database/migrations/0054-recalculate_balance_and_decay.ts @@ -15,7 +15,7 @@ /* eslint-disable no-unused-vars */ import fs from 'fs' -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' // Set precision value Decimal.set({ @@ -156,6 +156,5 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis } } -/* eslint-disable @typescript-eslint/no-empty-function */ -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ +/* eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function */ export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) {} diff --git a/database/migrations/0055-consistent_deleted_users.ts b/database/migrations/0055-consistent_deleted_users.ts index 561e0541a..93d5cb575 100644 --- a/database/migrations/0055-consistent_deleted_users.ts +++ b/database/migrations/0055-consistent_deleted_users.ts @@ -11,6 +11,5 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis AND users.deleted_at IS NOT NULL;`) } -/* eslint-disable @typescript-eslint/no-empty-function */ -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ +/* eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function */ export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) {} diff --git a/database/migrations/0056-consistent_transactions_table.ts b/database/migrations/0056-consistent_transactions_table.ts index 02ed3b7be..0d8721f07 100644 --- a/database/migrations/0056-consistent_transactions_table.ts +++ b/database/migrations/0056-consistent_transactions_table.ts @@ -34,6 +34,5 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis } } -/* eslint-disable @typescript-eslint/no-empty-function */ -/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ +/* eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function */ export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) {} diff --git a/database/migrations/0067-private_key_in_community_table.ts b/database/migrations/0067-private_key_in_community_table.ts new file mode 100644 index 000000000..f36e68b16 --- /dev/null +++ b/database/migrations/0067-private_key_in_community_table.ts @@ -0,0 +1,17 @@ +/* MIGRATION TO ADD PRIVATE KEY IN COMMUNITY TABLE + * + * This migration adds a field for the private key in the community.table + */ + +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn( + 'ALTER TABLE `communities` ADD COLUMN `private_key` binary(64) DEFAULT NULL AFTER `public_key`;', + ) +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('ALTER TABLE `communities` DROP COLUMN `private_key`;') +} 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 ba41f11d4..0fc8cf9c5 100644 --- a/database/src/config/index.ts +++ b/database/src/config/index.ts @@ -1,6 +1,7 @@ -// ATTENTION: DO NOT PUT ANY SECRETS IN HERE (or the .env) +/* eslint-disable n/no-process-env */ import dotenv from 'dotenv' + dotenv.config() const constants = { @@ -35,6 +36,4 @@ if ( ) } -const CONFIG = { ...constants, ...database, ...migrations } - -export default CONFIG +export const CONFIG = { ...constants, ...database, ...migrations } diff --git a/database/src/index.ts b/database/src/index.ts index 48056ab55..96785a721 100644 --- a/database/src/index.ts +++ b/database/src/index.ts @@ -1,6 +1,5 @@ -import 'reflect-metadata' import { createDatabase } from './prepare' -import CONFIG from './config' +import { CONFIG } from './config' import { createPool } from 'mysql' import { Migration } from 'ts-mysql-migrate' diff --git a/database/src/prepare.ts b/database/src/prepare.ts index 3c64b1c5e..2ecbb4c42 100644 --- a/database/src/prepare.ts +++ b/database/src/prepare.ts @@ -1,6 +1,6 @@ import { createConnection } from 'mysql2/promise' -import CONFIG from './config' +import { CONFIG } from './config' export const createDatabase = async (): Promise => { const con = await createConnection({ diff --git a/database/src/typeorm/DecimalTransformer.ts b/database/src/typeorm/DecimalTransformer.ts index 92efaf3bc..b1bcb8ca3 100644 --- a/database/src/typeorm/DecimalTransformer.ts +++ b/database/src/typeorm/DecimalTransformer.ts @@ -1,4 +1,4 @@ -import Decimal from 'decimal.js-light' +import { Decimal } from 'decimal.js-light' import { ValueTransformer } from 'typeorm' Decimal.set({ diff --git a/dht-node/.eslintrc.js b/dht-node/.eslintrc.js index f213be8c6..64f5a9051 100644 --- a/dht-node/.eslintrc.js +++ b/dht-node/.eslintrc.js @@ -1,20 +1,34 @@ +// eslint-disable-next-line import/no-commonjs, import/unambiguous module.exports = { root: true, env: { node: true, - // jest: true, }, parser: '@typescript-eslint/parser', - plugins: ['prettier', '@typescript-eslint' /*, 'jest' */], + plugins: ['prettier', '@typescript-eslint', 'import', 'n', 'promise'], extends: [ 'standard', 'eslint:recommended', 'plugin:prettier/recommended', - 'plugin:@typescript-eslint/recommended', + // 'plugin:import/recommended', + // 'plugin:import/typescript', + // 'plugin:security/recommended', + // 'plugin:@eslint-community/eslint-comments/recommended', ], - // add your custom rules here + settings: { + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'], + }, + 'import/resolver': { + typescript: { + project: ['./tsconfig.json'], + }, + node: true, + }, + }, rules: { - 'no-console': ['error'], + 'no-console': 'error', + camelcase: 'error', 'no-debugger': 'error', 'prettier/prettier': [ 'error', @@ -22,5 +36,170 @@ module.exports = { htmlWhitespaceSensitivity: 'ignore', }, ], + // import + // 'import/export': 'error', + // 'import/no-deprecated': 'error', + // 'import/no-empty-named-blocks': 'error', + // 'import/no-extraneous-dependencies': 'error', + // 'import/no-mutable-exports': 'error', + // 'import/no-unused-modules': 'error', + // 'import/no-named-as-default': 'error', + // 'import/no-named-as-default-member': 'error', + // 'import/no-amd': 'error', + // 'import/no-commonjs': 'error', + // 'import/no-import-module-exports': 'error', + // 'import/no-nodejs-modules': 'off', + // 'import/unambiguous': 'error', + // 'import/default': 'error', + // 'import/named': 'error', + // 'import/namespace': 'error', + // 'import/no-absolute-path': 'error', + // 'import/no-cycle': 'error', + // 'import/no-dynamic-require': 'error', + // 'import/no-internal-modules': 'off', + // 'import/no-relative-packages': 'error', + // 'import/no-relative-parent-imports': ['error', { ignore: ['@/*'] }], + // 'import/no-self-import': 'error', + // 'import/no-unresolved': 'error', + // 'import/no-useless-path-segments': 'error', + // 'import/no-webpack-loader-syntax': 'error', + // 'import/consistent-type-specifier-style': 'error', + // 'import/exports-last': 'off', + // 'import/extensions': 'error', + // 'import/first': 'error', + // 'import/group-exports': 'off', + // 'import/newline-after-import': 'error', + // 'import/no-anonymous-default-export': 'error', + // 'import/no-default-export': 'error', + // 'import/no-duplicates': 'error', + // 'import/no-named-default': 'error', + // 'import/no-namespace': 'error', + // 'import/no-unassigned-import': 'error', + // 'import/order': [ + // 'error', + // { + // groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'], + // 'newlines-between': 'always', + // pathGroups: [ + // { + // pattern: '@?*/**', + // group: 'external', + // position: 'after', + // }, + // { + // pattern: '@/**', + // group: 'external', + // position: 'after', + // }, + // ], + // alphabetize: { + // order: 'asc' /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */, + // caseInsensitive: true /* ignore case. Options: [true, false] */, + // }, + // distinctGroup: true, + // }, + // ], + // 'import/prefer-default-export': 'off', + // n + // '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-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-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-promises/fs': 'error', + // promise + // 'promise/catch-or-return': 'error', + // 'promise/no-return-wrap': 'error', + // 'promise/param-names': 'error', + // 'promise/always-return': 'error', + // 'promise/no-native': 'off', + // 'promise/no-nesting': 'warn', + // 'promise/no-promise-in-callback': 'warn', + // 'promise/no-callback-in-promise': 'warn', + // 'promise/avoid-new': 'warn', + // 'promise/no-new-statics': 'error', + // 'promise/no-return-in-finally': 'warn', + // 'promise/valid-params': 'warn', + // 'promise/prefer-await-to-callbacks': 'error', + // 'promise/no-multiple-resolved': 'error', + // eslint comments + // '@eslint-community/eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }], + // '@eslint-community/eslint-comments/no-restricted-disable': 'error', + // '@eslint-community/eslint-comments/no-use': 'off', + // '@eslint-community/eslint-comments/require-description': 'off', }, + overrides: [ + // only for ts files + { + files: ['*.ts', '*.tsx'], + extends: [ + 'plugin:@typescript-eslint/recommended', + // 'plugin:@typescript-eslint/recommended-requiring-type-checking', + // 'plugin:@typescript-eslint/strict', + ], + rules: { + // allow explicitly defined dangling promises + // '@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }], + 'no-void': ['error', { allowAsStatement: true }], + // ignore prefer-regexp-exec rule to allow string.match(regex) + '@typescript-eslint/prefer-regexp-exec': 'off', + // this should not run on ts files: https://github.com/import-js/eslint-plugin-import/issues/2215#issuecomment-911245486 + 'import/unambiguous': 'off', + // this is not compatible with typeorm, due to joined tables can be null, but are not defined as nullable + '@typescript-eslint/no-unnecessary-condition': 'off', + }, + parserOptions: { + tsconfigRootDir: __dirname, + project: ['./tsconfig.json'], + // this is to properly reference the referenced project database without requirement of compiling it + // eslint-disable-next-line camelcase + EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true, + }, + }, + { + files: ['*.test.ts'], + plugins: ['jest'], + rules: { + 'jest/no-disabled-tests': 'error', + 'jest/no-focused-tests': 'error', + 'jest/no-identical-title': 'error', + 'jest/prefer-to-have-length': 'error', + 'jest/valid-expect': 'error', + '@typescript-eslint/unbound-method': 'off', + 'jest/unbound-method': 'error', + }, + }, + ], } diff --git a/dht-node/package.json b/dht-node/package.json index d5dae0230..23238b9e4 100644 --- a/dht-node/package.json +++ b/dht-node/package.json @@ -27,21 +27,25 @@ "uuid": "^8.3.2" }, "devDependencies": { + "@eslint-community/eslint-plugin-eslint-comments": "^3.2.1", "@types/dotenv": "^8.2.0", "@types/jest": "^27.0.2", "@types/node": "^18.11.18", - "@typescript-eslint/eslint-plugin": "^5.48.0", - "@typescript-eslint/parser": "^5.48.0", + "@typescript-eslint/eslint-plugin": "^5.57.1", + "@typescript-eslint/parser": "^5.57.1", "@types/uuid": "^8.3.4", - "eslint": "^8.31.0", - "eslint-config-prettier": "^8.3.0", + "eslint": "^8.37.0", + "eslint-config-prettier": "^8.8.0", "eslint-config-standard": "^17.0.0", - "eslint-plugin-import": "^2.23.4", - "eslint-plugin-n": "^15.6.0", + "eslint-import-resolver-typescript": "^3.5.4", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jest": "^27.2.1", + "eslint-plugin-n": "^15.7.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-security": "^1.7.1", + "prettier": "^2.8.7", "jest": "^27.2.4", - "prettier": "^2.3.1", "ts-jest": "^27.0.5" } } diff --git a/dht-node/src/config/index.ts b/dht-node/src/config/index.ts index 43949201b..255a4def0 100644 --- a/dht-node/src/config/index.ts +++ b/dht-node/src/config/index.ts @@ -3,7 +3,7 @@ import dotenv from 'dotenv' dotenv.config() const constants = { - DB_VERSION: '0066-x-community-sendcoins-transactions_table', + DB_VERSION: '0067-private_key_in_community_table', LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info LOG_LEVEL: process.env.LOG_LEVEL || 'info', diff --git a/dht-node/src/dht_node/index.ts b/dht-node/src/dht_node/index.ts index 004fc816e..a767c323e 100644 --- a/dht-node/src/dht_node/index.ts +++ b/dht-node/src/dht_node/index.ts @@ -24,6 +24,8 @@ type CommunityApi = { url: string } +type KeyPair = { publicKey: Buffer; secretKey: Buffer } + export const startDHT = async (topic: string): Promise => { try { const TOPIC = DHT.hash(Buffer.from(topic)) @@ -32,11 +34,11 @@ export const startDHT = async (topic: string): Promise => { CONFIG.FEDERATION_DHT_SEED ? Buffer.alloc(KEY_SECRET_SEEDBYTES, CONFIG.FEDERATION_DHT_SEED) : null, - ) + ) as KeyPair const pubKeyString = keyPair.publicKey.toString('hex') logger.info(`keyPairDHT: publicKey=${pubKeyString}`) logger.debug(`keyPairDHT: secretKey=${keyPair.secretKey.toString('hex')}`) - await writeHomeCommunityEntry(pubKeyString) + await writeHomeCommunityEntry(keyPair) const ownApiVersions = await writeFederatedHomeCommunityEntries(pubKeyString) logger.info(`ApiList: ${JSON.stringify(ownApiVersions)}`) @@ -212,13 +214,14 @@ async function writeFederatedHomeCommunityEntries(pubKey: string): Promise { +async function writeHomeCommunityEntry(keyPair: KeyPair): Promise { try { // check for existing homeCommunity entry let homeCom = await DbCommunity.findOne({ foreign: false }) if (homeCom) { // simply update the existing entry, but it MUST keep the ID and UUID because of possible relations - homeCom.publicKey = Buffer.from(pubKey) + homeCom.publicKey = keyPair.publicKey + homeCom.privateKey = keyPair.secretKey homeCom.url = CONFIG.FEDERATION_COMMUNITY_URL + '/api/' homeCom.name = CONFIG.COMMUNITY_NAME homeCom.description = CONFIG.COMMUNITY_DESCRIPTION @@ -228,7 +231,8 @@ async function writeHomeCommunityEntry(pubKey: string): Promise { // insert a new homecommunity entry including a new ID and a new but ensured unique UUID homeCom = new DbCommunity() homeCom.foreign = false - homeCom.publicKey = Buffer.from(pubKey) + homeCom.publicKey = keyPair.publicKey + homeCom.privateKey = keyPair.secretKey homeCom.communityUuid = await newCommunityUuid() homeCom.url = CONFIG.FEDERATION_COMMUNITY_URL + '/api/' homeCom.name = CONFIG.COMMUNITY_NAME diff --git a/dht-node/yarn.lock b/dht-node/yarn.lock index 85c4d35fa..a1437fe79 100644 --- a/dht-node/yarn.lock +++ b/dht-node/yarn.lock @@ -298,14 +298,34 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@eslint/eslintrc@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" - integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== +"@eslint-community/eslint-plugin-eslint-comments@^3.2.1": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.1.tgz#3c65061e27f155eae3744c3b30c5a8253a959040" + integrity sha512-/HZbjIGaVO2zLlWX3gRgiHmKRVvvqrC0zVu3eXnIj1ORxoyfGSj50l0PfDfqihyZAqrDYzSMdJesXzFjvAoiLQ== + dependencies: + escape-string-regexp "^1.0.5" + ignore "^5.2.4" + +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" + integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== + +"@eslint/eslintrc@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.3.tgz#4910db5505f4d503f27774bf356e3704818a0331" + integrity sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.4.0" + espree "^9.5.2" globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" @@ -313,10 +333,15 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@humanwhocodes/config-array@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" - integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== +"@eslint/js@8.42.0": + version "8.42.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.42.0.tgz#484a1d638de2911e6f5a30c12f49c7e4a3270fb6" + integrity sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw== + +"@humanwhocodes/config-array@^0.11.10": + version "0.11.10" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" + integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" @@ -621,6 +646,18 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@pkgr/utils@^2.3.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.1.tgz#adf291d0357834c410ce80af16e711b56c7b1cd3" + integrity sha512-JOqwkgFEyi+OROIyq7l4Jy28h/WwhDnG/cPkXG2Z1iFbubB6jsHW1NDvmyOzTBxHr3yg68YGirmh1JUgMqa+9w== + dependencies: + cross-spawn "^7.0.3" + fast-glob "^3.2.12" + is-glob "^4.0.3" + open "^9.1.0" + picocolors "^1.0.0" + tslib "^2.5.0" + "@sinonjs/commons@^1.7.0": version "1.8.6" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" @@ -786,87 +823,88 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.48.0": - version "5.48.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.48.0.tgz#54f8368d080eb384a455f60c2ee044e948a8ce67" - integrity sha512-SVLafp0NXpoJY7ut6VFVUU9I+YeFsDzeQwtK0WZ+xbRN3mtxJ08je+6Oi2N89qDn087COdO0u3blKZNv9VetRQ== +"@typescript-eslint/eslint-plugin@^5.57.1": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz#2604cfaf2b306e120044f901e20c8ed926debf15" + integrity sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA== dependencies: - "@typescript-eslint/scope-manager" "5.48.0" - "@typescript-eslint/type-utils" "5.48.0" - "@typescript-eslint/utils" "5.48.0" + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.59.9" + "@typescript-eslint/type-utils" "5.59.9" + "@typescript-eslint/utils" "5.59.9" debug "^4.3.4" + grapheme-splitter "^1.0.4" ignore "^5.2.0" natural-compare-lite "^1.4.0" - regexpp "^3.2.0" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.48.0": - version "5.48.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.48.0.tgz#02803355b23884a83e543755349809a50b7ed9ba" - integrity sha512-1mxNA8qfgxX8kBvRDIHEzrRGrKHQfQlbW6iHyfHYS0Q4X1af+S6mkLNtgCOsGVl8+/LUPrqdHMssAemkrQ01qg== +"@typescript-eslint/parser@^5.57.1": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.9.tgz#a85c47ccdd7e285697463da15200f9a8561dd5fa" + integrity sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ== dependencies: - "@typescript-eslint/scope-manager" "5.48.0" - "@typescript-eslint/types" "5.48.0" - "@typescript-eslint/typescript-estree" "5.48.0" + "@typescript-eslint/scope-manager" "5.59.9" + "@typescript-eslint/types" "5.59.9" + "@typescript-eslint/typescript-estree" "5.59.9" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.48.0": - version "5.48.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.48.0.tgz#607731cb0957fbc52fd754fd79507d1b6659cecf" - integrity sha512-0AA4LviDtVtZqlyUQnZMVHydDATpD9SAX/RC5qh6cBd3xmyWvmXYF+WT1oOmxkeMnWDlUVTwdODeucUnjz3gow== +"@typescript-eslint/scope-manager@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz#eadce1f2733389cdb58c49770192c0f95470d2f4" + integrity sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ== dependencies: - "@typescript-eslint/types" "5.48.0" - "@typescript-eslint/visitor-keys" "5.48.0" + "@typescript-eslint/types" "5.59.9" + "@typescript-eslint/visitor-keys" "5.59.9" -"@typescript-eslint/type-utils@5.48.0": - version "5.48.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.48.0.tgz#40496dccfdc2daa14a565f8be80ad1ae3882d6d6" - integrity sha512-vbtPO5sJyFjtHkGlGK4Sthmta0Bbls4Onv0bEqOGm7hP9h8UpRsHJwsrCiWtCUndTRNQO/qe6Ijz9rnT/DB+7g== +"@typescript-eslint/type-utils@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz#53bfaae2e901e6ac637ab0536d1754dfef4dafc2" + integrity sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q== dependencies: - "@typescript-eslint/typescript-estree" "5.48.0" - "@typescript-eslint/utils" "5.48.0" + "@typescript-eslint/typescript-estree" "5.59.9" + "@typescript-eslint/utils" "5.59.9" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.48.0": - version "5.48.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.48.0.tgz#d725da8dfcff320aab2ac6f65c97b0df30058449" - integrity sha512-UTe67B0Ypius0fnEE518NB2N8gGutIlTojeTg4nt0GQvikReVkurqxd2LvYa9q9M5MQ6rtpNyWTBxdscw40Xhw== +"@typescript-eslint/types@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.9.tgz#3b4e7ae63718ce1b966e0ae620adc4099a6dcc52" + integrity sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw== -"@typescript-eslint/typescript-estree@5.48.0": - version "5.48.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.0.tgz#a7f04bccb001003405bb5452d43953a382c2fac2" - integrity sha512-7pjd94vvIjI1zTz6aq/5wwE/YrfIyEPLtGJmRfyNR9NYIW+rOvzzUv3Cmq2hRKpvt6e9vpvPUQ7puzX7VSmsEw== +"@typescript-eslint/typescript-estree@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz#6bfea844e468427b5e72034d33c9fffc9557392b" + integrity sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA== dependencies: - "@typescript-eslint/types" "5.48.0" - "@typescript-eslint/visitor-keys" "5.48.0" + "@typescript-eslint/types" "5.59.9" + "@typescript-eslint/visitor-keys" "5.59.9" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.48.0": - version "5.48.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.48.0.tgz#eee926af2733f7156ad8d15e51791e42ce300273" - integrity sha512-x2jrMcPaMfsHRRIkL+x96++xdzvrdBCnYRd5QiW5Wgo1OB4kDYPbC1XjWP/TNqlfK93K/lUL92erq5zPLgFScQ== +"@typescript-eslint/utils@5.59.9", "@typescript-eslint/utils@^5.10.0": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.9.tgz#adee890107b5ffe02cd46fdaa6c2125fb3c6c7c4" + integrity sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg== dependencies: + "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.48.0" - "@typescript-eslint/types" "5.48.0" - "@typescript-eslint/typescript-estree" "5.48.0" + "@typescript-eslint/scope-manager" "5.59.9" + "@typescript-eslint/types" "5.59.9" + "@typescript-eslint/typescript-estree" "5.59.9" eslint-scope "^5.1.1" - eslint-utils "^3.0.0" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.48.0": - version "5.48.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.0.tgz#4446d5e7f6cadde7140390c0e284c8702d944904" - integrity sha512-5motVPz5EgxQ0bHjut3chzBkJ3Z3sheYVcSwS5BpHZpLqSptSmELNtGixmgj65+rIfhvtQTz5i9OP2vtzdDH7Q== +"@typescript-eslint/visitor-keys@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz#9f86ef8e95aca30fb5a705bb7430f95fc58b146d" + integrity sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q== dependencies: - "@typescript-eslint/types" "5.48.0" + "@typescript-eslint/types" "5.59.9" eslint-visitor-keys "^3.3.0" abab@^2.0.3, abab@^2.0.5: @@ -985,7 +1023,7 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -array-includes@^3.1.4: +array-includes@^3.1.6: version "3.1.6" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== @@ -1001,7 +1039,7 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array.prototype.flat@^1.2.5: +array.prototype.flat@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== @@ -1011,6 +1049,16 @@ array.prototype.flat@^1.2.5: es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" +array.prototype.flatmap@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" + integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1087,6 +1135,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +big-integer@^1.6.44: + version "1.6.51" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" + integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -1116,6 +1169,13 @@ bogon@^1.0.0: compact-encoding "^2.11.0" compact-encoding-net "^1.2.0" +bplist-parser@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" + integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw== + dependencies: + big-integer "^1.6.44" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1172,6 +1232,13 @@ builtins@^5.0.1: dependencies: semver "^7.0.0" +bundle-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a" + integrity sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw== + dependencies: + run-applescript "^5.0.0" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -1387,13 +1454,6 @@ debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: dependencies: ms "2.1.2" -debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -1428,6 +1488,29 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +default-browser-id@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c" + integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA== + dependencies: + bplist-parser "^0.2.0" + untildify "^4.0.0" + +default-browser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-4.0.0.tgz#53c9894f8810bf86696de117a6ce9085a3cbc7da" + integrity sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA== + dependencies: + bundle-name "^3.0.0" + default-browser-id "^3.0.0" + execa "^7.1.1" + titleize "^3.0.0" + +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + define-properties@^1.1.3, define-properties@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" @@ -1526,6 +1609,14 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +enhanced-resolve@^5.12.0: + version "5.14.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz#de684b6803724477a4af5d74ccae5de52c25f6b3" + integrity sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -1612,28 +1703,43 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^8.3.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz#dec1d29ab728f4fa63061774e1672ac4e363d207" - integrity sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA== +eslint-config-prettier@^8.8.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" + integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== eslint-config-standard@^17.0.0: version "17.0.0" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz#fd5b6cf1dcf6ba8d29f200c461de2e19069888cf" integrity sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg== -eslint-import-resolver-node@^0.3.6: - version "0.3.6" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" - integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== +eslint-import-resolver-node@^0.3.7: + version "0.3.7" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7" + integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== dependencies: debug "^3.2.7" - resolve "^1.20.0" + is-core-module "^2.11.0" + resolve "^1.22.1" -eslint-module-utils@^2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974" - integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA== +eslint-import-resolver-typescript@^3.5.4: + version "3.5.5" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz#0a9034ae7ed94b254a360fbea89187b60ea7456d" + integrity sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw== + dependencies: + debug "^4.3.4" + enhanced-resolve "^5.12.0" + eslint-module-utils "^2.7.4" + get-tsconfig "^4.5.0" + globby "^13.1.3" + is-core-module "^2.11.0" + is-glob "^4.0.3" + synckit "^0.8.5" + +eslint-module-utils@^2.7.4: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" + integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== dependencies: debug "^3.2.7" @@ -1645,29 +1751,38 @@ eslint-plugin-es@^4.1.0: eslint-utils "^2.0.0" regexpp "^3.0.0" -eslint-plugin-import@^2.23.4: - version "2.26.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b" - integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== +eslint-plugin-import@^2.27.5: + version "2.27.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" + integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== dependencies: - array-includes "^3.1.4" - array.prototype.flat "^1.2.5" - debug "^2.6.9" + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + array.prototype.flatmap "^1.3.1" + debug "^3.2.7" doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.6" - eslint-module-utils "^2.7.3" + eslint-import-resolver-node "^0.3.7" + eslint-module-utils "^2.7.4" has "^1.0.3" - is-core-module "^2.8.1" + is-core-module "^2.11.0" is-glob "^4.0.3" minimatch "^3.1.2" - object.values "^1.1.5" - resolve "^1.22.0" + object.values "^1.1.6" + resolve "^1.22.1" + semver "^6.3.0" tsconfig-paths "^3.14.1" -eslint-plugin-n@^15.6.0: - version "15.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-n/-/eslint-plugin-n-15.6.0.tgz#cfb1d2e2e427d620eb9008f8b3b5a40de0c84120" - integrity sha512-Hd/F7wz4Mj44Jp0H6Jtty13NcE69GNTY0rVlgTIj1XBnGGVI6UTdDrpE6vqu3AHo07bygq/N+7OH/lgz1emUJw== +eslint-plugin-jest@^27.2.1: + version "27.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz#b85b4adf41c682ea29f1f01c8b11ccc39b5c672c" + integrity sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg== + dependencies: + "@typescript-eslint/utils" "^5.10.0" + +eslint-plugin-n@^15.7.0: + version "15.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz#e29221d8f5174f84d18f2eb94765f2eeea033b90" + integrity sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q== dependencies: builtins "^5.0.1" eslint-plugin-es "^4.1.0" @@ -1690,6 +1805,13 @@ eslint-plugin-promise@^6.1.1: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz#269a3e2772f62875661220631bd4dafcb4083816" integrity sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig== +eslint-plugin-security@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz#0e9c4a471f6e4d3ca16413c7a4a51f3966ba16e4" + integrity sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ== + dependencies: + safe-regex "^2.1.1" + eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -1698,10 +1820,10 @@ eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== +eslint-scope@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" + integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -1735,13 +1857,21 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^8.31.0: - version "8.31.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.31.0.tgz#75028e77cbcff102a9feae1d718135931532d524" - integrity sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA== +eslint-visitor-keys@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + +eslint@^8.37.0: + version "8.42.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.42.0.tgz#7bebdc3a55f9ed7167251fe7259f75219cade291" + integrity sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A== dependencies: - "@eslint/eslintrc" "^1.4.1" - "@humanwhocodes/config-array" "^0.11.8" + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.4.0" + "@eslint/eslintrc" "^2.0.3" + "@eslint/js" "8.42.0" + "@humanwhocodes/config-array" "^0.11.10" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" ajv "^6.10.0" @@ -1750,24 +1880,22 @@ eslint@^8.31.0: debug "^4.3.2" doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" - esquery "^1.4.0" + eslint-scope "^7.2.0" + eslint-visitor-keys "^3.4.1" + espree "^9.5.2" + esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" find-up "^5.0.0" glob-parent "^6.0.2" globals "^13.19.0" - grapheme-splitter "^1.0.4" + graphemer "^1.4.0" ignore "^5.2.0" import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" is-path-inside "^3.0.3" - js-sdsl "^4.1.4" js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" @@ -1775,29 +1903,28 @@ eslint@^8.31.0: minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.1" - regexpp "^3.2.0" strip-ansi "^6.0.1" strip-json-comments "^3.1.0" text-table "^0.2.0" -espree@^9.4.0: - version "9.4.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" - integrity sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg== +espree@^9.5.2: + version "9.5.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.2.tgz#e994e7dc33a082a7a82dceaf12883a829353215b" + integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw== dependencies: acorn "^8.8.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" + eslint-visitor-keys "^3.4.1" esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: estraverse "^5.1.0" @@ -1843,6 +1970,21 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" +execa@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43" + integrity sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -1873,7 +2015,7 @@ fast-fifo@^1.0.0: resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.1.0.tgz#17d1a3646880b9891dfa0c54e69c5fef33cad779" integrity sha512-Kl29QoNbNvn4nhDsLYjyIAaIqaJB6rBx5p3sL9VjaefJ+eMFBWVZiaoguaoZfzEKr5RhAti0UgM8703akGPJ6g== -fast-glob@^3.2.9: +fast-glob@^3.2.11, fast-glob@^3.2.12, fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== @@ -2023,7 +2165,7 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== -get-stream@^6.0.0: +get-stream@^6.0.0, get-stream@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== @@ -2036,6 +2178,13 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" +get-tsconfig@^4.5.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.6.0.tgz#e977690993a42f3e320e932427502a40f7af6d05" + integrity sha512-lgbo68hHTQnFddybKbbs/RDRJnJT5YyGy2kQzVwbq+g67X73i+5MVTval34QxGkOe9X5Ujf1UYpCaphLyltjEg== + dependencies: + resolve-pkg-maps "^1.0.0" + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -2086,6 +2235,17 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +globby@^13.1.3: + version "13.1.4" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.4.tgz#2f91c116066bcec152465ba36e5caa4a13c01317" + integrity sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g== + dependencies: + dir-glob "^3.0.1" + fast-glob "^3.2.11" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^4.0.0" + gopd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" @@ -2098,11 +2258,21 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + grapheme-splitter@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -2187,6 +2357,11 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== + hypercore-crypto@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/hypercore-crypto/-/hypercore-crypto-3.3.0.tgz#03ab5b44608a563e131f629f671c6f90a83c52e6" @@ -2208,7 +2383,7 @@ ignore-by-default@^1.0.1: resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== -ignore@^5.1.1, ignore@^5.2.0: +ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.4: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== @@ -2288,7 +2463,7 @@ is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.11.0, is-core-module@^2.8.1, is-core-module@^2.9.0: +is-core-module@^2.11.0, is-core-module@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== @@ -2302,6 +2477,16 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -2324,6 +2509,13 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -2371,6 +2563,11 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -2397,6 +2594,13 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -2849,11 +3053,6 @@ jest@^27.2.4: import-local "^3.0.2" jest-cli "^27.5.1" -js-sdsl@^4.1.4: - version "4.2.0" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.2.0.tgz#278e98b7bea589b8baaf048c20aeb19eb7ad09d0" - integrity sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ== - js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -3090,6 +3289,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -3102,11 +3306,6 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -3216,6 +3415,13 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== + dependencies: + path-key "^4.0.0" + nwsapi@^2.2.0: version "2.2.2" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0" @@ -3241,7 +3447,7 @@ object.assign@^4.1.4: has-symbols "^1.0.3" object-keys "^1.1.1" -object.values@^1.1.5: +object.values@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== @@ -3264,6 +3470,23 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +open@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-9.1.0.tgz#684934359c90ad25742f5a26151970ff8c6c80b6" + integrity sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg== + dependencies: + default-browser "^4.0.0" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^2.2.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -3358,6 +3581,11 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" @@ -3407,10 +3635,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.3.1: - version "2.8.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.2.tgz#c4ea1b5b454d7c4b59966db2e06ed7eec5dfd160" - integrity sha512-BtRV9BcncDyI2tsuS19zzhzoxD8Dh8LiCx7j7tHzrkz8GFXAexeWFdi22mjE1d16dftH2qNaytVxqiRTGlMfpw== +prettier@^2.8.7: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== pretty-format@^27.0.0, pretty-format@^27.5.1: version "27.5.1" @@ -3478,6 +3706,11 @@ record-cache@^1.1.1: dependencies: b4a "^1.3.1" +regexp-tree@~0.1.1: + version "0.1.27" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" + integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA== + regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" @@ -3487,7 +3720,7 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" -regexpp@^3.0.0, regexpp@^3.2.0: +regexpp@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== @@ -3519,12 +3752,17 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + resolve.exports@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== -resolve@^1.17.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.1: +resolve@^1.17.0, resolve@^1.20.0, resolve@^1.22.1: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -3550,6 +3788,13 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +run-applescript@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c" + integrity sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg== + dependencies: + execa "^5.0.0" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -3566,6 +3811,13 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" +safe-regex@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-2.1.1.tgz#f7128f00d056e2fe5c11e81a1324dd974aadced2" + integrity sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A== + dependencies: + regexp-tree "~0.1.1" + "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -3658,7 +3910,7 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.2, signal-exit@^3.0.3: +signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -3687,6 +3939,11 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + sodium-javascript@~0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/sodium-javascript/-/sodium-javascript-0.8.0.tgz#0a94d7bb58ab17be82255f3949259af59778fdbc" @@ -3857,6 +4114,11 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -3901,6 +4163,19 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +synckit@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.5.tgz#b7f4358f9bb559437f9f167eb6bc46b3c9818fa3" + integrity sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q== + dependencies: + "@pkgr/utils" "^2.3.1" + tslib "^2.5.0" + +tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" @@ -3938,6 +4213,11 @@ timeout-refresh@^2.0.0: resolved "https://registry.yarnpkg.com/timeout-refresh/-/timeout-refresh-2.0.1.tgz#f8ec7cf1f9d93b2635b7d4388cb820c5f6c16f98" integrity sha512-SVqEcMZBsZF9mA78rjzCrYrUs37LMJk3ShZ851ygZYW1cMeIjs9mL57KO6Iv5mmjSQnOe/29/VAfGXo+oRCiVw== +titleize@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" + integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ== + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -4036,6 +4316,11 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.5.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" + integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -4120,6 +4405,11 @@ universalify@^0.2.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + update-browserslist-db@^1.0.9: version "1.0.10" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" diff --git a/federation/src/config/index.ts b/federation/src/config/index.ts index 710248472..b44487aa9 100644 --- a/federation/src/config/index.ts +++ b/federation/src/config/index.ts @@ -11,7 +11,7 @@ Decimal.set({ */ const constants = { - DB_VERSION: '0066-x-community-sendcoins-transactions_table', + DB_VERSION: '0067-private_key_in_community_table', // DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info 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