← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 20881: Introduced LDAP authentication support. The flow: 1. user logs into dhis with a username / passwo...

 

Merge authors:
  Lars Helge Øverland (larshelge)
------------------------------------------------------------
revno: 20881 [merge]
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2015-10-27 10:11:44 -0400
message:
  Introduced LDAP authentication support. The flow: 1. user logs into dhis with a username / password. 2. username/password is matched/authenticated against dhis database. 3. if not successful, username is included in a pattern for the ldap DN (distinguished name) and a bind is attempted against LDAP server. 4. if authentication is successful, the username is used to look up a matching dhis user, from which we fetch the authorities / user roles. 5. If found, from now on, the combined ldap credentials and dhis authorities are assembled and used for the user session. Also introduced a DhisConfigurationProvider which loads properties from the dhis configuration file (can be reused for other purposes).
added:
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/ldap/
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/ldap/authentication/
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/ldap/authentication/DhisBindAuthenticator.java
  dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/
  dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/ConfigurationKey.java
  dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/ConfigurationPropertyFactoryBean.java
  dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/DefaultDhisConfigurationProvider.java
  dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/DhisConfigurationProvider.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/SecurityUtils.java
modified:
  dhis-2/dhis-services/dhis-service-core/pom.xml
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultUserDetailsService.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/security.xml
  dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/location/DefaultLocationManager.java
  dhis-2/dhis-support/dhis-support-external/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/hibernate/ConnectionPropertyFactoryBean.java
  dhis-2/dhis-support/dhis-support-system/pom.xml
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/DefaultAuthenticationSuccessHandler.java
  dhis-2/pom.xml


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-services/dhis-service-core/pom.xml'
--- dhis-2/dhis-services/dhis-service-core/pom.xml	2015-10-20 22:50:17 +0000
+++ dhis-2/dhis-services/dhis-service-core/pom.xml	2015-10-25 19:44:21 +0000
@@ -93,8 +93,12 @@
       <groupId>org.apache.jclouds.provider</groupId>
       <artifactId>aws-s3</artifactId>
     </dependency>
-
-     <!-- SMS -->
+    <dependency>
+      <groupId>org.springframework.security</groupId>
+      <artifactId>spring-security-ldap</artifactId>
+    </dependency>
+    
+    <!-- SMS -->
 
     <dependency>
       <groupId>org.smslib</groupId>

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultUserDetailsService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultUserDetailsService.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultUserDetailsService.java	2015-10-25 20:30:23 +0000
@@ -1,49 +1,15 @@
 package org.hisp.dhis.security;
 
-/*
- * Copyright (c) 2004-2015, University of Oslo
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 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.
- * Neither the name of the HISP project 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 COPYRIGHT OWNER 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.
- */
-
-import org.hisp.dhis.user.UserAuthorityGroup;
+import org.hisp.dhis.system.util.SecurityUtils;
 import org.hisp.dhis.user.UserCredentials;
 import org.hisp.dhis.user.UserService;
 import org.springframework.dao.DataAccessException;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
 /**
  * @author Torgeir Lorange Ostby
  */
@@ -88,25 +54,6 @@
         boolean credentialsExpired = userService.credentialsNonExpired( credentials );
 
         return new User( credentials.getUsername(), credentials.getPassword(),
-            !credentials.isDisabled(), true, credentialsExpired, true, getGrantedAuthorities( credentials ) );
-    }
-
-    // -------------------------------------------------------------------------
-    // Supportive methods
-    // -------------------------------------------------------------------------
-
-    private Collection<GrantedAuthority> getGrantedAuthorities( UserCredentials credentials )
-    {
-        Set<GrantedAuthority> authorities = new HashSet<>();
-
-        for ( UserAuthorityGroup group : credentials.getUserAuthorityGroups() )
-        {
-            for ( String authority : group.getAuthorities() )
-            {
-                authorities.add( new SimpleGrantedAuthority( authority ) );
-            }
-        }
-
-        return authorities;
+            !credentials.isDisabled(), true, credentialsExpired, true, SecurityUtils.getGrantedAuthorities( credentials ) );
     }
 }

