diff --git a/docs/help/Contents/Account Management/help.md b/docs/help/Contents/Account Management/help.md index 0d17ef57f237ec..f25f7a0bc9b266 100644 --- a/docs/help/Contents/Account Management/help.md +++ b/docs/help/Contents/Account Management/help.md @@ -8,9 +8,9 @@ Syntax: user_identity: 'user_name'@'host' -CREATE USER 命令用于创建一个 Palo 用户。在 Palo 中,一个 user_identity 唯一标识一个用户。user_identity 由两部分组成,user_name 和 host,其中 username 为用户名。host 标识用户端连接所在的主机地址。host 部分可以使用 % 进行模糊匹配。如果不指定 host,默认为 '%',即表示该用户可以从任意 host 连接到 Palo。 +CREATE USER 命令用于创建一个 Doris 用户。在 Doris 中,一个 user_identity 唯一标识一个用户。user_identity 由两部分组成,user_name 和 host,其中 username 为用户名。host 标识用户端连接所在的主机地址。host 部分可以使用 % 进行模糊匹配。如果不指定 host,默认为 '%',即表示该用户可以从任意 host 连接到 Doris。 -host 部分也可指定为 domain,语法为:'user_name'@['domain'],即使用中括号包围,则 Palo 会认为这个是一个 domain,并尝试解析其 ip 地址。目前仅支持百度内部的 BNS 解析。 +host 部分也可指定为 domain,语法为:'user_name'@['domain'],即使用中括号包围,则 Doris 会认为这个是一个 domain,并尝试解析其 ip 地址。目前仅支持百度内部的 BNS 解析。 如果指定了角色(ROLE),则会自动将该角色所拥有的权限赋予新创建的这个用户。如果不指定,则该用户默认没有任何权限。指定的 ROLE 必须已经存在。 @@ -54,7 +54,7 @@ Syntax: DROP USER 'user_name' - DROP USER 命令会删除一个 palo 用户。这里 Palo 不支持删除指定的 user_identity。当删除一个指定用户后,该用户所对应的所有 user_identity 都会被删除。比如之前通过 CREATE USER 语句创建了 jack@'192.%' 以及 jack@['domain'] 两个用户,则在执行 DROP USER 'jack' 后,jack@'192.%' 以及 jack@['domain'] 都将被删除。 + DROP USER 命令会删除一个 palo 用户。这里 Doris 不支持删除指定的 user_identity。当删除一个指定用户后,该用户所对应的所有 user_identity 都会被删除。比如之前通过 CREATE USER 语句创建了 jack@'192.%' 以及 jack@['domain'] 两个用户,则在执行 DROP USER 'jack' 后,jack@'192.%' 以及 jack@['domain'] 都将被删除。 ## example @@ -105,7 +105,7 @@ Syntax: GRANT privilege_list ON db_name[.tbl_name] TO user_identity [ROLE role_name] -privilege_list 是需要赋予的权限列表,以逗号分隔。当前Palo支持如下权限: +privilege_list 是需要赋予的权限列表,以逗号分隔。当前 Doris 支持如下权限: NODE_PRIV:集群节点操作权限,包括节点上下线等操作,只有 root 用户有该权限,不可赋予其他用户。 ADMIN_PRIV:除 NODE_PRIV 以外的所有权限。 diff --git a/fe/src/main/cup/sql_parser.cup b/fe/src/main/cup/sql_parser.cup index 7f0642ae07cc1d..58bba206e9b076 100644 --- a/fe/src/main/cup/sql_parser.cup +++ b/fe/src/main/cup/sql_parser.cup @@ -3281,6 +3281,8 @@ non_pred_expr ::= {: RESULT = new FunctionCallExpr(new FunctionName(null, id), params); :} | KW_DATABASE LPAREN RPAREN {: RESULT = new InformationFunction("DATABASE"); :} + | KW_USER LPAREN RPAREN + {: RESULT = new InformationFunction("USER"); :} | KW_CURRENT_USER LPAREN RPAREN {: RESULT = new InformationFunction("CURRENT_USER"); :} | KW_CONNECTION_ID LPAREN RPAREN diff --git a/fe/src/main/java/org/apache/doris/analysis/Analyzer.java b/fe/src/main/java/org/apache/doris/analysis/Analyzer.java index f5168e64c7eb18..b5916e402046cd 100644 --- a/fe/src/main/java/org/apache/doris/analysis/Analyzer.java +++ b/fe/src/main/java/org/apache/doris/analysis/Analyzer.java @@ -1440,6 +1440,14 @@ public String getQualifiedUser() { return globalState.context.getQualifiedUser(); } + public String getUserIdentity(boolean currentUser) { + if (currentUser) { + return ""; + } else { + return getQualifiedUser() + "@" + ConnectContext.get().getRemoteIP(); + } + } + public String getSchemaDb() { return schemaDb; } diff --git a/fe/src/main/java/org/apache/doris/analysis/InformationFunction.java b/fe/src/main/java/org/apache/doris/analysis/InformationFunction.java index 02c1e7108e63bf..5d27188bba2564 100644 --- a/fe/src/main/java/org/apache/doris/analysis/InformationFunction.java +++ b/fe/src/main/java/org/apache/doris/analysis/InformationFunction.java @@ -17,15 +17,13 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.PrimitiveType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; +import org.apache.doris.qe.ConnectContext; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; import org.apache.doris.thrift.TInfoFunc; -/** - */ public class InformationFunction extends Expr { private final String funcType; private long intValue; @@ -55,10 +53,10 @@ protected void analyzeImpl(Analyzer analyzer) throws AnalysisException { strValue = analyzer.getDefaultDb(); } else if (funcType.equalsIgnoreCase("USER")) { type = Type.VARCHAR; - strValue = analyzer.getQualifiedUser(); + strValue = ConnectContext.get().getUserIdentity().toString(); } else if (funcType.equalsIgnoreCase("CURRENT_USER")) { type = Type.VARCHAR; - strValue = analyzer.getQualifiedUser(); + strValue = ConnectContext.get().getCurrentUserIdentity().toString(); } else if (funcType.equalsIgnoreCase("CONNECTION_ID")) { type = Type.BIGINT; intValue = analyzer.getConnectId(); diff --git a/fe/src/main/java/org/apache/doris/analysis/SetPassVar.java b/fe/src/main/java/org/apache/doris/analysis/SetPassVar.java index eef92444236383..678e3c5caa57f3 100644 --- a/fe/src/main/java/org/apache/doris/analysis/SetPassVar.java +++ b/fe/src/main/java/org/apache/doris/analysis/SetPassVar.java @@ -57,12 +57,15 @@ public void analyze(Analyzer analyzer) throws AnalysisException { boolean isSelf = false; ConnectContext ctx = ConnectContext.get(); if (userIdent == null) { - // set userIdent as itself - userIdent = new UserIdentity(ClusterNamespace.getNameFromFullName(analyzer.getQualifiedUser()), - ctx.getRemoteIP()); + // set userIdent as what current_user() returns + userIdent = ctx.getCurrentUserIdentity(); isSelf = true; + } else { + userIdent.analyze(analyzer.getClusterName()); + if (userIdent.equals(ctx.getCurrentUserIdentity())) { + isSelf = true; + } } - userIdent.analyze(analyzer.getClusterName()); // Check password passwdBytes = MysqlPassword.checkPassword(passwdParam); @@ -92,6 +95,6 @@ public String toString() { @Override public String toSql() { - return "SET PASSWORD FOR " + userIdent + " = '*XXX'"; + return "SET PASSWORD FOR " + userIdent.toString() + " = '*XXX'"; } } diff --git a/fe/src/main/java/org/apache/doris/analysis/UserIdentity.java b/fe/src/main/java/org/apache/doris/analysis/UserIdentity.java index ad109bd9f396fc..181b7c20ecc9b6 100644 --- a/fe/src/main/java/org/apache/doris/analysis/UserIdentity.java +++ b/fe/src/main/java/org/apache/doris/analysis/UserIdentity.java @@ -160,6 +160,9 @@ public boolean equals(Object obj) { return false; } UserIdentity other = (UserIdentity) obj; + if (this.isDomain != other.isDomain) { + return false; + } return user.equals(other.getQualifiedUser()) && host.equals(other.getHost()); } @@ -168,6 +171,7 @@ public int hashCode() { int result = 17; result = 31 * result + user.hashCode(); result = 31 * result + host.hashCode(); + result = 31 * result + Boolean.valueOf(isDomain).hashCode(); return result; } diff --git a/fe/src/main/java/org/apache/doris/mysql/MysqlProto.java b/fe/src/main/java/org/apache/doris/mysql/MysqlProto.java index 2e661f09ede166..c81226638c94d9 100644 --- a/fe/src/main/java/org/apache/doris/mysql/MysqlProto.java +++ b/fe/src/main/java/org/apache/doris/mysql/MysqlProto.java @@ -17,6 +17,7 @@ package org.apache.doris.mysql; +import org.apache.doris.analysis.UserIdentity; import org.apache.doris.catalog.Catalog; import org.apache.doris.cluster.ClusterNamespace; import org.apache.doris.common.Config; @@ -28,12 +29,14 @@ import org.apache.doris.system.SystemInfoService; import com.google.common.base.Strings; +import com.google.common.collect.Lists; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.List; // MySQL protocol util public class MysqlProto { @@ -92,12 +95,14 @@ private static boolean authenticate(ConnectContext context, byte[] scramble, byt String qualifiedUser = ClusterNamespace.getFullName(clusterName, tmpUser); String remoteIp = context.getMysqlChannel().getRemoteIp(); + List currentUserIdentity = Lists.newArrayList(); if (!Catalog.getCurrentCatalog().getAuth().checkPassword(qualifiedUser, remoteIp, - scramble, randomString)) { + scramble, randomString, currentUserIdentity)) { ErrorReport.report(ErrorCode.ERR_ACCESS_DENIED_ERROR, qualifiedUser, usePasswd); return false; } + context.setCurrentUserIdentitfy(currentUserIdentity.get(0)); context.setQualifiedUser(qualifiedUser); return true; } diff --git a/fe/src/main/java/org/apache/doris/mysql/privilege/DbPrivTable.java b/fe/src/main/java/org/apache/doris/mysql/privilege/DbPrivTable.java index f30afbe283863b..bbe56e5d8754b7 100644 --- a/fe/src/main/java/org/apache/doris/mysql/privilege/DbPrivTable.java +++ b/fe/src/main/java/org/apache/doris/mysql/privilege/DbPrivTable.java @@ -26,6 +26,9 @@ import java.io.DataOutput; import java.io.IOException; +/* + * DbPrivTable saves all database level privs + */ public class DbPrivTable extends PrivTable { private static final Logger LOG = LogManager.getLogger(DbPrivTable.class); diff --git a/fe/src/main/java/org/apache/doris/mysql/privilege/PaloAuth.java b/fe/src/main/java/org/apache/doris/mysql/privilege/PaloAuth.java index 90302437be4857..07a35359a35d33 100644 --- a/fe/src/main/java/org/apache/doris/mysql/privilege/PaloAuth.java +++ b/fe/src/main/java/org/apache/doris/mysql/privilege/PaloAuth.java @@ -198,7 +198,8 @@ private void revokeTblPrivs(String host, String db, String user, String tbl, Pri } } - public boolean checkPassword(String remoteUser, String remoteHost, byte[] remotePasswd, byte[] randomString) { + public boolean checkPassword(String remoteUser, String remoteHost, byte[] remotePasswd, byte[] randomString, + List currentUser) { if (!Config.enable_auth_check) { return true; } @@ -209,7 +210,7 @@ public boolean checkPassword(String remoteUser, String remoteHost, byte[] remote readLock(); try { - return userPrivTable.checkPassword(remoteUser, remoteHost, remotePasswd, randomString); + return userPrivTable.checkPassword(remoteUser, remoteHost, remotePasswd, randomString, currentUser); } finally { readUnlock(); } diff --git a/fe/src/main/java/org/apache/doris/mysql/privilege/TablePrivTable.java b/fe/src/main/java/org/apache/doris/mysql/privilege/TablePrivTable.java index 973ed7fabcdba5..eaee241527e5b6 100644 --- a/fe/src/main/java/org/apache/doris/mysql/privilege/TablePrivTable.java +++ b/fe/src/main/java/org/apache/doris/mysql/privilege/TablePrivTable.java @@ -25,6 +25,9 @@ import java.io.DataOutput; import java.io.IOException; +/* + * TablePrivTable saves all table level privs + */ public class TablePrivTable extends PrivTable { public void getPrivs(String host, String db, String user, String tbl, PrivBitSet savedPrivs) { diff --git a/fe/src/main/java/org/apache/doris/mysql/privilege/UserPrivTable.java b/fe/src/main/java/org/apache/doris/mysql/privilege/UserPrivTable.java index 768fd0ec8a6d2f..cc3da9bfefc9dd 100644 --- a/fe/src/main/java/org/apache/doris/mysql/privilege/UserPrivTable.java +++ b/fe/src/main/java/org/apache/doris/mysql/privilege/UserPrivTable.java @@ -27,7 +27,11 @@ import java.io.DataOutput; import java.io.IOException; +import java.util.List; +/* + * UserPrivTable saves all global privs and also password for users + */ public class UserPrivTable extends PrivTable { private static final Logger LOG = LogManager.getLogger(UserPrivTable.class); @@ -61,7 +65,9 @@ public void getPrivs(String host, String user, PrivBitSet savedPrivs) { // validate the connection by host, user and password. // return true if this connection is valid, and 'savedPrivs' save all global privs got from user table. - public boolean checkPassword(String remoteUser, String remoteHost, byte[] remotePasswd, byte[] randomString) { + // if currentUser is not null, save the current user identity + public boolean checkPassword(String remoteUser, String remoteHost, byte[] remotePasswd, byte[] randomString, + List currentUser) { LOG.debug("check password for user: {} from {}, password: {}, random string: {}", remoteUser, remoteHost, remotePasswd, randomString); @@ -87,6 +93,9 @@ public boolean checkPassword(String remoteUser, String remoteHost, byte[] remote && (remotePasswd.length == 0 || MysqlPassword.checkScramble(remotePasswd, randomString, saltPassword))) { // found the matched entry + if (currentUser != null) { + currentUser.add(entry.getUserIdent()); + } return true; } else { continue; diff --git a/fe/src/main/java/org/apache/doris/qe/ConnectContext.java b/fe/src/main/java/org/apache/doris/qe/ConnectContext.java index 18275c6f41d887..a382d6702d1a6b 100644 --- a/fe/src/main/java/org/apache/doris/qe/ConnectContext.java +++ b/fe/src/main/java/org/apache/doris/qe/ConnectContext.java @@ -17,6 +17,7 @@ package org.apache.doris.qe; +import org.apache.doris.analysis.UserIdentity; import org.apache.doris.catalog.Catalog; import org.apache.doris.cluster.ClusterNamespace; import org.apache.doris.mysql.MysqlCapability; @@ -63,8 +64,9 @@ public class ConnectContext { private volatile String currentDb = ""; // cluster name private volatile String clusterName = ""; - // User + // user private volatile String qualifiedUser; + private volatile UserIdentity currentUserIdentity; // Serializer used to pack MySQL packet. private volatile MysqlSerializer serializer; // Variables belong to this session. @@ -164,6 +166,19 @@ public void setQualifiedUser(String qualifiedUser) { this.qualifiedUser = qualifiedUser; } + // for USER() function + public UserIdentity getUserIdentity() { + return new UserIdentity(qualifiedUser, remoteIP); + } + + public UserIdentity getCurrentUserIdentity() { + return currentUserIdentity; + } + + public void setCurrentUserIdentitfy(UserIdentity currentUserIdentity) { + this.currentUserIdentity = currentUserIdentity; + } + public SessionVariable getSessionVariable() { return sessionVariable; } diff --git a/fe/src/test/java/org/apache/doris/analysis/SetPassVarTest.java b/fe/src/test/java/org/apache/doris/analysis/SetPassVarTest.java index 5ab138161417f2..69bcf1c0358a09 100644 --- a/fe/src/test/java/org/apache/doris/analysis/SetPassVarTest.java +++ b/fe/src/test/java/org/apache/doris/analysis/SetPassVarTest.java @@ -47,6 +47,9 @@ public void setUp() { analyzer = AccessTestUtil.fetchAdminAnalyzer(true); MockedAuth.mockedAuth(auth); MockedAuth.mockedConnectContext(ctx, "root", "192.168.1.1"); + UserIdentity currentUser = new UserIdentity("root", "192.168.1.1"); + currentUser.setIsAnalyzed(); + ctx.setCurrentUserIdentitfy(currentUser); } @Test @@ -70,7 +73,7 @@ public void testNormal() throws UserException, AnalysisException { // empty password stmt = new SetPassVar(null, null); stmt.analyze(analyzer); - Assert.assertEquals("SET PASSWORD FOR 'testCluster:testUser'@'192.168.1.1' = '*XXX'", stmt.toString()); + Assert.assertEquals("SET PASSWORD FOR 'root'@'192.168.1.1' = '*XXX'", stmt.toString()); } @Test(expected = AnalysisException.class) diff --git a/fe/src/test/java/org/apache/doris/mysql/MysqlChannelTest.java b/fe/src/test/java/org/apache/doris/mysql/MysqlChannelTest.java index 0937f5aebba959..3474a72fab98d0 100644 --- a/fe/src/test/java/org/apache/doris/mysql/MysqlChannelTest.java +++ b/fe/src/test/java/org/apache/doris/mysql/MysqlChannelTest.java @@ -17,14 +17,13 @@ package org.apache.doris.mysql; -import org.junit.Assert; import org.easymock.EasyMock; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.net.InetSocketAddress; -import java.net.SocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; diff --git a/fe/src/test/java/org/apache/doris/mysql/MysqlProtoTest.java b/fe/src/test/java/org/apache/doris/mysql/MysqlProtoTest.java index 786efdfd04e702..90bcc29616420b 100644 --- a/fe/src/test/java/org/apache/doris/mysql/MysqlProtoTest.java +++ b/fe/src/test/java/org/apache/doris/mysql/MysqlProtoTest.java @@ -17,6 +17,7 @@ package org.apache.doris.mysql; +import org.apache.doris.analysis.UserIdentity; import org.apache.doris.catalog.Catalog; import org.apache.doris.catalog.Database; import org.apache.doris.common.DdlException; @@ -40,6 +41,7 @@ import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; +import java.util.List; @RunWith(PowerMockRunner.class) @PowerMockIgnore({ "org.apache.log4j.*", "javax.management.*" }) @@ -56,9 +58,20 @@ public void setUp() throws DdlException { // mock auth PaloAuth auth = EasyMock.createMock(PaloAuth.class); EasyMock.expect(auth.checkGlobalPriv(EasyMock.anyObject(ConnectContext.class), - EasyMock.anyObject(PrivPredicate.class))).andReturn(true).anyTimes(); + EasyMock.anyObject(PrivPredicate.class))).andReturn(true).anyTimes(); + EasyMock.expect(auth.checkPassword(EasyMock.anyString(), EasyMock.anyString(), (byte[]) EasyMock.anyObject(), - (byte[]) EasyMock.anyObject())).andReturn(true).anyTimes(); + (byte[]) EasyMock.anyObject(), (List) EasyMock.anyObject())).andDelegateTo( + new WrappedAuth() { + @Override + public boolean checkPassword(String remoteUser, String remoteHost, byte[] remotePasswd, + byte[] randomString, + List currentUser) { + UserIdentity userIdentity = new UserIdentity("defaut_cluster:user", "192.168.1.1"); + currentUser.add(userIdentity); + return true; + } + }).anyTimes(); EasyMock.replay(auth); // Mock catalog @@ -141,6 +154,7 @@ public void testNegotiate() throws Exception { mockAccess(); ConnectContext context = new ConnectContext(null); context.setCatalog(catalog); + context.setThreadLocalInfo(); Assert.assertTrue(MysqlProto.negotiate(context)); } diff --git a/fe/src/test/java/org/apache/doris/mysql/WrappedAuth.java b/fe/src/test/java/org/apache/doris/mysql/WrappedAuth.java new file mode 100644 index 00000000000000..272e8c959fe246 --- /dev/null +++ b/fe/src/test/java/org/apache/doris/mysql/WrappedAuth.java @@ -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 org.apache.doris.mysql; + +import org.apache.doris.analysis.UserIdentity; +import org.apache.doris.mysql.privilege.PaloAuth; + +import java.util.List; + +/* + * Author: Chenmingyu + * Date: Mar 24, 2019 + */ + +public class WrappedAuth extends PaloAuth { + @Override + public boolean checkPassword(String remoteUser, String remoteHost, byte[] remotePasswd, byte[] randomString, + List currentUser) { + return true; + } +} diff --git a/fe/src/test/java/org/apache/doris/mysql/privilege/MockedAuth.java b/fe/src/test/java/org/apache/doris/mysql/privilege/MockedAuth.java index a6bf7875c7bb62..fefa0758bbe760 100644 --- a/fe/src/test/java/org/apache/doris/mysql/privilege/MockedAuth.java +++ b/fe/src/test/java/org/apache/doris/mysql/privilege/MockedAuth.java @@ -17,6 +17,7 @@ package org.apache.doris.mysql.privilege; +import org.apache.doris.analysis.UserIdentity; import org.apache.doris.qe.ConnectContext; import org.apache.doris.qe.QueryState; @@ -53,6 +54,11 @@ public static void mockedConnectContext(ConnectContext ctx, String user, String ctx.getState(); result = new QueryState(); + + ctx.getCurrentUserIdentity(); + UserIdentity userIdentity = new UserIdentity(user, ip); + userIdentity.setIsAnalyzed(); + result = userIdentity; } }; } diff --git a/fe/src/test/java/org/apache/doris/mysql/privilege/SetPasswordTest.java b/fe/src/test/java/org/apache/doris/mysql/privilege/SetPasswordTest.java new file mode 100644 index 00000000000000..0e97876fcf2c10 --- /dev/null +++ b/fe/src/test/java/org/apache/doris/mysql/privilege/SetPasswordTest.java @@ -0,0 +1,158 @@ +// 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.mysql.privilege; + +import org.apache.doris.analysis.Analyzer; +import org.apache.doris.analysis.CreateUserStmt; +import org.apache.doris.analysis.SetPassVar; +import org.apache.doris.analysis.UserDesc; +import org.apache.doris.analysis.UserIdentity; +import org.apache.doris.catalog.Catalog; +import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.DdlException; +import org.apache.doris.mysql.MysqlPassword; +import org.apache.doris.persist.EditLog; +import org.apache.doris.persist.PrivInfo; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.system.SystemInfoService; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import mockit.Mocked; +import mockit.NonStrictExpectations; +import mockit.internal.startup.Startup; + +/* + * Author: Chenmingyu + * Date: Mar 24, 2019 + */ + +public class SetPasswordTest { + + private PaloAuth auth; + @Mocked + public Catalog catalog; + @Mocked + private Analyzer analyzer; + @Mocked + private EditLog editLog; + + static { + Startup.initializeIfPossible(); + } + + @Before + public void setUp() throws NoSuchMethodException, SecurityException, AnalysisException { + auth = new PaloAuth(); + new NonStrictExpectations() { + { + analyzer.getClusterName(); + minTimes = 0; + result = SystemInfoService.DEFAULT_CLUSTER; + + Catalog.getCurrentCatalog(); + minTimes = 0; + result = catalog; + + catalog.getAuth(); + minTimes = 0; + result = auth; + + catalog.getEditLog(); + minTimes = 0; + result = editLog; + + editLog.logCreateUser((PrivInfo) any); + minTimes = 0; + + MysqlPassword.checkPassword(anyString); + minTimes = 0; + result = new byte[10]; + } + }; + } + + @Test + public void test() throws DdlException { + UserIdentity userIdentity = new UserIdentity("default_cluster:cmy", "%"); + userIdentity.setIsAnalyzed(); + CreateUserStmt stmt = new CreateUserStmt(new UserDesc(userIdentity)); + auth.createUser(stmt); + + ConnectContext ctx = new ConnectContext(null); + // set password for 'cmy'@'%' + UserIdentity currentUser1 = new UserIdentity("default_cluster:cmy", "%"); + currentUser1.setIsAnalyzed(); + ctx.setCurrentUserIdentitfy(currentUser1); + ctx.setThreadLocalInfo(); + + UserIdentity user1 = new UserIdentity("default_cluster:cmy", "%"); + user1.setIsAnalyzed(); + SetPassVar setPassVar = new SetPassVar(user1, null); + try { + setPassVar.analyze(analyzer); + } catch (AnalysisException e) { + e.printStackTrace(); + Assert.fail(); + } + + // set password without for + SetPassVar setPassVar2 = new SetPassVar(null, null); + try { + setPassVar2.analyze(analyzer); + } catch (AnalysisException e) { + e.printStackTrace(); + Assert.fail(); + } + + // create user cmy2@'192.168.1.1' + UserIdentity userIdentity2 = new UserIdentity("default_cluster:cmy2", "192.168.1.1"); + userIdentity2.setIsAnalyzed(); + stmt = new CreateUserStmt(new UserDesc(userIdentity2)); + auth.createUser(stmt); + + UserIdentity currentUser2 = new UserIdentity("default_cluster:cmy2", "192.168.1.1"); + currentUser2.setIsAnalyzed(); + ctx.setCurrentUserIdentitfy(currentUser2); + ctx.setThreadLocalInfo(); + + // set password without for + SetPassVar setPassVar3 = new SetPassVar(null, null); + try { + setPassVar3.analyze(analyzer); + } catch (AnalysisException e) { + e.printStackTrace(); + Assert.fail(); + } + + // set password for cmy2@'192.168.1.1' + UserIdentity user2 = new UserIdentity("default_cluster:cmy2", "192.168.1.1"); + user2.setIsAnalyzed(); + SetPassVar setPassVar4 = new SetPassVar(user2, null); + try { + setPassVar4.analyze(analyzer); + } catch (AnalysisException e) { + e.printStackTrace(); + Assert.fail(); + } + + } + +} diff --git a/fe/src/test/java/org/apache/doris/qe/SetExecutorTest.java b/fe/src/test/java/org/apache/doris/qe/SetExecutorTest.java index f3062573aa45fe..079bb67417c10d 100644 --- a/fe/src/test/java/org/apache/doris/qe/SetExecutorTest.java +++ b/fe/src/test/java/org/apache/doris/qe/SetExecutorTest.java @@ -60,6 +60,10 @@ public void setUp() throws DdlException { ctx.setCatalog(AccessTestUtil.fetchAdminCatalog()); ctx.setQualifiedUser("root"); ctx.setRemoteIP("192.168.1.1"); + UserIdentity currentUser = new UserIdentity("root", "192.168.1.1"); + currentUser.setIsAnalyzed(); + ctx.setCurrentUserIdentitfy(currentUser); + ctx.setThreadLocalInfo(); new NonStrictExpectations() { {