feat(table): added sanitize html option to column styles for table panel, fixes #4596

This commit is contained in:
Torkel Ödegaard
2016-07-11 09:38:06 +02:00
parent 4c4cb20bde
commit 65683ab241
8 changed files with 45 additions and 11 deletions

View File

@@ -12,7 +12,7 @@ func init() {
} }
func updateAppDashboards() { func updateAppDashboards() {
time.Sleep(time.Second * 1) time.Sleep(time.Second * 5)
plog.Debug("Looking for App Dashboard Updates") plog.Debug("Looking for App Dashboard Updates")

View File

@@ -72,6 +72,10 @@
Import Import
</a> </a>
<a class="pull-right small muted" target="_blank" href="https://grafana.net/dashboards?utm_source=grafana_search">
Explore ready made dashboards on Grafana.net
</a>
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
</div> </div>

View File

@@ -5,6 +5,10 @@
<div class="page-header"> <div class="page-header">
<h1>Plugins</h1> <h1>Plugins</h1>
<a class="btn btn-inverse" href="https://grafana.net/plugins?utm_source=grafana_plugin_list" target="_blank">
Explore plugins on Grafana.net
</a>
<div class="page-header-tabs"> <div class="page-header-tabs">
<ul class="gf-tabs"> <ul class="gf-tabs">
<li class="gf-tabs-item"> <li class="gf-tabs-item">

View File

@@ -103,6 +103,11 @@
<metric-segment-model property="style.dateFormat" options="editor.dateFormats" on-change="editor.render()" custom="true"></metric-segment-model> <metric-segment-model property="style.dateFormat" options="editor.dateFormats" on-change="editor.render()" custom="true"></metric-segment-model>
</li> </li>
</ul> </ul>
<ul class="tight-form-list" ng-if="style.type === 'string'">
<li class="tight-form-item">
<editor-checkbox text="Sanitize HTML" model="style.sanitize" change="editor.render()"></editor-checkbox>
</li>
</ul>
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
<div class="tight-form" ng-if="style.type === 'number'"> <div class="tight-form" ng-if="style.type === 'number'">
@@ -152,7 +157,7 @@
Decimals Decimals
</li> </li>
<li style="width: 105px"> <li style="width: 105px">
<input type="number" class="input-mini tight-form-input" ng-model="style.decimals" ng-change="render()" ng-model-onblur> <input type="number" class="input-mini tight-form-input" ng-model="style.decimals" ng-change="editor.render()" ng-model-onblur>
</li> </li>
</ul> </ul>
<div class="clearfix"></div> <div class="clearfix"></div>

View File

@@ -45,7 +45,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
}; };
/** @ngInject */ /** @ngInject */
constructor($scope, $injector, private annotationsSrv) { constructor($scope, $injector, private annotationsSrv, private $sanitize) {
super($scope, $injector); super($scope, $injector);
this.pageIndex = 0; this.pageIndex = 0;
@@ -159,7 +159,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
} }
function appendTableRows(tbodyElem) { function appendTableRows(tbodyElem) {
var renderer = new TableRenderer(panel, data, ctrl.dashboard.isTimezoneUtc()); var renderer = new TableRenderer(panel, data, ctrl.dashboard.isTimezoneUtc(), ctrl.$sanitize);
tbodyElem.empty(); tbodyElem.empty();
tbodyElem.html(renderer.render(ctrl.pageIndex)); tbodyElem.html(renderer.render(ctrl.pageIndex));
} }

View File

@@ -8,7 +8,7 @@ export class TableRenderer {
formaters: any[]; formaters: any[];
colorState: any; colorState: any;
constructor(private panel, private table, private isUtc) { constructor(private panel, private table, private isUtc, private sanitize) {
this.formaters = []; this.formaters = [];
this.colorState = {}; this.colorState = {};
} }
@@ -24,7 +24,7 @@ export class TableRenderer {
return _.first(style.colors); return _.first(style.colors);
} }
defaultCellFormater(v) { defaultCellFormater(v, style) {
if (v === null || v === void 0 || v === undefined) { if (v === null || v === void 0 || v === undefined) {
return ''; return '';
} }
@@ -33,7 +33,11 @@ export class TableRenderer {
v = v.join(', '); v = v.join(', ');
} }
return v; if (style && style.sanitize) {
return this.sanitize(v);
} else {
return _.escape(v);
}
} }
createColumnFormater(style, column) { createColumnFormater(style, column) {
@@ -61,7 +65,7 @@ export class TableRenderer {
} }
if (_.isString(v)) { if (_.isString(v)) {
return v; return this.defaultCellFormater(v, style);
} }
if (style.colorMode) { if (style.colorMode) {
@@ -72,7 +76,9 @@ export class TableRenderer {
}; };
} }
return this.defaultCellFormater; return (value) => {
return this.defaultCellFormater(value, style);
};
} }
formatColumnValue(colIndex, value) { formatColumnValue(colIndex, value) {
@@ -96,7 +102,6 @@ export class TableRenderer {
renderCell(columnIndex, value, addWidthHack = false) { renderCell(columnIndex, value, addWidthHack = false) {
value = this.formatColumnValue(columnIndex, value); value = this.formatColumnValue(columnIndex, value);
value = _.escape(value);
var style = ''; var style = '';
if (this.colorState.cell) { if (this.colorState.cell) {
style = ' style="background-color:' + this.colorState.cell + ';color: white"'; style = ' style="background-color:' + this.colorState.cell + ';color: white"';

View File

@@ -13,6 +13,7 @@ describe('when rendering table', () => {
{text: 'Undefined'}, {text: 'Undefined'},
{text: 'String'}, {text: 'String'},
{text: 'United', unit: 'bps'}, {text: 'United', unit: 'bps'},
{text: 'Sanitized'},
]; ];
var panel = { var panel = {
@@ -47,11 +48,20 @@ describe('when rendering table', () => {
type: 'number', type: 'number',
unit: 'ms', unit: 'ms',
decimals: 2, decimals: 2,
},
{
pattern: 'Sanitized',
type: 'string',
sanitize: true,
} }
] ]
}; };
var renderer = new TableRenderer(panel, table, 'utc'); var sanitize = function(value) {
return 'sanitized';
};
var renderer = new TableRenderer(panel, table, 'utc', sanitize);
it('time column should be formated', () => { it('time column should be formated', () => {
var html = renderer.renderCell(0, 1388556366666); var html = renderer.renderCell(0, 1388556366666);
@@ -107,6 +117,11 @@ describe('when rendering table', () => {
var html = renderer.renderCell(3, undefined); var html = renderer.renderCell(3, undefined);
expect(html).to.be('<td></td>'); expect(html).to.be('<td></td>');
}); });
it('sanitized value should render as', () => {
var html = renderer.renderCell(6, 'text <a href="http://google.com">link</a>');
expect(html).to.be('<td>sanitized</td>');
});
}); });
}); });

View File

@@ -101,6 +101,7 @@
.search-button-row { .search-button-row {
padding-top: 20px; padding-top: 20px;
line-height: 2.5rem;
button, a { button, a {
margin-right: 10px; margin-right: 10px;
} }