From 96d2464538106caf2988b2a314f908b0fce2af36 Mon Sep 17 00:00:00 2001 From: pesse Date: Fri, 15 Mar 2019 00:06:14 +0100 Subject: [PATCH 1/7] Simple test to check if we get what we expect --- src/main/java/org/utplsql/cli/RunCommand.java | 2 +- src/test/java/org/utplsql/cli/RunCommandTest.java | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/utplsql/cli/RunCommand.java b/src/main/java/org/utplsql/cli/RunCommand.java index cbfca36..65ae15c 100644 --- a/src/main/java/org/utplsql/cli/RunCommand.java +++ b/src/main/java/org/utplsql/cli/RunCommand.java @@ -124,7 +124,7 @@ public class RunCommand implements ICommand { private ReporterFactory reporterFactory; private ReporterManager reporterManager; - private ConnectionInfo getConnectionInfo() { + ConnectionInfo getConnectionInfo() { return connectionInfoList.get(0); } diff --git a/src/test/java/org/utplsql/cli/RunCommandTest.java b/src/test/java/org/utplsql/cli/RunCommandTest.java index 84eccdc..941a0e1 100644 --- a/src/test/java/org/utplsql/cli/RunCommandTest.java +++ b/src/test/java/org/utplsql/cli/RunCommandTest.java @@ -85,4 +85,11 @@ void reporterOptions_TwoReporters() { assertTrue(reporterOptions2.outputToScreen()); } + @Test + void connectionString_asSysdba() { + RunCommand runCmd = TestHelper.createRunCommand("sys as sysdba/mypass@connectstring/service"); + + assertEquals("sys as sysdba/mypass@connectstring/service", + runCmd.getConnectionInfo().getConnectionString()); + } } From 3af01221e1085e285d04cd522574720a47159db7 Mon Sep 17 00:00:00 2001 From: pesse Date: Fri, 15 Mar 2019 00:15:49 +0100 Subject: [PATCH 2/7] Some simple tests to ensure parsing of special-chars User/PW is possible --- .../org/utplsql/cli/ConnectionConfigTest.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/test/java/org/utplsql/cli/ConnectionConfigTest.java diff --git a/src/test/java/org/utplsql/cli/ConnectionConfigTest.java b/src/test/java/org/utplsql/cli/ConnectionConfigTest.java new file mode 100644 index 0000000..6509d8a --- /dev/null +++ b/src/test/java/org/utplsql/cli/ConnectionConfigTest.java @@ -0,0 +1,44 @@ +package org.utplsql.cli; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ConnectionConfigTest { + + @Test + void parse() { + ConnectionConfig info = new ConnectionConfig("test/pw@my.local.host/service"); + + assertEquals("test", info.getUser()); + assertEquals("pw", info.getPassword()); + assertEquals("my.local.host/service", info.getConnect()); + } + + @Test + void parseSysDba() { + ConnectionConfig info = new ConnectionConfig("sys as sysdba/pw@my.local.host/service"); + + assertEquals("sys as sysdba", info.getUser()); + assertEquals("pw", info.getPassword()); + assertEquals("my.local.host/service", info.getConnect()); + } + + @Test + void parseSpecialCharsPW() { + ConnectionConfig info = new ConnectionConfig("test/\"p@ssw0rd=\"@my.local.host/service"); + + assertEquals("test", info.getUser()); + assertEquals("p@ssw0rd=", info.getPassword()); + assertEquals("my.local.host/service", info.getConnect()); + } + + @Test + void parseSpecialCharsUser() { + ConnectionConfig info = new ConnectionConfig("\"User/Mine@=\"/pw@my.local.host/service"); + + assertEquals("User/Mine@=", info.getUser()); + assertEquals("pw", info.getPassword()); + assertEquals("my.local.host/service", info.getConnect()); + } +} From 41fa06b532a1770fc9ec7d5e070198540de78619 Mon Sep 17 00:00:00 2001 From: pesse Date: Fri, 15 Mar 2019 07:41:16 +0100 Subject: [PATCH 3/7] Support user/password containing / and @ --- .../java/org/utplsql/cli/ConnectionConfig.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/utplsql/cli/ConnectionConfig.java b/src/main/java/org/utplsql/cli/ConnectionConfig.java index b98c6a5..ec2734d 100644 --- a/src/main/java/org/utplsql/cli/ConnectionConfig.java +++ b/src/main/java/org/utplsql/cli/ConnectionConfig.java @@ -10,16 +10,26 @@ public class ConnectionConfig { private final String connect; public ConnectionConfig( String connectString ) { - Matcher m = Pattern.compile("^([^/]+)/([^@]+)@(.*)$").matcher(connectString); + Matcher m = Pattern.compile("^(\".+\"|[^/]+)/(\".+\"|[^@]+)@(.*)$").matcher(connectString); if ( m.find() ) { - user = m.group(1); - password = m.group(2); + user = stripEnclosingQuotes(m.group(1)); + password = stripEnclosingQuotes(m.group(2)); connect = m.group(3); } else throw new IllegalArgumentException("Not a valid connectString: '" + connectString + "'"); } + private String stripEnclosingQuotes( String value ) { + if ( value.length() > 1 + && value.startsWith("\"") + && value.endsWith("\"")) { + return value.substring(1, value.length()-1); + } else { + return value; + } + } + public String getConnect() { return connect; } From 7fa4a72b71fca4a3cde2cf68d333b75063bae9a0 Mon Sep 17 00:00:00 2001 From: pesse Date: Fri, 15 Mar 2019 08:03:16 +0100 Subject: [PATCH 4/7] Improvement of tests --- .../org/utplsql/cli/DataSourceProviderIT.java | 8 ++++++ .../java/org/utplsql/cli/RunCommandIT.java | 26 ++++++++++--------- src/test/java/org/utplsql/cli/TestHelper.java | 12 +++++++++ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/test/java/org/utplsql/cli/DataSourceProviderIT.java b/src/test/java/org/utplsql/cli/DataSourceProviderIT.java index cfff041..0bef99a 100644 --- a/src/test/java/org/utplsql/cli/DataSourceProviderIT.java +++ b/src/test/java/org/utplsql/cli/DataSourceProviderIT.java @@ -20,6 +20,14 @@ void connectToDatabase() throws SQLException { assertNotNull(dataSource); } + //@Test + void connectAsSysdba() throws SQLException { + ConnectionConfig config = new ConnectionConfig("sys as sysdba/oracle@localhost:1522/ORCLPDB1"); + DataSource dataSource = new TestedDataSourceProvider(config).getDataSource(); + + assertNotNull(dataSource); + } + @Test void initNlsLang() throws SQLException { System.setProperty("NLS_LANG", "BRAZILIAN PORTUGUESE_BRAZIL.WE8ISO8859P1"); diff --git a/src/test/java/org/utplsql/cli/RunCommandIT.java b/src/test/java/org/utplsql/cli/RunCommandIT.java index a6373fb..ae14b5a 100644 --- a/src/test/java/org/utplsql/cli/RunCommandIT.java +++ b/src/test/java/org/utplsql/cli/RunCommandIT.java @@ -5,6 +5,7 @@ import org.utplsql.api.reporter.CoreReporters; import java.nio.file.Paths; +import java.sql.SQLException; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -13,6 +14,14 @@ */ class RunCommandIT extends AbstractFileOutputTest { + private void assertValidReturnCode(int returnCode) throws SQLException { + // Only expect failure-exit-code to work on several framework versions + if (OptionalFeatures.FAIL_ON_ERROR.isAvailableFor(TestHelper.getFrameworkVersion())) + assertEquals(2, returnCode); + else + assertEquals(0, returnCode); + } + @Test void run_Default() throws Exception { @@ -23,11 +32,7 @@ void run_Default() throws Exception { "-c", "--failure-exit-code=2"); - // Only expect failure-exit-code to work on several framework versions - if (OptionalFeatures.FAIL_ON_ERROR.isAvailableFor(TestHelper.getFrameworkVersion())) - assertEquals(2, result); - else - assertEquals(0, result); + assertValidReturnCode(result); } @Test @@ -35,9 +40,10 @@ void run_Debug() throws Exception { int result = TestHelper.runApp("run", TestHelper.getConnectionString(), - "--debug"); + "--debug", + "--failure-exit-code=2"); - assertEquals(1, result); + assertValidReturnCode(result); } @Test @@ -55,11 +61,7 @@ void run_MultipleReporters() throws Exception { "-c", "--failure-exit-code=2"); - // Only expect failure-exit-code to work on several framework versions - if (OptionalFeatures.FAIL_ON_ERROR.isAvailableFor(TestHelper.getFrameworkVersion())) - assertEquals(2, result); - else - assertEquals(0, result); + assertValidReturnCode(result); } diff --git a/src/test/java/org/utplsql/cli/TestHelper.java b/src/test/java/org/utplsql/cli/TestHelper.java index ca1abc9..77375bd 100644 --- a/src/test/java/org/utplsql/cli/TestHelper.java +++ b/src/test/java/org/utplsql/cli/TestHelper.java @@ -45,4 +45,16 @@ static Version getFrameworkVersion() throws SQLException { static String getConnectionString() { return sUser + "/" + sPass + "@" + sUrl; } + + static String getUser() { + return sUser; + } + + static String getPass() { + return sPass; + } + + static String getUrl() { + return sUrl; + } } From 42078345dcd987d5959ed1d234fd0af5adbabb0c Mon Sep 17 00:00:00 2001 From: pesse Date: Tue, 19 Mar 2019 22:03:33 +0100 Subject: [PATCH 5/7] Update documentation how to run utPLSQL-cli as sysdba --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 35a088d..6f71924 100644 --- a/README.md +++ b/README.md @@ -227,6 +227,16 @@ UT_XUNIT_REPORTER: Provides outcomes in a format conforming with JUnit 4 and above as defined in: https://gist.github.com/kuzuha/232902acab1344d6b578 ``` +## Using utPLSQL-cli as sysdba + +Since 3.1.3 it is possible to run utPLSQL-cli as sysdba by running + +``` +utplsql run "sys as sysdba"/pw@connectstring +``` + +It is, however, __not recommended__ to run utPLSQL with sysdba privileges. + ## Enabling Color Outputs on Windows To enable color outputs on Windows cmd you need to install an open-source utility called [ANSICON](http://adoxa.altervista.org/ansicon/). From cb5072a52de3a79d8b4d308daac8fbd4ddea9424 Mon Sep 17 00:00:00 2001 From: pesse Date: Tue, 19 Mar 2019 22:33:28 +0100 Subject: [PATCH 6/7] Output warning in case of connecting as SYSDBA/SYSOPER --- .../java/org/utplsql/cli/ConnectionConfig.java | 6 ++++++ .../java/org/utplsql/cli/DataSourceProvider.java | 7 +++++++ .../org/utplsql/cli/ConnectionConfigTest.java | 15 ++++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/utplsql/cli/ConnectionConfig.java b/src/main/java/org/utplsql/cli/ConnectionConfig.java index ec2734d..e5d70de 100644 --- a/src/main/java/org/utplsql/cli/ConnectionConfig.java +++ b/src/main/java/org/utplsql/cli/ConnectionConfig.java @@ -45,4 +45,10 @@ public String getPassword() { public String getConnectString() { return user + "/" + password + "@" + connect; } + + public boolean isSysDba() { + return user != null && + (user.toLowerCase().endsWith(" as sysdba") + || user.toLowerCase().endsWith(" as sysoper")); + } } diff --git a/src/main/java/org/utplsql/cli/DataSourceProvider.java b/src/main/java/org/utplsql/cli/DataSourceProvider.java index 7fee23e..c9eb9b6 100644 --- a/src/main/java/org/utplsql/cli/DataSourceProvider.java +++ b/src/main/java/org/utplsql/cli/DataSourceProvider.java @@ -26,6 +26,7 @@ public static DataSource getDataSource(ConnectionInfo info, int maxConnections ) requireOjdbc(); ConnectionConfig config = new ConnectionConfig(info.getConnectionString()); + warnIfSysDba(config); HikariDataSource pds = new TestedDataSourceProvider(config).getDataSource(); pds.setAutoCommit(false); @@ -43,4 +44,10 @@ private static void requireOjdbc() { throw new RuntimeException("Can't run utPLSQL-cli without Oracle JDBC driver"); } } + + private static void warnIfSysDba(ConnectionConfig config) { + if ( config.isSysDba() ) { + System.out.println("WARNING: You are connecting to the database as SYSDBA or SYSOPER, which is NOT RECOMMENDED and can put your database at risk!"); + } + } } diff --git a/src/test/java/org/utplsql/cli/ConnectionConfigTest.java b/src/test/java/org/utplsql/cli/ConnectionConfigTest.java index 6509d8a..ee1e0b9 100644 --- a/src/test/java/org/utplsql/cli/ConnectionConfigTest.java +++ b/src/test/java/org/utplsql/cli/ConnectionConfigTest.java @@ -2,7 +2,7 @@ import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.*; public class ConnectionConfigTest { @@ -13,6 +13,7 @@ void parse() { assertEquals("test", info.getUser()); assertEquals("pw", info.getPassword()); assertEquals("my.local.host/service", info.getConnect()); + assertFalse(info.isSysDba()); } @Test @@ -22,6 +23,16 @@ void parseSysDba() { assertEquals("sys as sysdba", info.getUser()); assertEquals("pw", info.getPassword()); assertEquals("my.local.host/service", info.getConnect()); + assertTrue(info.isSysDba()); + } + @Test + void parseSysOper() { + ConnectionConfig info = new ConnectionConfig("myOperUser as sysoper/passw0rd@my.local.host/service"); + + assertEquals("myOperUser as sysoper", info.getUser()); + assertEquals("passw0rd", info.getPassword()); + assertEquals("my.local.host/service", info.getConnect()); + assertTrue(info.isSysDba()); } @Test @@ -31,6 +42,7 @@ void parseSpecialCharsPW() { assertEquals("test", info.getUser()); assertEquals("p@ssw0rd=", info.getPassword()); assertEquals("my.local.host/service", info.getConnect()); + assertFalse(info.isSysDba()); } @Test @@ -40,5 +52,6 @@ void parseSpecialCharsUser() { assertEquals("User/Mine@=", info.getUser()); assertEquals("pw", info.getPassword()); assertEquals("my.local.host/service", info.getConnect()); + assertFalse(info.isSysDba()); } } From 9b1714f20237b12c43d43ff3437f420ae1f2c5c3 Mon Sep 17 00:00:00 2001 From: pesse Date: Tue, 19 Mar 2019 22:43:00 +0100 Subject: [PATCH 7/7] Improve documentation for connecting with special chars --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 6f71924..7637624 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,11 @@ To connect using TNS, you need to have the ORACLE_HOME environment variable set. The file tnsnames.ora must exist in path %ORACLE_HOME%/network/admin The file tnsnames.ora must contain valid TNS entries. +In case you use a username containing `/` or a password containing `@` you should encapsulate it with double quotes `"`: +``` +utplsql run "my/Username"/"myP@ssword"@connectstring +``` + ### run `utplsql run []`