blob: 08aa9675065b17f9f6a1f8df5d7229954c439539 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.doris.analysis;
import org.apache.doris.catalog.AccessPrivilegeWithCols;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.Config;
import org.apache.doris.common.FeNameFormat;
import org.apache.doris.mysql.privilege.ColPrivilegeKey;
import org.apache.doris.mysql.privilege.PrivBitSet;
import org.apache.doris.mysql.privilege.Privilege;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import java.util.List;
import java.util.Map;
import java.util.Set;
// REVOKE STMT
// revoke privilege from some user, this is an administrator operation.
// REVOKE privilege[(col1,col2...)] [, privilege] ON db.tbl FROM user_identity [ROLE 'role'];
// REVOKE privilege [, privilege] ON resource 'resource' FROM user_identity [ROLE 'role'];
// REVOKE role [, role] FROM user_identity
public class RevokeStmt extends DdlStmt {
private UserIdentity userIdent;
// Indicates which permissions are revoked from this role
private String role;
private TablePattern tblPattern;
private ResourcePattern resourcePattern;
private WorkloadGroupPattern workloadGroupPattern;
private Set<Privilege> privileges = Sets.newHashSet();
private Map<ColPrivilegeKey, Set<String>> colPrivileges = Maps.newHashMap();
// Indicates that these roles are revoked from a user
private List<String> roles;
List<AccessPrivilegeWithCols> accessPrivileges;
public RevokeStmt(UserIdentity userIdent, String role, TablePattern tblPattern,
List<AccessPrivilegeWithCols> privileges) {
this(userIdent, role, tblPattern, null, null, privileges, ResourceTypeEnum.GENERAL);
}
public RevokeStmt(UserIdentity userIdent, String role,
ResourcePattern resourcePattern, List<AccessPrivilegeWithCols> privileges, ResourceTypeEnum type) {
this(userIdent, role, null, resourcePattern, null, privileges, type);
}
public RevokeStmt(UserIdentity userIdent, String role,
WorkloadGroupPattern workloadGroupPattern, List<AccessPrivilegeWithCols> privileges) {
this(userIdent, role, null, null, workloadGroupPattern, privileges, ResourceTypeEnum.GENERAL);
}
public RevokeStmt(List<String> roles, UserIdentity userIdent) {
this.roles = roles;
this.userIdent = userIdent;
}
private RevokeStmt(UserIdentity userIdent, String role, TablePattern tblPattern, ResourcePattern resourcePattern,
WorkloadGroupPattern workloadGroupPattern, List<AccessPrivilegeWithCols> accessPrivileges,
ResourceTypeEnum type) {
this.userIdent = userIdent;
this.role = role;
this.tblPattern = tblPattern;
this.resourcePattern = resourcePattern;
this.workloadGroupPattern = workloadGroupPattern;
if (this.resourcePattern != null) {
this.resourcePattern.setResourceType(type);
}
this.accessPrivileges = accessPrivileges;
}
public UserIdentity getUserIdent() {
return userIdent;
}
public TablePattern getTblPattern() {
return tblPattern;
}
public ResourcePattern getResourcePattern() {
return resourcePattern;
}
public WorkloadGroupPattern getWorkloadGroupPattern() {
return workloadGroupPattern;
}
public String getQualifiedRole() {
return role;
}
public Set<Privilege> getPrivileges() {
return privileges;
}
public List<String> getRoles() {
return roles;
}
public Map<ColPrivilegeKey, Set<String>> getColPrivileges() {
return colPrivileges;
}
@Override
public void analyze(Analyzer analyzer) throws AnalysisException {
if (Config.access_controller_type.equalsIgnoreCase("ranger-doris")) {
throw new AnalysisException("Revoke is prohibited when Ranger is enabled.");
}
if (userIdent != null) {
userIdent.analyze();
} else {
FeNameFormat.checkRoleName(role, false /* can not be superuser */, "Can not revoke from role");
}
if (tblPattern != null) {
tblPattern.analyze(analyzer);
} else if (resourcePattern != null) {
resourcePattern.analyze();
} else if (workloadGroupPattern != null) {
workloadGroupPattern.analyze();
} else if (roles != null) {
for (int i = 0; i < roles.size(); i++) {
String originalRoleName = roles.get(i);
FeNameFormat.checkRoleName(originalRoleName, true /* can be admin */, "Can not revoke role");
}
}
if (!CollectionUtils.isEmpty(accessPrivileges)) {
GrantStmt.checkAccessPrivileges(accessPrivileges);
for (AccessPrivilegeWithCols accessPrivilegeWithCols : accessPrivileges) {
accessPrivilegeWithCols.transferAccessPrivilegeToDoris(privileges, colPrivileges, tblPattern);
}
}
if (CollectionUtils.isEmpty(privileges) && CollectionUtils.isEmpty(roles) && MapUtils.isEmpty(colPrivileges)) {
throw new AnalysisException("No privileges or roles in revoke statement.");
}
// Revoke operation obey the same rule as Grant operation. reuse the same method
if (tblPattern != null) {
GrantStmt.checkTablePrivileges(privileges, tblPattern, colPrivileges);
} else if (resourcePattern != null) {
privileges = PrivBitSet.convertResourcePrivToCloudPriv(resourcePattern, privileges);
GrantStmt.checkResourcePrivileges(privileges, resourcePattern);
} else if (workloadGroupPattern != null) {
GrantStmt.checkWorkloadGroupPrivileges(privileges, workloadGroupPattern);
} else if (roles != null) {
GrantStmt.checkRolePrivileges();
}
}
@Override
public String toSql() {
StringBuilder sb = new StringBuilder();
sb.append("REVOKE ");
if (!CollectionUtils.isEmpty(privileges)) {
sb.append(Joiner.on(", ").join(privileges));
}
if (!MapUtils.isEmpty(colPrivileges)) {
sb.append(GrantStmt.colPrivMapToString(colPrivileges));
}
if (!CollectionUtils.isEmpty(roles)) {
sb.append(Joiner.on(", ").join(roles));
}
if (tblPattern != null) {
sb.append(" ON ").append(tblPattern).append(" FROM ");
} else if (resourcePattern != null) {
sb.append(" ON RESOURCE '").append(resourcePattern).append("' FROM ");
} else if (workloadGroupPattern != null) {
sb.append(" ON WORKLOAD GROUP '").append(workloadGroupPattern).append("' FROM ");
} else {
sb.append(" FROM ");
}
if (!Strings.isNullOrEmpty(role)) {
sb.append(" ROLE '").append(role).append("'");
} else {
sb.append(userIdent);
}
return sb.toString();
}
@Override
public String toString() {
return toSql();
}
}