Sebastian Sdorra avatar Sebastian Sdorra committed 0400a50

added option for explicit jira credentials

Comments (0)

Files changed (8)

src/main/java/sonia/scm/jira/EncryptionUtil.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.jira;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Strings;
+import sonia.scm.security.CipherUtil;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class EncryptionUtil
+{
+
+  /** Field description */
+  private static final String PREFIX = "{enc}";
+
+  //~--- methods --------------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param value
+   *
+   * @return
+   */
+  public static String decrypt(String value)
+  {
+    if (!value.startsWith(PREFIX))
+    {
+      throw new IllegalArgumentException("value is not encrypted");
+    }
+
+    value = value.substring(PREFIX.length());
+
+    return CipherUtil.getInstance().decode(value);
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param value
+   *
+   * @return
+   */
+  public static String encrypt(String value)
+  {
+    value = CipherUtil.getInstance().encode(value);
+
+    return PREFIX.concat(value);
+  }
+
+  //~--- get methods ----------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param value
+   *
+   * @return
+   */
+  public static boolean isEncrypted(String value)
+  {
+    return ! Strings.isNullOrEmpty(value) && value.startsWith(PREFIX);
+  }
+}

src/main/java/sonia/scm/jira/JiraConfiguration.java

   public static final String PROPERTY_JIRA_URL = "jira.url";
 
   /** Field description */
+  public static final String PROPERTY_PASSWORD = "jira.password";
+
+  /** Field description */
   public static final String PROPERTY_UPDATEISSUES = "jira.update-issues";
 
   /** Field description */
+  public static final String PROPERTY_USERNAME = "jira.username";
+
+  /** Field description */
   public static final String SEPARATOR = ",";
 
   //~--- constructors ---------------------------------------------------------
     updateIssues = getBooleanProperty(repository, PROPERTY_UPDATEISSUES);
     autoClose = getBooleanProperty(repository, PROPERTY_AUTOCLOSE);
     autoCloseWords = getSetProperty(repository, PROPERTY_AUTOCLOSEWORDS);
+    username = repository.getProperty(PROPERTY_USERNAME);
+    password = getEncryptedProperty(repository, PROPERTY_PASSWORD);
   }
 
   //~--- get methods ----------------------------------------------------------
    *
    * @return
    */
