Merge pull request #5026 from tsiegleauq/remove-duplicate-trust-implementation

Add trust pipe and remove duplicated functions
This commit is contained in:
Emanuel Schütze 2019-09-19 14:56:12 +02:00 committed by GitHub
commit ee50191da6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 173 additions and 299 deletions

View File

@ -1,5 +1,4 @@
import { Injectable } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs';
@ -51,12 +50,7 @@ export interface ParagraphToChoose {
/**
* The raw HTML of this paragraph.
*/
rawHtml: string;
/**
* The HTML of this paragraph, wrapped in a `SafeHtml`-object.
*/
safeHtml: SafeHtml;
html: string;
/**
* The first line number
@ -186,7 +180,6 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
* @param mapperService Maps collection strings to classes
* @param dataSend sending changed objects
* @param httpService OpenSlides own Http service
* @param sanitizer DOM Sanitizer
* @param lineNumbering Line numbering for motion text
* @param diff Display changes in motion text as diff.
* @param personalNoteService service fo personal notes
@ -201,7 +194,6 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
relationManager: RelationManagerService,
config: ConfigService,
private httpService: HttpService,
private readonly sanitizer: DomSanitizer,
private readonly lineNumbering: LinenumberingService,
private readonly diff: DiffService,
private operator: OperatorService
@ -713,8 +705,7 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
const affected: LineNumberRange = this.lineNumbering.getLineNumberRange(paragraph);
return {
paragraphNo: index,
safeHtml: this.sanitizer.bypassSecurityTrustHtml(paragraph),
rawHtml: this.lineNumbering.stripLineNumbers(paragraph),
html: this.lineNumbering.stripLineNumbers(paragraph),
lineFrom: affected.from,
lineTo: affected.to
};

View File

@ -1,6 +1,6 @@
<mat-card class="os-card">
<div>
<div *ngIf="legalNotice" class="legal-notice-text" [innerHtml]="legalNotice"></div>
<div *ngIf="legalNotice" class="legal-notice-text" [innerHtml]="legalNotice | trust: 'html'"></div>
<div *ngIf="!legalNotice" translate>
The event manager hasn't set up a legal notice yet.
</div>

View File

@ -27,13 +27,13 @@
<mat-card class="os-card" *ngIf="entry.value !== '' && !entry.blockProperties">
<div class="key-part">{{ entry.key | translate }}</div>
<div *ngIf="!entry.trusted">{{ entry.value }}</div>
<div *ngIf="entry.trusted" [innerHTML]="sanitize(entry.value)"></div>
<div *ngIf="entry.trusted" [innerHTML]="entry.value | trust: 'html'"></div>
</mat-card>
<mat-card class="os-card" *ngIf="entry.blockProperties">
<div *ngFor="let property of entry.blockProperties">
<div class="key-part">{{ property.key | translate }}</div>
<div *ngIf="!property.trusted">{{ property.value }}</div>
<div *ngIf="property.trusted" [innerHTML]="sanitize(property.value)"></div>
<div *ngIf="property.trusted" [innerHTML]="property.value | trust: 'html'"></div>
</div>
</mat-card>
</div>

View File

@ -1,5 +1,4 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { SearchProperty } from 'app/core/ui-services/search.service';
import { BaseViewModel } from 'app/site/base/base-view-model';
@ -45,10 +44,8 @@ export class PreviewComponent implements OnDestroy {
/**
* Default constructor
*
* @param sanitizer DomSanitizer
*/
public constructor(private sanitizer: DomSanitizer, private cd: ChangeDetectorRef) {}
public constructor(private cd: ChangeDetectorRef) {}
/**
* detach the change detection
@ -56,15 +53,4 @@ export class PreviewComponent implements OnDestroy {
public ngOnDestroy(): void {
this.cd.detach();
}
/**
* Function to sanitize any text to show html.
*
* @param text The text to sanitize.
*
* @returns {SafeHtml} The sanitized text as `HTML`.
*/
public sanitize(text: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(text);
}
}

View File

@ -1,5 +1,5 @@
<mat-card class="os-card">
<div *ngIf="privacyPolicy" [innerHtml]="privacyPolicy"></div>
<div *ngIf="privacyPolicy" [innerHtml]="privacyPolicy | trust: 'html'"></div>
<div *ngIf="!privacyPolicy" translate>
The event manager hasn't set up a privacy policy yet.
</div>

View File

@ -0,0 +1,11 @@
import { inject } from '@angular/core/testing';
import { DomSanitizer } from '@angular/platform-browser';
import { TrustPipe } from './trust.pipe';
describe('TrustHtmlPipe', () => {
it('create an instance', inject([DomSanitizer], (domSanitizer: DomSanitizer) => {
const pipe = new TrustPipe(domSanitizer);
expect(pipe).toBeTruthy();
}));
});

View File

