KYLIN-3128 Configs for allowing export query results for admin/nonadmin user
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/bcda327f Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/bcda327f Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/bcda327f Branch: refs/heads/master Commit: bcda327f734d4833d3baff11709376c14da779bf Parents: e787d7c Author: nichunen <chunen...@kyligence.io> Authored: Fri Dec 22 17:22:08 2017 +0800 Committer: Hongbin Ma <m...@kyligence.io> Committed: Fri Dec 22 18:11:43 2017 +0800 ---------------------------------------------------------------------- .../org/apache/kylin/common/KylinConfigBase.java | 10 +++++++++- .../src/main/resources/kylin-defaults.properties | 4 ++++ examples/test_case_data/sandbox/kylin.properties | 3 +++ .../kylin/rest/controller/QueryController.java | 12 ++++++++++++ .../java/org/apache/kylin/rest/msg/Message.java | 4 ++++ webapp/app/js/controllers/query.js | 5 ++++- webapp/app/js/services/admin.js | 1 + webapp/app/js/services/kylinProperties.js | 18 +++++++++++++++++- webapp/app/partials/query/query_detail.html | 2 +- 9 files changed, 55 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/bcda327f/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java ---------------------------------------------------------------------- diff --git a/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java b/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java index 21362e9..5620ac0 100644 --- a/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java +++ b/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java @@ -1367,6 +1367,14 @@ abstract public class KylinConfigBase implements Serializable { return Boolean.parseBoolean(getOptional("kylin.web.cross-domain-enabled", "true")); } + public boolean isAdminUserExportAllowed() { + return Boolean.parseBoolean(getOptional("kylin.web.export-allow-admin", "true")); + } + + public boolean isNoneAdminUserExportAllowed() { + return Boolean.parseBoolean(getOptional("kylin.web.export-allow-other", "true")); + } + // ============================================================================ // RESTCLIENT // ============================================================================ @@ -1412,6 +1420,6 @@ abstract public class KylinConfigBase implements Serializable { "kylin.web.timezone,kylin.query.cache-enabled,kylin.env,kylin.web.hive-limit,kylin.storage.default,kylin.engine.default,kylin.web.link-hadoop,kylin.web.link-diagnostic," + "kylin.web.contact-mail,kylin.web.help.length,kylin.web.help.0,kylin.web.help.1,kylin.web.help.2,kylin.web.help.3," + "kylin.web.help,kylin.web.hide-measures,kylin.web.link-streaming-guide,kylin.server.external-acl-provider,kylin.security.profile," - + "kylin.htrace.show-gui-trace-toggle"); + + "kylin.htrace.show-gui-trace-toggle,kylin.web.export-allow-admin,kylin.web.export-allow-other"); } } http://git-wip-us.apache.org/repos/asf/kylin/blob/bcda327f/core-common/src/main/resources/kylin-defaults.properties ---------------------------------------------------------------------- diff --git a/core-common/src/main/resources/kylin-defaults.properties b/core-common/src/main/resources/kylin-defaults.properties index c7afc19..e19ff2e 100644 --- a/core-common/src/main/resources/kylin-defaults.properties +++ b/core-common/src/main/resources/kylin-defaults.properties @@ -45,6 +45,10 @@ kylin.web.timezone=GMT+8 kylin.web.cross-domain-enabled=true +#allow user to export query result +kylin.web.export-allow-admin=true +kylin.web.export-allow-other=true + #max connections of one route kylin.restclient.connection.default-max-per-route=20 http://git-wip-us.apache.org/repos/asf/kylin/blob/bcda327f/examples/test_case_data/sandbox/kylin.properties ---------------------------------------------------------------------- diff --git a/examples/test_case_data/sandbox/kylin.properties b/examples/test_case_data/sandbox/kylin.properties index 00fea26..a6d4adc 100644 --- a/examples/test_case_data/sandbox/kylin.properties +++ b/examples/test_case_data/sandbox/kylin.properties @@ -153,6 +153,9 @@ kylin.web.help.1=odbc|ODBC Driver| kylin.web.help.2=tableau|Tableau Guide| kylin.web.help.3=onboard|Cube Design Tutorial| +#allow user to export query result +kylin.web.export-allow-admin=true +kylin.web.export-allow-other=true ### OTHER ### http://git-wip-us.apache.org/repos/asf/kylin/blob/bcda327f/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java index e944563..4f83780 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java +++ b/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java @@ -29,11 +29,15 @@ import java.util.Map; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; +import org.apache.kylin.common.KylinConfig; import org.apache.kylin.common.debug.BackdoorToggles; import org.apache.kylin.metadata.querymeta.SelectedColumnMeta; import org.apache.kylin.metadata.querymeta.TableMeta; +import org.apache.kylin.rest.exception.ForbiddenException; import org.apache.kylin.rest.exception.InternalErrorException; import org.apache.kylin.rest.model.Query; +import org.apache.kylin.rest.msg.Message; +import org.apache.kylin.rest.msg.MsgPicker; import org.apache.kylin.rest.request.MetaRequest; import org.apache.kylin.rest.request.PrepareSqlRequest; import org.apache.kylin.rest.request.SQLRequest; @@ -118,6 +122,14 @@ public class QueryController extends BasicController { @RequestMapping(value = "/query/format/{format}", method = RequestMethod.GET, produces = { "application/json" }) @ResponseBody public void downloadQueryResult(@PathVariable String format, SQLRequest sqlRequest, HttpServletResponse response) { + KylinConfig config = queryService.getConfig(); + Message msg = MsgPicker.getMsg(); + + if ((isAdmin() && !config.isAdminUserExportAllowed()) + || (!isAdmin() && !config.isNoneAdminUserExportAllowed())) { + throw new ForbiddenException(msg.getEXPORT_RESULT_NOT_ALLOWED()); + } + SQLResponse result = queryService.doQueryWithCache(sqlRequest); response.setContentType("text/" + format + ";charset=utf-8"); http://git-wip-us.apache.org/repos/asf/kylin/blob/bcda327f/server-base/src/main/java/org/apache/kylin/rest/msg/Message.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/msg/Message.java b/server-base/src/main/java/org/apache/kylin/rest/msg/Message.java index 2ab4c24..9f3e909 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/msg/Message.java +++ b/server-base/src/main/java/org/apache/kylin/rest/msg/Message.java @@ -349,6 +349,10 @@ public class Message { return "Column metadata inconsistent with JDBC meta."; } + public String getEXPORT_RESULT_NOT_ALLOWED() { + return "Current user is not allowed to export query result."; + } + // Access public String getACL_PERMISSION_REQUIRED() { return "Acl permission required."; http://git-wip-us.apache.org/repos/asf/kylin/blob/bcda327f/webapp/app/js/controllers/query.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/controllers/query.js b/webapp/app/js/controllers/query.js index 0a3d04d..1c03684 100644 --- a/webapp/app/js/controllers/query.js +++ b/webapp/app/js/controllers/query.js @@ -433,7 +433,10 @@ KylinApp }) - .controller('QueryResultCtrl', function ($scope, storage, $base64, $q, $location, $anchorScroll, $routeParams, QueryService, GraphService) { + .controller('QueryResultCtrl', function ($scope, storage, $base64, $q, $location, $anchorScroll, $routeParams, QueryService, GraphService, kylinConfig) { + $scope.isAdminExportAllowed = kylinConfig.isAdminExportAllowed(); + $scope.isNonAdminExportAllowed = kylinConfig.isNonAdminExportAllowed(); + $scope.buildGraphMetadata = function (query) { if (!query.graph.show) { return; http://git-wip-us.apache.org/repos/asf/kylin/blob/bcda327f/webapp/app/js/services/admin.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/services/admin.js b/webapp/app/js/services/admin.js index 47dce92..6c4fd40 100644 --- a/webapp/app/js/services/admin.js +++ b/webapp/app/js/services/admin.js @@ -20,6 +20,7 @@ KylinApp.factory('AdminService', ['$resource', function ($resource, config) { return $resource(Config.service.url + 'admin/:action', {}, { env: {method: 'GET', params: {action: 'env'}, isArray: false}, config: {method: 'GET', params: {action: 'config'}, isArray: false}, + publicConfig: {method: 'GET', params: {action: 'public_config'}, isArray: false}, cleanStorage: {method: 'DELETE', params: {action: 'storage'}, isArray: false}, updateConfig: {method: 'PUT', params: {action: 'config'}, isArray: false} }); http://git-wip-us.apache.org/repos/asf/kylin/blob/bcda327f/webapp/app/js/services/kylinProperties.js ---------------------------------------------------------------------- diff --git a/webapp/app/js/services/kylinProperties.js b/webapp/app/js/services/kylinProperties.js index a2af4ed..76d7763 100644 --- a/webapp/app/js/services/kylinProperties.js +++ b/webapp/app/js/services/kylinProperties.js @@ -23,7 +23,7 @@ KylinApp.service('kylinConfig', function (AdminService, $log) { this.init = function () { - return AdminService.config({}, function (config) { + return AdminService.publicConfig({}, function (config) { _config = config.config; }, function (e) { $log.error("failed to load kylin.properties" + e); @@ -115,5 +115,21 @@ KylinApp.service('kylinConfig', function (AdminService, $log) { return true; } + this.isAdminExportAllowed = function(){ + var status = this.getProperty("kylin.web.export-allow-admin").trim(); + if(status!=='false'){ + return true; + } + return false; + } + + this.isNonAdminExportAllowed = function(){ + var status = this.getProperty("kylin.web.export-allow-other").trim(); + if(status!=='false'){ + return true; + } + return false; + } + }); http://git-wip-us.apache.org/repos/asf/kylin/blob/bcda327f/webapp/app/partials/query/query_detail.html ---------------------------------------------------------------------- diff --git a/webapp/app/partials/query/query_detail.html b/webapp/app/partials/query/query_detail.html index 8e1286c..0d35527 100644 --- a/webapp/app/partials/query/query_detail.html +++ b/webapp/app/partials/query/query_detail.html @@ -86,7 +86,7 @@ <span ng-if="!curQuery.graph.show"><i class="fa fa-bar-chart-o"></i> Visualization</span> <span ng-if="curQuery.graph.show"><i class="fa fa-list-ul"></i> Grid</span> </button> - <a class="btn btn-default btn-xs" href="{{config.service.url}}query/format/csv?sql={{exportSql}}&project={{curQuery.project}}" target="_blank"> + <a class="btn btn-default btn-xs" ng-if="(userService.hasRole('ROLE_ADMIN')&&isAdminExportAllowed)||(!userService.hasRole('ROLE_ADMIN')&&isNonAdminExportAllowed)" href="{{config.service.url}}query/format/csv?sql={{exportSql}}&project={{curQuery.project}}" target="_blank"> <i class="fa fa-cloud-download"></i> Export</a> <a class="btn btn-default btn-xs" ng-click="refreshUi();"> <i ng-class="{true: 'fa fa-compress', false: 'fa fa-expand'}[ui.fullScreen]"></i>