Skip to content

Commit

Permalink
Add DistSQL to set user admin (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
RaigorJiang authored Nov 1, 2024
1 parent 130a617 commit 87df9b8
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.InsertStatement;
import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.SelectStatement;
import org.apache.shardingsphere.sql.parser.statement.core.statement.dml.UpdateStatement;
import org.apache.shardingsphere.sql.parser.statement.mysql.dal.MySQLShowDatabasesStatement;

/**
* ACL operation extractor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,14 @@ public static void checkPrivilegesExist(final Collection<DistRoleOrPrivilegeSegm
ShardingSpherePreconditions.checkMustEmpty(invalidDistPrivileges, () -> new UnsupportedOperationException(String.format("Unsupported privileges type %s", invalidDistPrivileges)));
}

/**
* Check user have roles.
*
* @param userRoles user roles
* @param revokeRoles to be revoked roles
*/
public static void checkUserHaveRole(final Collection<RoleSubject> userRoles, final Collection<RoleSubject> revokeRoles) {
revokeRoles.forEach(each -> {
ShardingSpherePreconditions.checkState(userRoles.contains(each),
() -> new UserNotHaveRoleException(each.getRoleName()));
});
revokeRoles.forEach(each -> ShardingSpherePreconditions.checkState(userRoles.contains(each),
() -> new UserNotHaveRoleException(each.getRoleName())));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* 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 com.sphereex.dbplusengine.authority.distsql.handler.update;

import com.sphereex.dbplusengine.authority.distsql.handler.converter.AuthorityStatementConverter;
import com.sphereex.dbplusengine.authority.distsql.segment.DistUserSegment;
import com.sphereex.dbplusengine.authority.distsql.statement.user.AlterDistUserSetAdminStatement;
import com.sphereex.dbplusengine.authority.exception.definition.MissingRequiredUserException;
import com.sphereex.dbplusengine.distsql.handler.aware.DistSQLExecutorGranteeAware;
import lombok.Setter;
import org.apache.shardingsphere.authority.config.AuthorityRuleConfiguration;
import org.apache.shardingsphere.authority.config.UserConfiguration;
import org.apache.shardingsphere.authority.rule.AuthorityRule;
import org.apache.shardingsphere.distsql.handler.engine.update.rdl.rule.spi.global.GlobalRuleDefinitionExecutor;
import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
import org.apache.shardingsphere.infra.metadata.user.Grantee;
import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;

import java.util.Collection;
import java.util.Collections;
import java.util.Optional;

/**
* Alter dist user set admin executor.
*/
@Setter
public final class AlterDistUserSetAdminExecutor implements GlobalRuleDefinitionExecutor<AlterDistUserSetAdminStatement, AuthorityRule>, DistSQLExecutorGranteeAware {

private AuthorityRule rule;

private Grantee grantee;

@Override
public void checkBeforeUpdate(final AlterDistUserSetAdminStatement sqlStatement) {
if (sqlStatement.isAdmin()) {
checkNoAdmins();
} else {
checkCurrentUserIsAdmin();
checkTargetUserIsAdmin(sqlStatement);
}
checkUserExist(sqlStatement);
}

private void checkNoAdmins() {
Collection<UserConfiguration> users = rule.getConfiguration().getUsers();
ShardingSpherePreconditions.checkState(users.stream().noneMatch(UserConfiguration::isAdmin),
() -> new UnsupportedOperationException("Unsupported when there is already an admin user"));
}

private void checkCurrentUserIsAdmin() {
Optional<ShardingSphereUser> currentUser = rule.findUser(grantee);
ShardingSpherePreconditions.checkState(currentUser.isPresent() && currentUser.get().isAdmin(),
() -> new UnsupportedOperationException("Unsupported because current user is not admin"));
}

private void checkTargetUserIsAdmin(final AlterDistUserSetAdminStatement sqlStatement) {
Optional<Grantee> toBeAlteredGrantee = rule.getGrantees().stream().filter(each -> each.accept(new Grantee(sqlStatement.getUser().getUser(), sqlStatement.getUser().getHost()))).findFirst();
ShardingSpherePreconditions.checkState(toBeAlteredGrantee.isPresent(), () -> new MissingRequiredUserException(Collections.singleton(grantee)));
Optional<ShardingSphereUser> toBeAlteredUser = rule.findUser(toBeAlteredGrantee.get());
ShardingSpherePreconditions.checkState(toBeAlteredUser.isPresent(), () -> new MissingRequiredUserException(Collections.singleton(grantee)));
ShardingSpherePreconditions.checkState(toBeAlteredUser.get().isAdmin(),
() -> new UnsupportedOperationException("Unsupported because to be altered user is not admin"));
}

private void checkUserExist(final AlterDistUserSetAdminStatement sqlStatement) {
DistUserSegment userSegment = sqlStatement.getUser();
Grantee grantee = new Grantee(userSegment.getUser(), userSegment.getHost());
ShardingSpherePreconditions.checkContains(rule.getGrantees(), grantee, () -> new MissingRequiredUserException(Collections.singleton(grantee)));
}

@Override
public AuthorityRuleConfiguration buildToBeAlteredRuleConfiguration(final AlterDistUserSetAdminStatement sqlStatement) {
Optional<Grantee> toBeAlteredGrantee = rule.getGrantees().stream().filter(each -> each.accept(new Grantee(sqlStatement.getUser().getUser(), sqlStatement.getUser().getHost()))).findFirst();
ShardingSpherePreconditions.checkState(toBeAlteredGrantee.isPresent(), () -> new MissingRequiredUserException(Collections.singleton(grantee)));
Optional<ShardingSphereUser> toBeAlteredUser = rule.findUser(toBeAlteredGrantee.get());
ShardingSpherePreconditions.checkState(toBeAlteredUser.isPresent(), () -> new MissingRequiredUserException(Collections.singleton(grantee)));
AuthorityRuleConfiguration result = AuthorityStatementConverter.createAuthorityRuleConfiguration(rule.getConfiguration());
result.getUsers().removeIf(each -> new Grantee(each.getUsername(), each.getHostname()).equals(toBeAlteredUser.get().getGrantee()));
result.getUsers().add(new UserConfiguration(toBeAlteredGrantee.get().getUsername(),
toBeAlteredUser.get().getPassword(), toBeAlteredGrantee.get().getHostname(), toBeAlteredUser.get().getAuthenticationMethodName(), sqlStatement.isAdmin()));
return result;
}

@Override
public Class<AuthorityRule> getRuleClass() {
return AuthorityRule.class;
}

@Override
public Class<AlterDistUserSetAdminStatement> getType() {
return AlterDistUserSetAdminStatement.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
com.sphereex.dbplusengine.authority.distsql.handler.update.AlterPrivilegeProviderExecutor
com.sphereex.dbplusengine.authority.distsql.handler.update.CreateDistUserExecutor
com.sphereex.dbplusengine.authority.distsql.handler.update.AlterDistUserExecutor
com.sphereex.dbplusengine.authority.distsql.handler.update.AlterDistUserSetAdminExecutor
com.sphereex.dbplusengine.authority.distsql.handler.update.DropDistUserExecutor
com.sphereex.dbplusengine.authority.distsql.handler.update.CreateDistRoleExecutor
com.sphereex.dbplusengine.authority.distsql.handler.update.DropDistRoleExecutor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,11 @@ FROM
ALL
: A L L
;

SET
: S E T
;

ADMIN
: A D M I N
;
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ alterDistUser
: ALTER DIST USER ifExists? alterUserEntry
;

alterDistUserSetAdmin
: ALTER DIST USER userName_ SET ADMIN EQ_ boolean_
;

boolean_
: TRUE | FALSE
;

dropDistUser
: DROP DIST USER ifExists? userList
;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ execute
: (alterPrivilegeProvider
| createDistUser
| alterDistUser
| alterDistUserSetAdmin
| dropDistUser
| createDistRole
| dropDistRole
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.sphereex.dbplusengine.authority.distsql.statement.role.CreateDistRoleStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.role.DropDistRoleStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.role.ShowDistRolesStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.user.AlterDistUserSetAdminStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.user.AlterDistUserStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.user.CreateDistUserStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.user.DropDistUserStatement;
Expand All @@ -39,6 +40,7 @@
import org.apache.shardingsphere.distsql.parser.autogen.SphereExAuthorityDistSQLStatementParser.AclObjectTypeContext;
import org.apache.shardingsphere.distsql.parser.autogen.SphereExAuthorityDistSQLStatementParser.AlgorithmDefinitionContext;
import org.apache.shardingsphere.distsql.parser.autogen.SphereExAuthorityDistSQLStatementParser.AlterDistUserContext;
import org.apache.shardingsphere.distsql.parser.autogen.SphereExAuthorityDistSQLStatementParser.AlterDistUserSetAdminContext;
import org.apache.shardingsphere.distsql.parser.autogen.SphereExAuthorityDistSQLStatementParser.AlterPrivilegeProviderContext;
import org.apache.shardingsphere.distsql.parser.autogen.SphereExAuthorityDistSQLStatementParser.AlterUserEntryIdentifiedByContext;
import org.apache.shardingsphere.distsql.parser.autogen.SphereExAuthorityDistSQLStatementParser.ColumnNamesContext;
Expand Down Expand Up @@ -131,6 +133,13 @@ public ASTNode visitAlterUserEntryIdentifiedBy(final AlterUserEntryIdentifiedByC
return new DistUserSegment(user, host, null, auth, false);
}

@Override
public ASTNode visitAlterDistUserSetAdmin(final AlterDistUserSetAdminContext ctx) {
String user = getIdentifierValue(ctx.userName_().userIdentifierOrText().textOrIdentifier(0));
String host = null == ctx.userName_().userIdentifierOrText().AT_() ? null : getIdentifierValue(ctx.userName_().userIdentifierOrText().textOrIdentifier(1));
return new AlterDistUserSetAdminStatement(new DistUserSegment(user, host, null, null, false), null != ctx.boolean_().TRUE());
}

@Override
public ASTNode visitDropDistUser(final DropDistUserContext ctx) {
return new DropDistUserStatement(ctx.userList().userName_().stream().map(each -> (DistUserSegment) visit(each)).collect(Collectors.toList()), null != ctx.ifExists());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@

package com.sphereex.dbplusengine.authority.distsql.acl;

import com.sphereex.dbplusengine.authority.distsql.statement.user.AlterDistUserStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.privilege.GrantDistPrivilegesStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.privilege.RevokeDistPrivilegesStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.role.CreateDistRoleStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.user.CreateDistUserStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.role.DropDistRoleStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.user.AlterDistUserSetAdminStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.user.AlterDistUserStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.user.CreateDistUserStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.user.DropDistUserStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.privilege.GrantDistPrivilegesStatement;
import com.sphereex.dbplusengine.authority.distsql.statement.privilege.RevokeDistPrivilegesStatement;
import com.sphereex.dbplusengine.distsql.acl.DistSQLACLObjectProvider;
import org.apache.shardingsphere.distsql.statement.DistSQLStatement;

Expand All @@ -42,6 +43,7 @@ public final class AuthorityACLObjectProvider implements DistSQLACLObjectProvide
static {
ACL_OBJECTS.put(CreateDistUserStatement.class, ACL_OBJECT);
ACL_OBJECTS.put(AlterDistUserStatement.class, ACL_OBJECT);
ACL_OBJECTS.put(AlterDistUserSetAdminStatement.class, ACL_OBJECT);
ACL_OBJECTS.put(DropDistUserStatement.class, ACL_OBJECT);
ACL_OBJECTS.put(CreateDistRoleStatement.class, ACL_OBJECT);
ACL_OBJECTS.put(DropDistRoleStatement.class, ACL_OBJECT);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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 com.sphereex.dbplusengine.authority.distsql.statement.user;

import com.sphereex.dbplusengine.authority.distsql.segment.DistUserSegment;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.distsql.statement.rdl.rule.global.GlobalRuleDefinitionStatement;
import org.apache.shardingsphere.sql.parser.statement.core.statement.dcl.DCLStatement;

/**
* Alter dist user set admin statement.
*/
@RequiredArgsConstructor
@Getter
public final class AlterDistUserSetAdminStatement extends GlobalRuleDefinitionStatement implements DCLStatement {

private final DistUserSegment user;

private final boolean admin;
}

0 comments on commit 87df9b8

Please sign in to comment.