@ -0,0 +1,29 @@
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeHtml, SafeResourceUrl, SafeScript, SafeStyle, SafeUrl } from '@angular/platform-browser';
/**
* Pipe to use bypassSecurityTrust
*/
@Pipe({
name: 'trust'
})
export class TrustPipe implements PipeTransform {
public constructor(protected sanitizer: DomSanitizer) {}
public transform(value: any, type: string): SafeHtml | SafeStyle | SafeScript | SafeUrl | SafeResourceUrl {
switch (type) {
case 'html':
return this.sanitizer.bypassSecurityTrustHtml(value);
case 'style':
return this.sanitizer.bypassSecurityTrustStyle(value);
case 'script':
return this.sanitizer.bypassSecurityTrustScript(value);
case 'url':
return this.sanitizer.bypassSecurityTrustUrl(value);
case 'resourceUrl':
return this.sanitizer.bypassSecurityTrustResourceUrl(value);
default:
throw new Error(`Invalid safe type specified: ${type}`);
}
}
}

View File

@ -107,6 +107,7 @@ import { PreviewComponent } from './components/preview/preview.component';
import { PdfViewerModule } from 'ng2-pdf-viewer';
import { GlobalSpinnerComponent } from 'app/site/common/components/global-spinner/global-spinner.component';
import { HeightResizingDirective } from './directives/height-resizing.directive';
import { TrustPipe } from './pipes/trust.pipe';
/**
* Share Module for all "dumb" components and pipes.
@ -254,7 +255,8 @@ import { HeightResizingDirective } from './directives/height-resizing.directive'
GlobalSpinnerComponent,
OverlayComponent,
PreviewComponent,
NgxMaterialTimepickerModule
NgxMaterialTimepickerModule,
TrustPipe
],
declarations: [
PermsDirective,
@ -299,7 +301,8 @@ import { HeightResizingDirective } from './directives/height-resizing.directive'
SuperSearchComponent,
OverlayComponent,
PreviewComponent,
HeightResizingDirective
HeightResizingDirective,
TrustPipe
],
providers: [
{
@ -313,7 +316,8 @@ import { HeightResizingDirective } from './directives/height-resizing.directive'
SortFilterBarComponent,
SortBottomSheetComponent,
DecimalPipe,
ProgressSnackBarComponent
ProgressSnackBarComponent,
TrustPipe
],
entryComponents: [
SortBottomSheetComponent,

View File

@ -76,7 +76,7 @@
<div *ngIf="assignment">
<div
*ngIf="assignment.assignment.description"
[innerHTML]="getSanitizedText(assignment.assignment.description)"
[innerHTML]="assignment.assignment.description | trust: 'html'"
></div>
</div>
<div class="meta-info-grid">

View File

@ -1,7 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatSnackBar } from '@angular/material';
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
@ -181,8 +181,7 @@ export class AssignmentDetailComponent extends BaseViewComponent implements OnIn
private tagRepo: TagRepositoryService,
private promptService: PromptService,
private pdfService: AssignmentPdfExportService,
private mediafileRepo: MediafileRepositoryService,
private sanitizer: DomSanitizer
private mediafileRepo: MediafileRepositoryService
) {
super(title, translate, matSnackBar);
this.subscriptions.push(
@ -503,17 +502,6 @@ export class AssignmentDetailComponent extends BaseViewComponent implements OnIn
.then(null, this.raiseError);
}
/**
* Sanitize the text.
*
* @param text {string} The text to display.
*
* @returns {SafeHtml} the sanitized text.
*/
public getSanitizedText(text: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(text);
}
public addToAgenda(): void {
this.itemRepo.addItemToAgenda(this.assignment).then(null, this.raiseError);
}

View File

@ -8,6 +8,6 @@
<div class="app-content">
<h1>{{ welcomeTitle | translate }}</h1>
<div [innerHTML]="welcomeText"></div>
<div [innerHTML]="welcomeText | trust: 'html'"></div>
</div>
</mat-card>

View File

