From 10419d13de12b760adeeba50669744888a993826 Mon Sep 17 00:00:00 2001 From: Christopher Valles Date: Fri, 17 Jan 2014 12:13:03 +0000 Subject: [PATCH 1/3] Adding final permission system and checks --- rd_service/server.py | 29 ++++++++++++++++++++++++++++- rd_service/settings_example.py | 6 ++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/rd_service/server.py b/rd_service/server.py index 306fbfa082..d3a41fdc99 100644 --- a/rd_service/server.py +++ b/rd_service/server.py @@ -238,7 +238,34 @@ def get(self, query_result_id): def post(self, _): params = json.loads(self.request.body) - + + group = [group for group in settings.GROUPS if self.current_user in settings.GROUPS[group]] + if len(group) == 0: + group = settings.DEFAULT_GROUP + else: + group = group[0] + + permissions = settings.PERMISSIONS[group] + + if '*' not in permissions: + if params['query'].lower().find('select') == -1: + logging.error("You can only run SELECT queries") + self.write({'job': { + 'error': "You can only run SELECT statements", + }}) + return + + res = sqlparse.parse(params['query']) + tokens = res[0].tokens + tableName = [tokens[cons[0] + 2].to_unicode().lower() for cons in enumerate(tokens) if cons[1].to_unicode() == 'from'][0] + + if tableName not in permissions: + logging.error("Permission denied for user %s in table %s" % (self.current_user, tableName)) + self.write({'job': { + 'error': "You don't have permission to access this table", + }}) + return + if params['ttl'] == 0: query_result = None else: diff --git a/rd_service/settings_example.py b/rd_service/settings_example.py index 01511ec989..c6bc5a91b4 100644 --- a/rd_service/settings_example.py +++ b/rd_service/settings_example.py @@ -24,6 +24,12 @@ LOG_LEVEL = "INFO" ANALYTICS = "" +GROUPS = { +} + +PERMISSIONS = { +} + # Configuration of the operational database for the Django models django.conf.settings.configure(DATABASES = { 'default': { 'ENGINE': 'dbpool.db.backends.postgresql_psycopg2', From fd691643c0d50d3a5ccc3e7584bdee1e44489788 Mon Sep 17 00:00:00 2001 From: Christopher Valles Date: Tue, 4 Feb 2014 12:08:02 +0000 Subject: [PATCH 2/3] DAT-694 new graphs added --- rd_ui/app/scripts/controllers.js | 13 +++++- rd_ui/app/scripts/ng-highchart.js | 11 ++++- rd_ui/app/scripts/query_fiddle/renderers.js | 47 ++++++++++++++++----- rd_ui/app/scripts/services.js | 1 - rd_ui/app/styles/redash.css | 6 +++ rd_ui/app/views/queryfiddle.html | 5 ++- 6 files changed, 69 insertions(+), 14 deletions(-) diff --git a/rd_ui/app/scripts/controllers.js b/rd_ui/app/scripts/controllers.js index 923b6fb858..eaa57dc0f5 100644 --- a/rd_ui/app/scripts/controllers.js +++ b/rd_ui/app/scripts/controllers.js @@ -71,7 +71,18 @@ $scope.tabs = [{'key': 'table', 'name': 'Table'}, {'key': 'chart', 'name': 'Chart'}, {'key': 'pivot', 'name': 'Pivot Table'}, {'key': 'cohort', 'name': 'Cohort'}]; - + + $scope.chartType = 'line'; + $scope.chartTypes = [ + {value: 'line', name: 'Line'}, + {value: 'bar', name: 'Bar'}, + {value: 'scatter', name: 'Scattered Plot'} + ]; + + $scope.updateChartType = function() { + $scope.$broadcast('chart-type-changed', $scope.chartType); + }; + $scope.lockButton = function (lock) { $scope.queryExecuting = lock; }; diff --git a/rd_ui/app/scripts/ng-highchart.js b/rd_ui/app/scripts/ng-highchart.js index b4c445a297..7347172f82 100644 --- a/rd_ui/app/scripts/ng-highchart.js +++ b/rd_ui/app/scripts/ng-highchart.js @@ -29,7 +29,16 @@ angular.module('highchart', []) // Making sure that the DOM is ready before creating the chart element, so it gets proper width. $timeout(function(){ scope.chart = new Highcharts.Chart(newSettings); - + + //Update chart type when type changes + scope.$on('chart-type-changed', function(event, type){ + _.each(scope.chart.series, function(s){ + s.update({ + 'type': type + }); + }); + }); + //Update when charts data changes scope.$watch(function () { return (scope.series && scope.series.length) || 0; diff --git a/rd_ui/app/scripts/query_fiddle/renderers.js b/rd_ui/app/scripts/query_fiddle/renderers.js index 36caa05ca8..7178103fe4 100644 --- a/rd_ui/app/scripts/query_fiddle/renderers.js +++ b/rd_ui/app/scripts/query_fiddle/renderers.js @@ -1,9 +1,9 @@ var renderers = angular.module('redash.renderers', []); var defaultChartOptions = { - "title": { - "text": null + title: { + text: null }, - "tooltip": { + tooltip: { valueDecimals: 2, formatter: function () { if (moment.isMoment(this.x)) { @@ -68,12 +68,39 @@ var defaultChartOptions = { enabled: false }, plotOptions: { - "column": { - "stacking": "normal", - "pointPadding": 0, - "borderWidth": 1, - "groupPadding": 0, - "shadow": false + column: { + stacking: "normal", + pointPadding: 0, + borderWidth: 1, + groupPadding: 0, + shadow: false + }, + line: { + dataLabels: { + enabled: true + } + }, + scatter: { + marker: { + radius: 5, + states: { + hover: { + enabled: true, + lineColor: 'rgb(100,100,100)' + } + } + }, + states: { + hover: { + marker: { + enabled: false + } + } + }, + tooltip: { + headerFormat: '{series.name}
', + pointFormat: '{point.x} cm, {point.y} kg' + } } }, "series": [] @@ -102,7 +129,7 @@ renderers.directive('chartRenderer', function () { if ($scope.stacking() === undefined) { stacking = 'normal'; } - + _.each($scope.queryResult.getChartData(), function (s) { $scope.chartSeries.push(_.extend(s, {'stacking': stacking})); }); diff --git a/rd_ui/app/scripts/services.js b/rd_ui/app/scripts/services.js index ab32673cef..f63ca5b1ca 100644 --- a/rd_ui/app/scripts/services.js +++ b/rd_ui/app/scripts/services.js @@ -117,7 +117,6 @@ if (series[seriesName] == undefined) { series[seriesName] = { name: seriesName, - type: 'column', data: [] } } diff --git a/rd_ui/app/styles/redash.css b/rd_ui/app/styles/redash.css index 843ccff766..870d04b439 100644 --- a/rd_ui/app/styles/redash.css +++ b/rd_ui/app/styles/redash.css @@ -193,4 +193,10 @@ to add those CSS styles here. */ -webkit-border-radius: 6px 0 6px 6px; -moz-border-radius: 6px 0 6px 6px; border-radius: 6px 0 6px 6px; +} + +/* Charts */ +.chart-tab span { + display:block; + padding:10px; } \ No newline at end of file diff --git a/rd_ui/app/views/queryfiddle.html b/rd_ui/app/views/queryfiddle.html index 37a5aeaaf0..6815f0607a 100644 --- a/rd_ui/app/views/queryfiddle.html +++ b/rd_ui/app/views/queryfiddle.html @@ -55,7 +55,10 @@

