aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-11-17 14:34:09 +0100
committerChocobozzz <me@florianbigard.com>2020-11-17 14:34:09 +0100
commit9ff36c2d70956d2775d207c7809adb6fe7f2f2a5 (patch)
treec9058f8210d9674b69307c4f7c5ccde85a1ba597
parent9afb5c10e5935e667e33219bdbd775e9ed1b4330 (diff)
downloadPeerTube-9ff36c2d70956d2775d207c7809adb6fe7f2f2a5.tar.gz
PeerTube-9ff36c2d70956d2775d207c7809adb6fe7f2f2a5.tar.zst
PeerTube-9ff36c2d70956d2775d207c7809adb6fe7f2f2a5.zip
Refactor markdown/sanitize html code
-rw-r--r--client/src/app/core/renderer/html-renderer.service.ts23
-rw-r--r--client/src/app/core/renderer/markdown.service.ts32
-rw-r--r--server/lib/emailer.ts32
-rw-r--r--shared/core-utils/index.ts4
-rw-r--r--shared/core-utils/renderer/html.ts21
-rw-r--r--shared/core-utils/renderer/index.ts2
-rw-r--r--shared/core-utils/renderer/markdown.ts23
7 files changed, 67 insertions, 70 deletions
diff --git a/client/src/app/core/renderer/html-renderer.service.ts b/client/src/app/core/renderer/html-renderer.service.ts
index 302d92ed9..1fe91b96b 100644
--- a/client/src/app/core/renderer/html-renderer.service.ts
+++ b/client/src/app/core/renderer/html-renderer.service.ts
@@ -1,5 +1,6 @@
1import { Injectable } from '@angular/core' 1import { Injectable } from '@angular/core'
2import { LinkifierService } from './linkifier.service' 2import { LinkifierService } from './linkifier.service'
3import { SANITIZE_OPTIONS } from '@shared/core-utils/renderer/html'
3 4
4@Injectable() 5@Injectable()
5export class HtmlRendererService { 6export class HtmlRendererService {
@@ -25,27 +26,7 @@ export class HtmlRendererService {
25 // Convert possible markdown to html 26 // Convert possible markdown to html
26 const html = this.linkifier.linkify(text) 27 const html = this.linkifier.linkify(text)
27 28
28 return this.sanitizeHtml(html, { 29 return this.sanitizeHtml(html, SANITIZE_OPTIONS)
29 allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ],
30 allowedSchemes: [ 'http', 'https' ],
31 allowedAttributes: {
32 'a': [ 'href', 'class', 'target', 'rel' ]
33 },
34 transformTags: {
35 a: (tagName, attribs) => {
36 let rel = 'noopener noreferrer'
37 if (attribs.rel === 'me') rel += ' me'
38
39 return {
40 tagName,
41 attribs: Object.assign(attribs, {
42 target: '_blank',
43 rel
44 })
45 }
46 }
47 }
48 })
49 } 30 }
50 31
51 private async loadSanitizeHtml () { 32 private async loadSanitizeHtml () {
diff --git a/client/src/app/core/renderer/markdown.service.ts b/client/src/app/core/renderer/markdown.service.ts
index 0e5c2ed75..0fde3f99d 100644
--- a/client/src/app/core/renderer/markdown.service.ts
+++ b/client/src/app/core/renderer/markdown.service.ts
@@ -1,6 +1,13 @@
1import * as MarkdownIt from 'markdown-it' 1import * as MarkdownIt from 'markdown-it'
2import { buildVideoLink } from 'src/assets/player/utils' 2import { buildVideoLink } from 'src/assets/player/utils'
3import { Injectable } from '@angular/core' 3import { Injectable } from '@angular/core'
4import {
5 COMPLETE_RULES,
6 ENHANCED_RULES,
7 ENHANCED_WITH_HTML_RULES,
8 TEXT_RULES,
9 TEXT_WITH_HTML_RULES
10} from '@shared/core-utils/renderer/markdown'
4import { HtmlRendererService } from './html-renderer.service' 11import { HtmlRendererService } from './html-renderer.service'
5 12
6type MarkdownParsers = { 13type MarkdownParsers = {
@@ -25,21 +32,6 @@ type MarkdownParserConfigs = {
25 32
26@Injectable() 33@Injectable()
27export class MarkdownService { 34export class MarkdownService {
28 static TEXT_RULES = [
29 'linkify',
30 'autolink',
31 'emphasis',
32 'link',
33 'newline',
34 'list'
35 ]
36 static TEXT_WITH_HTML_RULES = MarkdownService.TEXT_RULES.concat([ 'html_inline', 'html_block' ])
37
38 static ENHANCED_RULES = MarkdownService.TEXT_RULES.concat([ 'image' ])
39 static ENHANCED_WITH_HTML_RULES = MarkdownService.TEXT_WITH_HTML_RULES.concat([ 'image' ])
40
41 static COMPLETE_RULES = MarkdownService.ENHANCED_WITH_HTML_RULES.concat([ 'block', 'inline', 'heading', 'paragraph' ])
42
43 private markdownParsers: MarkdownParsers = { 35 private markdownParsers: MarkdownParsers = {
44 textMarkdownIt: null, 36 textMarkdownIt: null,
45 textWithHTMLMarkdownIt: null, 37 textWithHTMLMarkdownIt: null,
@@ -48,13 +40,13 @@ export class MarkdownService {
48 completeMarkdownIt: null 40 completeMarkdownIt: null
49 } 41 }
50 private parsersConfig: MarkdownParserConfigs = { 42 private parsersConfig: MarkdownParserConfigs = {
51 textMarkdownIt: { rules: MarkdownService.TEXT_RULES, html: false }, 43 textMarkdownIt: { rules: TEXT_RULES, html: false },
52 textWithHTMLMarkdownIt: { rules: MarkdownService.TEXT_WITH_HTML_RULES, html: true, escape: true }, 44 textWithHTMLMarkdownIt: { rules: TEXT_WITH_HTML_RULES, html: true, escape: true },
53 45
54 enhancedMarkdownIt: { rules: MarkdownService.ENHANCED_RULES, html: false }, 46 enhancedMarkdownIt: { rules: ENHANCED_RULES, html: false },
55 enhancedWithHTMLMarkdownIt: { rules: MarkdownService.ENHANCED_WITH_HTML_RULES, html: true, escape: true }, 47 enhancedWithHTMLMarkdownIt: { rules: ENHANCED_WITH_HTML_RULES, html: true, escape: true },
56 48
57 completeMarkdownIt: { rules: MarkdownService.COMPLETE_RULES, html: true } 49 completeMarkdownIt: { rules: COMPLETE_RULES, html: true }
58 } 50 }
59 51
60 constructor (private htmlRenderer: HtmlRendererService) {} 52 constructor (private htmlRenderer: HtmlRendererService) {}
diff --git a/server/lib/emailer.ts b/server/lib/emailer.ts
index 40f278608..650a3c090 100644
--- a/server/lib/emailer.ts
+++ b/server/lib/emailer.ts
@@ -5,6 +5,7 @@ import { join } from 'path'
5import { VideoChannelModel } from '@server/models/video/video-channel' 5import { VideoChannelModel } from '@server/models/video/video-channel'
6import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist' 6import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist'
7import { MVideoImport, MVideoImportVideo } from '@server/types/models/video/video-import' 7import { MVideoImport, MVideoImportVideo } from '@server/types/models/video/video-import'
8import { SANITIZE_OPTIONS, TEXT_WITH_HTML_RULES } from '@shared/core-utils'
8import { AbuseState, EmailPayload, UserAbuse } from '@shared/models' 9import { AbuseState, EmailPayload, UserAbuse } from '@shared/models'
9import { SendEmailOptions } from '../../shared/models/server/emailer.model' 10import { SendEmailOptions } from '../../shared/models/server/emailer.model'
10import { isTestInstance, root } from '../helpers/core-utils' 11import { isTestInstance, root } from '../helpers/core-utils'
@@ -20,14 +21,7 @@ const markdownItEmoji = require('markdown-it-emoji/light')
20const MarkdownItClass = require('markdown-it') 21const MarkdownItClass = require('markdown-it')
21const markdownIt = new MarkdownItClass('default', { linkify: true, breaks: true, html: true }) 22const markdownIt = new MarkdownItClass('default', { linkify: true, breaks: true, html: true })
22 23
23markdownIt.enable([ 24markdownIt.enable(TEXT_WITH_HTML_RULES)
24 'linkify',
25 'autolink',
26 'emphasis',
27 'link',
28 'newline',
29 'list'
30])
31 25
32markdownIt.use(markdownItEmoji) 26markdownIt.use(markdownItEmoji)
33 27
@@ -39,27 +33,7 @@ const toSafeHtml = text => {
39 const html = markdownIt.render(textWithLineFeed) 33 const html = markdownIt.render(textWithLineFeed)
40 34
41 // Convert to safe Html 35 // Convert to safe Html
42 return sanitizeHtml(html, { 36 return sanitizeHtml(html, SANITIZE_OPTIONS)
43 allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ],
44 allowedSchemes: [ 'http', 'https' ],
45 allowedAttributes: {
46 a: [ 'href', 'class', 'target', 'rel' ]
47 },
48 transformTags: {
49 a: (tagName, attribs) => {
50 let rel = 'noopener noreferrer'
51 if (attribs.rel === 'me') rel += ' me'
52
53 return {
54 tagName,
55 attribs: Object.assign(attribs, {
56 target: '_blank',
57 rel
58 })
59 }
60 }
61 }
62 })
63} 37}
64 38
65const Email = require('email-templates') 39const Email = require('email-templates')
diff --git a/shared/core-utils/index.ts b/shared/core-utils/index.ts
index 54e233522..42d7cab1d 100644
--- a/shared/core-utils/index.ts
+++ b/shared/core-utils/index.ts
@@ -1,3 +1,7 @@
1export * from './abuse'
2export * from './i18n'
1export * from './logs' 3export * from './logs'
2export * from './miscs' 4export * from './miscs'
3export * from './plugins' 5export * from './plugins'
6export * from './renderer'
7export * from './users'
diff --git a/shared/core-utils/renderer/html.ts b/shared/core-utils/renderer/html.ts
new file mode 100644
index 000000000..37ae5147c
--- /dev/null
+++ b/shared/core-utils/renderer/html.ts
@@ -0,0 +1,21 @@
1export const SANITIZE_OPTIONS = {
2 allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ],
3 allowedSchemes: [ 'http', 'https' ],
4 allowedAttributes: {
5 a: [ 'href', 'class', 'target', 'rel' ]
6 },
7 transformTags: {
8 a: (tagName, attribs) => {
9 let rel = 'noopener noreferrer'
10 if (attribs.rel === 'me') rel += ' me'
11
12 return {
13 tagName,
14 attribs: Object.assign(attribs, {
15 target: '_blank',
16 rel
17 })
18 }
19 }
20 }
21}
diff --git a/shared/core-utils/renderer/index.ts b/shared/core-utils/renderer/index.ts
new file mode 100644
index 000000000..0ad29d782
--- /dev/null
+++ b/shared/core-utils/renderer/index.ts
@@ -0,0 +1,2 @@
1export * from './markdown'
2export * from './html'
diff --git a/shared/core-utils/renderer/markdown.ts b/shared/core-utils/renderer/markdown.ts
new file mode 100644
index 000000000..dff746d87
--- /dev/null
+++ b/shared/core-utils/renderer/markdown.ts
@@ -0,0 +1,23 @@
1export const TEXT_RULES = [
2 'linkify',
3 'autolink',
4 'emphasis',
5 'link',
6 'newline',
7 'list'
8]
9
10export const TEXT_WITH_HTML_RULES = TEXT_RULES.concat([
11 'html_inline',
12 'html_block'
13])
14
15export const ENHANCED_RULES = TEXT_RULES.concat([ 'image' ])
16export const ENHANCED_WITH_HTML_RULES = TEXT_WITH_HTML_RULES.concat([ 'image' ])
17
18export const COMPLETE_RULES = ENHANCED_WITH_HTML_RULES.concat([
19 'block',
20 'inline',
21 'heading',
22 'paragraph'
23])