@ -1,5 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
import { Title } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core'; // showcase
@ -16,7 +16,7 @@ import { ConfigService } from 'app/core/ui-services/config.service';
})
export class StartComponent extends BaseComponent implements OnInit {
public welcomeTitle: string;
public welcomeText: SafeHtml;
public welcomeText: string;
/**
* Constructor of the StartComponent
@ -24,14 +24,8 @@ export class StartComponent extends BaseComponent implements OnInit {
* @param titleService the title serve
* @param translate to translation module
* @param configService read out config values
* @param sanitizer
*/
public constructor(
titleService: Title,
translate: TranslateService,
private configService: ConfigService,
private sanitizer: DomSanitizer
) {
public constructor(titleService: Title, translate: TranslateService, private configService: ConfigService) {
super(titleService, translate);
}
@ -50,18 +44,7 @@ export class StartComponent extends BaseComponent implements OnInit {
// set the welcome text
this.configService.get<string>('general_event_welcome_text').subscribe(welcomeText => {
this.welcomeText = this.sanitizeText(this.translate.instant(welcomeText));
this.welcomeText = this.translate.instant(welcomeText);
});
}
/**
* Sanitizes the value from database.
*
* @param text The plain text to sanitize.
*
* @returns {SafeHtml} Html, that will be rendered with styles and so on...
*/
public sanitizeText(text: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(text);
}
}

View File

@ -84,7 +84,7 @@
<div *pblNgridCellDef="'summary'; row as motion" class="cell-slot fill">
<a class="detail-link" [routerLink]="motion.getDetailStateURL()"></a>
<div class="innerTable">
<div class="motion-text" [innerHtml]="sanitizeText(getAmendmentSummary(motion))"></div>
<div class="motion-text" [innerHtml]="getAmendmentSummary(motion) | trust: 'html'"></div>
</div>
</div>

View File

@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';
import { MatDialog, MatSnackBar } from '@angular/material';
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, ParamMap } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
@ -94,7 +94,6 @@ export class AmendmentListComponent extends BaseListViewComponent<ViewMotion> im
public motionSortService: MotionSortListService,
public amendmentSortService: AmendmentSortListService,
public amendmentFilterService: AmendmentFilterListService,
private sanitizer: DomSanitizer,
private dialog: MatDialog,
private motionExport: MotionExportService,
private linenumberingService: LinenumberingService,
@ -163,8 +162,4 @@ export class AmendmentListComponent extends BaseListViewComponent<ViewMotion> im
const parentMotion = this.parentMotionId ? this.motionRepo.getViewModel(this.parentMotionId) : undefined;
this.pdfExport.exportAmendmentList(this.dataSource.filteredData, parentMotion);
}
public sanitizeText(text: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(text);
}
}

View File

@ -12,7 +12,11 @@
<!-- Next-button -->
<div class="extra-controls-slot">
<div *ngIf="matStepper.selectedIndex === 0">
<button mat-button [disabled]="contentForm.value.selectedParagraphs.length === 0" (click)="matStepper.next()">
<button
mat-button
[disabled]="contentForm.value.selectedParagraphs.length === 0"
(click)="matStepper.next()"
>
<span class="upper" translate>Next</span>
</button>
</div>
@ -48,7 +52,7 @@
[checked]="isParagraphSelected(paragraph)"
>
</mat-radio-button>
<div class="paragraph-text motion-text" [innerHTML]="paragraph.safeHtml"></div>
<div class="paragraph-text motion-text" [innerHTML]="paragraph.html | trust: 'html'"></div>
</section>
</div>
</mat-step>

View File

