changeset 1764:8e0d3c92f621

Allow user to choose custom credentials for client and agent users Reviewed-by: jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2015-August/015585.html PR2581
author Anirudhan Mukundan <amukunda@redhat.com>
date Fri, 28 Aug 2015 13:27:54 -0400
parents 6a3aa751cd82
children 42aec8731685
files setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/CredentialPanel.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/MongoUserSetupView.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/UserPropertiesView.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/model/UserCredsValidator.java setup/command/src/main/java/com/redhat/thermostat/setup/command/locale/LocaleResources.java setup/command/src/main/resources/com/redhat/thermostat/setup/locale/strings.properties
diffstat 7 files changed, 485 insertions(+), 233 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/CredentialPanel.java	Fri Aug 28 13:27:54 2015 -0400
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.setup.command.internal;
+
+import com.redhat.thermostat.client.swing.components.FontAwesomeIcon;
+import com.redhat.thermostat.client.swing.components.Icon;
+import com.redhat.thermostat.setup.command.internal.model.UserCredsValidator;
+import com.redhat.thermostat.setup.command.locale.LocaleResources;
+import com.redhat.thermostat.shared.locale.Translate;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.ToolTipManager;
+import javax.swing.border.Border;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.util.Arrays;
+
+public class CredentialPanel extends JPanel {
+
+    private String titleText;
+    private String helpMessage;
+    private String defaultUsername;
+    private char[] defaultPassword;
+
+    private JPanel messagePanel;
+    private JLabel usernameText;
+    private JLabel passwordText1;
+    private JLabel passwordText2;
+    private JLabel errorMessage;
+    private JTextField username;
+    private JPasswordField password1;
+    private JPasswordField password2;
+    private JCheckBox showPasswordCheckbox;
+    private JButton useDefaultsBtn;
+    private ComponentTitledBorder titledBorder;
+    private JLabel title;
+
+    private static final UserCredsValidator validator = new UserCredsValidator();
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+    private static final Icon infoIcon = new FontAwesomeIcon('\uf05a', 15);
+
+    public CredentialPanel(String titleText, String helpMessage, String defaultUsername, char[] defaultPassword) {
+        this.titleText = titleText;
+        this.helpMessage = helpMessage;
+        this.defaultUsername = defaultUsername;
+        this.defaultPassword = defaultPassword;
+
+        //enable tooltips
+        ToolTipManager.sharedInstance().registerComponent(this);
+        ToolTipManager.sharedInstance().setInitialDelay(0);
+
+        initComponents();
+    }
+
+    private void initComponents() {
+        showPasswordCheckbox = new JCheckBox(translator.localize(LocaleResources.SHOW_PASSWORDS).getContents());
+        showPasswordCheckbox.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent) {
+                togglePasswords(showPasswordCheckbox.isSelected());
+            }
+        });
+        showPasswordCheckbox.setSelected(false);
+
+        useDefaultsBtn = new JButton(translator.localize(LocaleResources.USE_DEFAULTS).getContents());
+        useDefaultsBtn.setPreferredSize(new Dimension(140, 30));
+        useDefaultsBtn.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent) {
+                username.setText(defaultUsername);
+                password1.setText(String.valueOf(defaultPassword));
+                password2.setText(String.valueOf(defaultPassword));
+                removeErrorMessage();
+            }
+        });
+
+        usernameText = new JLabel();
+        usernameText.setText(translator.localize(LocaleResources.USERNAME).getContents());
+        passwordText1 = new JLabel();
+        passwordText1.setText(translator.localize(LocaleResources.PASSWORD).getContents());
+        passwordText2 = new JLabel();
+        passwordText2.setText(translator.localize(LocaleResources.VERIFY_PASSWORD).getContents());
+
+        username = new JTextField();
+        password1 = new JPasswordField();
+        password2 = new JPasswordField();
+
+        title = new JLabel(titleText, infoIcon, JLabel.CENTER);
+        title.setHorizontalTextPosition(JLabel.LEFT);
+        title.setIconTextGap(20);
+        title.setOpaque(true);
+
+        titledBorder = new ComponentTitledBorder(title, BorderFactory.createEtchedBorder());
+        setBorder(titledBorder);
+
+        errorMessage = new JLabel();
+        errorMessage.setForeground(Color.RED);
+        errorMessage.setHorizontalAlignment(SwingConstants.CENTER);
+
+        messagePanel = new JPanel(new BorderLayout());
+        messagePanel.add(errorMessage, BorderLayout.CENTER);
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                .addGroup(layout.createSequentialGroup()
+                    .addContainerGap()
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                        .addGroup(layout.createSequentialGroup()
+                            .addGap(25, 25, 25)
+                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                                .addComponent(passwordText1)
+                                .addComponent(usernameText)
+                                .addComponent(passwordText2))
+                            .addGap(65, 65, 65)
+                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                                .addGroup(layout.createSequentialGroup()
+                                    .addComponent(showPasswordCheckbox)
+                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 6, Short.MAX_VALUE)
+                                    .addComponent(useDefaultsBtn))
+                                .addComponent(password2, javax.swing.GroupLayout.Alignment.TRAILING)
+                                .addComponent(password1)
+                                .addComponent(username))))
+                    .addContainerGap())
+                .addComponent(messagePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                .addGroup(layout.createSequentialGroup()
+                    .addContainerGap()
+                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(usernameText)
+                        .addComponent(username, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(passwordText1)
+                        .addComponent(password1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(passwordText2)
+                        .addComponent(password2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(showPasswordCheckbox)
+                        .addComponent(useDefaultsBtn))
+                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                    .addComponent(messagePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addGap(0, 0, 0))
+        );
+    }
+
+    public JTextField getUsernameField() {
+        return username;
+    }
+
+    public String getUsername() {
+        return username.getText();
+    }
+
+    public JTextField getPasswordField1() {
+        return password1;
+    }
+
+    public JTextField getPasswordField2() {
+        return password2;
+    }
+
+    public char[] getPassword() {
+        return password1.getPassword();
+    }
+
+    private void togglePasswords(boolean isVisible) {
+        if (isVisible) {
+            password1.setEchoChar((char) 0);
+            password2.setEchoChar((char) 0);
+        } else {
+            password1.setEchoChar('*');
+            password2.setEchoChar('*');
+        }
+    }
+
+    public void removeErrorMessage() {
+        errorMessage.setText(null);
+        this.revalidate();
+        this.repaint();
+    }
+
+    public void showPasswordMismatch() {
+        errorMessage.setText(translator.localize(LocaleResources.PASSWORD_MISMATCH).getContents());
+        this.revalidate();
+        this.repaint();
+    }
+
+    public void showDetailsMissing() {
+        errorMessage.setText(translator.localize(LocaleResources.DETAILS_MISSING).getContents());
+        this.revalidate();
+        this.repaint();
+    }
+
+    public boolean isInputValid() {
+        //ensure credentials are not empty
+        try {
+            validator.validateUsername(username.getText());
+            validator.validatePassword(password1.getPassword());
+            validator.validatePassword(password2.getPassword());
+        } catch (IllegalArgumentException e) {
+            showDetailsMissing();
+            return false;
+        }
+
+        //ensure passwords match
+        if (!Arrays.equals(password1.getPassword(), password2.getPassword())) {
+            showPasswordMismatch();
+            return false;
+        }
+
+        removeErrorMessage();
+        return true;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        usernameText.setEnabled(enabled);
+        passwordText1.setEnabled(enabled);
+        passwordText2.setEnabled(enabled);
+        username.setEnabled(enabled);
+        password1.setEnabled(enabled);
+        password2.setEnabled(enabled);
+        showPasswordCheckbox.setEnabled(enabled);
+        useDefaultsBtn.setEnabled(enabled);
+    }
+
+    @Override
+    public String getToolTipText(MouseEvent e) {
+        if (titledBorder.getTitleRect().contains(e.getPoint())) {
+            return helpMessage;
+        } else {
+            return null;
+        }
+    }
+
+    public class ComponentTitledBorder implements Border {
+        private static final int OFFSET = 5;
+        public final Component comp;
+        private Rectangle rect;
+
+        private Border border;
+
+        public ComponentTitledBorder(Component comp, Border border) {
+            this.comp = comp;
+            this.border = border;
+        }
+
+        public boolean isBorderOpaque() {
+            return true;
+        }
+
+        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
+            Insets borderInsets = border.getBorderInsets(c);
+            Insets insets = getBorderInsets(c);
+            int temp = (insets.top - borderInsets.top) / 2;
+            border.paintBorder(c, g, x, y + temp, width, height - temp);
+            Dimension size = comp.getPreferredSize();
+            rect = new Rectangle(OFFSET, 0, size.width, size.height);
+            SwingUtilities.paintComponent(g, comp, (Container) c, rect);
+        }
+
+        public Insets getBorderInsets(Component c) {
+            Dimension size = comp.getPreferredSize();
+            Insets insets = border.getBorderInsets(c);
+            insets.top = Math.max(insets.top, size.height);
+            return insets;
+        }
+
+        public Rectangle getTitleRect() {
+            return rect;
+        }
+
+    }
+}
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/MongoUserSetupView.java	Fri Aug 28 09:59:28 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/MongoUserSetupView.java	Fri Aug 28 13:27:54 2015 -0400
@@ -44,51 +44,30 @@
 import javax.swing.BoxLayout;
 import javax.swing.ImageIcon;
 import javax.swing.JButton;