+  public String getPassword()
+  {
+    return password;
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @return
+   */
   public String getUrl()
   {
     return url;
    *
    * @return
    */
+  public String getUsername()
+  {
+    return username;
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @return
+   */
   public boolean isAutoCloseEnabled()
   {
     return isUpdateIssuesEnabled() && autoClose
    *
    * @return
    */
+  private String getEncryptedProperty(Repository repository, String key)
+  {
+    String value = repository.getProperty(key);
+
+    if (EncryptionUtil.isEncrypted(value))
+    {
+      value = EncryptionUtil.decrypt(value);
+    }
+
+    return value;
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param repository
+   * @param key
+   *
+   * @return
+   */
   private Set<String> getSetProperty(Repository repository, String key)
   {
     Set<String> values;
   private Set<String> autoCloseWords;
 
   /** Field description */
+  @XmlJavaTypeAdapter(XmlEncryptionAdapter.class)
+  private String password;
+
+  /** Field description */
   @XmlElement(name = "update-issues")
   private boolean updateIssues;
 
   /** Field description */
   private String url;
+
+  /** Field description */
+  private String username;
 }

src/main/java/sonia/scm/jira/JiraIssueRequestFactory.java

 
 //~--- non-JDK imports --------------------------------------------------------
 
+import com.google.common.base.Strings;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
 import org.apache.shiro.session.Session;
 import org.apache.shiro.subject.Subject;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import sonia.scm.repository.Repository;
 import sonia.scm.security.CipherUtil;
 import sonia.scm.util.AssertUtil;
   /** Field description */
   public static final String SCM_CREDENTIALS = "SCM_CREDENTIALS";
 
+  /**
+   * the logger for JiraIssueRequestFactory
+   */
+  private static final Logger logger =
+    LoggerFactory.getLogger(JiraIssueRequestFactory.class);
+
   //~--- constructors ---------------------------------------------------------
 
   /**
   public JiraIssueRequest createRequest(JiraConfiguration configuration,
     Repository repository)
   {
-    String[] credentials = getUserCredentials();
+    String username = configuration.getUsername();
+    String password = configuration.getPassword();
 
-    return new JiraIssueRequest(handlerFactory, credentials[0], credentials[1],
+    if (Strings.isNullOrEmpty(username))
+    {
+      if (logger.isTraceEnabled())
+      {
+        logger.trace("no username configured, use current credentials");
+      }
+
+      String[] credentials = getUserCredentials();
+
+      username = credentials[0];
+      password = credentials[1];
+    }
+
+    if (logger.isDebugEnabled())
+    {
+      logger.debug("create jira issue request for user {}", username);
+    }
+
+    return new JiraIssueRequest(handlerFactory, username, password,
       configuration, repository);
   }
 

src/main/java/sonia/scm/jira/JiraRepositoryListener.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.jira;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Strings;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.HandlerEvent;
+import sonia.scm.plugin.ext.Extension;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryListener;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@Extension
+public class JiraRepositoryListener implements RepositoryListener
+{
+
+  /**
+   * the logger for JiraRepositoryListener
+   */
+  private static final Logger logger =
+    LoggerFactory.getLogger(JiraRepositoryListener.class);
+
+  //~--- methods --------------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param repository
+   * @param event
+   */
+  @Override
+  public void onEvent(Repository repository, HandlerEvent event)
+  {
+    if (event == HandlerEvent.BEFORE_MODIFY)
+    {
+      String password =
+        repository.getProperty(JiraConfiguration.PROPERTY_PASSWORD);
+
+      if (!Strings.isNullOrEmpty(password)
+        &&!EncryptionUtil.isEncrypted(password))
+      {
+        if (logger.isTraceEnabled())
+        {
+          logger.trace("encrypt password before repository is modified");
+        }
+
+        repository.setProperty(JiraConfiguration.PROPERTY_PASSWORD,
+          EncryptionUtil.encrypt(password));
+      }
+    }
+  }
+}

src/main/java/sonia/scm/jira/XmlEncryptionAdapter.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.jira;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Strings;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class XmlEncryptionAdapter extends XmlAdapter<String, String>
+{
+
+  /**
+   * Method description
+   *
+   *
+   * @param v
+   *
+   * @return
+   *
+   * @throws Exception
+   */
+  @Override
+  public String marshal(String v) throws Exception
+  {
+    if (!Strings.isNullOrEmpty(v) &&!EncryptionUtil.isEncrypted(v))
+    {
+      v = EncryptionUtil.encrypt(v);
+    }
+
+    return v;
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param v
+   *
+   * @return
+   *
+   * @throws Exception
+   */
+  @Override
+  public String unmarshal(String v) throws Exception
+  {
+    if (EncryptionUtil.isEncrypted(v))
+    {
+      v = EncryptionUtil.decrypt(v);
+    }
+
+    return v;
+  }
+}

src/main/resources/sonia/scm/jira/sonia.jira.globalconfigpanel.js

         fieldLabel: Sonia.jira.I18n.autoCloseWordsText,
         helpText: Sonia.jira.I18n.autoCloseWordsHelpText,
         value: Sonia.jira.I18n.autoCloseDefaultValues
+      },{
+        id: 'username',
+        name: 'username',
+        xtype: 'textfield',
+        fieldLabel: Sonia.jira.I18n.usernameText,
+        helpText: Sonia.jira.I18n.usernameHelpText
+      },{
+        id: 'password',
+        name: 'password',
+        xtype: 'textfield',
+        fieldLabel: Sonia.jira.I18n.passwordText,
+        inputType: 'password',
+        helpText: Sonia.jira.I18n.passwordHelpText
       }]
     }
 

src/main/resources/sonia/scm/jira/sonia.jira.js

   
   autoCloseWordsText: 'Auto-Close Words',
   autoCloseWordsHelpText: 'Comma separated list of words to enable the auto close function. \n\
-                           Each commit message of a changeset is being searched for these words.'
+                           Each commit message of a changeset is being searched for these words.',
   
+  usernameText: 'Username',
+  usernameHelpText: 'Jira username for connection. Leave this field empty to create the connection\n\
+                     with the credentials of the user which is logged in.',
+  
+  passwordText: 'Password',
+  passwordHelpText: 'Jira password for connection.'
 }
 
 Sonia.jira.toggleFields = function(cmps, scope){

src/main/resources/sonia/scm/jira/sonia.jira.repositoryconfigpanel.js

         property: 'jira.auto-close-words',
         helpText: Sonia.jira.I18n.autoCloseWordsHelpText,
         value: Sonia.jira.I18n.autoCloseDefaultValues
+      },{
+        id: 'jiraUsername',
+        name: 'jiraUsername',
+        fieldLabel: Sonia.jira.I18n.usernameText,
+        property: 'jira.username',
+        helpText: Sonia.jira.I18n.usernameHelpText
+      },{
+        id: 'jiraPassword',
+        name: 'jiraPassword',
+        fieldLabel: Sonia.jira.I18n.passwordText,
+        property: 'jira.password',
+        inputType: 'password',
+        helpText: Sonia.jira.I18n.passwordHelpText
       }]
     }
     
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.