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() {
time.Sleep(time.Second * 1)
time.Sleep(time.Second * 5)
plog.Debug("Looking for App Dashboard Updates")

View File

@@ -72,6 +72,10 @@
Import
</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>
</div>

View File

@@ -5,6 +5,10 @@
<div class="page-header">
<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">
<ul class="gf-tabs">
<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>
</li>
</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>
<div class="tight-form" ng-if="style.type === 'number'">
@@ -152,7 +157,7 @@
Decimals
</li>
<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>
</ul>
<div class="clearfix"></div>

View File

@@ -45,7 +45,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
};
/** @ngInject */
constructor($scope, $injector, private annotationsSrv) {
constructor($scope, $injector, private annotationsSrv, private $sanitize) {
super($scope, $injector);
this.pageIndex = 0;
@@ -159,7 +159,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
}
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.html(renderer.render(ctrl.pageIndex));
}

View File

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

View File

@@ -13,6 +13,7 @@ describe('when rendering table', () => {
{text: 'Undefined'},
{text: 'String'},
{text: 'United', unit: 'bps'},
{text: 'Sanitized'},
];
var panel = {
@@ -47,11 +48,20 @@ describe('when rendering table', () => {
type: 'number',
unit: 'ms',
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', () => {
var html = renderer.renderCell(0, 1388556366666);
@@ -107,6 +117,11 @@ describe('when rendering table', () => {
var html = renderer.renderCell(3, undefined);
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 {
padding-top: 20px;
line-height: 2.5rem;
button, a {
margin-right: 10px;
}