-import javax.swing.JCheckBox;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
-import javax.swing.JPasswordField;
-import javax.swing.JTextField;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
 import java.awt.BorderLayout;
-import java.awt.Color;
 import java.awt.Component;
 import java.awt.Dimension;
-import java.awt.FlowLayout;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
 import java.awt.LayoutManager;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.net.URL;
-import java.util.Arrays;
 
 public class MongoUserSetupView extends JPanel implements SetupView {
 
     private JButton backBtn;
-    private JButton defaultSetupBtn;
     private JButton nextBtn;
     private JButton cancelBtn;
 
-    private JTextField usernameField;
-    private JPasswordField passwordField1;
-    private JPasswordField passwordField2;
-
     private JPanel toolbar;
     private JPanel midPanel;
-    private JPanel detailsPanel;
-    private JPanel messagePanel;
-
-    private JLabel usernameLabel;
-    private JLabel passwordLabel1;
-    private JLabel passwordLabel2;
-    private JLabel passwordMismatchLabel;
-    private JLabel detailsMissingLabel;
-    private JCheckBox showPasswordCheckbox;
+    private CredentialPanel credentialPanel;
 
     private static final String THERMOSTAT_LOGO = "thermostat.png";
     private static final String PROGRESS = "Step 2 of 3";
+    private static final String DEFAULT_STORAGE_USER = "mongodevuser";
+    private static final char[] DEFAULT_STORAGE_PASSWORD = new char[] {'m', 'o', 'n', 'g', 'o', 'd', 'e', 'v', 'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
 
     public MongoUserSetupView(LayoutManager layout) {
@@ -99,7 +78,20 @@
 
         this.add(midPanel, BorderLayout.CENTER);
         this.add(toolbar, BorderLayout.SOUTH);
+    }
 
+    @Override
+    public void setTitleAndProgress(JLabel title, JLabel progress) {
+        title.setText(translator.localize(LocaleResources.MONGO_SETUP_TITLE).getContents());
+        progress.setText(PROGRESS);
+    }
+
+    private void createMidPanel() {
+        credentialPanel = new CredentialPanel(
+            translator.localize(LocaleResources.MONGO_CRED_TITLE).getContents(),
+            translator.localize(LocaleResources.STORAGE_HELP_INFO).getContents(),
+            DEFAULT_STORAGE_USER,
+            DEFAULT_STORAGE_PASSWORD);
         DocumentListener inputValidator = new DocumentListener() {
             @Override
             public void insertUpdate(DocumentEvent documentEvent) {
@@ -116,85 +108,16 @@
                 validateInput();
             }
         };
-        usernameField.getDocument().addDocumentListener(inputValidator);
-        passwordField1.getDocument().addDocumentListener(inputValidator);
-        passwordField2.getDocument().addDocumentListener(inputValidator);
-    }
-
-    @Override
-    public void setTitleAndProgress(JLabel title, JLabel progress) {
-        title.setText(translator.localize(LocaleResources.MONGO_SETUP_TITLE).getContents());
-        progress.setText(PROGRESS);
-    }
-
-    private void createMidPanel() {
-        usernameLabel = new JLabel("Username: ");
-        usernameField = new JTextField(30);
-        passwordLabel1 = new JLabel("Password:");
-        passwordField1 = new JPasswordField(30);
-        passwordLabel2 = new JLabel("Verify Password:");
-        passwordField2 = new JPasswordField(30);
-        showPasswordCheckbox = new JCheckBox("Show passwords");
-        showPasswordCheckbox.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent actionEvent) {
-                togglePasswords(showPasswordCheckbox.isSelected());
-            }
-        });
-
-        defaultSetupBtn = new JButton("Use Defaults");
-        defaultSetupBtn.setPreferredSize(new Dimension(140, 30));
-        passwordMismatchLabel = new JLabel("Passwords don't match!");
-        passwordMismatchLabel.setForeground(Color.RED);
-        detailsMissingLabel = new JLabel("Please fill in ALL fields");
-        detailsMissingLabel.setForeground(Color.RED);
-        detailsPanel = new JPanel(new GridBagLayout());
+        credentialPanel.getUsernameField().getDocument().addDocumentListener(inputValidator);
+        credentialPanel.getPasswordField1().getDocument().addDocumentListener(inputValidator);
+        credentialPanel.getPasswordField2().getDocument().addDocumentListener(inputValidator);
 
