Commits

Stefan Saasen committed d893ec7

Improve form handling

* Validate form input for HipChat room configurations
* Require XSRF tokens
* Show error and success messages
* Redirect to space admin actions after setting the API key (if the key is missing or invalid)

Comments (0)

Files changed (10)

src/main/java/com/atlassian/labs/hipchat/actions/SaveConfigurationAction.java

 import com.atlassian.confluence.security.Permission;
 import com.atlassian.confluence.security.PermissionManager;
 import com.atlassian.labs.hipchat.components.ConfigurationManager;
+import com.atlassian.xwork.RequireSecurityToken;
 import com.opensymphony.xwork.Action;
 import org.apache.commons.lang.StringUtils;
 
     private ConfigurationManager configurationManager;
     private PermissionManager permissionManager;
 
+    private String spaceKey;
     private String hipChatAuthToken;
 
     @Override
     }
 
     @Override
+    @RequireSecurityToken(true)
     public String execute() throws Exception {
         configurationManager.updateConfiguration(hipChatAuthToken);
+
+        if(StringUtils.isNotBlank(spaceKey)) {
+            return "redirect";
+        }
         return Action.SUCCESS;
     }
 
+    public String getSpaceKey() {
+        return spaceKey;
+    }
+
+    public void setSpaceKey(String spaceKey) {
+        this.spaceKey = spaceKey;
+    }
     // =================================================================================================================
     // We have to use setter injection if we don't use the defaultStack
     // See https://jira.atlassian.com/browse/CONF-23137

src/main/java/com/atlassian/labs/hipchat/actions/SaveSpaceConfigurationAction.java

 
 import com.atlassian.confluence.core.ConfluenceActionSupport;
 import com.atlassian.confluence.security.PermissionManager;
+import com.atlassian.confluence.security.SpacePermission;
+import com.atlassian.confluence.spaces.SpaceManager;
 import com.atlassian.labs.hipchat.components.ConfigurationManager;
