mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
Merge pull request #5038 from Ocelot-Social-Community/5037-logging-mails-in-dev-mode
chore: 🍰 Log E-Mail If Not Sending It
This commit is contained in:
commit
1926238953
86
backend/src/middleware/helpers/cleanHtml.js
Normal file
86
backend/src/middleware/helpers/cleanHtml.js
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import sanitizeHtml from 'sanitize-html'
|
||||||
|
import linkifyHtml from 'linkifyjs/html'
|
||||||
|
|
||||||
|
const standardSanitizeHtmlOptions = {
|
||||||
|
allowedTags: [
|
||||||
|
'img',
|
||||||
|
'p',
|
||||||
|
'h3',
|
||||||
|
'h4',
|
||||||
|
'br',
|
||||||
|
'hr',
|
||||||
|
'b',
|
||||||
|
'i',
|
||||||
|
'u',
|
||||||
|
'em',
|
||||||
|
'strong',
|
||||||
|
'a',
|
||||||
|
'pre',
|
||||||
|
'ul',
|
||||||
|
'li',
|
||||||
|
'ol',
|
||||||
|
's',
|
||||||
|
'strike',
|
||||||
|
'span',
|
||||||
|
'blockquote',
|
||||||
|
],
|
||||||
|
allowedAttributes: {
|
||||||
|
a: ['href', 'class', 'target', 'data-*', 'contenteditable'],
|
||||||
|
span: ['contenteditable', 'class', 'data-*'],
|
||||||
|
img: ['src'],
|
||||||
|
},
|
||||||
|
allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com'],
|
||||||
|
parser: {
|
||||||
|
lowerCaseTags: true,
|
||||||
|
},
|
||||||
|
transformTags: {
|
||||||
|
h1: 'h3',
|
||||||
|
h2: 'h3',
|
||||||
|
h3: 'h3',
|
||||||
|
h4: 'h4',
|
||||||
|
h5: 'strong',
|
||||||
|
i: 'em',
|
||||||
|
a: (tagName, attribs) => {
|
||||||
|
return {
|
||||||
|
tagName: 'a',
|
||||||
|
attribs: {
|
||||||
|
...attribs,
|
||||||
|
href: attribs.href || '',
|
||||||
|
target: '_blank',
|
||||||
|
rel: 'noopener noreferrer nofollow',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
b: 'strong',
|
||||||
|
s: 'strike',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cleanHtml(dirty, _key, sanitizeHtmlOptions = standardSanitizeHtmlOptions) {
|
||||||
|
if (!dirty) {
|
||||||
|
return dirty
|
||||||
|
}
|
||||||
|
|
||||||
|
dirty = linkifyHtml(dirty)
|
||||||
|
dirty = sanitizeHtml(dirty, sanitizeHtmlOptions)
|
||||||
|
|
||||||
|
// remove empty html tags and duplicated linebreaks and returns
|
||||||
|
dirty = dirty
|
||||||
|
// remove all tags with "space only"
|
||||||
|
.replace(/<[a-z-]+>[\s]+<\/[a-z-]+>/gim, '')
|
||||||
|
.replace(/[\n]{3,}/gim, '\n\n')
|
||||||
|
.replace(/(\r\n|\n\r|\r|\n)/g, '<br>$1')
|
||||||
|
|
||||||
|
// replace all p tags with line breaks (and spaces) only by single linebreaks
|
||||||
|
// limit linebreaks to max 2 (equivalent to html "br" linebreak)
|
||||||
|
.replace(/(<br ?\/?>\s*){2,}/gim, '<br>')
|
||||||
|
// remove additional linebreaks after p tags
|
||||||
|
.replace(/<\/(p|div|th|tr)>\s*(<br ?\/?>\s*)+\s*<(p|div|th|tr)>/gim, '</p><p>')
|
||||||
|
// remove additional linebreaks inside p tags
|
||||||
|
.replace(/<[a-z-]+>(<[a-z-]+>)*\s*(<br ?\/?>\s*)+\s*(<\/[a-z-]+>)*<\/[a-z-]+>/gim, '')
|
||||||
|
// remove additional linebreaks when first child inside p tags
|
||||||
|
.replace(/<p>(\s*<br ?\/?>\s*)+/gim, '<p>')
|
||||||
|
// remove additional linebreaks when last child inside p tags
|
||||||
|
.replace(/(\s*<br ?\/?>\s*)+<\/p+>/gim, '</p>')
|
||||||
|
return dirty
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import CONFIG from '../../../config'
|
import CONFIG from '../../../config'
|
||||||
|
import { cleanHtml } from '../../../middleware/helpers/cleanHtml.js'
|
||||||
import nodemailer from 'nodemailer'
|
import nodemailer from 'nodemailer'
|
||||||
import { htmlToText } from 'nodemailer-html-to-text'
|
import { htmlToText } from 'nodemailer-html-to-text'
|
||||||
|
|
||||||
@ -10,6 +11,27 @@ if (!hasEmailConfig) {
|
|||||||
if (!CONFIG.TEST) {
|
if (!CONFIG.TEST) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log('Warning: Middlewares will not try to send mails.')
|
console.log('Warning: Middlewares will not try to send mails.')
|
||||||
|
// TODO: disable e-mail logging on database seeding?
|
||||||
|
// TODO: implement general logging like 'log4js', see Gradido project: https://github.com/gradido/gradido/blob/master/backend/log4js-config.json
|
||||||
|
sendMailCallback = async (templateArgs) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('--- Log Unsend E-Mail ---')
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('To: ' + templateArgs.to)
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('From: ' + templateArgs.from)
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('Subject: ' + templateArgs.subject)
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('Content:')
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(
|
||||||
|
cleanHtml(templateArgs.html, 'dummyKey', {
|
||||||
|
allowedTags: ['a'],
|
||||||
|
allowedAttributes: { a: ['href'] },
|
||||||
|
}).replace(/&/g, '&'),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sendMailCallback = async (templateArgs) => {
|
sendMailCallback = async (templateArgs) => {
|
||||||
|
|||||||
@ -1,100 +1,15 @@
|
|||||||
import walkRecursive from '../helpers/walkRecursive'
|
import walkRecursive from '../helpers/walkRecursive'
|
||||||
// import { getByDot, setByDot, getItems, replaceItems } from 'feathers-hooks-common'
|
import { cleanHtml } from '../middleware/helpers/cleanHtml.js'
|
||||||
import sanitizeHtml from 'sanitize-html'
|
|
||||||
// import { isEmpty, intersection } from 'lodash'
|
|
||||||
import linkifyHtml from 'linkifyjs/html'
|
|
||||||
|
|
||||||
function clean(dirty) {
|
|
||||||
if (!dirty) {
|
|
||||||
return dirty
|
|
||||||
}
|
|
||||||
|
|
||||||
dirty = linkifyHtml(dirty)
|
|
||||||
dirty = sanitizeHtml(dirty, {
|
|
||||||
allowedTags: [
|
|
||||||
'img',
|
|
||||||
'p',
|
|
||||||
'h3',
|
|
||||||
'h4',
|
|
||||||
'br',
|
|
||||||
'hr',
|
|
||||||
'b',
|
|
||||||
'i',
|
|
||||||
'u',
|
|
||||||
'em',
|
|
||||||
'strong',
|
|
||||||
'a',
|
|
||||||
'pre',
|
|
||||||
'ul',
|
|
||||||
'li',
|
|
||||||
'ol',
|
|
||||||
's',
|
|
||||||
'strike',
|
|
||||||
'span',
|
|
||||||
'blockquote',
|
|
||||||
],
|
|
||||||
allowedAttributes: {
|
|
||||||
a: ['href', 'class', 'target', 'data-*', 'contenteditable'],
|
|
||||||
span: ['contenteditable', 'class', 'data-*'],
|
|
||||||
img: ['src'],
|
|
||||||
},
|
|
||||||
allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com'],
|
|
||||||
parser: {
|
|
||||||
lowerCaseTags: true,
|
|
||||||
},
|
|
||||||
transformTags: {
|
|
||||||
h1: 'h3',
|
|
||||||
h2: 'h3',
|
|
||||||
h3: 'h3',
|
|
||||||
h4: 'h4',
|
|
||||||
h5: 'strong',
|
|
||||||
i: 'em',
|
|
||||||
a: (tagName, attribs) => {
|
|
||||||
return {
|
|
||||||
tagName: 'a',
|
|
||||||
attribs: {
|
|
||||||
...attribs,
|
|
||||||
href: attribs.href || '',
|
|
||||||
target: '_blank',
|
|
||||||
rel: 'noopener noreferrer nofollow',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
b: 'strong',
|
|
||||||
s: 'strike',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// remove empty html tags and duplicated linebreaks and returns
|
|
||||||
dirty = dirty
|
|
||||||
// remove all tags with "space only"
|
|
||||||
.replace(/<[a-z-]+>[\s]+<\/[a-z-]+>/gim, '')
|
|
||||||
.replace(/[\n]{3,}/gim, '\n\n')
|
|
||||||
.replace(/(\r\n|\n\r|\r|\n)/g, '<br>$1')
|
|
||||||
|
|
||||||
// replace all p tags with line breaks (and spaces) only by single linebreaks
|
|
||||||
// limit linebreaks to max 2 (equivalent to html "br" linebreak)
|
|
||||||
.replace(/(<br ?\/?>\s*){2,}/gim, '<br>')
|
|
||||||
// remove additional linebreaks after p tags
|
|
||||||
.replace(/<\/(p|div|th|tr)>\s*(<br ?\/?>\s*)+\s*<(p|div|th|tr)>/gim, '</p><p>')
|
|
||||||
// remove additional linebreaks inside p tags
|
|
||||||
.replace(/<[a-z-]+>(<[a-z-]+>)*\s*(<br ?\/?>\s*)+\s*(<\/[a-z-]+>)*<\/[a-z-]+>/gim, '')
|
|
||||||
// remove additional linebreaks when first child inside p tags
|
|
||||||
.replace(/<p>(\s*<br ?\/?>\s*)+/gim, '<p>')
|
|
||||||
// remove additional linebreaks when last child inside p tags
|
|
||||||
.replace(/(\s*<br ?\/?>\s*)+<\/p+>/gim, '</p>')
|
|
||||||
return dirty
|
|
||||||
}
|
|
||||||
|
|
||||||
const fields = ['content', 'contentExcerpt', 'reasonDescription']
|
const fields = ['content', 'contentExcerpt', 'reasonDescription']
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Mutation: async (resolve, root, args, context, info) => {
|
Mutation: async (resolve, root, args, context, info) => {
|
||||||
args = walkRecursive(args, fields, clean)
|
args = walkRecursive(args, fields, cleanHtml)
|
||||||
return resolve(root, args, context, info)
|
return resolve(root, args, context, info)
|
||||||
},
|
},
|
||||||
Query: async (resolve, root, args, context, info) => {
|
Query: async (resolve, root, args, context, info) => {
|
||||||
const result = await resolve(root, args, context, info)
|
const result = await resolve(root, args, context, info)
|
||||||
return walkRecursive(result, fields, clean)
|
return walkRecursive(result, fields, cleanHtml)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ Feature: Notification for a mention
|
|||||||
Background:
|
Background:
|
||||||
Given the following "users" are in the database:
|
Given the following "users" are in the database:
|
||||||
| slug | email | password | id | name | termsAndConditionsAgreedVersion |
|
| slug | email | password | id | name | termsAndConditionsAgreedVersion |
|
||||||
| wolle-aus-hamburg | wolle@example.org | 1234 | wolle | Wolle aus Hamburg | 0.0.4 |
|
| wolle-aus-hamburg | wolle@example.org | 1234 | wolle | Wolfgang aus Hamburg | 0.0.4 |
|
||||||
| matt-rider | matt@example.org | 4321 | matt | Matt Rider | 0.0.4 |
|
| matt-rider | matt@example.org | 4321 | matt | Matt Rider | 0.0.4 |
|
||||||
|
|
||||||
Scenario: Mention another user, re-login as this user and see notifications
|
Scenario: Mention another user, re-login as this user and see notifications
|
||||||
|
|||||||
@ -97,7 +97,7 @@ storiesOf('RegistrationSlider', module)
|
|||||||
email: 'wolle.huss@pjannto.com',
|
email: 'wolle.huss@pjannto.com',
|
||||||
emailSend: false,
|
emailSend: false,
|
||||||
nonce: '47539',
|
nonce: '47539',
|
||||||
name: 'Wolle',
|
name: 'Wolfgang',
|
||||||
password: 'Hello',
|
password: 'Hello',
|
||||||
passwordConfirmation: 'Hello',
|
passwordConfirmation: 'Hello',
|
||||||
termsAndConditionsConfirmed: true,
|
termsAndConditionsConfirmed: true,
|
||||||
@ -127,7 +127,7 @@ storiesOf('RegistrationSlider', module)
|
|||||||
email: 'wolle.huss@pjannto.com',
|
email: 'wolle.huss@pjannto.com',
|
||||||
emailSend: false,
|
emailSend: false,
|
||||||
nonce: '47539',
|
nonce: '47539',
|
||||||
name: 'Wolle',
|
name: 'Wolfgang',
|
||||||
password: 'Hello',
|
password: 'Hello',
|
||||||
passwordConfirmation: 'Hello',
|
passwordConfirmation: 'Hello',
|
||||||
termsAndConditionsConfirmed: true,
|
termsAndConditionsConfirmed: true,
|
||||||
@ -171,7 +171,7 @@ storiesOf('RegistrationSlider', module)
|
|||||||
email: 'wolle.huss@pjannto.com',
|
email: 'wolle.huss@pjannto.com',
|
||||||
emailSend: true,
|
emailSend: true,
|
||||||
nonce: '47539',
|
nonce: '47539',
|
||||||
name: 'Wolle',
|
name: 'Wolfgang',
|
||||||
password: 'Hello',
|
password: 'Hello',
|
||||||
passwordConfirmation: 'Hello',
|
passwordConfirmation: 'Hello',
|
||||||
termsAndConditionsConfirmed: true,
|
termsAndConditionsConfirmed: true,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user