You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by me...@apache.org on 2021/03/22 09:32:13 UTC

[shardingsphere] branch master updated: Create MySQLPrivilegesLoader (#9767)

This is an automated email from the ASF dual-hosted git repository.

menghaoran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 0f4db5e  Create MySQLPrivilegesLoader (#9767)
0f4db5e is described below

commit 0f4db5edf2303753337aed6c5a8dc8cb24255819
Author: Juan Pan(Trista) <pa...@apache.org>
AuthorDate: Mon Mar 22 17:31:38 2021 +0800

    Create MySQLPrivilegesLoader (#9767)
---
 .../loader/dialect/MySQLPrivilegesLoader.java      | 243 +++++++++++++++++++++
 1 file changed, 243 insertions(+)

diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/auth/builder/loader/dialect/MySQLPrivilegesLoader.java b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/auth/builder/loader/dialect/MySQLPrivilegesLoader.java
new file mode 100644
index 0000000..16652d4
--- /dev/null
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/auth/builder/loader/dialect/MySQLPrivilegesLoader.java
@@ -0,0 +1,243 @@
+/*
+ * 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.shardingsphere.infra.metadata.auth.builder.loader.dialect;
+
+import com.google.common.base.Joiner;
+import org.apache.shardingsphere.infra.metadata.auth.model.privilege.PrivilegeType;
+import org.apache.shardingsphere.infra.metadata.auth.model.privilege.ShardingSpherePrivilege;
+import org.apache.shardingsphere.infra.metadata.auth.model.privilege.database.SchemaPrivilege;
+import org.apache.shardingsphere.infra.metadata.auth.model.privilege.database.TablePrivilege;
+import org.apache.shardingsphere.infra.metadata.auth.model.user.Grantee;
+import org.apache.shardingsphere.infra.metadata.auth.model.user.ShardingSphereUser;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * MySQL privileges loader.
+ */
+public final class MySQLPrivilegesLoader {
+    
+    /**
+     * Load.
+     *
+     * @param users users
+     * @param dataSource data source
+     * @return privileges
+     * @throws SQLException sql exception
+     */
+    public Map<ShardingSphereUser, ShardingSpherePrivilege> load(final Collection<ShardingSphereUser> users, final DataSource dataSource) throws SQLException {
+        Map<ShardingSphereUser, ShardingSpherePrivilege> result = new LinkedHashMap<>();
+        fillGlobalPrivilege(result, dataSource, users);
+        fillSchemaPrivilege(result, dataSource, users);
+        fillTablePrivilege(result, dataSource, users);
+        return result;
+    }
+    
+    private void fillGlobalPrivilege(final Map<ShardingSphereUser, ShardingSpherePrivilege> privileges, final DataSource dataSource, final Collection<ShardingSphereUser> users) throws SQLException {
+        try (Connection connection = dataSource.getConnection()) {
+            Statement statement = connection.createStatement();
+            try (ResultSet resultSet = statement.executeQuery(getGlobalPrivilegeSQL(users))) {
+                while (resultSet.next()) {
+                    fillGlobalPrivilege(privileges, resultSet);
+                }
+            }
+        }
+    }
+    
+    private void fillGlobalPrivilege(final Map<ShardingSphereUser, ShardingSpherePrivilege> privileges, final ResultSet resultSet) throws SQLException {
+        Optional<ShardingSphereUser> user = getShardingSphereUser(privileges, resultSet);
+        if (user.isPresent()) {
+            privileges.get(user.get()).getAdministrativePrivilege().getPrivileges().addAll(loadAdministrativePrivileges(resultSet));
+            privileges.get(user.get()).getDatabasePrivilege().getGlobalPrivileges().addAll(loadDatabaseGlobalPrivileges(resultSet));
+        }
+    }
+    
+    private void fillSchemaPrivilege(final Map<ShardingSphereUser, ShardingSpherePrivilege> privileges, final DataSource dataSource, final Collection<ShardingSphereUser> users) throws SQLException {
+        try (Connection connection = dataSource.getConnection()) {
+            Statement statement = connection.createStatement();
+            try (ResultSet resultSet = statement.executeQuery(getSchemaPrivilegeSQL(users))) {
+                while (resultSet.next()) {
+                    fillSchemaPrivilege(privileges, resultSet);
+                }
+            }
+        }
+    }
+    
+    private void fillSchemaPrivilege(final Map<ShardingSphereUser, ShardingSpherePrivilege> privileges, final ResultSet resultSet) throws SQLException {
+        Optional<ShardingSphereUser> user = getShardingSphereUser(privileges, resultSet);
+        if (user.isPresent()) {
+            String db = resultSet.getString("Db");
+            SchemaPrivilege schemaPrivilege = new SchemaPrivilege(db);
+            schemaPrivilege.getGlobalPrivileges().addAll(loadDatabaseGlobalPrivileges(resultSet));
+            privileges.get(user.get()).getDatabasePrivilege().getSpecificPrivileges().put(db, schemaPrivilege);
+        }
+    }
+    
+    private void fillTablePrivilege(final Map<ShardingSphereUser, ShardingSpherePrivilege> privileges, final DataSource dataSource, final Collection<ShardingSphereUser> users) throws SQLException {
+        try (Connection connection = dataSource.getConnection()) {
+            Statement statement = connection.createStatement();
+            try (ResultSet resultSet = statement.executeQuery(getTablePrivilegeSQL(users))) {
+                while (resultSet.next()) {
+                    fillTablePrivilege(privileges, resultSet);
+                }
+            }
+        }
+    }
+    
+    private void fillTablePrivilege(final Map<ShardingSphereUser, ShardingSpherePrivilege> privileges, final ResultSet resultSet) throws SQLException {
+        Optional<ShardingSphereUser> user = getShardingSphereUser(privileges, resultSet);
+        if (user.isPresent()) {
+            String db = resultSet.getString("Db");
+            String tableName = resultSet.getString("Table_name");
+            String[] tablePrivileges = (String[]) resultSet.getArray("Table_priv").getArray();
+            TablePrivilege tablePrivilege = new TablePrivilege(tableName, getPrivileges(tablePrivileges));
+            ShardingSpherePrivilege privilege = privileges.get(user.get());
+            if (!privilege.getDatabasePrivilege().getSpecificPrivileges().containsKey(db)) {
+                privilege.getDatabasePrivilege().getSpecificPrivileges().put(db, new SchemaPrivilege(db));
+            }
+            privilege.getDatabasePrivilege().getSpecificPrivileges().get(db).getSpecificPrivileges().put(tableName, tablePrivilege);
+        }
+    }
+    
+    private String getGlobalPrivilegeSQL(final Collection<ShardingSphereUser> users) {
+        Collection<String> result = new LinkedList<>();
+        StringBuilder builder = new StringBuilder("SELECT * FROM mysql.user WHERE (user, host) in ( ");
+        users.forEach(each -> builder.append("(").append(each.getGrantee().getUsername()).append(", ").append(each.getGrantee().getHostname()).append(")"));
+        return builder.append(Joiner.on(", ").join(result)).append(" )").toString();
+    }
+    
+    private String getSchemaPrivilegeSQL(final Collection<ShardingSphereUser> users) {
+        Collection<String> result = new LinkedList<>();
+        StringBuilder builder = new StringBuilder("SELECT * FROM mysql.db WHERE (user, host) in ( ");
+        users.forEach(each -> builder.append("(").append(each.getGrantee().getUsername()).append(", ").append(each.getGrantee().getHostname()).append(")"));
+        return builder.append(Joiner.on(", ").join(result)).append(" )").toString();
+    }
+    
+    private String getTablePrivilegeSQL(final Collection<ShardingSphereUser> users) {
+        Collection<String> result = new LinkedList<>();
+        StringBuilder builder = new StringBuilder("SELECT Db, Table_name, Table_priv FROM mysql.tables_priv WHERE (user, host) in ( ");
+        users.forEach(each -> builder.append("(").append(each.getGrantee().getUsername()).append(", ").append(each.getGrantee().getHostname()).append(")"));
+        return builder.append(Joiner.on(", ").join(result)).append(" )").toString();
+    }
+    
+    private Optional<ShardingSphereUser> getShardingSphereUser(final Map<ShardingSphereUser, ShardingSpherePrivilege> privileges, final ResultSet resultSet) throws SQLException {
+        Grantee grantee = new Grantee(resultSet.getString("user"), resultSet.getString("host"));
+        return privileges.keySet().stream().filter(each -> each.getGrantee().equals(grantee)).findFirst();
+    }
+    
+    private Collection<PrivilegeType> getPrivileges(final String[] privileges) {
+        return Arrays.stream(privileges).map(this::getPrivilegeType).collect(Collectors.toSet());
+    }
+    
+    private PrivilegeType getPrivilegeType(final String privilege) {
+        switch (privilege) {
+            case "Select":
+                return PrivilegeType.SELECT;
+            case "Insert":
+                return PrivilegeType.INSERT;
+            case "Update":
+                return PrivilegeType.UPDATE;
+            case "Delete":
+                return PrivilegeType.DELETE;
+            case "Create":
+                return PrivilegeType.CREATE;
+            case "Alter":
+                return PrivilegeType.ALTER;
+            case "Drop":
+                return PrivilegeType.DROP;
+            case "Grant":
+                return PrivilegeType.GRANT;
+            case "Index":
+                return PrivilegeType.INDEX;
+            case "References":
+                return PrivilegeType.REFERENCES;
+            case "Create View":
+                return PrivilegeType.CREATE_VIEW;
+            case "Show view":
+                return PrivilegeType.SHOW_VIEW;
+            case "Trigger":
+                return PrivilegeType.TRIGGER;
+            default:
+                throw new UnsupportedOperationException(privilege);
+        }
+    }
+    
+    private Collection<PrivilegeType> loadAdministrativePrivileges(final ResultSet resultSet) throws SQLException {
+        Collection<PrivilegeType> result = new LinkedList<>();
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Super_priv"), PrivilegeType.SUPER, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Reload_priv"), PrivilegeType.RELOAD, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Shutdown_priv"), PrivilegeType.SHUTDOWN, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Process_priv"), PrivilegeType.PROCESS, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("File_priv"), PrivilegeType.FILE, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Show_db_priv"), PrivilegeType.SHOW_DB, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Repl_slave_priv"), PrivilegeType.REPL_SLAVE, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Repl_client_priv"), PrivilegeType.REPL_CLIENT, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Create_user_priv"), PrivilegeType.CREATE_USER, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Create_tablespace_priv"), PrivilegeType.CREATE_TABLESPACE, result);
+        return result;
+    }
+    
+    private Collection<PrivilegeType> loadDatabaseGlobalPrivileges(final ResultSet resultSet) throws SQLException {
+        Collection<PrivilegeType> result = new LinkedList<>();
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Select_priv"), PrivilegeType.SELECT, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Insert_priv"), PrivilegeType.INSERT, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Update_priv"), PrivilegeType.UPDATE, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Delete_priv"), PrivilegeType.DELETE, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Create_priv"), PrivilegeType.CREATE, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Alter_priv"), PrivilegeType.ALTER, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Drop_priv"), PrivilegeType.DROP, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Grant_priv"), PrivilegeType.GRANT, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Index_priv"), PrivilegeType.INDEX, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("References_priv"), PrivilegeType.REFERENCES, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Create_tmp_table_priv"), PrivilegeType.CREATE_TMP, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Lock_tables_priv"), PrivilegeType.LOCK_TABLES, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Execute_priv"), PrivilegeType.EXECUTE, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Create_view_priv"), PrivilegeType.CREATE_VIEW, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Show_view_priv"), PrivilegeType.SHOW_VIEW, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Create_routine_priv"), PrivilegeType.CREATE_PROC, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Alter_routine_priv"), PrivilegeType.ALTER_PROC, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Event_priv"), PrivilegeType.EVENT, result);
+        addToPrivilegeTypesIfPresent(resultSet.getBoolean("Trigger_priv"), PrivilegeType.TRIGGER, result);
+        return result;
+    }
+    
+    private void addToPrivilegeTypesIfPresent(final boolean hasPrivilege, final PrivilegeType privilegeType, final Collection<PrivilegeType> target) {
+        if (hasPrivilege) {
+            target.add(privilegeType);
+        }
+    }
+    
+    /**
+     * Get database type.
+     * @return database type
+     */
+    public String getDatabaseType() {
+        return "MySQL";
+    }
+}