-
+
+ + Graph type: +
From 886b7fd5131c6f5464ad64fdac45d1dcef63f2af Mon Sep 17 00:00:00 2001 From: Christopher Valles Date: Tue, 4 Feb 2014 12:17:25 +0000 Subject: [PATCH 3/3] Rolling back two files --- rd_service/server.py | 29 +---------------------------- rd_service/settings_example.py | 6 ------ 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/rd_service/server.py b/rd_service/server.py index d3a41fdc99..306fbfa082 100644 --- a/rd_service/server.py +++ b/rd_service/server.py @@ -238,34 +238,7 @@ def get(self, query_result_id): def post(self, _): params = json.loads(self.request.body) - - group = [group for group in settings.GROUPS if self.current_user in settings.GROUPS[group]] - if len(group) == 0: - group = settings.DEFAULT_GROUP - else: - group = group[0] - - permissions = settings.PERMISSIONS[group] - - if '*' not in permissions: - if params['query'].lower().find('select') == -1: - logging.error("You can only run SELECT queries") - self.write({'job': { - 'error': "You can only run SELECT statements", - }}) - return - - res = sqlparse.parse(params['query']) - tokens = res[0].tokens - tableName = [tokens[cons[0] + 2].to_unicode().lower() for cons in enumerate(tokens) if cons[1].to_unicode() == 'from'][0] - - if tableName not in permissions: - logging.error("Permission denied for user %s in table %s" % (self.current_user, tableName)) - self.write({'job': { - 'error': "You don't have permission to access this table", - }}) - return - + if params['ttl'] == 0: query_result = None else: diff --git a/rd_service/settings_example.py b/rd_service/settings_example.py index c6bc5a91b4..01511ec989 100644 --- a/rd_service/settings_example.py +++ b/rd_service/settings_example.py @@ -24,12 +24,6 @@ LOG_LEVEL = "INFO" ANALYTICS = "" -GROUPS = { -} - -PERMISSIONS = { -} - # Configuration of the operational database for the Django models django.conf.settings.configure(DATABASES = { 'default': { 'ENGINE': 'dbpool.db.backends.postgresql_psycopg2',