@ -158,7 +158,7 @@ export class AmendmentCreateWizardComponent extends BaseViewComponent {
});
this.contentForm.addControl(
'text_' + paragraph.paragraphNo,
new FormControl(paragraph.rawHtml, Validators.required)
new FormControl(paragraph.html, Validators.required)
);
this.contentForm.patchValue({
selectedParagraphs: [paragraph]
@ -195,7 +195,7 @@ export class AmendmentCreateWizardComponent extends BaseViewComponent {
this.contentForm.addControl(
'text_' + paragraph.paragraphNo,
new FormControl(paragraph.rawHtml, Validators.required)
new FormControl(paragraph.html, Validators.required)
);
this.contentForm.patchValue({
selectedParagraphs: newParagraphs

View File

@ -11,7 +11,7 @@
<ng-container class="meta-text-block-content">
<ng-container *ngIf="!isCommentEdited(section)">
<div *ngIf="comments[section.id]" [innerHTML]="sanitizeText(comments[section.id].comment)"></div>
<div *ngIf="comments[section.id]" [innerHTML]="comments[section.id].comment | trust: 'html'"></div>
<div class="no-content" *ngIf="!comments[section.id] || !comments[section.id].comment" translate>
No comment
</div>

View File

@ -1,7 +1,7 @@
import { Component, Input } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
import { Title } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
@ -65,7 +65,6 @@ export class MotionCommentsComponent extends BaseViewComponent {
* @param formBuilder Form builder to handle text editing
* @param operator service to get the sections
* @param pdfService service to export a comment section to pdf
* @param sanitizer to sanitize the inner html text
* @param titleService set the browser title
* @param translate the translation service
* @param matSnackBar showing errors and information
@ -75,7 +74,6 @@ export class MotionCommentsComponent extends BaseViewComponent {
private formBuilder: FormBuilder,
private operator: OperatorService,
private pdfService: MotionPdfExportService,
private sanitizer: DomSanitizer,
titleService: Title,
translate: TranslateService,
matSnackBar: MatSnackBar
@ -189,15 +187,4 @@ export class MotionCommentsComponent extends BaseViewComponent {
public pdfExportSection(section: ViewMotionCommentSection): void {
this.pdfService.exportComment(section, this.motion);
}
/**
* Sanitize the text to be safe.
*
* @param text to be sanitized.
*
* @returns SafeHtml
*/
public sanitizeText(text: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(text);
}
}

View File

@ -67,7 +67,7 @@
[attr.data-change-id]="changedTitle.getChangeId()"
>
<div class="bold">{{ 'Changed title' | translate }}:</div>
<div [innerHTML]="getFormattedTitleDiff()"></div>
<div [innerHTML]="getFormattedTitleDiff() | trust: 'html'"></div>
</div>
</div>
</div>
@ -122,7 +122,7 @@
[class.line-numbers-inline]="isLineNumberingInline()"
[class.line-numbers-outside]="isLineNumberingOutside()"
[attr.data-change-id]="change.getChangeId()"
[innerHTML]="getDiff(change)"
[innerHTML]="getDiff(change) | trust: 'html'"
></div>
</div>
</div>

View File

@ -1,7 +1,7 @@
import { AfterViewInit, Component, ElementRef, EventEmitter, Input, Output } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
import { Title } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
@ -81,7 +81,6 @@ export class MotionDetailDiffComponent extends BaseViewComponent implements Afte
* @param title
* @param translate
* @param matSnackBar
* @param sanitizer
* @param diff
* @param recoRepo
* @param dialogService
@ -93,7 +92,6 @@ export class MotionDetailDiffComponent extends BaseViewComponent implements Afte
title: Title,
protected translate: TranslateService, // protected required for ng-translate-extract
matSnackBar: MatSnackBar,
private sanitizer: DomSanitizer,
private diff: DiffService,
private recoRepo: ChangeRecommendationRepositoryService,
private dialogService: MatDialog,
@ -157,9 +155,8 @@ export class MotionDetailDiffComponent extends BaseViewComponent implements Afte
* Returns the diff string from the motion to the change
* @param {ViewUnifiedChange} change
*/
public getDiff(change: ViewUnifiedChange): SafeHtml {
const html = this.diff.getChangeDiff(this.motion.text, change, this.lineLength, this.highlightedLine);
return this.sanitizer.bypassSecurityTrustHtml(html);
public getDiff(change: ViewUnifiedChange): string {
return this.diff.getChangeDiff(this.motion.text, change, this.lineLength, this.highlightedLine);
}
/**
@ -253,9 +250,9 @@ export class MotionDetailDiffComponent extends BaseViewComponent implements Afte
return this.changes.find((obj: ViewUnifiedChange) => obj.isTitleChange());
}
public getFormattedTitleDiff(): SafeHtml {
public getFormattedTitleDiff(): string {
const change = this.getTitleChangingObject();
return this.sanitizer.bypassSecurityTrustHtml(this.recoRepo.getTitleChangesAsDiff(this.motion.title, change));
return this.recoRepo.getTitleChangesAsDiff(this.motion.title, change);
}
/**

View File

@ -655,7 +655,7 @@
></os-motion-detail-original-change-recommendations>
<div
*ngIf="!isLineNumberingOutside() || !isRecoMode(ChangeRecoMode.Original)"
[innerHTML]="sanitizedText(getFormattedTextPlain())"
[innerHTML]="getFormattedTextPlain() | trust: 'html'"
></div>
</div>
<os-motion-detail-diff
@ -693,7 +693,7 @@
<div
class="motion-text line-numbers-none"
*ngIf="!editMotion && motion.isStatuteAmendment()"
[innerHTML]="getFormattedStatuteAmendment()"
[innerHTML]="getFormattedStatuteAmendment() | trust: 'html'"
></div>
<!-- The HTML Editor for motions and traditional amendments -->
@ -755,7 +755,7 @@
>
<span translate>Reason</span>&nbsp;<span *ngIf="reasonRequired && editMotion">*</span>
</h3>
<div class="motion-text" *ngIf="!editMotion"><div [innerHtml]="sanitizedText(motion.reason)"></div></div>
<div class="motion-text" *ngIf="!editMotion" [innerHtml]="motion.reason | trust: 'html'"></div>
<!-- The HTML Editor -->
<editor
@ -883,9 +883,10 @@
{{ 'Line' | translate }} {{ paragraph.diffLineFrom }} - {{ paragraph.diffLineTo - 1 }}:
</h3>
<div class="paragraphcontext" [innerHtml]="sanitizedText(paragraph.textPre)"></div>
<div [innerHtml]="sanitizedText(paragraph.text)"></div>
<div class="paragraphcontext" [innerHtml]="sanitizedText(paragraph.textPost)"></div>
<!-- TODO: Seems to be directly duplicated in the slide -->
<div class="paragraphcontext" [innerHtml]="paragraph.textPre | trust: 'html'"></div>
<div [innerHtml]="paragraph.text | trust: 'html'"></div>
<div class="paragraphcontext" [innerHtml]="paragraph.textPost | trust: 'html'"></div>
</div>
</div>
<div *ngIf="!motion.diffLines">

View File

@ -4,7 +4,7 @@ import { MatCheckboxChange } from '@angular/material/checkbox';
import { ErrorStateMatcher } from '@angular/material/core';
import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
@ -22,7 +22,7 @@ import { WorkflowRepositoryService } from 'app/core/repositories/motions/workflo
import { TagRepositoryService } from 'app/core/repositories/tags/tag-repository.service';
import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service';
import { ConfigService } from 'app/core/ui-services/config.service';
import { DiffLinesInParagraph, DiffService, LineRange } from 'app/core/ui-services/diff.service';
import { DiffLinesInParagraph, LineRange } from 'app/core/ui-services/diff.service';
import { LinenumberingService } from 'app/core/ui-services/linenumbering.service';
import { PersonalNoteService } from 'app/core/ui-services/personal-note.service';
import { PromptService } from 'app/core/ui-services/prompt.service';
@ -398,12 +398,10 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
* @param mediafileRepo Mediafile Repository
* @param DS The DataStoreService
* @param configService The configuration provider
* @param sanitizer For making HTML SafeHTML
* @param promptService ensure safe deletion
* @param pdfExport export the motion to pdf
* @param personalNoteService: personal comments and favorite marker
* @param linenumberingService The line numbering service
* @param diffService The diff service
* @param categoryRepo Repository for categories
* @param viewModelStore accessing view models
* @param categoryRepo access the category repository
@ -433,12 +431,10 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
private changeRecoRepo: ChangeRecommendationRepositoryService,
private statuteRepo: StatuteParagraphRepositoryService,
private configService: ConfigService,
private sanitizer: DomSanitizer,
private promptService: PromptService,
private pdfExport: MotionPdfExportService,
private personalNoteService: PersonalNoteService,
private linenumberingService: LinenumberingService,
private diffService: DiffService,
private categoryRepo: CategoryRepositoryService,
private userRepo: UserRepositoryService,
private notifyService: NotifyService,
@ -861,17 +857,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
return this.repo.formatMotion(this.motion.id, this.crMode, changes, this.lineLength, this.highlightedLine);
}
/**
* Called from the template to make a HTML string compatible with [innerHTML]
* (otherwise line-number-data-attributes would be stripped out)
*
* @param {string} text
* @returns {SafeHtml}
*/
public sanitizedText(text: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(text);
}
/**
* If `this.motion` is an amendment, this returns the list of all changed paragraphs.
*
@ -882,34 +867,13 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
return this.repo.getAmendmentParagraphs(this.motion, this.lineLength, includeUnchanged);
}
/**
* If `this.motion` is an amendment, this returns a specified line range from the parent motion
* (e.g. to show the contect in which this amendment is happening)
*
* @param from the line number to start
* @param to the line number to stop
* @returns safe html strings
*/
public getParentMotionRange(from: number, to: number): SafeHtml {
const parentMotion = this.repo.getViewModel(this.motion.parent_id);
const str = this.diffService.extractMotionLineRange(
parentMotion.text,
{ from, to },
true,
this.lineLength,
this.highlightedLine
);
return this.sanitizer.bypassSecurityTrustHtml(str);
}
/**
* get the diff html from the statute amendment, as SafeHTML for [innerHTML]
*
* @returns safe html strings
*/
public getFormattedStatuteAmendment(): SafeHtml {
const diffHtml = this.repo.formatStatuteAmendment(this.statuteParagraphs, this.motion, this.lineLength);
return this.sanitizer.bypassSecurityTrustHtml(diffHtml);
public getFormattedStatuteAmendment(): string {
return this.repo.formatStatuteAmendment(this.statuteParagraphs, this.motion, this.lineLength);
}
public getChangesForDiffMode(): ViewUnifiedChange[] {

View File

@ -39,7 +39,7 @@
<!-- Content -->
<ng-container class="meta-text-block-content">
<ng-container *ngIf="!isEditMode">
<div *ngIf="motion && motion.personalNote" [innerHTML]="sanitizeText(personalNoteText)"></div>
<div *ngIf="motion && motion.personalNote" [innerHTML]="personalNoteText | trust: 'html'"></div>
<div class="no-content" *ngIf="!motion || !motion.hasNotes" translate>
No personal note
</div>

View File

@ -1,7 +1,7 @@
import { Component, Input } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { MatSnackBar } from '@angular/material';
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
import { Title } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
@ -46,7 +46,6 @@ export class PersonalNoteComponent extends BaseViewComponent {
* @param personalNoteService
* @param formBuilder
* @param pdfService
* @param sanitizer
*/
public constructor(
title: Title,
@ -54,8 +53,7 @@ export class PersonalNoteComponent extends BaseViewComponent {
matSnackBar: MatSnackBar,
private personalNoteService: PersonalNoteService,
formBuilder: FormBuilder,
private pdfService: MotionPdfExportService,
private sanitizer: DomSanitizer
private pdfService: MotionPdfExportService
) {
super(title, translate, matSnackBar);
this.personalNoteForm = formBuilder.group({
@ -102,15 +100,4 @@ export class PersonalNoteComponent extends BaseViewComponent {
public printPersonalNote(): void {
this.pdfService.exportPersonalNote(this.motion.personalNote, this.motion);
}
/**
* Sanitize the text to be safe.
*
* @param text to be sanitized.
*
* @returns SafeHtml
*/
public sanitizeText(text: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(text);
}
}

View File

@ -26,7 +26,7 @@
<mat-card>
<mat-card-title>{{ statuteParagraph.title }}</mat-card-title>
<mat-card-content>
<div [innerHTML]="statuteParagraph.text"></div>
<div [innerHTML]="statuteParagraph.text | trust: 'html'"></div>
</mat-card-content>
</mat-card>
<mat-action-row>

View File

@ -32,7 +32,7 @@
<div>
<span *ngIf="!editTopic">
<!-- Render topic text as HTML -->
<div [innerHTML]="sanitizedText(topic.text)"></div>
<div [innerHTML]="topic.text | trust: 'html'"></div>
</span>
</div>

View File

@ -1,7 +1,7 @@
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
@ -81,8 +81,7 @@ export class TopicDetailComponent extends BaseViewComponent {
private repo: TopicRepositoryService,
private promptService: PromptService,
private operator: OperatorService,
private itemRepo: ItemRepositoryService,
private sanitizer: DomSanitizer
private itemRepo: ItemRepositoryService
) {
super(title, translate, matSnackBar);
this.getTopicByUrl();
@ -241,16 +240,4 @@ export class TopicDetailComponent extends BaseViewComponent {
this.setEditMode(false);
}
}
/**
* Function to sanitize text.
* Necessary to render styles etc. correctly.
*
* @param text which will be sanitized.
*
* @returns safeHtml which can be displayed whithout loss.
*/
public sanitizedText(text: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(text);
}
}

View File

@ -315,7 +315,7 @@
<!-- About me -->
<div *ngIf="user.about_me">
<h4 translate>About me</h4>
<div [innerHTML]="sanitizedText(user.about_me)"></div>
<div [innerHTML]="user.about_me | trust: 'html'"></div>
</div>
<!-- Username -->

View File

@ -1,7 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
@ -97,8 +97,7 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
private operator: OperatorService,
private promptService: PromptService,
private pdfService: UserPdfExportService,
private groupRepo: GroupRepositoryService,
private sanitizer: DomSanitizer
private groupRepo: GroupRepositoryService
) {
super(title, translate, matSnackBar);
// prevent 'undefined' to appear in the ui
@ -422,18 +421,6 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
this.pdfService.exportSingleUserAccessPDF(this.user);
}
/**
* Function to sanitize the text.
* Necessary to render text etc. correctly.
*
* @param text which should be sanitized.
*
* @returns safeHtml which can be displayed.
*/
public sanitizedText(text: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(text);
}
/**
* (Re)- send an invitation email for this user after confirmation
*/

View File

@ -4,7 +4,7 @@
<h2 translate>Election</h2>
</div>
<div *ngIf="data.data && data.data.description" [innerHTML]="data.data.description"></div>
<div *ngIf="data.data && data.data.description" [innerHTML]="data.data.description | trust: 'html'"></div>
<h3 translate>Candidates</h3>
<ul *ngIf="data.data.assignment_related_users && data.data.assignment_related_users.length">

View File

@ -1,5 +1,5 @@
<div id="background" *ngIf="data">
<div id="message">
<div [innerHTML]="trustHTML(data.data.message)"></div>
<div [innerHTML]="data.data.message | trust: 'html'"></div>
</div>
</div>

View File

@ -1,5 +1,4 @@
import { Component, ViewEncapsulation } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { BaseSlideComponent } from 'app/slides/base-slide-component';
import { ProjectorMessageSlideData } from './projector-message-slide-data';
@ -11,11 +10,7 @@ import { ProjectorMessageSlideData } from './projector-message-slide-data';
encapsulation: ViewEncapsulation.None
})
export class ProjectorMessageSlideComponent extends BaseSlideComponent<ProjectorMessageSlideData> {
public constructor(private sanitizer: DomSanitizer) {
public constructor() {
super();
}
public trustHTML(html: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(html);
}
}

View File

@ -1,5 +1,9 @@
<div *ngIf="data">
<div id="sidebox" *ngIf="data.data.show_meta_box" [ngStyle]="{'margin-top': projector.show_header_footer ? '144px' : '94px'}">
<div
id="sidebox"
*ngIf="data.data.show_meta_box"
[ngStyle]="{ 'margin-top': projector.show_header_footer ? '144px' : '94px' }"
>
<!-- Submitters -->
<h3 translate>Submitters</h3>
<span *ngFor="let submitter of data.data.submitter; let last = last">
@ -13,9 +17,9 @@
</div>
</div>
<div [ngStyle]="{width: data.data.show_meta_box ? 'calc(100% - 250px)' : '100%'}">
<div [ngStyle]="{ width: data.data.show_meta_box ? 'calc(100% - 250px)' : '100%' }">
<!-- Title -->
<div class="spacer" [ngStyle]="{height: projector.show_header_footer ? '50px' : '0'}"></div>
<div class="spacer" [ngStyle]="{ height: projector.show_header_footer ? '50px' : '0' }"></div>
<div class="slidetitle">
<h1>
<span *ngIf="data.data.identifier">{{ data.data.identifier }}:</span>
@ -33,65 +37,67 @@
</div>
<div id="text-wrapper">
<div id="text" [ngStyle]="textDivStyles">
<!-- Text -->
<span *ngIf="isStatuteAmendment() || isParagraphBasedAmendment() || !!getFormattedText()" class="text-prefix-label">{{ preamble | translate }}</span>
<!-- Regular motions or traditional amendments -->
<ng-container *ngIf="!isStatuteAmendment() && !isParagraphBasedAmendment()">
<div
class="motion-text"
[class.line-numbers-none]="isLineNumberingNone()"
[class.line-numbers-inline]="isLineNumberingInline()"
[class.line-numbers-outside]="isLineNumberingOutside()"
<div id="text" [ngStyle]="textDivStyles">
<!-- Text -->
<span
*ngIf="isStatuteAmendment() || isParagraphBasedAmendment() || !!getFormattedText()"
class="text-prefix-label"
>{{ preamble | translate }}</span
>
<div *ngIf="getTitleChangingObject() && crMode === 'diff'">
<div class="bold">
{{ 'Changed title' | translate }}:
<!-- Regular motions or traditional amendments -->
<ng-container *ngIf="!isStatuteAmendment() && !isParagraphBasedAmendment()">
<div
class="motion-text"
[class.line-numbers-none]="isLineNumberingNone()"
[class.line-numbers-inline]="isLineNumberingInline()"
[class.line-numbers-outside]="isLineNumberingOutside()"
>
<div *ngIf="getTitleChangingObject() && crMode === 'diff'">
<div class="bold">{{ 'Changed title' | translate }}:</div>
<div [innerHTML]="getFormattedTitleDiff() | trust: 'html'"></div>
</div>
<div [innerHTML]="getFormattedTitleDiff()"></div>
<div *ngIf="getFormattedText()" [innerHTML]="getFormattedText() | trust: 'html'"></div>
</div>
<div *ngIf="getFormattedText()" [innerHTML]="sanitizedText(getFormattedText())"></div>
</div>
</ng-container>
</ng-container>
<!-- Statute amendments -->
<div
class="motion-text line-numbers-none"
*ngIf="isStatuteAmendment()"
[innerHTML]="getFormattedStatuteAmendment()"
></div>
<!-- Amendment text -->
<section class="text-holder" *ngIf="isParagraphBasedAmendment()">
<div class="alert alert-info" *ngIf="getAmendedParagraphs().length === 0">
<span translate>No changes at the text.</span>
</div>
<!-- Statute amendments -->
<div
*ngFor="let paragraph of getAmendedParagraphs()"
class="motion-text motion-text-diff amendment-view"
[class.line-numbers-none]="isLineNumberingNone()"
[class.line-numbers-inline]="isLineNumberingInline()"
[class.line-numbers-outside]="isLineNumberingOutside()"
>
<h3 *ngIf="paragraph.diffLineTo === paragraph.diffLineFrom + 1" class="amendment-line-header">
<span translate>Line</span> {{ paragraph.diffLineFrom }}:
</h3>
<h3 *ngIf="paragraph.diffLineTo !== paragraph.diffLineFrom + 1" class="amendment-line-header">
<span translate>Line</span> {{ paragraph.diffLineFrom }} - {{ paragraph.diffLineTo - 1 }}:
</h3>
class="motion-text line-numbers-none"
*ngIf="isStatuteAmendment()"
[innerHTML]="getFormattedStatuteAmendment() | trust: 'html'"
></div>
<div class="paragraph-context" [innerHtml]="sanitizedText(paragraph.textPre)"></div>
<div [innerHtml]="sanitizedText(paragraph.text)"></div>
<div class="paragraph-context" [innerHtml]="sanitizedText(paragraph.textPost)"></div>
<!-- Amendment text -->
<section class="text-holder" *ngIf="isParagraphBasedAmendment()">
<div class="alert alert-info" *ngIf="getAmendedParagraphs().length === 0">
<span translate>No changes at the text.</span>
</div>
<div
*ngFor="let paragraph of getAmendedParagraphs()"
class="motion-text motion-text-diff amendment-view"
[class.line-numbers-none]="isLineNumberingNone()"
[class.line-numbers-inline]="isLineNumberingInline()"
[class.line-numbers-outside]="isLineNumberingOutside()"
>
<h3 *ngIf="paragraph.diffLineTo === paragraph.diffLineFrom + 1" class="amendment-line-header">
<span translate>Line</span> {{ paragraph.diffLineFrom }}:
</h3>
<h3 *ngIf="paragraph.diffLineTo !== paragraph.diffLineFrom + 1" class="amendment-line-header">
<span translate>Line</span> {{ paragraph.diffLineFrom }} - {{ paragraph.diffLineTo - 1 }}:
</h3>
<div class="paragraph-context" [innerHtml]="paragraph.textPre | trust: 'html'"></div>
<div [innerHtml]="paragraph.text | trust: 'html'"></div>
<div class="paragraph-context" [innerHtml]="paragraph.textPost | trust: 'html'"></div>
</div>
</section>
<!-- Reason -->
<div *ngIf="data.data.reason">
<h3 translate>Reason</h3>
<div [innerHTML]="data.data.reason | trust: 'html'"></div>
</div>
</section>
<!-- Reason -->
<div *ngIf="data.data.reason">
<h3 translate>Reason</h3>
<div [innerHTML]="data.data.reason"></div>
</div>
</div>
</div>
</div>

View File

@ -1,5 +1,4 @@
import { Component, Input, ViewEncapsulation } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
@ -114,7 +113,6 @@ export class MotionSlideComponent extends BaseMotionSlideComponent<MotionSlideDa
translate: TranslateService,
motionRepo: MotionRepositoryService,
private changeRepo: ChangeRecommendationRepositoryService,
private sanitizer: DomSanitizer,
private lineNumbering: LinenumberingService,
private diff: DiffService
) {
@ -257,17 +255,6 @@ export class MotionSlideComponent extends BaseMotionSlideComponent<MotionSlideDa
return this.lnMode === LineNumberingMode.Outside;
}
/**
* Called from the template to make a HTML string compatible with [innerHTML]
* (otherwise line-number-data-attributes would be stripped out)
*
* @param {string} text
* @returns {SafeHtml}
*/
public sanitizedText(text: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(text);
}
/**
* Extracts a renderable HTML string representing the given line number range of this motion
*
@ -308,10 +295,9 @@ export class MotionSlideComponent extends BaseMotionSlideComponent<MotionSlideDa
return this.changeRepo.getTitleWithChanges(this.data.data.title, this.getTitleChangingObject(), this.crMode);
}
public getFormattedTitleDiff(): SafeHtml {
public getFormattedTitleDiff(): string {
const change = this.getTitleChangingObject();
const diff = this.changeRepo.getTitleChangesAsDiff(this.data.data.title, change);
return this.sanitizer.bypassSecurityTrustHtml(diff);
return this.changeRepo.getTitleChangesAsDiff(this.data.data.title, change);
}
/**
@ -430,9 +416,8 @@ export class MotionSlideComponent extends BaseMotionSlideComponent<MotionSlideDa
*
* @returns safe html strings
*/
public getFormattedStatuteAmendment(): SafeHtml {
let diffHtml = this.diff.diff(this.data.data.base_statute.text, this.data.data.text);
diffHtml = this.lineNumbering.insertLineBreaksWithoutNumbers(diffHtml, this.lineLength, true);
return this.sanitizer.bypassSecurityTrustHtml(diffHtml);
public getFormattedStatuteAmendment(): string {
const diffHtml = this.diff.diff(this.data.data.base_statute.text, this.data.data.text);
return this.lineNumbering.insertLineBreaksWithoutNumbers(diffHtml, this.lineLength, true);
}
}

View File

@ -6,5 +6,5 @@
{{ data.data.title }}
</h1>
<div [innerHTML]="sanitizedText(data.data.text)"></div>
<div [innerHTML]="data.data.text | trust: 'html'"></div>
</div>

View File

@ -1,5 +1,4 @@
import { Component } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { BaseSlideComponent } from 'app/slides/base-slide-component';
import { TopicSlideData } from './topic-slide-data';
@ -10,19 +9,7 @@ import { TopicSlideData } from './topic-slide-data';
styleUrls: ['./topic-slide.component.scss']
})
export class TopicSlideComponent extends BaseSlideComponent<TopicSlideData> {
public constructor(private sanitizer: DomSanitizer) {
public constructor() {
super();
}
/**
* Function to sanitize text.
* Necessary to render the text correctly.
*
* @param text which should be displayed.
*
* @returns safeHtml which can be displayed.
*/
public sanitizedText(text: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(text);
}
}