This is an automated email from the ASF dual-hosted git repository. nju_yaho pushed a commit to tag ebay-3.1.0-release-20200701 in repository https://gitbox.apache.org/repos/asf/kylin.git
commit 45647aaa492abf7fc5184f3de72f538d0408bbe2 Author: sanjulian <julian....@hotmail.com> AuthorDate: Sun Jun 28 11:28:06 2020 +0800 KYLIN-4600 Forbidden users except system admin to do metadata addition & update in Production --- .../org/apache/kylin/common/KylinConfigBase.java | 4 +++ .../org/apache/kylin/rest/service/CubeService.java | 29 +++++++++++++--------- .../apache/kylin/rest/service/HybridService.java | 8 ++++-- .../apache/kylin/rest/service/ModelService.java | 13 +++++++--- .../apache/kylin/rest/service/TableService.java | 12 ++++++--- .../org/apache/kylin/rest/util/AclEvaluate.java | 11 ++++++++ webapp/app/js/services/kylinProperties.js | 8 ++++++ webapp/app/partials/cubes/cubes.html | 6 ++--- webapp/app/partials/models/models_tree.html | 14 +++++------ webapp/app/partials/tables/source_table_tree.html | 8 +++--- webapp/app/partials/tables/table_detail.html | 2 +- 11 files changed, 79 insertions(+), 36 deletions(-) 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 f9bafee..01d0e10 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 @@ -262,6 +262,10 @@ public abstract class KylinConfigBase implements Serializable { return "DEV".equals(getOptional("kylin.env", "DEV")); } + public boolean isProdEnv() { + return Boolean.parseBoolean(getOptional("kylin.env.is-prod", "false")); + } + public String getDeployEnv() { return getOptional("kylin.env", "DEV"); } diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java b/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java index 1a4b468..59781c5 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java +++ b/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java @@ -106,7 +106,6 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; @@ -213,10 +212,11 @@ public class CubeService extends BasicService implements InitializingBean { CubeUpdate update = new CubeUpdate(cube.latestCopyForWrite()).setOwner(owner).setCost(cost); return getCubeManager().updateCube(update); } - - @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN - + " or hasPermission(#project, 'ADMINISTRATION') or hasPermission(#project, 'MANAGEMENT')") + public CubeInstance createCubeAndDesc(ProjectInstance project, CubeDesc desc) throws IOException { + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectWritePermission(project.getName()); + } Message msg = MsgPicker.getMsg(); String cubeName = desc.getName(); @@ -288,7 +288,9 @@ public class CubeService extends BasicService implements InitializingBean { public CubeDesc updateCubeAndDesc(CubeInstance cube, CubeDesc desc, String newProjectName, boolean forceUpdate) throws IOException { - aclEvaluate.checkProjectWritePermission(cube); + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectWritePermission(newProjectName); + } Message msg = MsgPicker.getMsg(); final List<CubingJob> cubingJobs = jobService.listJobsByRealizationName(cube.getName(), null, @@ -844,10 +846,11 @@ public class CubeService extends BasicService implements InitializingBean { } } } - - @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN - + " or hasPermission(#project, 'ADMINISTRATION') or hasPermission(#project, 'MANAGEMENT')") + public CubeDesc saveCube(CubeDesc desc, ProjectInstance project) throws IOException { + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectWritePermission(project.getName()); + } Message msg = MsgPicker.getMsg(); desc.setDraft(false); @@ -867,10 +870,11 @@ public class CubeService extends BasicService implements InitializingBean { return desc; } - @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN - + " or hasPermission(#project, 'ADMINISTRATION') or hasPermission(#project, 'MANAGEMENT')") public void saveDraft(ProjectInstance project, CubeInstance cube, String uuid, RootPersistentEntity... entities) throws IOException { + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectWritePermission(project.getName()); + } Draft draft = new Draft(); draft.setProject(project.getName()); draft.setUuid(uuid); @@ -878,9 +882,10 @@ public class CubeService extends BasicService implements InitializingBean { getDraftManager().save(draft); } - @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN - + " or hasPermission(#project, 'ADMINISTRATION') or hasPermission(#project, 'MANAGEMENT')") public void saveDraft(ProjectInstance project, String uuid, RootPersistentEntity... entities) throws IOException { + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectWritePermission(project.getName()); + } Draft draft = new Draft(); draft.setProject(project.getName()); draft.setUuid(uuid); diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/HybridService.java b/server-base/src/main/java/org/apache/kylin/rest/service/HybridService.java index 9de5941..b159183 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/service/HybridService.java +++ b/server-base/src/main/java/org/apache/kylin/rest/service/HybridService.java @@ -45,7 +45,9 @@ public class HybridService extends BasicService { public HybridInstance createHybridInstance(String hybridName, String projectName, String modelName, String[] cubeNames) { - aclEvaluate.checkProjectWritePermission(projectName); + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectWritePermission(projectName); + } List<String> args = new ArrayList<String>(); args.add("-name"); args.add(hybridName); @@ -68,7 +70,9 @@ public class HybridService extends BasicService { public HybridInstance updateHybridInstance(String hybridName, String projectName, String modelName, String[] cubeNames) { - aclEvaluate.checkProjectWritePermission(projectName); + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectWritePermission(projectName); + } List<String> args = new ArrayList<String>(); args.add("-name"); args.add(hybridName); diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server-base/src/main/java/org/apache/kylin/rest/service/ModelService.java index 7ff3919..ecb738d 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/service/ModelService.java +++ b/server-base/src/main/java/org/apache/kylin/rest/service/ModelService.java @@ -131,7 +131,9 @@ public class ModelService extends BasicService { } public DataModelDesc createModelDesc(String projectName, DataModelDesc desc) throws IOException { - aclEvaluate.checkProjectWritePermission(projectName); + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectWritePermission(projectName); + } Message msg = MsgPicker.getMsg(); if (getDataModelManager().getDataModelDesc(desc.getName()) != null) { throw new BadRequestException(String.format(Locale.ROOT, msg.getDUPLICATE_MODEL_NAME(), desc.getName())); @@ -146,7 +148,9 @@ public class ModelService extends BasicService { } public DataModelDesc updateModelAndDesc(String project, DataModelDesc desc) throws IOException { - aclEvaluate.checkProjectWritePermission(project); + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectWritePermission(project); + } validateModel(project, desc); checkModelCompatibility(project, desc); getDataModelManager().updateDataModelDesc(desc); @@ -381,8 +385,9 @@ public class ModelService extends BasicService { } public DataModelDesc updateModelToResourceStore(DataModelDesc modelDesc, String projectName) throws IOException { - - aclEvaluate.checkProjectWritePermission(projectName); + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectWritePermission(projectName); + } Message msg = MsgPicker.getMsg(); modelDesc.setDraft(false); diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/TableService.java b/server-base/src/main/java/org/apache/kylin/rest/service/TableService.java index 0d3f9f0..266ae68 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/service/TableService.java +++ b/server-base/src/main/java/org/apache/kylin/rest/service/TableService.java @@ -176,7 +176,9 @@ public class TableService extends BasicService { * @throws Exception on error */ public String[] loadHiveTablesToProject(String[] hiveTables, String project) throws Exception { - aclEvaluate.checkProjectAdminPermission(project); + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectAdminPermission(project); + } List<Pair<TableDesc, TableExtDesc>> allMeta = extractHiveTableMeta(hiveTables, project); return loadTablesToProject(allMeta, project); } @@ -191,7 +193,9 @@ public class TableService extends BasicService { private String[] loadTablesToProject(List<Pair<TableDesc, TableExtDesc>> allMeta, String project) throws IOException { - aclEvaluate.checkProjectAdminPermission(project); + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectAdminPermission(project); + } // do schema check TableMetadataManager metaMgr = getTableManager(); CubeManager cubeMgr = getCubeManager(); @@ -600,7 +604,9 @@ public class TableService extends BasicService { } // To deal with case sensitive issue for table resource path final String project = prjInstance.getName(); - aclEvaluate.checkProjectWritePermission(project); + if (!aclEvaluate.checkProjectWritePermissionInProd()) { + aclEvaluate.checkProjectWritePermission(project); + } // Check whether it's able to do the change Set<CubeInstance> infCubes = cubeService.listAllCubes(project).stream() diff --git a/server-base/src/main/java/org/apache/kylin/rest/util/AclEvaluate.java b/server-base/src/main/java/org/apache/kylin/rest/util/AclEvaluate.java index dcd625a..49be5da 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/util/AclEvaluate.java +++ b/server-base/src/main/java/org/apache/kylin/rest/util/AclEvaluate.java @@ -160,4 +160,15 @@ public class AclEvaluate { aclUtil.checkIsGlobalAdmin(); } + /** + * @return indicates whether the environment is in production or not + * if in production, if the user is not global admin, AccessDeniedException will be thrown + */ + public boolean checkProjectWritePermissionInProd() { + if (KylinConfig.getInstanceFromEnv().isProdEnv()) { + checkIsGlobalAdmin(); + return true; + } + return false; + } } \ No newline at end of file diff --git a/webapp/app/js/services/kylinProperties.js b/webapp/app/js/services/kylinProperties.js index 4762753..7d0657c 100644 --- a/webapp/app/js/services/kylinProperties.js +++ b/webapp/app/js/services/kylinProperties.js @@ -83,6 +83,14 @@ KylinApp.service('kylinConfig', function (AdminService, $log) { return this.deployEnv.toUpperCase().trim(); } + this.isProd = function() { + var status = this.getProperty("kylin.env.is-prod").trim(); + if(status!=='false'){ + return true; + } + return false; + } + this.getHiveLimit = function () { this.hiveLimit = this.getProperty("kylin.web.hive-limit"); if (!this.hiveLimit) { diff --git a/webapp/app/partials/cubes/cubes.html b/webapp/app/partials/cubes/cubes.html index 605f4e5..7264db3 100644 --- a/webapp/app/partials/cubes/cubes.html +++ b/webapp/app/partials/cubes/cubes.html @@ -101,7 +101,7 @@ <li ng-if="cube.status=='DISABLED' && (userService.hasRole('ROLE_ADMIN') || hasPermission('cube',cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))"><a ng-click="enable(cube)">Enable</a></li> <li ng-if="cube.status=='DISABLED' && (userService.hasRole('ROLE_ADMIN') || hasPermission('cube',cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))"><a ng-click="startDeleteSegment(cube)">Delete Segment</a></li> <li ng-if="cube.status=='DISABLED' && (userService.hasRole('ROLE_ADMIN') || hasPermission('cube',cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))"><a ng-click="purge(cube)">Purge</a></li> - <li ng-if="cube.status!='DESCBROKEN' && (userService.hasRole('ROLE_ADMIN') || hasPermission('cube',cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))"><a ng-click="cloneCube(cube)">Clone</a></li> + <li ng-if="cube.status!='DESCBROKEN' && (userService.hasRole('ROLE_ADMIN') || (!kylinConfig.isProd() && hasPermission('cube',cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask)))"><a ng-click="cloneCube(cube)">Clone</a></li> <li ng-if="cube.status=='READY' && kylinConfig.isCubeMigrationEnabled() && (userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask) || hasPermission(cubeProjectEntity, permissions.ADMINISTRATION.mask))"><a ng-click="startMigrateCube(cube, 0);">Migrate</a></li> </ul> @@ -112,12 +112,12 @@ <li ng-if="cube.status!='DISABLED' && userService.hasRole('ROLE_ADMIN')"><a ng-click="viewAssignment(cube, $index);">Assignment</a></li> <li ng-if="cube.status!='DESCBROKEN' && cube.lambda"><a ng-click="startRefresh(cube, $index)">Refresh</a></li> <li ng-if="cube.status=='DISABLED' && (userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask)) "><a ng-click="dropCube(cube, $index)" tooltip="Drop the cube, related jobs and data permanently.">Drop</a></li> - <li ng-if="cube.status=='DISABLED' && (userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))"><a ng-click="cubeEdit(cube);">Edit</a></li> + <li ng-if="cube.status=='DISABLED' && (userService.hasRole('ROLE_ADMIN') || (!kylinConfig.isProd() && hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask)))"><a ng-click="cubeEdit(cube);">Edit</a></li> <li><a ng-click="startMerge(cube, $index)">Merge</a></li> <li ng-if="cube.status=='DISABLED'"><a ng-click="enable(cube, $index)">Enable</a></li> <li ng-if="cube.status=='DISABLED'"><a ng-click="purge(cube, $index)">Purge</a></li> <li><a ng-click="cloneCube(cube)">Clone</a></li> - <li ng-if="cube.status=='READY' && (userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask))"><a ng-click="startMigrateCube(cube, 0);">Migrate</a></li> + <li ng-if="cube.status=='READY' && kylinConfig.isCubeMigrationEnabled() && (userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask))"><a ng-click="startMigrateCube(cube, 0);">Migrate</a></li> </ul> <span ng-if="!(userService.hasRole('ROLE_ADMIN') || hasPermission('cube',cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))" class="dropdown-menu" role="menu"> N/A diff --git a/webapp/app/partials/models/models_tree.html b/webapp/app/partials/models/models_tree.html index 1ce3222..6f02435 100644 --- a/webapp/app/partials/models/models_tree.html +++ b/webapp/app/partials/models/models_tree.html @@ -20,18 +20,18 @@ <div class="row"> <div class="col-xs-12" style="margin-top:10px;"> <!--<i class="fa fa-plus fa-2x" style="color:green;"> New</i>--> - <a ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission('project',projectModel, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask)" class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="true"> + <a ng-if="userService.hasRole('ROLE_ADMIN') || (!kylinConfig.isProd() && hasPermission('project',projectModel, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))" class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="true"> <i class="fa fa-plus fa-2x" style="color:#2e8965;"> New<span class="caret"></span></i> <!--<i> New </i> <span class="caret"></span>--> </a> <ul class="dropdown-menu"> - <li ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission('project',projectModel, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask)"> + <li ng-if="userService.hasRole('ROLE_ADMIN') || (!kylinConfig.isProd() && hasPermission('project',projectModel, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))"> <a href="models/add"><i class="fa fa-star"></i>New Model</a> </li> - <li ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission('project',projectModel, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask)"> + <li ng-if="userService.hasRole('ROLE_ADMIN') || (!kylinConfig.isProd() && hasPermission('project',projectModel, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))"> <a href="cubes/add"><i class="fa fa-cube"></i>New Cube</a> </li> - <li ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission('project',projectModel, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask)"> + <li ng-if="userService.hasRole('ROLE_ADMIN') || (!kylinConfig.isProd() && hasPermission('project',projectModel, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))"> <a href="hybrid/add"><i class="kylin-icon-hybrid"></i>New Hybrid</a> </li> </ul> @@ -57,8 +57,8 @@ </button> <ul class="dropdown-menu" role="menu" style="right:0;left:auto;" ng-if="(userService.hasRole('ROLE_ADMIN') || hasPermission('model',model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))"> <li><a ng-click="listCubes(model)" title="Using Cubes" style="cursor:pointer;margin-right: 8px;" >Cubes</a></li> - <li><a ng-click="editModel(model, false)" title="Edit Model" style="cursor:pointer;margin-right: 8px;" >Edit</a></li> - <li><a ng-click="cloneModel(model)" title="Clone Model" style="cursor:pointer;margin-right: 8px;" >Clone </a></li> + <li ng-if="userService.hasRole('ROLE_ADMIN') || !kylinConfig.isProd()"><a ng-click="editModel(model, false)" title="Edit Model" style="cursor:pointer;margin-right: 8px;" >Edit</a></li> + <li ng-if="userService.hasRole('ROLE_ADMIN') || !kylinConfig.isProd()"><a ng-click="cloneModel(model)" title="Clone Model" style="cursor:pointer;margin-right: 8px;" >Clone</a></li> <li><a ng-click="dropModel(model)" title="Drop Model" style="cursor:pointer;margin-right: 8px;">Drop</a></li> <li ng-if="userService.hasRole('ROLE_ADMIN')"> <a ng-click="editModel(model, true)">Edit(JSON)</a></li> @@ -86,7 +86,7 @@ Action <span class="ace-icon fa fa-caret-down icon-on-right"></span> </button> <ul class="dropdown-menu" role="menu" style="right:0;left:auto;" ng-if="(userService.hasRole('ROLE_ADMIN') || hasPermission('model', hybridInstance, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))"> - <li><a ng-click="editHybridInstance(hybridInstance)" title="Edit Hybrid" style="cursor:pointer;margin-right: 8px;" >Edit</a></li> + <li ng-if="userService.hasRole('ROLE_ADMIN') || !kylinConfig.isProd()"><a ng-click="editHybridInstance(hybridInstance)" title="Edit Hybrid" style="cursor:pointer;margin-right: 8px;" >Edit</a></li> <li><a ng-click="dropHybridInstance(hybridInstance)" title="Drop Hybrid" style="cursor:pointer;margin-right: 8px;">Drop</a></li> </ul> </div> diff --git a/webapp/app/partials/tables/source_table_tree.html b/webapp/app/partials/tables/source_table_tree.html index af6398c..81ac794 100755 --- a/webapp/app/partials/tables/source_table_tree.html +++ b/webapp/app/partials/tables/source_table_tree.html @@ -25,10 +25,10 @@ <!--button--> <div class="col-xs-5" style="padding-left: 0px;margin-top: 20px;"> <div class="pull-right"> - <a class="btn btn-xs btn-primary" tooltip="Load Table" ng-if="userService.hasRole('ROLE_ADMIN')|| hasPermission('project',projectModel, permissions.ADMINISTRATION.mask)" ng-click="openModal()"><i class="fa fa-download"></i></a> - <a class="btn btn-xs btn-info" tooltip="Load Table From Tree" ng-if="userService.hasRole('ROLE_ADMIN')|| hasPermission('project',projectModel, permissions.ADMINISTRATION.mask)" ng-click="openTreeModal()"><i class="fa fa-download"></i></a> - <a class="btn btn-xs btn-primary" tooltip="Add Streaming Table" ng-if="userService.hasRole('ROLE_ADMIN')|| hasPermission('project',projectModel, permissions.ADMINISTRATION.mask)" ng-click="openStreamingSourceModal()"><i class="fa fa-area-chart"></i></a> - <a class="btn btn-xs btn-info" tooltip-placement="left" tooltip="Add Streaming Table V2" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission('project',projectModel, permissions.ADMINISTRATION.mask)" ng-click="openStreamingSourceModalV2()"><i class="fa fa-area-chart"></i></a> + <a class="btn btn-xs btn-primary" tooltip="Load Table" ng-if="userService.hasRole('ROLE_ADMIN')|| (!kylinConfig.isProd() && hasPermission('project',projectModel, permissions.ADMINISTRATION.mask))" ng-click="openModal()"><i class="fa fa-download"></i></a> + <a class="btn btn-xs btn-info" tooltip="Load Table From Tree" ng-if="userService.hasRole('ROLE_ADMIN')|| (!kylinConfig.isProd() && hasPermission('project',projectModel, permissions.ADMINISTRATION.mask))" ng-click="openTreeModal()"><i class="fa fa-download"></i></a> + <a class="btn btn-xs btn-primary" tooltip="Add Streaming Table" ng-if="userService.hasRole('ROLE_ADMIN')|| (!kylinConfig.isProd() && hasPermission('project',projectModel, permissions.ADMINISTRATION.mask))" ng-click="openStreamingSourceModal()"><i class="fa fa-area-chart"></i></a> + <a class="btn btn-xs btn-info" tooltip-placement="left" tooltip="Add Streaming Table V2" ng-if="userService.hasRole('ROLE_ADMIN') || (!kylinConfig.isProd() && hasPermission('project',projectModel, permissions.ADMINISTRATION.mask))" ng-click="openStreamingSourceModalV2()"><i class="fa fa-area-chart"></i></a> </div> </div> diff --git a/webapp/app/partials/tables/table_detail.html b/webapp/app/partials/tables/table_detail.html index 533ef66..0456504 100644 --- a/webapp/app/partials/tables/table_detail.html +++ b/webapp/app/partials/tables/table_detail.html @@ -20,7 +20,7 @@ <div class="col-xs-12" ng-show="tableModel.selectedSrcDb&&tableModel.selectedSrcTable.name"> <h3 class="text-info">Table Schema:{{ tableModel.selectedSrcTable.name}}</h3> <a class="btn btn-primary pull-right" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission('project',projectModel, permissions.ADMINISTRATION.mask)" ng-click="unloadTable(tableModel.selectedSrcTable.database+'.'+tableModel.selectedSrcTable.name)" style="margin-left:10px;" ><span class="fa fa-remove"></span> Unload Table</a> - <a class="btn btn-success pull-right" ng-if="tableModel.selectedSrcTable.source_type==0&&(userService.hasRole('ROLE_ADMIN') || hasPermission('project',projectModel, permissions.ADMINISTRATION.mask))" ng-click="openReloadModal(tableModel.selectedSrcTable.database+'.'+tableModel.selectedSrcTable.name)" style="margin-left:10px;" ><span class="fa fa-download"></span> Reload Table</a> + <a class="btn btn-success pull-right" ng-if="tableModel.selectedSrcTable.source_type==0&&(userService.hasRole('ROLE_ADMIN') || (!kylinConfig.isProd() && hasPermission('project',projectModel, permissions.ADMINISTRATION.mask)))" ng-click="openReloadModal(tableModel.selectedSrcTable.database+'.'+tableModel.selectedSrcTable.name)" style="margin-left:10px;" ><span class="fa fa-download"></span> Reload Table</a> <a class="btn btn-info pull-right" ng-if="tableModel.selectedSrcTable.source_type==0&&(userService.hasRole('ROLE_ADMIN') || hasPermission('project',projectModel, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))" ng-click="calCardinality(tableModel.selectedSrcTable.database+'.'+tableModel.selectedSrcTable.name)" style="margin-left:10px;"><span class="fa fa-download"></span> Cardinality</a> <div class="tabbable nav-tabs-custom"> <ul class="nav nav-tabs">