From cdecc1fc31abce64cf15588e4615520c06ced0fe Mon Sep 17 00:00:00 2001 From: Honghua Zhu Date: Mon, 1 Jan 2024 23:41:56 +0800 Subject: [PATCH] =?UTF-8?q?mongo=EF=BC=9A=E5=AE=9E=E7=8E=B0=E6=89=80?= =?UTF-8?q?=E6=9C=89=E7=9A=84role=E5=92=8Cuser=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mongo/bson/command/role/RoleCommand.java | 230 +++++++++++++++++- .../mongo/bson/command/user/UserCommand.java | 55 +++++ 2 files changed, 275 insertions(+), 10 deletions(-) diff --git a/lealone-plugins/mongo/src/main/java/com/lealone/plugins/mongo/bson/command/role/RoleCommand.java b/lealone-plugins/mongo/src/main/java/com/lealone/plugins/mongo/bson/command/role/RoleCommand.java index 91c44ebeb..bc7d9f264 100644 --- a/lealone-plugins/mongo/src/main/java/com/lealone/plugins/mongo/bson/command/role/RoleCommand.java +++ b/lealone-plugins/mongo/src/main/java/com/lealone/plugins/mongo/bson/command/role/RoleCommand.java @@ -5,9 +5,18 @@ */ package com.lealone.plugins.mongo.bson.command.role; +import org.bson.BsonArray; +import org.bson.BsonBoolean; import org.bson.BsonDocument; +import org.bson.BsonInt32; +import org.bson.BsonString; +import org.bson.BsonValue; import org.bson.io.ByteBufferBsonInput; +import com.lealone.common.util.StatementBuilder; +import com.lealone.db.Database; +import com.lealone.db.LealoneDatabase; +import com.lealone.db.auth.Role; import com.lealone.plugins.mongo.bson.command.BsonCommand; import com.lealone.plugins.mongo.server.MongoServerConnection; import com.lealone.plugins.mongo.server.MongoTask; @@ -44,51 +53,252 @@ public static BsonDocument execute(ByteBufferBsonInput input, BsonDocument doc, private static BsonDocument createRole(ByteBufferBsonInput input, BsonDocument doc, MongoServerConnection conn, MongoTask task) { - return null; + String name = getString(doc, "createRole"); + Database db = getDatabase(doc); + StatementBuilder sql = new StatementBuilder("CREATE ROLE IF NOT EXISTS "); + sql.append('`').append(name).append('`'); + conn.executeUpdateLocal(db, sql); + grantPrivilegesToRole(input, doc, conn, task, name); + grantRolesToRole(input, doc, conn, task, name); + return newOkBsonDocument(); } private static BsonDocument dropRole(ByteBufferBsonInput input, BsonDocument doc, MongoServerConnection conn, MongoTask task) { - return null; + String name = getString(doc, "dropRole"); + Database db = getDatabase(doc); + StatementBuilder sql = new StatementBuilder("DROP ROLE IF EXISTS "); + sql.append('`').append(name).append('`'); + conn.executeUpdateLocal(db, sql); + return newOkBsonDocument(); } private static BsonDocument dropAllRolesFromDatabase(ByteBufferBsonInput input, BsonDocument doc, MongoServerConnection conn, MongoTask task) { - return null; + Database db = getDatabase(doc); + for (Role role : db.getAllRoles()) { + StatementBuilder sql = new StatementBuilder("DROP ROLE IF EXISTS "); + sql.append('`').append(role.getName()).append('`'); + conn.executeUpdateLocal(db, sql); + } + return newOkBsonDocument(); } private static BsonDocument grantPrivilegesToRole(ByteBufferBsonInput input, BsonDocument doc, MongoServerConnection conn, MongoTask task) { - return null; + String role = getString(doc, "grantPrivilegesToRole"); + grantPrivilegesToRole(input, doc, conn, task, role); + return newOkBsonDocument(); + } + + private static void grantPrivilegesToRole(ByteBufferBsonInput input, BsonDocument doc, + MongoServerConnection conn, MongoTask task, String role) { + BsonArray privileges = doc.getArray("privileges", null); + Database db = getDatabase(doc); + if (privileges != null) { + for (int i = 0, size = privileges.size(); i < size; i++) { + BsonDocument privilege = privileges.get(i).asDocument(); + BsonDocument resource = privilege.getDocument("resource"); + BsonArray actions = privilege.getArray("actions", null); + if (actions != null) { + String dbName = getStringOrNull(resource, "db"); + String collection = getStringOrNull(resource, "collection"); + if (db.getName().equalsIgnoreCase(dbName) && collection != null + && !collection.isEmpty()) { + StatementBuilder sql = new StatementBuilder("GRANT"); + for (int j = 0, actionSize = actions.size(); j < actionSize; j++) { + switch (actions.get(j).asString().getValue()) { + case "find": + sql.append(" SELECT"); + break; + case "update": + sql.append(" UPDATE"); + break; + case "insert": + sql.append(" INSERT"); + break; + case "remove": + sql.append(" DELETE"); + break; + } + } + sql.append(" ON ").append(collection).append(" TO ").append(role); + conn.executeUpdateLocal(db, sql); + } + } + } + } } private static BsonDocument grantRolesToRole(ByteBufferBsonInput input, BsonDocument doc, MongoServerConnection conn, MongoTask task) { - return null; + String role = getString(doc, "grantRolesToRole"); + grantRolesToRole(input, doc, conn, task, role); + return newOkBsonDocument(); + } + + private static void grantRolesToRole(ByteBufferBsonInput input, BsonDocument doc, + MongoServerConnection conn, MongoTask task, String role) { + BsonArray roles = doc.getArray("roles", null); + Database db = getDatabase(doc); + if (roles != null) { + for (int i = 0, size = roles.size(); i < size; i++) { + String roleName = null; + if (roles.get(i).isString()) { + roleName = roles.get(i).asString().getValue(); + } else { + BsonDocument roleDoc = roles.get(i).asDocument(); + String dbName = getStringOrNull(roleDoc, "db"); + String roleName2 = getStringOrNull(roleDoc, "role"); + if (db.getName().equalsIgnoreCase(dbName) && roleName2 != null + && !roleName2.isEmpty()) { + roleName = roleName2; + } + } + if (roleName != null) { + StatementBuilder sql = new StatementBuilder("GRANT"); + sql.append(roleName).append(" TO ").append(role); + conn.executeUpdateLocal(db, sql); + } + } + } } private static BsonDocument invalidateUserCache(ByteBufferBsonInput input, BsonDocument doc, MongoServerConnection conn, MongoTask task) { - return null; + return newOkBsonDocument(); } private static BsonDocument revokePrivilegesFromRole(ByteBufferBsonInput input, BsonDocument doc, MongoServerConnection conn, MongoTask task) { - return null; + String role = getString(doc, "revokePrivilegesFromRole"); + BsonArray privileges = doc.getArray("privileges", null); + Database db = getDatabase(doc); + if (privileges != null) { + for (int i = 0, size = privileges.size(); i < size; i++) { + BsonDocument privilege = privileges.get(i).asDocument(); + BsonDocument resource = privilege.getDocument("resource"); + BsonArray actions = privilege.getArray("actions", null); + if (actions != null) { + String dbName = getStringOrNull(resource, "db"); + String collection = getStringOrNull(resource, "collection"); + if (db.getName().equalsIgnoreCase(dbName) && collection != null + && !collection.isEmpty()) { + StatementBuilder sql = new StatementBuilder("REVOKE"); + for (int j = 0, actionSize = actions.size(); j < actionSize; j++) { + switch (actions.get(j).asString().getValue()) { + case "find": + sql.append(" SELECT"); + break; + case "update": + sql.append(" UPDATE"); + break; + case "insert": + sql.append(" INSERT"); + break; + case "remove": + sql.append(" DELETE"); + break; + } + } + sql.append(" ON ").append(collection).append(" FROM ").append(role); + conn.executeUpdateLocal(db, sql); + } + } + } + } + return newOkBsonDocument(); } private static BsonDocument revokeRolesFromRole(ByteBufferBsonInput input, BsonDocument doc, MongoServerConnection conn, MongoTask task) { - return null; + String role = getString(doc, "revokeRolesFromRole"); + BsonArray roles = doc.getArray("roles", null); + Database db = getDatabase(doc); + if (roles != null) { + for (int i = 0, size = roles.size(); i < size; i++) { + String roleName = null; + if (roles.get(i).isString()) { + roleName = roles.get(i).asString().getValue(); + } else { + BsonDocument roleDoc = roles.get(i).asDocument(); + String dbName = getStringOrNull(roleDoc, "db"); + String roleName2 = getStringOrNull(roleDoc, "role"); + if (db.getName().equalsIgnoreCase(dbName) && roleName2 != null + && !roleName2.isEmpty()) { + roleName = roleName2; + } + } + if (roleName != null) { + StatementBuilder sql = new StatementBuilder("REVOKE"); + sql.append(roleName).append(" FROM ").append(role); + conn.executeUpdateLocal(db, sql); + } + } + } + return newOkBsonDocument(); } private static BsonDocument rolesInfo(ByteBufferBsonInput input, BsonDocument doc, MongoServerConnection conn, MongoTask task) { - return null; + BsonArray roles = new BsonArray(); + BsonValue rolesInfo = doc.get("rolesInfo"); + if (rolesInfo.isInt32()) { + Database db = getDatabase(doc); + for (Role role : db.getAllRoles()) { + addRoleBsonDocument(roles, role, db); + } + } else if (rolesInfo.isDocument()) { + addRoleBsonDocument(roles, rolesInfo.asDocument(), doc); + } else if (rolesInfo.isArray()) { + for (BsonValue user : rolesInfo.asArray()) { + addRoleBsonDocument(roles, user.asDocument(), doc); + } + } else if (rolesInfo.isString()) { + Database db = getDatabase(doc); + String roleName = rolesInfo.asString().getValue(); + Role role = db.findRole(null, roleName); + addRoleBsonDocument(roles, role, db); + } + BsonDocument document = new BsonDocument(); + document.append("roles", roles); + setOk(document); + return document; } private static BsonDocument updateRole(ByteBufferBsonInput input, BsonDocument doc, MongoServerConnection conn, MongoTask task) { - return null; + String name = getString(doc, "updateRole"); + grantPrivilegesToRole(input, doc, conn, task, name); + grantRolesToRole(input, doc, conn, task, name); + return newOkBsonDocument(); + } + + private static void addRoleBsonDocument(BsonArray roles, BsonDocument rolesInfo, BsonDocument doc) { + String roleName = getStringOrNull(rolesInfo, "role"); + String dbName = getStringOrNull(rolesInfo, "db"); + Database db = dbName == null ? getDatabase(doc) + : LealoneDatabase.getInstance().getDatabase(dbName); + if (roleName != null) { + Role role = db.findRole(null, roleName); + if (role != null) + addRoleBsonDocument(roles, role, db); + } else { + for (Role role : db.getAllRoles()) { + addRoleBsonDocument(roles, role, db); + } + } + } + + private static void addRoleBsonDocument(BsonArray roles, Role role, Database db) { + BsonDocument u = new BsonDocument(); + u.append("_id", new BsonString(db.getName() + "." + role.getName())); + u.append("roleId", new BsonInt32(role.getId())); + u.append("role", new BsonString(role.getName())); + u.append("db", new BsonString(db.getName())); + u.append("roles", new BsonArray()); + u.append("inheritedRoles", new BsonArray()); + u.append("isBuiltin", new BsonBoolean(false)); + roles.add(u); } } diff --git a/lealone-plugins/mongo/src/main/java/com/lealone/plugins/mongo/bson/command/user/UserCommand.java b/lealone-plugins/mongo/src/main/java/com/lealone/plugins/mongo/bson/command/user/UserCommand.java index 1b466996e..616414334 100644 --- a/lealone-plugins/mongo/src/main/java/com/lealone/plugins/mongo/bson/command/user/UserCommand.java +++ b/lealone-plugins/mongo/src/main/java/com/lealone/plugins/mongo/bson/command/user/UserCommand.java @@ -53,6 +53,7 @@ public static BsonDocument createUser(ByteBufferBsonInput input, BsonDocument do sql.append('`').append(name).append('`').append(" PASSWORD '"); sql.append(pwd).append("' ADMIN"); conn.executeUpdateLocal(db, sql); + grantRolesToUser(input, doc, conn, task, name); return newOkBsonDocument(); } @@ -78,6 +79,7 @@ public static BsonDocument updateUser(ByteBufferBsonInput input, BsonDocument do sql.append('`').append(name).append('`').append(" SET PASSWORD '"); sql.append(pwd).append("'"); conn.executeUpdateLocal(db, sql); + grantRolesToUser(input, doc, conn, task, name); return newOkBsonDocument(); } @@ -143,11 +145,64 @@ private static void addUserBsonDocument(BsonArray users, User user, Database db) public static BsonDocument grantRolesToUser(ByteBufferBsonInput input, BsonDocument doc, MongoServerConnection conn, MongoTask task) { + String user = getString(doc, "grantRolesToUser"); + grantRolesToUser(input, doc, conn, task, user); return newOkBsonDocument(); } + private static void grantRolesToUser(ByteBufferBsonInput input, BsonDocument doc, + MongoServerConnection conn, MongoTask task, String user) { + BsonArray roles = doc.getArray("roles", null); + Database db = getDatabase(doc); + if (roles != null) { + for (int i = 0, size = roles.size(); i < size; i++) { + String roleName = null; + if (roles.get(i).isString()) { + roleName = roles.get(i).asString().getValue(); + } else { + BsonDocument roleDoc = roles.get(i).asDocument(); + String dbName = getStringOrNull(roleDoc, "db"); + String roleName2 = getStringOrNull(roleDoc, "role"); + if (db.getName().equalsIgnoreCase(dbName) && roleName2 != null + && !roleName2.isEmpty()) { + roleName = roleName2; + } + } + if (roleName != null) { + StatementBuilder sql = new StatementBuilder("GRANT"); + sql.append(roleName).append(" TO ").append(user); + conn.executeUpdateLocal(db, sql); + } + } + } + } + public static BsonDocument revokeRolesFromUser(ByteBufferBsonInput input, BsonDocument doc, MongoServerConnection conn, MongoTask task) { + String user = getString(doc, "revokeRolesFromUser"); + BsonArray roles = doc.getArray("roles", null); + Database db = getDatabase(doc); + if (roles != null) { + for (int i = 0, size = roles.size(); i < size; i++) { + String roleName = null; + if (roles.get(i).isString()) { + roleName = roles.get(i).asString().getValue(); + } else { + BsonDocument roleDoc = roles.get(i).asDocument(); + String dbName = getStringOrNull(roleDoc, "db"); + String roleName2 = getStringOrNull(roleDoc, "role"); + if (db.getName().equalsIgnoreCase(dbName) && roleName2 != null + && !roleName2.isEmpty()) { + roleName = roleName2; + } + } + if (roleName != null) { + StatementBuilder sql = new StatementBuilder("REVOKE"); + sql.append(roleName).append(" FROM ").append(user); + conn.executeUpdateLocal(db, sql); + } + } + } return newOkBsonDocument(); } }