=== added directory 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/ldap'
=== added directory 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/ldap/authentication'
=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/ldap/authentication/DhisBindAuthenticator.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/ldap/authentication/DhisBindAuthenticator.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/ldap/authentication/DhisBindAuthenticator.java	2015-10-27 14:11:44 +0000
@@ -0,0 +1,70 @@
+package org.hisp.dhis.security.ldap.authentication;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 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.
+ * Neither the name of the HISP project 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 COPYRIGHT OWNER 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.
+ */
+
+import org.hisp.dhis.external.conf.DhisConfigurationProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.ldap.core.DirContextOperations;
+import org.springframework.ldap.core.support.BaseLdapPathContextSource;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.ldap.authentication.BindAuthenticator;
+
+/**
+ * Authenticator which checks whether LDAP authentication is configured. If not,
+ * the authentication will be aborted, otherwise authentication is delegated to
+ * Spring BindAuthenticator.
+ * 
+ * @author Lars Helge Overland
+ */
+public class DhisBindAuthenticator
+    extends BindAuthenticator
+{
+    @Autowired
+    private DhisConfigurationProvider configurationProvider;
+    
+    public DhisBindAuthenticator( BaseLdapPathContextSource contextSource )
+    {
+        super( contextSource );
+    }
+
+    @Override
+    public DirContextOperations authenticate( Authentication authentication )
+    {
+        boolean ldapConf = configurationProvider.isLdapConfigured();
+        
+        System.out.println( "IS LDAP CONF " + ldapConf );
+        if ( !ldapConf )
+        {
+            throw new BadCredentialsException( "LDAP authentication is not configured" );
+        }
+        
+        return super.authenticate( authentication );
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/security.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/security.xml	2015-08-25 13:54:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/security.xml	2015-10-27 14:11:44 +0000
@@ -21,13 +21,49 @@
   </bean>
 
   <!-- Security : Authentication providers -->
+  
   <sec:authentication-manager alias="authenticationManager">
     <sec:authentication-provider user-service-ref="userDetailsService">
       <sec:password-encoder ref="bCryptPasswordEncoder" />
     </sec:authentication-provider>
+    <sec:authentication-provider ref="ldapAuthenticationProvider" />
   </sec:authentication-manager>
 
+  <!-- LDAP -->
+  
+  <bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
+    <constructor-arg ref="ldapUrl" />
+    <property name="userDn" ref="ldapManagerDn" />
+    <property name="password" ref="ldapManagerPassword" />
+  </bean>
+  
+  <bean id="ldapAuthenticationProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
+    <constructor-arg>
+      <bean class="org.hisp.dhis.security.ldap.authentication.DhisBindAuthenticator">
+        <constructor-arg ref="contextSource"/>
+        <property name="userDnPatterns" ref="ldapDnPatterns" />
+      </bean>
+    </constructor-arg>
+    <constructor-arg>
+      <bean class="org.springframework.security.ldap.authentication.UserDetailsServiceLdapAuthoritiesPopulator">
+        <constructor-arg ref="userDetailsService" />
+      </bean>
+    </constructor-arg>
+  </bean>
+  
+  <bean id="ldapUrl" class="org.hisp.dhis.external.conf.ConfigurationPropertyFactoryBean"><constructor-arg value="KEY_LDAP_URL" /></bean>
+  
+  <bean id="ldapManagerDn" class="org.hisp.dhis.external.conf.ConfigurationPropertyFactoryBean"><constructor-arg value="KEY_LDAP_MANAGER_DN" /></bean>
+  
+  <bean id="ldapManagerPassword" class="org.hisp.dhis.external.conf.ConfigurationPropertyFactoryBean"><constructor-arg value="KEY_LDAP_MANAGER_PASSWORD" /></bean>
+    
+  <bean id="ldapDnPatterns" class="org.hisp.dhis.external.conf.ConfigurationPropertyFactoryBean">
+    <constructor-arg value="KEY_LDAP_DN_PATTERNS" />
+    <property name="list" value="true" />
+  </bean>  
+    
   <!-- OAuth2 -->
+  
   <bean id="clientDetailsService" class="org.hisp.dhis.security.oauth2.DefaultClientDetailsService" />
 
   <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
@@ -50,6 +86,5 @@
   <sec:authentication-manager id="clientAuthenticationManager">
     <sec:authentication-provider user-service-ref="clientDetailsUserService" />
   </sec:authentication-manager>
-  <!-- End OAuth2 -->
 
 </beans>

=== added directory 'dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf'
=== added file 'dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/ConfigurationKey.java'
--- dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/ConfigurationKey.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/ConfigurationKey.java	2015-10-27 14:11:44 +0000
@@ -0,0 +1,71 @@
+package org.hisp.dhis.external.conf;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 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.
+ * Neither the name of the HISP project 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 COPYRIGHT OWNER 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.
+ */
+
+/**
+ * @author Lars Helge Overland
+ */
+public enum ConfigurationKey
+{
+    KEY_LDAP_URL( "ldap.url", "ldaps://0:1" ),
+    KEY_LDAP_MANAGER_DN( "ldap.manager.dn" ),
+    KEY_LDAP_MANAGER_PASSWORD( "ldap.manager.password" ),
+    KEY_LDAP_DN_PATTERNS( "ldap.dn.patterns", "" ),    
+    KEY_FILESTORE_PROVIDER( "filestore.provider", "filesystem" ),
+    KEY_FILE_STORE_CONTAINER( "filestore.container" ),
+    KEY_FILE_STORE_LOCATION( "filestore.location" ),
+    KEY_FILE_STORE_IDENTITY( "filestore.identity" ),
+    KEY_FILE_STORE_SECRET( "filestore.secret" );
+
+    private final String key;
+    
+    private final String defaultValue;
+    
+    ConfigurationKey( String key )
+    {
+        this.key = key;
+        this.defaultValue = null;
+    }
+
+    ConfigurationKey( String key, String defaultValue )
+    {
+        this.key = key;
+        this.defaultValue = defaultValue;
+    }
+    
+    public String getKey()
+    {
+        return key;
+    }
+    
+    public String getDefaultValue()
+    {
+        return defaultValue;
+    }
+}

=== added file 'dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/ConfigurationPropertyFactoryBean.java'
--- dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/ConfigurationPropertyFactoryBean.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/ConfigurationPropertyFactoryBean.java	2015-10-27 03:18:11 +0000
@@ -0,0 +1,104 @@
+package org.hisp.dhis.external.conf;
+
+import java.util.List;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 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.
+ * Neither the name of the HISP project 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 COPYRIGHT OWNER 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.
+ */
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.Assert;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Factory bean which allows for DHIS configuration property values to be 
+ * injected into target beans. 
+ * 
+ * @param key must reflect a {@link ConfigurationKey}.
+ * 
+ * @author Lars Helge Overland
+ */
+public class ConfigurationPropertyFactoryBean
+    implements FactoryBean<Object>
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private DhisConfigurationProvider configurationProvider;
+    
+    private ConfigurationKey key;
+    
+    public ConfigurationPropertyFactoryBean( ConfigurationKey key )
+    {
+        this.key = key;
+    }
+    
+    private boolean list;
+
+    public void setList( boolean list )
+    {
+        this.list = list;
+    }
+
+    // -------------------------------------------------------------------------
+    // FactoryBean implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public Object getObject()
+        throws Exception
+    {
+        Assert.notNull( key, "Configuration key must be specified" );
+        
+        String value = configurationProvider.getProperty( key );
+        
+        if ( list )
+        {
+            return value != null ? Lists.newArrayList( value.split( ";" ) ) : value;
+        }
+        else
+        {
+            return value;
+        }
+    }
+
+    @Override
+    public Class<?> getObjectType()
+    {
+        return list ? List.class : String.class;
+    }
+
+    @Override
+    public boolean isSingleton()
+    {
+        return true;
+    }
+}

=== added file 'dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/DefaultDhisConfigurationProvider.java'
--- dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/DefaultDhisConfigurationProvider.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/DefaultDhisConfigurationProvider.java	2015-10-27 14:11:44 +0000
@@ -0,0 +1,136 @@
+package org.hisp.dhis.external.conf;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 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.
+ * Neither the name of the HISP project 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 COPYRIGHT OWNER 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.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hisp.dhis.external.location.LocationManager;
+import org.hisp.dhis.external.location.LocationManagerException;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class DefaultDhisConfigurationProvider
+    implements DhisConfigurationProvider
+{
+    private static final Log log = LogFactory.getLog( DefaultDhisConfigurationProvider.class );
+
+    private static final String CONF_FILENAME = "dhis.conf";
+    
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    private LocationManager locationManager;
+    
+    public void setLocationManager( LocationManager locationManager )
+    {
+        this.locationManager = locationManager;
+    }
+
+    /**
+     * Cache for properties.
+     */
+    private Properties properties;
+    
+    public void init()
+    {
+        InputStream in = null;
+        
+        try
+        {
+            in = locationManager.getInputStream( CONF_FILENAME );
+        }
+        catch ( LocationManagerException ex1 )
+        {
+            log.debug( "Could not load dhis.conf" );
+                        
+            try // Deprecated
+            {
+                in = locationManager.getInputStream( "hibernate.properties" );
+            }
+            catch ( LocationManagerException ex2 )
+            {
+                log.debug( "Could not load hibernate.properties" );
+            }
+        }
+        
+        Properties properties = new Properties();
+        
+        if ( in != null )
+        {
+            try
+            {
+                properties.load( in );
+            }
+            catch ( IOException ex )
+            {
+                throw new IllegalStateException( "Properties could not be loaded", ex );
+            }
+        }
+        
+        this.properties = properties;
+    }
+
+    // -------------------------------------------------------------------------
+    // DhisConfigurationProvider implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public Properties getProperties()
+    {
+        return properties;
+    }
+
+    @Override
+    public String getProperty( ConfigurationKey key  )
+    {
+        return properties.getProperty( key.getKey(), key.getDefaultValue() );
+    }
+
+    @Override
+    public String getPropertyOrDefault( ConfigurationKey key, String defaultValue )
+    {
+        return properties.getProperty( key.getKey(), defaultValue );
+    }
+
+    @Override
+    public boolean isLdapConfigured()
+    {
+        String ldapUrl = getProperty( ConfigurationKey.KEY_LDAP_URL );
+        String dnPatterns = getProperty( ConfigurationKey.KEY_LDAP_DN_PATTERNS );
+        
+        return !( ConfigurationKey.KEY_LDAP_URL.getDefaultValue().equals( ldapUrl ) ||
+            ConfigurationKey.KEY_LDAP_DN_PATTERNS.getDefaultValue().equals( dnPatterns ) );
+    }
+}

=== added file 'dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/DhisConfigurationProvider.java'
--- dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/DhisConfigurationProvider.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/DhisConfigurationProvider.java	2015-10-27 14:11:44 +0000
@@ -0,0 +1,73 @@
+package org.hisp.dhis.external.conf;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 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.
+ * Neither the name of the HISP project 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 COPYRIGHT OWNER 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.
+ */
+
+import java.util.Properties;
+
+/**
+ * Interface which provides access to the DHIS 2 configuration specified through
+ * the dhis.config or hibernate.properties file.
+ * 
+ * @author Lars Helge Overland
+ */
+public interface DhisConfigurationProvider
+{
+    /**
+     * Get configuration as a set of properties.
+     * 
+     * @return a Properties instance.
+     */
+    Properties getProperties();
+    
+    /**
+     * Get the property value for the given key, or the default value for the
+     * configuration key if not exists.
+     * 
+     * @param key the configuration key.
+     * @return the property value.
+     */
+    String getProperty( ConfigurationKey key );
+
+    /**
+     * Get the property value for the given key, or the default value if not
+     * exists.
+     * 
+     * @param key the configuration key.
+     * @param defaultValue the default value.
+     * @return the property value.
+     */
+    String getPropertyOrDefault( ConfigurationKey key, String defaultValue );
+    
+    /**
+     * Indicates whether LDAP authentication is configured.
+     * 
+     * @return true if LDAP authentication is configured.
+     */
+    boolean isLdapConfigured();
+}

=== modified file 'dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/location/DefaultLocationManager.java'
--- dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/location/DefaultLocationManager.java	2015-10-01 13:14:27 +0000
+++ dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/location/DefaultLocationManager.java	2015-10-27 03:18:11 +0000
@@ -44,7 +44,6 @@
 
 /**
  * @author Lars Helge Overland
- * @version $Id$
  */
 public class DefaultLocationManager
     implements LocationManager

=== modified file 'dhis-2/dhis-support/dhis-support-external/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-support/dhis-support-external/src/main/resources/META-INF/dhis/beans.xml	2014-12-04 06:39:46 +0000
+++ dhis-2/dhis-support/dhis-support-external/src/main/resources/META-INF/dhis/beans.xml	2015-10-27 03:18:11 +0000
@@ -13,10 +13,13 @@
   <bean id="dhisResolver" class="org.hisp.dhis.external.location.DefaultLocationManagerResolver">
     <property name="locationManager" ref="locationManager" />
   </bean>
+  
+  <bean id="dhisConfigurationProvider" class="org.hisp.dhis.external.conf.DefaultDhisConfigurationProvider" init-method="init">
+    <property name="locationManager" ref="locationManager" />  
+  </bean>
 
   <bean id="locationManager" class="org.hisp.dhis.external.location.DefaultLocationManager" init-method="init">
     <property name="environmentVariable" value="DHIS2_HOME" />
-    <!-- Change environment variable -->
     <property name="systemProperty" value="dhis2.home" />
   </bean>
 

=== modified file 'dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/hibernate/ConnectionPropertyFactoryBean.java'
--- dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/hibernate/ConnectionPropertyFactoryBean.java	2015-02-19 09:18:17 +0000
+++ dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/hibernate/ConnectionPropertyFactoryBean.java	2015-10-27 03:18:11 +0000
@@ -33,7 +33,6 @@
 
 /**
  * @author Lars Helge Overland
- * @version $Id$
  */
 public class ConnectionPropertyFactoryBean
     implements FactoryBean<String>

=== modified file 'dhis-2/dhis-support/dhis-support-system/pom.xml'
--- dhis-2/dhis-support/dhis-support-system/pom.xml	2015-10-20 22:50:17 +0000
+++ dhis-2/dhis-support/dhis-support-system/pom.xml	2015-10-25 20:30:23 +0000
@@ -60,6 +60,10 @@
       <groupId>org.springframework</groupId>
       <artifactId>spring-jdbc</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.springframework.security</groupId>
+      <artifactId>spring-security-core</artifactId>
+    </dependency>
 
     <!-- Geotools -->
 

=== added file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/SecurityUtils.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/SecurityUtils.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/SecurityUtils.java	2015-10-25 20:30:23 +0000
@@ -0,0 +1,28 @@
+package org.hisp.dhis.system.util;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.hisp.dhis.user.UserAuthorityGroup;
+import org.hisp.dhis.user.UserCredentials;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+public class SecurityUtils
+{
+    public static Collection<GrantedAuthority> getGrantedAuthorities( UserCredentials credentials )
+    {
+        Set<GrantedAuthority> authorities = new HashSet<>();
+
+        for ( UserAuthorityGroup group : credentials.getUserAuthorityGroups() )
+        {
+            for ( String authority : group.getAuthorities() )
+            {
+                authorities.add( new SimpleGrantedAuthority( authority ) );
+            }
+        }
+
+        return authorities;
+    }
+}

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/DefaultAuthenticationSuccessHandler.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/DefaultAuthenticationSuccessHandler.java	2015-08-06 14:04:41 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/security/DefaultAuthenticationSuccessHandler.java	2015-10-27 03:18:11 +0000
@@ -41,6 +41,7 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.userdetails.User;
+import org.springframework.security.ldap.userdetails.LdapUserDetailsImpl;
 import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
 
 /**
@@ -69,7 +70,16 @@
     {
         HttpSession session = request.getSession();
         
-        String username = ((User)authentication.getPrincipal()).getUsername();
+        String username = null;
+        
+        if ( User.class.isAssignableFrom( authentication.getClass() ) )
+        {
+            username = ((User)authentication.getPrincipal()).getUsername();
+        }
+        else if ( LdapUserDetailsImpl.class.isAssignableFrom( authentication.getClass() ) )
+        {
+            username = ((LdapUserDetailsImpl)authentication.getPrincipal()).getUsername();
+        }        
 
         session.setAttribute( "userIs", username);
         session.setAttribute( LoginInterceptor.JLI_SESSION_VARIABLE, Boolean.TRUE );

=== modified file 'dhis-2/pom.xml'
--- dhis-2/pom.xml	2015-10-21 09:51:51 +0000
+++ dhis-2/pom.xml	2015-10-25 19:44:21 +0000
@@ -509,6 +509,11 @@
           </exclusion>
         </exclusions>
       </dependency>
+      <dependency>
+        <groupId>org.springframework.security</groupId>
+        <artifactId>spring-security-ldap</artifactId>
+        <version>${spring.security.version}</version>
+      </dependency>
 
       <!-- OAuth 2.0 -->
       <dependency>