Mercurial > hg > release > thermostat-1.4
changeset 1759:97c799a0efbb
thermostat gui should not fail after running setup.
Reviewed-by: neugens
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2015-August/015524.html
PR2581
author | Severin Gehwolf <sgehwolf@redhat.com> |
---|---|
date | Tue, 25 Aug 2015 17:32:00 +0200 |
parents | 1498494ddf96 |
children | ce735787f5e3 |
files | setup/command/src/main/java/com/redhat/thermostat/setup/command/SetupCommand.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/Activator.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupWindow.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/model/ThermostatSetup.java setup/command/src/test/java/com/redhat/thermostat/setup/command/SetupCommandTest.java setup/command/src/test/java/com/redhat/thermostat/setup/command/internal/model/ThermostatSetupTest.java |
diffstat | 6 files changed, 95 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/SetupCommand.java Thu Sep 03 11:40:37 2015 +0200 +++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/SetupCommand.java Tue Aug 25 17:32:00 2015 +0200 @@ -54,6 +54,7 @@ import com.redhat.thermostat.setup.command.internal.model.ThermostatSetup; import com.redhat.thermostat.shared.config.CommonPaths; import com.redhat.thermostat.shared.locale.LocalizedString; +import com.redhat.thermostat.utils.keyring.Keyring; public class SetupCommand extends AbstractCommand { @@ -63,6 +64,7 @@ private SetupWindow mainWindow; private CommonPaths paths; private Launcher launcher; + private Keyring keyring; private ThermostatSetup thermostatSetup; private Console console; private String[] origArgsList; @@ -84,6 +86,8 @@ requireNonNull(paths, new LocalizedString("CommonPaths dependency not available")); this.launcher = dependentServices.getService(Launcher.class); requireNonNull(launcher, new LocalizedString("Launcher dependency not available")); + this.keyring = dependentServices.getService(Keyring.class); + requireNonNull(keyring, new LocalizedString("Keyring dependency not available")); createMainWindowAndRun(); } catch (InterruptedException | InvocationTargetException e) { @@ -115,9 +119,14 @@ dependentServices.addService(Launcher.class, launcher); } + public void setKeyring(Keyring keyring) { + dependentServices.addService(Keyring.class, keyring); + } + public void setServicesUnavailable() { dependentServices.removeService(Launcher.class); dependentServices.removeService(CommonPaths.class); + dependentServices.removeService(Keyring.class); } public boolean isStorageRequired() { @@ -126,7 +135,7 @@ //package-private for testing void createMainWindowAndRun() throws CommandException { - thermostatSetup = ThermostatSetup.create(launcher, paths, console); + thermostatSetup = ThermostatSetup.create(launcher, paths, console, keyring); mainWindow = new SetupWindow(thermostatSetup); mainWindow.run(); }
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/Activator.java Thu Sep 03 11:40:37 2015 +0200 +++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/Activator.java Tue Aug 25 17:32:00 2015 +0200 @@ -48,6 +48,7 @@ import org.osgi.framework.BundleContext; import com.redhat.thermostat.setup.command.SetupCommand; +import com.redhat.thermostat.utils.keyring.Keyring; public class Activator implements BundleActivator { @@ -63,15 +64,18 @@ Class<?>[] deps = new Class<?>[] { CommonPaths.class, - Launcher.class + Launcher.class, + Keyring.class }; tracker = new MultipleServiceTracker(context, deps, new MultipleServiceTracker.Action() { @Override public void dependenciesAvailable(Map<String, Object> services) { CommonPaths paths = (CommonPaths) services.get(CommonPaths.class.getName()); Launcher launcher = (Launcher) services.get(Launcher.class.getName()); + Keyring keyring = (Keyring) services.get(Keyring.class.getName()); setupCommand.setPaths(paths); setupCommand.setLauncher(launcher); + setupCommand.setKeyring(keyring); } @Override
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupWindow.java Thu Sep 03 11:40:37 2015 +0200 +++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupWindow.java Tue Aug 25 17:32:00 2015 +0200 @@ -250,10 +250,12 @@ thermostatSetup.createMongodbUser(storageUsername, storagePassword); try { if (userPropertiesView.makeAgentUserSelected()) { - thermostatSetup.createAgentUser(DEFAULT_AGENT_USER, DEFAULT_USER_PASSWORD); + char[] agentPassword = Arrays.copyOf(DEFAULT_USER_PASSWORD, DEFAULT_USER_PASSWORD.length); + thermostatSetup.createAgentUser(DEFAULT_AGENT_USER, agentPassword); } if (userPropertiesView.makeClientAdminSelected()) { - thermostatSetup.createClientAdminUser(DEFAULT_CLIENT_USER, DEFAULT_USER_PASSWORD); + char[] clientPassword = Arrays.copyOf(DEFAULT_USER_PASSWORD, DEFAULT_USER_PASSWORD.length); + thermostatSetup.createClientAdminUser(DEFAULT_CLIENT_USER, clientPassword); } thermostatSetup.commit(); } catch (IOException e) {
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/model/ThermostatSetup.java Thu Sep 03 11:40:37 2015 +0200 +++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/model/ThermostatSetup.java Tue Aug 25 17:32:00 2015 +0200 @@ -41,11 +41,16 @@ import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Objects; import java.util.Properties; import com.redhat.thermostat.common.cli.Console; +import com.redhat.thermostat.common.config.ClientPreferences; import com.redhat.thermostat.launcher.Launcher; import com.redhat.thermostat.shared.config.CommonPaths; +import com.redhat.thermostat.utils.keyring.Keyring; +import com.redhat.thermostat.utils.keyring.KeyringException; public class ThermostatSetup implements PersistableSetup { @@ -60,15 +65,21 @@ private final StructureInformation structureInfo; private final CredentialsFileCreator creator; private final CommonPaths paths; + private final Keyring keyring; + private final ClientPreferences prefs; private String agentUserName; private char[] agentPassword; + private String clientUsername; + private char[] clientPassword; - ThermostatSetup(ThermostatUserSetup userSetup, MongodbUserSetup mongodbUserSetup, StructureInformation structureInfo, CommonPaths paths, CredentialsFileCreator creator) { + ThermostatSetup(ThermostatUserSetup userSetup, MongodbUserSetup mongodbUserSetup, StructureInformation structureInfo, CommonPaths paths, CredentialsFileCreator creator, Keyring keyring, ClientPreferences prefs) { this.mongodbUserSetup = mongodbUserSetup; this.userSetup = userSetup; this.structureInfo = structureInfo; this.paths = paths; this.creator = creator; + this.keyring = keyring; + this.prefs = prefs; } public void createMongodbUser(String username, char[] password) { @@ -94,6 +105,10 @@ }, "Client admin user username => role assignment." ); + // Hold on to these credentials so that they can be written to keyring + // on commit(). This makes gui work out of the box after setup has run. + this.clientUsername = username; + this.clientPassword = password; } public void createAgentUser(String username, char[] password) { @@ -118,9 +133,30 @@ mongodbUserSetup.commit(); userSetup.commit(); writeAgentAuthFile(); + storeClientCredsToKeyring(); } + private void storeClientCredsToKeyring() throws IOException { + Objects.requireNonNull(clientUsername); + Objects.requireNonNull(clientPassword); + try { + prefs.setSaveEntitlements(true); // force writing on flush() + String url = prefs.getConnectionUrl(); + prefs.setUserName(clientUsername); + // Unconditionally save the chosen username. If setup was run again + // it will overwrite existing credentials. + keyring.savePassword(url, clientUsername, clientPassword); + prefs.flush(); + } catch (KeyringException e) { + throw new IOException(e); + } finally { + Arrays.fill(clientPassword, '\0'); + } + } + private void writeAgentAuthFile() throws IOException { + Objects.requireNonNull(agentPassword); + Objects.requireNonNull(agentUserName); Properties credentialProps = new Properties(); credentialProps.setProperty("username", agentUserName); credentialProps.setProperty("password", String.valueOf(agentPassword)); @@ -128,6 +164,8 @@ creator.create(credentialsFile); try (FileOutputStream fout = new FileOutputStream(credentialsFile)) { credentialProps.store(fout, "Credentials used for 'thermostat agent' connections."); + } finally { + Arrays.fill(agentPassword, '\0'); } } @@ -135,13 +173,14 @@ return structureInfo.isWebAppInstalled(); } - public static ThermostatSetup create(Launcher launcher, CommonPaths paths, Console console) { + public static ThermostatSetup create(Launcher launcher, CommonPaths paths, Console console, Keyring keyring) { CredentialFinder finder = new CredentialFinder(paths); CredentialsFileCreator creator = new CredentialsFileCreator(); StampFiles stampFiles = new StampFiles(paths); StructureInformation info = new StructureInformation(paths); MongodbUserSetup mongoSetup = new MongodbUserSetup(new UserCredsValidator(), launcher, finder, creator , console, paths, stampFiles, info); ThermostatUserSetup userSetup = new ThermostatUserSetup(new UserPropertiesFinder(finder), new UserCredsValidator(), creator, stampFiles); - return new ThermostatSetup(userSetup, mongoSetup, info, paths, creator); + ClientPreferences prefs = new ClientPreferences(paths); + return new ThermostatSetup(userSetup, mongoSetup, info, paths, creator, keyring, prefs); } }
--- a/setup/command/src/test/java/com/redhat/thermostat/setup/command/SetupCommandTest.java Thu Sep 03 11:40:37 2015 +0200 +++ b/setup/command/src/test/java/com/redhat/thermostat/setup/command/SetupCommandTest.java Tue Aug 25 17:32:00 2015 +0200 @@ -64,6 +64,7 @@ import com.redhat.thermostat.common.cli.Console; import com.redhat.thermostat.launcher.Launcher; import com.redhat.thermostat.shared.config.CommonPaths; +import com.redhat.thermostat.utils.keyring.Keyring; public class SetupCommandTest { @@ -76,6 +77,7 @@ private PrintStream output, error; private CommonPaths paths; private Launcher launcher; + private Keyring keyring; @Before public void setUp() { @@ -90,6 +92,7 @@ errorBaos = new ByteArrayOutputStream(); error = new PrintStream(errorBaos); launcher = mock(Launcher.class); + keyring = mock(Keyring.class); when(ctxt.getArguments()).thenReturn(mockArgs); when(ctxt.getConsole()).thenReturn(console); @@ -209,6 +212,20 @@ verify(launcher).run(argThat(new ArgsMatcher(argsList)), eq(false)); } + @Test + public void testKeyringNotSetFailure() { + cmd = createSetupCommand(); + + cmd.setPaths(mock(CommonPaths.class)); + cmd.setLauncher(mock(Launcher.class)); + try { + cmd.run(ctxt); + fail(); + } catch (CommandException e) { + assertTrue(e.getMessage().contains("Keyring dependency not available")); + } + } + private SetupCommand createSetupCommand() { return new SetupCommand() { @Override @@ -226,6 +243,7 @@ private void setServices() { cmd.setPaths(paths); cmd.setLauncher(launcher); + cmd.setKeyring(keyring); } private static class ArgsMatcher extends BaseMatcher<String[]> {
--- a/setup/command/src/test/java/com/redhat/thermostat/setup/command/internal/model/ThermostatSetupTest.java Thu Sep 03 11:40:37 2015 +0200 +++ b/setup/command/src/test/java/com/redhat/thermostat/setup/command/internal/model/ThermostatSetupTest.java Tue Aug 25 17:32:00 2015 +0200 @@ -57,7 +57,9 @@ import org.junit.Before; import org.junit.Test; +import com.redhat.thermostat.common.config.ClientPreferences; import com.redhat.thermostat.shared.config.CommonPaths; +import com.redhat.thermostat.utils.keyring.Keyring; public class ThermostatSetupTest { @@ -73,7 +75,7 @@ @Test public void testIsWebAppInstalledDelegates() { StructureInformation structureInfo = mock(StructureInformation.class); - ThermostatSetup setup = new ThermostatSetup(userSetup, mongoUserSetup, structureInfo, mock(CommonPaths.class), mock(CredentialsFileCreator.class)); + ThermostatSetup setup = new ThermostatSetup(userSetup, mongoUserSetup, structureInfo, mock(CommonPaths.class), mock(CredentialsFileCreator.class), mock(Keyring.class), mock(ClientPreferences.class)); when(structureInfo.isWebAppInstalled()).thenReturn(true); assertTrue(setup.isWebAppInstalled()); verify(structureInfo).isWebAppInstalled(); @@ -81,7 +83,7 @@ @Test public void testCreateAgentUser() { - ThermostatSetup setup = new ThermostatSetup(userSetup, mongoUserSetup, mock(StructureInformation.class), mock(CommonPaths.class), mock(CredentialsFileCreator.class)); + ThermostatSetup setup = new ThermostatSetup(userSetup, mongoUserSetup, mock(StructureInformation.class), mock(CommonPaths.class), mock(CredentialsFileCreator.class), mock(Keyring.class), mock(ClientPreferences.class)); setup.createAgentUser("foo-agent", new char[] { 't' }); verify(userSetup).createRecursiveRole(eq("thermostat-agent"), argThat(new RoleMatcher(UserRoles.AGENT_ROLES)), any(String.class)); verify(userSetup).assignRolesToUser(eq("foo-agent"), argThat(new RoleMatcher(new String[] { "thermostat-agent", UserRoles.GRANT_FILES_WRITE_ALL })), any(String.class)); @@ -89,7 +91,7 @@ @Test public void testCreateClientAdminUser() { - ThermostatSetup setup = new ThermostatSetup(userSetup, mongoUserSetup, mock(StructureInformation.class), mock(CommonPaths.class), mock(CredentialsFileCreator.class)); + ThermostatSetup setup = new ThermostatSetup(userSetup, mongoUserSetup, mock(StructureInformation.class), mock(CommonPaths.class), mock(CredentialsFileCreator.class), mock(Keyring.class), mock(ClientPreferences.class)); setup.createClientAdminUser("foo-client", new char[] { 't' }); verify(userSetup).createRecursiveRole(eq("thermostat-client"), argThat(new RoleMatcher(UserRoles.CLIENT_ROLES)), any(String.class)); verify(userSetup).createRecursiveRole(eq("thermostat-cmdc"), argThat(new RoleMatcher(UserRoles.CMD_CHANNEL_GRANT_ALL_ACTIONS)), any(String.class)); @@ -99,18 +101,27 @@ } @Test - public void flushCreatesAgentAuthFile() throws IOException { + public void commitCreatesAgentAuthFileStoresToKeyring() throws IOException { CommonPaths paths = mock(CommonPaths.class); File mockAgentAuthFile = File.createTempFile("thermostat-test-", getClass().getName()); + Keyring keyring = mock(Keyring.class); + ClientPreferences prefs = mock(ClientPreferences.class); try { when(paths.getUserAgentAuthConfigFile()).thenReturn(mockAgentAuthFile); - ThermostatSetup setup = new ThermostatSetup(userSetup, mongoUserSetup, mock(StructureInformation.class), paths, mock(CredentialsFileCreator.class)); + ThermostatSetup setup = new ThermostatSetup(userSetup, mongoUserSetup, mock(StructureInformation.class), paths, mock(CredentialsFileCreator.class), keyring, prefs); List<String> contents = Files.readAllLines(mockAgentAuthFile.toPath(), Charset.forName("UTF-8")); assertEquals(0, contents.size()); setup.createAgentUser("damian", new char[] { 't', 'e', 's', 't' }); + String clientUser = "client-admin"; + char[] clientPass = new char[] { 't' }; + setup.createClientAdminUser(clientUser, clientPass); setup.commit(); verify(userSetup).commit(); verify(mongoUserSetup).commit(); + verify(keyring).savePassword(prefs.getConnectionUrl(), clientUser, clientPass); + verify(prefs).flush(); + verify(prefs).setSaveEntitlements(true); + verify(prefs).setUserName(clientUser); contents = Files.readAllLines(mockAgentAuthFile.toPath(), Charset.forName("UTF-8")); assertTrue("username and password must be present", contents.size() > 2); assertTrue("username=damian expected to be found in agent.auth file", contents.contains("username=damian"));