-        GridBagConstraints c = new GridBagConstraints();
-        c.fill = GridBagConstraints.HORIZONTAL;
-        c.gridx = 0;
-        c.gridy = 0;
-        c.gridwidth = 1;
-        c.insets.top = 40;
-        detailsPanel.add(usernameLabel, c);
-        c.gridx = 1;
-        c.gridy = 0;
-        c.gridwidth = 2;
-        detailsPanel.add(usernameField, c);
-        c.gridx = 0;
-        c.gridy = 1;
-        c.gridwidth = 1;
-        c.insets.top = 10;
-        detailsPanel.add(passwordLabel1, c);
-        c.gridx = 1;
-        c.gridy = 1;
-        c.gridwidth = 2;
-        detailsPanel.add(passwordField1, c);
-        c.gridx = 0;
-        c.gridy = 2;
-        c.gridwidth = 1;
-        detailsPanel.add(passwordLabel2, c);
-        c.gridx = 1;
-        c.gridy = 2;
-        c.gridwidth = 2;
-        detailsPanel.add(passwordField2, c);
-        c.gridx = 1;
-        c.gridy = 3;
-        c.gridwidth = 1;
-        detailsPanel.add(showPasswordCheckbox, c);
-
-        c.fill = GridBagConstraints.NONE;
-        c.anchor = GridBagConstraints.LINE_END;
-        c.gridx = 2;
-        c.gridy = 3;
-        c.gridwidth = 1;
-        detailsPanel.add(defaultSetupBtn, c);
-
-        messagePanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
-
-        midPanel = new JPanel(new BorderLayout());
-        midPanel.add(detailsPanel, BorderLayout.NORTH);
-        midPanel.add(messagePanel, BorderLayout.SOUTH);
+        midPanel = new JPanel();
+        midPanel.setLayout(new BoxLayout(midPanel, BoxLayout.PAGE_AXIS));
+        midPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+        midPanel.add(Box.createRigidArea(new Dimension(0, 20)));
+        midPanel.add(credentialPanel);
+        midPanel.add(Box.createRigidArea(new Dimension(0, 20)));
     }
 
     private void createToolbarPanel() {
@@ -219,59 +142,24 @@
         toolbar.add(cancelBtn);
     }
 
