diff --git a/cspell.json b/cspell.json index 02c1c1e801..c60ae1e524 100644 --- a/cspell.json +++ b/cspell.json @@ -143,7 +143,8 @@ "BPMECM", "berseria", "zestiria", - "validatable" + "validatable", + "edjs" ], "dictionaries": [ "html", diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/display-rich-text/display-rich-text.widget.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/display-rich-text/display-rich-text.widget.spec.ts index d63d815b8e..24c8212237 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/display-rich-text/display-rich-text.widget.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/display-rich-text/display-rich-text.widget.spec.ts @@ -19,7 +19,6 @@ import { DebugElement } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { CoreTestingModule } from '@alfresco/adf-core'; - import { DisplayRichTextWidgetComponent } from './display-rich-text.widget'; describe('DisplayRichTextWidgetComponent', () => { @@ -44,28 +43,40 @@ describe('DisplayRichTextWidgetComponent', () => { text: 'Editor.js', level: 1 } + }, + { + id: '2', + type: 'paragraph', + data: { + text: 'Display some formatted text' + } + } + ], + version: 1 + } + }; + + const mockUnsafeFormField: any = { + id: 'fake-unsafe-form-field', + name: 'fake-label', + value: { + time: 1658154611110, + blocks: [ + { + id: '1', + type: 'paragraph', + data: { + text: '' + } } ], version: 1 - }, - required: false, - readOnly: false, - overrideId: false, - colspan: 1, - placeholder: null, - minLength: 0, - maxLength: 0, - params: { - existingColspan: 1, - maxColspan: 1 } }; beforeEach(() => { TestBed.configureTestingModule({ - imports: [ - CoreTestingModule - ] + imports: [CoreTestingModule] }); fixture = TestBed.createComponent(DisplayRichTextWidgetComponent); widget = fixture.componentInstance; @@ -79,11 +90,22 @@ describe('DisplayRichTextWidgetComponent', () => { }); it('should parse editorjs data to html', async () => { - const expectedHtml = '

Editor.js

'; + const expectedHtml = '

Editor.js

Display some formatted text

'; + fixture.detectChanges(); await fixture.whenStable(); + const parsedHtmlEl = debugEl.query(By.css(cssSelector.parsedHTML)); expect(parsedHtmlEl.nativeElement.innerHTML).toEqual(expectedHtml); }); + it('should sanitize unsafe HTML', async () => { + widget.field = mockUnsafeFormField; + + fixture.detectChanges(); + await fixture.whenStable(); + + const parsedHtmlEl = debugEl.query(By.css(cssSelector.parsedHTML)); + expect(parsedHtmlEl.nativeElement.innerHTML.includes('')).toBe(false); + }); }); diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/display-rich-text/display-rich-text.widget.ts b/lib/process-services-cloud/src/lib/form/components/widgets/display-rich-text/display-rich-text.widget.ts index d2ae1168b5..d9cdd470f5 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/display-rich-text/display-rich-text.widget.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/display-rich-text/display-rich-text.widget.ts @@ -17,10 +17,11 @@ /* eslint-disable @angular-eslint/component-selector */ -import { Component, OnInit, ViewEncapsulation } from '@angular/core'; +import { Component, OnInit, SecurityContext, ViewEncapsulation } from '@angular/core'; import { WidgetComponent, FormService } from '@alfresco/adf-core'; -/* cspell:disable-next-line */ import edjsHTML from 'editorjs-html'; +import { DomSanitizer } from '@angular/platform-browser'; + @Component({ selector: 'display-rich-text', templateUrl: './display-rich-text.widget.html', @@ -39,16 +40,23 @@ import edjsHTML from 'editorjs-html'; encapsulation: ViewEncapsulation.None }) export class DisplayRichTextWidgetComponent extends WidgetComponent implements OnInit { - parsedHTML: any; - constructor(public formService: FormService) { + constructor(public formService: FormService, private readonly sanitizer: DomSanitizer) { super(formService); } ngOnInit(): void { - /* cspell:disable-next-line */ this.parsedHTML = edjsHTML().parseStrict(this.field.value); + + if (!(this.parsedHTML instanceof Error)) { + this.sanitizeHtmlContent(); + } else { + throw this.parsedHTML; + } } + private sanitizeHtmlContent(): void { + this.parsedHTML = this.sanitizer.sanitize(SecurityContext.HTML, this.parsedHTML.join('')); + } }