Commit fd5b6407 authored by Piotr Gawron's avatar Piotr Gawron
Browse files

user is automatically created when local user doesn't exist and authentication goes via ldap

parent 8d0dc7af
......@@ -221,7 +221,7 @@ public enum ConfigurationElementType {
ConfigurationElementTypeGroup.LDAP_CONFIGURATION), //
LDAP_EMAIL_ATTRIBUTE("LDAP email attribute", "mail", ConfigurationElementEditType.STRING, true,
ConfigurationElementTypeGroup.LDAP_CONFIGURATION),//
LDAP_FILTER("LDAP filter ", "(memberof=cn=gitlab,cn=groups,cn=accounts,dc=uni,dc=lu)", ConfigurationElementEditType.STRING, true,
LDAP_FILTER("LDAP filter ", "(memberof=cn=minerva,cn=groups,cn=accounts,dc=uni,dc=lu)", ConfigurationElementEditType.STRING, true,
ConfigurationElementTypeGroup.LDAP_CONFIGURATION), //
;
......
......@@ -118,8 +118,13 @@ public class User implements Serializable {
*/
private boolean removed = false;
@Column(name="terms_of_use_consent")
private boolean termsOfUseConsent = false;
/**
* User is connected to LDAP directory.
*/
private boolean connectedToLdap = false;
@Column(name = "terms_of_use_consent")
private boolean termsOfUseConsent = false;
/**
* Set of user privileges.
......@@ -378,4 +383,12 @@ public class User implements Serializable {
this.termsOfUseConsent = termsOfUseConsent;
}
public boolean isConnectedToLdap() {
return connectedToLdap;
}
public void setConnectedToLdap(boolean connectedToLdap) {
this.connectedToLdap = connectedToLdap;
}
}
-- user account can be connected to LDAP directory
alter table user_table add column connectedtoldap boolean default false;
......@@ -2,9 +2,6 @@ package lcsb.mapviewer.persist.dao.user;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import lcsb.mapviewer.model.user.User;
import lcsb.mapviewer.persist.dao.BaseDao;
......@@ -16,102 +13,80 @@ import lcsb.mapviewer.persist.dao.BaseDao;
*/
public class UserDao extends BaseDao<User> {
/**
* Service that provides password encoding.
*/
@Autowired
private PasswordEncoder passwordEncoder;
/**
* Default constructor.
*/
public UserDao() {
super(User.class, "removed");
}
/**
* Returns user with a given login and password.
*
* @param login
* user login
* @param password
* - user password (plain text)
* @return user for given login and password
*/
public User getUserByLoginAndPassword(String login, String password) {
if (password == null) {
return getUserByLoginAndCryptedPassword(login, null);
}
return getUserByLoginAndCryptedPassword(login, passwordEncoder.encode(password));
}
/**
* Default constructor.
*/
public UserDao() {
super(User.class, "removed");
}
/**
* Returns user with a given login and password.
*
* @param login
* user login
* @param password
* - user password (encrypted)
* @return user for given login and password
*/
public User getUserByLoginAndCryptedPassword(String login, String password) {
List<?> list = getSession()
.createQuery(" from User where login=:login and cryptedPassword =:passwd " + removableAndStatemant()).setParameter("login", login)
.setParameter("passwd", password).list();
if (list.size() == 0) {
return null;
} else {
User user = (User) list.get(0);
return user;
}
}
/**
* Returns user with a given login and password.
*
* @param login
* user login
* @param password
* - user password (encrypted)
* @return user for given login and password
*/
public User getUserByLoginAndCryptedPassword(String login, String password) {
List<?> list = getSession()
.createQuery(" from User where login=:login and cryptedPassword =:passwd " + removableAndStatemant())
.setParameter("login", login).setParameter("passwd", password).list();
if (list.size() == 0) {
return null;
} else {
User user = (User) list.get(0);
return user;
}
}
/**
* Returns user with a given login.
*
* @param login
* user login
* @return user for a given login
*/
public User getUserByLogin(String login) {
return getByParameter("login", login);
}
/**
* Returns user with a given login.
*
* @param login
* user login
* @return user for a given login
*/
public User getUserByLogin(String login) {
return getByParameter("login", login);
}
/**
* Returns user with a given email.
*
* @param email
* user email
* @return user for a given email
*/
public User getUserByEmail(String email) {
return getByParameter("email", email);
}
/**
* Returns user with a given email.
*
* @param email
* user email
* @return user for a given email
*/
public User getUserByEmail(String email) {
return getByParameter("email", email);
}
@Override
public void delete(User object) {
object.setRemoved(true);
object.setLogin("[REMOVED]_" + object.getId() + "_" + object.getLogin());
update(object);
}
@Override
public void delete(User object) {
object.setRemoved(true);
object.setLogin("[REMOVED]_" + object.getId() + "_" + object.getLogin());
update(object);
}
/**
* Returns {@link User} for given "name surname" string.
*
* @param nameSurnameString
* string identifing user with name and surname separated by single
* space
* @return {@link User} for given "name surname" string
*/
public User getUserByNameSurname(String nameSurnameString) {
List<?> list = getSession()
.createQuery(" from " + this.getClazz().getSimpleName() + " where concat(name, ' ', surname) " + " = :param_val " + removableAndStatemant())
.setParameter("param_val", nameSurnameString).list();
if (list.size() == 0) {
return null;
} else {
return (User) list.get(0);
}
}
/**
* Returns {@link User} for given "name surname" string.
*
* @param nameSurnameString
* string identifing user with name and surname separated by single
* space
* @return {@link User} for given "name surname" string
*/
public User getUserByNameSurname(String nameSurnameString) {
List<?> list = getSession().createQuery(" from " + this.getClazz().getSimpleName()
+ " where concat(name, ' ', surname) " + " = :param_val " + removableAndStatemant())
.setParameter("param_val", nameSurnameString).list();
if (list.size() == 0) {
return null;
} else {
return (User) list.get(0);
}
}
}
......@@ -122,49 +122,6 @@ public class UserDaoTest extends PersistTestFunctions {
}
}
@Test
public void testGetUserByLoginAndPassword() throws Exception {
try {
User user = new User();
user.setCryptedPassword(passwordEncoder.encode(testPasswd));
user.setLogin(testLogin);
userDao.add(user);
User user2 = userDao.getUserByLoginAndPassword(testLogin, testPasswd);
assertNotNull(user2);
assertEquals(user2.getId(), user.getId());
assertEquals(user2.getLogin(), user.getLogin());
assertEquals(user2.getCryptedPassword(), user.getCryptedPassword());
userDao.delete(user);
// after we remove it we shouldn't be able to get it
User user3 = userDao.getUserByLoginAndPassword(testLogin, testPasswd);
assertNull(user3);
// after we remove it we shouldn't be able to get the removed and modified
// object
User user4 = userDao.getUserByLoginAndPassword(user2.getLogin(), testPasswd);
assertNull(user4);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testGetUserByLoginAndEmptyPassword() throws Exception {
try {
User user = new User();
user.setCryptedPassword(passwordEncoder.encode(testPasswd));
user.setLogin(testLogin);
userDao.add(user);
User user2 = userDao.getUserByLoginAndPassword(testLogin, null);
assertNull(user2);
userDao.delete(user);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testGetUserByLogin() throws Exception {
try {
......
......@@ -78,7 +78,7 @@ public class LdapService implements ILdapService {
@Override
public boolean login(String login, String password) throws LDAPException {
if (!isValidConfiguratio()) {
if (!isValidConfiguration()) {
logger.warn("Invalid LDAP configuration");
return false;
}
......@@ -98,7 +98,7 @@ public class LdapService implements ILdapService {
@Override
public List<String> getUsernames() throws LDAPException {
if (!isValidConfiguratio()) {
if (!isValidConfiguration()) {
logger.warn("Invalid LDAP configuration");
return new ArrayList<>();
}
......@@ -128,7 +128,7 @@ public class LdapService implements ILdapService {
@Override
public UserDTO getUserByLogin(String login) throws LDAPException {
if (!isValidConfiguratio()) {
if (!isValidConfiguration()) {
logger.warn("Invalid LDAP configuration");
return null;
}
......@@ -187,11 +187,11 @@ public class LdapService implements ILdapService {
}
}
private Filter createObjectClassFilter() {
private Filter createObjectClassFilter() throws LDAPException {
String objectClass = configurationService.getConfigurationValue(ConfigurationElementType.LDAP_OBJECT_CLASS);
if (objectClass == null || objectClass.trim().isEmpty()) {
objectClass = "*";
if (objectClass == null || objectClass.trim().isEmpty() || objectClass .equals( "*")) {
return Filter.create("objectClass=*");
}
return Filter.createEqualityFilter("objectClass", objectClass);
......@@ -220,7 +220,7 @@ public class LdapService implements ILdapService {
}
@Override
public boolean isValidConfiguratio() {
public boolean isValidConfiguration() {
try {
String baseDn = configurationService.getConfigurationValue(ConfigurationElementType.LDAP_BASE_DN);
if (baseDn == null || baseDn.trim().isEmpty()) {
......
......@@ -5,7 +5,6 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
......@@ -60,7 +59,6 @@ import lcsb.mapviewer.converter.zip.ZipEntryFile;
import lcsb.mapviewer.model.Project;
import lcsb.mapviewer.model.ProjectStatus;
import lcsb.mapviewer.model.cache.UploadedFileEntry;
import lcsb.mapviewer.model.graphics.MapCanvasType;
import lcsb.mapviewer.model.log.LogType;
import lcsb.mapviewer.model.map.BioEntity;
import lcsb.mapviewer.model.map.MiriamData;
......@@ -477,20 +475,7 @@ public class ProjectService implements IProjectService {
for (User user : userDao.getAll()) {
if (!processedUser.contains(user)) {
processedUser.add(user);
for (PrivilegeType type : PrivilegeType.values()) {
if (Project.class.equals(type.getPrivilegeObjectType())) {
int level = userService.getUserPrivilegeLevel(user, type, (Integer) null);
if (level < 0) {
if (configurationService.getValue(type).getValue().equalsIgnoreCase("true")) {
level = 1;
} else {
level = 0;
}
}
ObjectPrivilege privilege = new ObjectPrivilege(project, level, type, user);
userService.setUserPrivilege(user, privilege);
}
}
userService.createDefaultProjectPrivilegesForUser(project, user);
}
}
......
......@@ -56,6 +56,6 @@ public interface ILdapService {
* @return true if LDAP configuration
* ({@link ConfigurationElementTypeGroup#LDAP_CONFIGURATION}) is valid
*/
boolean isValidConfiguratio();
boolean isValidConfiguration();
}
......@@ -3,6 +3,7 @@ package lcsb.mapviewer.services.interfaces;
import java.util.List;
import lcsb.mapviewer.commands.ColorExtractor;
import lcsb.mapviewer.model.Project;
import lcsb.mapviewer.model.user.BasicPrivilege;
import lcsb.mapviewer.model.user.PrivilegeType;
import lcsb.mapviewer.model.user.User;
......@@ -198,4 +199,10 @@ public interface IUserService {
String login(String login, String password, String id);
ILdapService getLdapService();
void setLdapService(ILdapService ldapService);
void createDefaultProjectPrivilegesForUser(Project project, User user);
}
......@@ -6,13 +6,14 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({ CommentServiceTest.class, //
ConfigurationServiceTest.class, //
ExternalServicesServiceTest.class, //
LayoutServiceTest.class, //
Md5PasswordEncoderTest.class, //
ProjectServiceTest.class, //
SearchServiceTest.class, //
UserServiceTest.class,//
ConfigurationServiceTest.class, //
ExternalServicesServiceTest.class, //
LayoutServiceTest.class, //
LdapServiceTest.class, //
Md5PasswordEncoderTest.class, //
ProjectServiceTest.class, //
SearchServiceTest.class, //
UserServiceTest.class,//
})
public class AllImplServiceTests {
......
......@@ -69,9 +69,9 @@ public class LdapServiceTest extends ServiceTestFunctions {
@Test
public void testIsValidConfiguration() throws Exception {
try {
assertTrue(ldapService.isValidConfiguratio());
assertTrue(ldapService.isValidConfiguration());
configurationService.setConfigurationValue(ConfigurationElementType.LDAP_BASE_DN, "");
assertFalse(ldapService.isValidConfiguratio());
assertFalse(ldapService.isValidConfiguration());
} catch (Exception e) {
e.printStackTrace();
throw e;
......
......@@ -11,14 +11,24 @@ import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.test.annotation.Rollback;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.sdk.LDAPConnection;
import com.unboundid.ldap.sdk.LDAPException;
import lcsb.mapviewer.model.Project;
import lcsb.mapviewer.model.user.BasicPrivilege;
import lcsb.mapviewer.model.user.ConfigurationElementType;
import lcsb.mapviewer.model.user.ObjectPrivilege;
import lcsb.mapviewer.model.user.PrivilegeType;
import lcsb.mapviewer.model.user.User;
import lcsb.mapviewer.services.ServiceTestFunctions;
import lcsb.mapviewer.services.interfaces.ILdapService;
@Rollback(true)
public class UserServiceTest extends ServiceTestFunctions {
......@@ -46,6 +56,58 @@ public class UserServiceTest extends ServiceTestFunctions {
}
}
@Test
public void testLoginFromLdap() throws Exception {
ILdapService originalLdapService = userService.getLdapService();
try {
String login = "john.doe.test";
String passwd = "test_passwd";
assertNull(userService.getUserByLogin(login));
LdapService ldapService = createMockLdapService("testFiles/ldap/john-doe-test-example.ldif", login, passwd);
userService.setLdapService(ldapService);
assertNull(userService.login(login, "incorrect password"));
assertNotNull("User from LDAP wasn't authenticated", userService.login(login, passwd));
User user = userService.getUserByLogin(login);
assertNotNull("After authentication from LDAP user is not present in the system", user);
assertTrue(user.isConnectedToLdap());
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
userService.setLdapService(originalLdapService);
}
}
private LdapService createMockLdapService(String filename, String login, String passwd) throws LDAPException {
configurationService.setConfigurationValue(ConfigurationElementType.LDAP_BASE_DN, "dc=uni,dc=lu");
configurationService.setConfigurationValue(ConfigurationElementType.LDAP_OBJECT_CLASS, "person");
LdapService ldapService = Mockito.spy(LdapService.class);
ldapService.setConfigurationService(configurationService);
Mockito.when(ldapService.getConnection()).thenAnswer(new Answer<LDAPConnection>() {
@Override
public LDAPConnection answer(InvocationOnMock invocation) throws Throwable {
// Create the configuration to use for the server.
InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=uni,dc=lu");
config.addAdditionalBindCredentials("uid=" + login + ",cn=users,cn=accounts,dc=uni,dc=lu", passwd);
config.setSchema(null);
// Create the directory server instance, populate it with data from the
// "test-data.ldif" file, and start listening for client connections.
InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
ds.importFromLDIF(true, filename);
ds.startListening();
return ds.getConnection();
}
});
return ldapService;
}
@Test
public void testLoginWithNull() {
try {
......
version: 1
dn: dc=uni,dc=lu
objectClass: top
objectClass: domain
dc: uni
dn: cn=accounts,dc=uni,dc=lu
objectClass: extensibleObject
cn: accounts
dn: cn=users,cn=accounts,dc=uni,dc=lu
objectClass: extensibleObject
cn: users
dn: uid=john.doe.test,cn=users,cn=accounts,dc=uni,dc=lu
objectClass: mepOriginEntry
objectClass: ipaSshGroupOfPubKeys
objectClass: posixaccount
objectClass: inetuser
objectClass: krbprincipalaux
objectClass: krbticketpolicyaux
objectClass: organizationalperson
objectClass: inetorgperson
objectClass: ipasshuser
objectClass: top
objectClass: person
objectClass: ipaobject
cn: John Doe
gidNumber: 369550501
homeDirectory: /home/john.doe.test
ipaUniqueID: adf723e6-20e4-11e5-8907-001a4ae51219
sn: Doe
uid: john.doe.test
uidNumber: 369550501
displayName: John Doe
gecos: John Doe
givenName: John
initials: JD
krbLastPwdChange: 20180608111630Z
krbPasswordExpiration: 20190223111630Z
krbPrincipalName: john.doe.test@UNI.LU
loginShell: /bin/bash
mail: john.doe.test@uni.lu
memberOf: cn=lcsb,cn=groups,cn=accounts,dc=uni,dc=lu
memberOf: ipaUniqueID=d7549fa2-03a2-11e5-95f9-00163e0a4f7b,cn=hbac,dc=uni,dc
=lu
memberOf: ipaUniqueID=eff7677e-03a2-11e5-add5-00163e0a4f7b,cn=sudorules,cn=s
udo,dc=uni,dc=lu
memberOf: ipaUniqueID=f10ec0f6-7ef6-11e5-957b-001a4ae5121e,cn=hbac,dc=uni,dc
=lu
memberOf: ipaUniqueID=2cf9b59e-7ef7-11e5-89c0-001a4ae5121e,cn=sudorules,cn=s
udo,dc=uni,dc=lu
memberOf: ipaUniqueID=eeb5f68e-9775-11e5-81fb-00163e0a4f7b,cn=hbac,dc=uni,dc
=lu
memberOf: ipaUniqueID=176f7fb4-9776-11e5-a097-00163e0a4f7b,cn=sudorules,cn=s
udo,dc=uni,dc=lu
memberOf: ipaUniqueID=7dda82ae-99e1-11e5-834b-001a4ae5121e,cn=hbac,dc=uni,dc
=lu
memberOf: ipaUniqueID=a44d842c-99e1-11e5-9c2f-001a4ae5121e,cn=sudorules,cn=s
udo,dc=uni,dc=lu
memberOf: cn=webdav-public-minerva,cn=groups,cn=accounts,dc=uni,dc=lu
memberOf: ipaUniqueID=1d1f58b8-a247-11e5-ac5d-00163e0a4f7b,cn=hbac,dc=uni,dc
=lu
memberOf: ipaUniqueID=41f879a8-a247-11e5-9d34-00163e0a4f7b,cn=sudorules,cn=s
udo,dc=uni,dc=lu
memberOf: ipaUniqueID=33e9e6a2-c8d1-11e5-b578-001a4ae5121e,cn=hbac,dc=uni,dc
=lu
memberOf: ipaUniqueID=572fea30-c8d1-11e5-b770-001a4ae5121e,cn=sudorules,cn=s
udo,dc=uni,dc=lu