-    private void togglePasswords(boolean isVisible) {
-        if (isVisible) {
-            passwordField1.setEchoChar((char) 0);
-            passwordField2.setEchoChar((char) 0);
+    private void validateInput() {
+        if (credentialPanel.isInputValid()) {
+            nextBtn.setEnabled(true);
         } else {
-            passwordField1.setEchoChar('*');
-            passwordField2.setEchoChar('*');
-        }
-    }
-
-    private void validateInput() {
-        if (usernameField.getText().isEmpty() || passwordField1.getPassword().length == 0 || passwordField2.getPassword().length == 0) {
-            showDetailsMissing();
             nextBtn.setEnabled(false);
-        } else if (!(Arrays.equals(passwordField1.getPassword(), passwordField2.getPassword()))) {
-            showPasswordMismatch();
-            nextBtn.setEnabled(false);
-        } else {
-            removeErrorMessages();
-            nextBtn.setEnabled(true);
         }
     }
 
     public void enableButtons() {
         backBtn.setEnabled(true);
-        defaultSetupBtn.setEnabled(true);
         nextBtn.setEnabled(true);
+        credentialPanel.setEnabled(true);
     }
 
     public void disableButtons() {
         backBtn.setEnabled(false);
-        defaultSetupBtn.setEnabled(false);
         nextBtn.setEnabled(false);
-    }
-
-    private void showPasswordMismatch() {
-        messagePanel.removeAll();
-        messagePanel.add(passwordMismatchLabel);
-        midPanel.revalidate();
-        midPanel.repaint();
-    }
-
-    private void showDetailsMissing() {
-        messagePanel.removeAll();
-        messagePanel.add(detailsMissingLabel);
-        midPanel.revalidate();
-        midPanel.repaint();
-    }
-
-    private void removeErrorMessages() {
-        messagePanel.removeAll();
-        midPanel.revalidate();
-        midPanel.repaint();
+        credentialPanel.setEnabled(false);
     }
 
     @Override
@@ -283,10 +171,6 @@
         return backBtn;
     }
 
-    public JButton getDefaultSetupBtn() {
-        return defaultSetupBtn;
-    }
-
     public JButton getNextBtn() {
         return nextBtn;
     }
@@ -296,19 +180,10 @@
     }
 
     public String getUsername() {
-        return usernameField.getText();
-    }
-
-    public void setUsername(String username) {
-        this.usernameField.setText(username);
+        return credentialPanel.getUsername();
     }
 
     public char[] getPassword() {
-        return passwordField1.getPassword();
-    }
-
-    public void setPassword(char[] password) {
-        this.passwordField1.setText(String.valueOf(password));
-        this.passwordField2.setText(String.valueOf(password));
+        return credentialPanel.getPassword();
     }
 }
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupWindow.java	Fri Aug 28 09:59:28 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupWindow.java	Fri Aug 28 13:27:54 2015 -0400
@@ -80,11 +80,6 @@
     private final ThermostatSetup thermostatSetup;
     private SwingWorker<IOException, Void> finishAction;
 