+import com.atlassian.xwork.RequireSecurityToken;
 import com.opensymphony.xwork.Action;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Arrays;
 
 public class SaveSpaceConfigurationAction extends ConfluenceActionSupport
 {
-    private final ConfigurationManager configurationManager;
-    private final PermissionManager permissionManager;
+    private ConfigurationManager configurationManager;
+    private PermissionManager permissionManager;
+    private SpaceManager spaceManager;
 
-    private String hipChatAuthToken;
     private String key;
     private String roomId;
 
-    public SaveSpaceConfigurationAction(ConfigurationManager configurationManager, PermissionManager permissionManager)
-    {
-        this.configurationManager = configurationManager;
-        this.permissionManager = permissionManager;
+    @Override public void validate() {
+        super.validate();
+
+        if(StringUtils.isBlank(key) || spaceManager.getSpace(key) == null) {
+            addActionError(getText("hipchat.spaceconfig.spacekeyerror"));
+        }
+    }
+
+    @Override public boolean isPermitted() {
+        return spacePermissionManager.hasPermissionForSpace(getRemoteUser(), Arrays.asList(SpacePermission.ADMINISTER_SPACE_PERMISSION), spaceManager.getSpace(key));
     }
 
     @Override
+    @RequireSecurityToken(true)
     public String execute() throws Exception
     {
-        // TODO: Validate inputs.
         configurationManager.setNotifyRooms(key, roomId);
         return Action.SUCCESS;
     }
     public void setRoomId(String roomId) {
         this.roomId = roomId;
     }
+
+    // =================================================================================================================
+    // We have to use setter injection if we don't use the defaultStack
+    // See https://jira.atlassian.com/browse/CONF-23137
+    public void setPermissionManager(PermissionManager permissionManager) {
+        this.permissionManager = permissionManager;
+    }
+
+    public void setConfigurationManager(ConfigurationManager configurationManager) {
+        this.configurationManager = configurationManager;
+    }
+
+    public void setSpaceManager(SpaceManager spaceManager) {
+        this.spaceManager = spaceManager;
+    }
 }

src/main/java/com/atlassian/labs/hipchat/actions/ViewConfigurationAction.java

 
     private final ConfigurationManager configurationManager;
     private final PermissionManager permissionManager;
-
     private boolean successFullUpdate;
 
     public ViewConfigurationAction(ConfigurationManager configurationManager, PermissionManager permissionManager) {

src/main/java/com/atlassian/labs/hipchat/actions/ViewSpaceConfigurationAction.java

 import com.atlassian.labs.hipchat.utils.InvalidAuthTokenException;
 import com.atlassian.plugin.webresource.WebResourceUrlProvider;
 import com.opensymphony.xwork.Action;
+import org.apache.commons.lang.StringUtils;
 
 public class ViewSpaceConfigurationAction extends AbstractSpaceAdminAction
 {
 
     private String roomId;
     private String roomsHtml;
+    private boolean successFullUpdate;
 
     public ViewSpaceConfigurationAction(HipChatProxyClient hipChatProxyClient, ConfigurationManager configurationManager)
     {
         this.configurationManager = configurationManager;
     }
 
+    public void setResult(String result) {
+        if ("success".equals(result)) {
+            successFullUpdate = true;
+        }
+    }
+    
     @Override
     public String execute()
     {
         setRoomId(configurationManager.getHipChatRooms(key));
-        if(configurationManager.getHipChatAuthToken().equals("")){
+        if(StringUtils.isBlank(configurationManager.getHipChatAuthToken())) {
             return Action.INPUT;
         } else {
             try {
     public void setRoomsHtml(String roomsHtml) {
         this.roomsHtml = roomsHtml;
     }
+
+    public boolean isSuccessFullUpdate() {
+        return successFullUpdate;
+    }
 }

src/main/resources/atlassian-plugin.properties

 hipchat-space-configuration.name=HipChat
 hipchat.integrations=Integrations
 com.atlassian.labs.hipchat.actions.ViewSpaceConfigurationAction.action.name=HipChat Configuration
+com.atlassian.labs.hipchat.actions.SaveSpaceConfigurationAction.action.name=HipChat Room Configuration
 
+# Messages
+hipchat.action.success.spaceconfig=Room configuration successfully saved
+hipchat.action.success.apitokenconfig=API token successfully saved
 
 # Form handling
-hipchat.token.form.invalidtokenerror=Invalid HipChat authentication token
+hipchat.token.form.invalidtokenerror=Invalid HipChat authentication token
+hipchat.spaceconfig.spacekeyerror=The space key is missing or invalid

src/main/resources/atlassian-plugin.xml

                 <param name="RequireSecurityToken">true</param>
                 <result name="input" type="velocity">/templates/admin/configuration.vm</result>
                 <result name="error" type="velocity">/templates/admin/configuration.vm</result>
+                <result name="redirect" type="redirect">/spaces/hipchat.action?key=${spaceKey}</result>
                 <result name="success" type="redirect">/admin/hipchat.action?result=success</result>
             </action>
 
     <!-- Space config -->
     <xwork name="spaceConfigurationAction" key="spaceConfigurationAction">
         <package name="space-configure" extends="default" namespace="/spaces">
-            <default-interceptor-ref name="validatingStack"/>
+            <default-interceptor-ref name="defaultStack"/>
 
             <action name="hipchat" class="com.atlassian.labs.hipchat.actions.ViewSpaceConfigurationAction">
                 <result name="success" type="velocity">/templates/admin/space-config.vm</result>
                 <result name="error" type="velocity">/templates/admin/space-config-invalid-auth-token.vm</result>
             </action>
             <action name="doconfigure-hipchat" class="com.atlassian.labs.hipchat.actions.SaveSpaceConfigurationAction">
-                <result name="success" type="redirect">/spaces/hipchat.action?key=${key}</result>
+                <interceptor-ref name="validatingStack"/>
+                <param name="RequireSecurityToken">true</param>
+                <result name="input" type="velocity">/templates/admin/space-config.vm</result>
+                <result name="error" type="velocity">/templates/admin/space-config.vm</result>
+                <result name="success" type="redirect">/spaces/hipchat.action?key=${key}&amp;result=success</result>
             </action>
 
         </package>

src/main/resources/templates/admin/configuration.vm

 <body>
 <form action="$req.contextPath/admin/doconfigure-hipchat.action" method="post" class="aui">
     #form_xsrfToken()
+    <input type="hidden" name="spaceKey" value="$!req.getParameter("spaceKey")" />
     <h2>HipChat API Auth Token Configuration</h2>
 
     #if($actionErrors && $actionErrors.size() > 0)
         <div class="aui-message success shadowed closeable">
             <p class="title">
                 <span class="aui-icon icon-success"></span>
-                <strong>API token successfully saved</strong>
+                <strong>$action.getText("hipchat.action.success.apitokenconfig")</strong>
             </p>
         </div>
         <!-- .aui-message -->

src/main/resources/templates/admin/space-config-invalid-auth-token.vm

             <p>
                 Make sure your
                 <a href="https://hipchat.com/admin/api" title="HipChat API Tokens" target="_blank">HipChat API Auth Token</a>
-                is configured properly on the <a href="../admin/hipchat.action">Confluence HipChat Configuration page</a>.
+                is configured properly on the <a href="../admin/hipchat.action?spaceKey=$!key">Confluence HipChat Configuration page</a>.
                 Make sure you're using an <b>Admin</b> token, not a <b>Notification</b> token.
             </p>
         </div><!-- .aui-message -->

src/main/resources/templates/admin/space-config-no-auth-token.vm

             Before you can link this space to HipChat, you need to create an <b>Admin</b>
             <a href="https://hipchat.com/admin/api" title="HipChat API Tokens" target="_blank">HipChat API Auth
                 Token</a>
-            then register that token in the <a href="../admin/hipchat.action">Confluence HipChat Configuration page</a>.
+            then register that token in the <a href="../admin/hipchat.action?spaceKey=$!key">Confluence HipChat Configuration page</a>.
         </p>
     </div>
     <!-- .aui-message -->

src/main/resources/templates/admin/space-config.vm

     <h2>HipChat Configuration</h2>
     #form_xsrfToken()
     <input type="hidden" name="key" value="$generalUtil.urlEncode($action.key)"/>
-
+        #if($actionErrors && $actionErrors.size() > 0)
+        <div class="aui-message error">
+            <span class="svg-icon error size-18"></span>
+            <strong>$action.getText("errors.occurred")</strong>
+            <ul>
+                #foreach($error in $actionErrors)
+                    <li>$error</li>
+                #end
+            </ul>
+        </div>
+        #end
+        #if($action.successFullUpdate)
+            <div class="aui-message success shadowed closeable">
+                <p class="title">
+                    <span class="aui-icon icon-success"></span>
+                    <strong>$action.getText("hipchat.action.success.spaceconfig")</strong>
+                </p>
+            </div>
+        <!-- .aui-message -->
+        #end
     <p>
         Confluence can notify HipChat when a blog post is posted in this space. Just pick the HipChat room(s)
         where you would like notifications sent.