-    private static final String DEFAULT_AGENT_USER = "agent-tester";
-    private static final String DEFAULT_CLIENT_USER = "client-tester";
-    private static final char[] DEFAULT_USER_PASSWORD = new char[] { 't', 'e', 's', 't', 'e', 'r' };
-    private static final String DEFAULT_STORAGE_USER = "mongodevuser";
-    private static final char[] DEFAULT_STORAGE_PASSWORD = new char[] { 'm', 'o', 'n', 'g', 'o', 'd', 'e', 'v', 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' };
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
     private static final Logger logger = LoggingUtils.getLogger(SetupWindow.class);
 
@@ -199,13 +194,6 @@
                 showView(startView);
             }
         });
-        mongoUserSetupView.getDefaultSetupBtn().addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent actionEvent) {
-                mongoUserSetupView.setUsername(DEFAULT_STORAGE_USER);
-                mongoUserSetupView.setPassword(DEFAULT_STORAGE_PASSWORD);
-            }
-        });
         mongoUserSetupView.getNextBtn().addActionListener(new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent actionEvent) {
@@ -215,6 +203,7 @@
                 if (thermostatSetup.isWebAppInstalled()) {
                     mainView.remove(mongoUserSetupView);
                     showView(userPropertiesView);
+                    setLargeFrame(true);
                 } else {
                     //webapp isn't installed so just run setup
                     //now to create mongodb user and quit
@@ -257,14 +246,8 @@
                 userPropertiesView.disableButtons();
                 thermostatSetup.createMongodbUser(storageUsername, storagePassword);
                 try {
-                    if (userPropertiesView.makeAgentUserSelected()) {
-                        char[] agentPassword = Arrays.copyOf(DEFAULT_USER_PASSWORD, DEFAULT_USER_PASSWORD.length);
-                        thermostatSetup.createAgentUser(DEFAULT_AGENT_USER, agentPassword);
-                    }
-                    if (userPropertiesView.makeClientAdminSelected()) {
-                        char[] clientPassword = Arrays.copyOf(DEFAULT_USER_PASSWORD, DEFAULT_USER_PASSWORD.length);
-                        thermostatSetup.createClientAdminUser(DEFAULT_CLIENT_USER, clientPassword);
-                    }
+                    thermostatSetup.createAgentUser(userPropertiesView.getAgentUsername(), userPropertiesView.getAgentPassword());
+                    thermostatSetup.createClientAdminUser(userPropertiesView.getClientUsername(), userPropertiesView.getClientPassword());
                     thermostatSetup.commit();
                     return null;
                 } catch (IOException e) {
@@ -282,7 +265,7 @@
         };
         finishAction.execute();
     }
-    
+
     private void showView(SetupView view) {
         mainView.add(view.getUiComponent(), BorderLayout.CENTER);
         view.setTitleAndProgress(title, progress);
@@ -293,5 +276,5 @@
     private void shutdown() {
         shutdown.countDown();
     }
-    
+
 }
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/UserPropertiesView.java	Fri Aug 28 09:59:28 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/UserPropertiesView.java	Fri Aug 28 13:27:54 2015 -0400
@@ -44,14 +44,13 @@
 import javax.swing.BoxLayout;
 import javax.swing.ImageIcon;
 import javax.swing.JButton;
-import javax.swing.JCheckBox;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
 import java.awt.BorderLayout;
 import java.awt.Component;
 import java.awt.Dimension;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
 import java.awt.LayoutManager;
 import java.net.URL;
 
@@ -60,13 +59,14 @@
     private JButton finishBtn;
     private JButton backBtn;
     private JButton cancelBtn;
-
     private JPanel toolbar;
     private JPanel midPanel;
-    private JPanel detailsPanel;
-    private JCheckBox makeAgentUserBtn;
-    private JCheckBox makeClientAdminBtn;
+    private CredentialPanel clientInfoPanel;
+    private CredentialPanel agentInfoPanel;
 
+    private static final String DEFAULT_CLIENT_USER = "client-tester";
+    private static final String DEFAULT_AGENT_USER = "agent-tester";
+    private static final char[] DEFAULT_USER_PASSWORD = new char[] {'t', 'e', 's', 't', 'e', 'r'};
     private static final String THERMOSTAT_LOGO = "thermostat.png";
     private static final String PROGRESS = "Step 3 of 3";
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
@@ -79,6 +79,29 @@
 
         this.add(midPanel, BorderLayout.CENTER);
         this.add(toolbar, BorderLayout.SOUTH);
+
+        DocumentListener inputValidator = new DocumentListener() {
+            @Override
+            public void insertUpdate(DocumentEvent documentEvent) {
+                validateInput();
+            }
+
+            @Override
+            public void removeUpdate(DocumentEvent documentEvent) {
+                validateInput();
+            }
+
+            @Override
+            public void changedUpdate(DocumentEvent documentEvent) {
+                validateInput();
+            }
+        };
+        clientInfoPanel.getUsernameField().getDocument().addDocumentListener(inputValidator);
+        clientInfoPanel.getPasswordField1().getDocument().addDocumentListener(inputValidator);
+        clientInfoPanel.getPasswordField2().getDocument().addDocumentListener(inputValidator);
+        agentInfoPanel.getUsernameField().getDocument().addDocumentListener(inputValidator);
+        agentInfoPanel.getPasswordField1().getDocument().addDocumentListener(inputValidator);
+        agentInfoPanel.getPasswordField2().getDocument().addDocumentListener(inputValidator);
     }
 
     @Override
@@ -88,31 +111,24 @@
     }
 
     public void createMidPanel() {
-        JLabel agentInfo = new JLabel(translator.localize(LocaleResources.AGENT_INFO).getContents());
-        JLabel clientInfo = new JLabel(translator.localize(LocaleResources.CLIENT_INFO).getContents());
-        makeAgentUserBtn = new JCheckBox(translator.localize(LocaleResources.CREATE_AGENT_USER).getContents());
-        makeAgentUserBtn.setSelected(true);
-        makeClientAdminBtn = new JCheckBox(translator.localize(LocaleResources.CREATE_CLIENT_ADMIN).getContents());
-        makeClientAdminBtn.setSelected(true);
-        detailsPanel = new JPanel(new GridBagLayout());
+        clientInfoPanel = new CredentialPanel(
+            translator.localize(LocaleResources.CLIENT_CRED_TITLE).getContents(),
+            translator.localize(LocaleResources.CLIENT_HELP_INFO).getContents(),
+            DEFAULT_CLIENT_USER,
+            DEFAULT_USER_PASSWORD);
+        agentInfoPanel = new CredentialPanel(
+            translator.localize(LocaleResources.AGENT_CRED_TITLE).getContents(),
+            translator.localize(LocaleResources.AGENT_HELP_INFO).getContents(),
+            DEFAULT_AGENT_USER,
+            DEFAULT_USER_PASSWORD);
 
-        GridBagConstraints c = new GridBagConstraints();
-        c.fill = GridBagConstraints.HORIZONTAL;
-        c.gridy = 0;
-        c.insets.top = 40;
-        detailsPanel.add(agentInfo, c);
-        c.gridy = 1;
-        c.insets.top = 10;
-        detailsPanel.add(makeAgentUserBtn, c);
-        c.insets.top = 25;
-        c.gridy = 2;
-        detailsPanel.add(clientInfo, c);
-        c.insets.top = 10;
-        c.gridy = 3;
-        detailsPanel.add(makeClientAdminBtn, c);
-
-        midPanel = new JPanel(new BorderLayout());
-        midPanel.add(detailsPanel, BorderLayout.NORTH);
+        midPanel = new JPanel();
+        midPanel.setLayout(new BoxLayout(midPanel, BoxLayout.PAGE_AXIS));
+        midPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+        midPanel.add(Box.createRigidArea(new Dimension(0, 20)));
+        midPanel.add(clientInfoPanel);
+        midPanel.add(Box.createRigidArea(new Dimension(0, 20)));
+        midPanel.add(agentInfoPanel);
     }
 
     private void createToolbarPanel() {
@@ -124,6 +140,7 @@
         backBtn.setEnabled(false);
         finishBtn = new JButton(translator.localize(LocaleResources.FINISH).getContents());
         finishBtn.setPreferredSize(new Dimension(70, 30));
+        finishBtn.setEnabled(true);
         cancelBtn = new JButton(translator.localize(LocaleResources.CANCEL).getContents());
         cancelBtn.setPreferredSize(new Dimension(70, 30));
 
@@ -137,16 +154,24 @@
         toolbar.add(cancelBtn);
     }
 
+    private void validateInput() {
+        if (clientInfoPanel.isInputValid() && agentInfoPanel.isInputValid()) {
+            finishBtn.setEnabled(true);
+        } else {
+            finishBtn.setEnabled(false);
+        }
+    }
+
     public void enableButtons() {
-        makeAgentUserBtn.setEnabled(true);
-        makeClientAdminBtn.setEnabled(true);
         finishBtn.setEnabled(true);
+        agentInfoPanel.setEnabled(true);
+        clientInfoPanel.setEnabled(true);
     }
 
     public void disableButtons() {
-        makeAgentUserBtn.setEnabled(false);
-        makeClientAdminBtn.setEnabled(false);
         finishBtn.setEnabled(false);
+        agentInfoPanel.setEnabled(false);
+        clientInfoPanel.setEnabled(false);
     }
 
     @Override
@@ -162,11 +187,20 @@
         return cancelBtn;
     }
 
-    public boolean makeAgentUserSelected() {
-        return makeAgentUserBtn.isSelected();
+    public String getAgentUsername() {
+        return agentInfoPanel.getUsername();
+    }
+
+    public char[] getAgentPassword() {
+        return agentInfoPanel.getPassword();
     }
 
-    public boolean makeClientAdminSelected() {
-        return makeClientAdminBtn.isSelected();
+    public String getClientUsername() {
+        return clientInfoPanel.getUsername();
     }
+
+    public char[] getClientPassword() {
+        return clientInfoPanel.getPassword();
+    }
+
 }
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/model/UserCredsValidator.java	Fri Aug 28 09:59:28 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/model/UserCredsValidator.java	Fri Aug 28 13:27:54 2015 -0400
@@ -36,15 +36,15 @@
 
 package com.redhat.thermostat.setup.command.internal.model;
 
-class UserCredsValidator {
-    
-    void validateUsername(String username) {
+public class UserCredsValidator {
+
+    public void validateUsername(String username) {
         if (username == null || username.isEmpty()) {
             throw new IllegalArgumentException("Name must not be null or empty");
         }
     }
-    
-    void validatePassword(char[] password) {
+
+    public void validatePassword(char[] password) {
         if (password == null || password.length == 0) {
             throw new IllegalArgumentException("Password must not be null or empty");
         }
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/locale/LocaleResources.java	Fri Aug 28 09:59:28 2015 -0400
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/locale/LocaleResources.java	Fri Aug 28 13:27:54 2015 -0400
@@ -45,21 +45,30 @@
     WELCOME_SCREEN_TITLE,
     MONGO_SETUP_TITLE,
     USERS_SETUP_TITLE,
+    MONGO_CRED_TITLE,
+    CLIENT_CRED_TITLE,
+    AGENT_CRED_TITLE,
     NEXT,
     BACK,
     CANCEL,
     FINISH,
-    AGENT_INFO,
-    CLIENT_INFO,
+    AGENT_HELP_INFO,
+    CLIENT_HELP_INFO,
+    STORAGE_HELP_INFO,
+    PASSWORD_MISMATCH,
+    DETAILS_MISSING,
+    SHOW_PASSWORDS,
+    USE_DEFAULTS,
     THERMOSTAT_BRIEF,
     THERMOSTAT_BLURB,
     STORAGE_FAILED,
-    CREATE_AGENT_USER,
-    CREATE_CLIENT_ADMIN,
     SERVICE_UNAVAILABLE_MESSAGE,
     SETUP_FAILED,
     SETUP_INTERRUPTED,
     SETUP_CANCELLED,
+    USERNAME,
+    PASSWORD,
+    VERIFY_PASSWORD,
     ;
 
     static final String RESOURCE_BUNDLE =
--- a/setup/command/src/main/resources/com/redhat/thermostat/setup/locale/strings.properties	Fri Aug 28 09:59:28 2015 -0400
+++ b/setup/command/src/main/resources/com/redhat/thermostat/setup/locale/strings.properties	Fri Aug 28 13:27:54 2015 -0400
@@ -6,6 +6,12 @@
 
 USERS_SETUP_TITLE=Thermostat Users Setup
 
+MONGO_CRED_TITLE=MongoDB User
+
+CLIENT_CRED_TITLE=Client User
+
+AGENT_CRED_TITLE=Agent User
+
 NEXT=Next>
 
 BACK=<Back
@@ -53,15 +59,13 @@
     layer:\
 <p>
 
-CREATE_AGENT_USER=Create Agent User
-
-CREATE_CLIENT_ADMIN=Create Client Admin User
-
 STORAGE_FAILED=Thermostat storage failed
 
-AGENT_INFO=Agents connect to storage and send collected data from JVMs
+AGENT_HELP_INFO=Use these credentials for "thermostat agent" (File agent.auth). This wizard will set this up appropriately for you.
 
-CLIENT_INFO=Clients connect to storage and retrieve data to display
+STORAGE_HELP_INFO=These credentials are used by the mongodb storage
+
+CLIENT_HELP_INFO=Use these credentials for "thermostat gui" or any other thermostat CLI command except for "thermostat agent"
 
 SERVICE_UNAVAILABLE_MESSAGE={0} service dependency unavailable
 
@@ -70,3 +74,17 @@
 SETUP_INTERRUPTED=Setup was interrupted.
 
 SETUP_CANCELLED=Setup was cancelled.
+
+PASSWORD_MISMATCH=Passwords don't match!
+
+DETAILS_MISSING=Please fill in ALL fields
+
+SHOW_PASSWORDS=Show passwords
+
+USE_DEFAULTS=Use Defaults
+
+USERNAME=Username:
+
+PASSWORD=Password:
+
+VERIFY_PASSWORD=Verify Password:
\ No newline at end of file