package models.services; import models.enums.AccountRole; import org.apache.directory.api.ldap.model.cursor.CursorException; import org.apache.directory.api.ldap.model.cursor.EntryCursor; import org.apache.directory.api.ldap.model.entry.Entry; import org.apache.directory.api.ldap.model.exception.LdapException; import org.apache.directory.api.ldap.model.message.SearchScope; import org.apache.directory.ldap.client.api.LdapConnectionConfig; import org.apache.directory.ldap.client.api.LdapNetworkConnection; import org.apache.directory.ldap.client.api.exception.InvalidConnectionException; import play.Configuration; import play.Logger; import play.api.i18n.Lang; import play.i18n.MessagesApi; import javax.inject.Inject; import javax.inject.Singleton; import java.io.IOException; /** * LDAP service to establish LDAP connection and request user account data from directory. */ @Singleton public class LdapService { private Configuration configuration; private MessagesApi messagesApi; @Inject public LdapService(Configuration configuration, MessagesApi messagesApi) { this.messagesApi = messagesApi; this.configuration = configuration; this.ldapServer = configuration.getString("ldap.server"); this.ldapPort = Integer.parseInt(configuration.getString("ldap.port")); this.ldapStartTls = Boolean.parseBoolean(configuration.getString("ldap.startTls")); } /** * First name */ private String firstName = null; /** * Last name */ private String lastName = null; /** * Account role */ private AccountRole role = null; /** * LDAP server host */ String ldapServer = null; /** * LDAP port */ int ldapPort; /** * If true, Start TLS is used for LDAP connection */ boolean ldapStartTls; /** * Getter for first name. * * @return First name */ public String getFirstName() { return firstName; } /** * Getter for last name. * * @return Last name */ public String getLastName() { return lastName; } /** * Getter for account role. * * @return Account role */ public AccountRole getRole() { return role; } /** * Connects to the LDAP ldapServer. If successful connected, the user is searched. If found, the user * data is read and set into firstName and lastName. * * @param userName User * @param password Password * @throws LdapConnectorException */ public void connect(String userName, String password) throws LdapConnectorException { // connection and search related parameters String userRoot = configuration.getString("ldap.userRoot"); String groupRoot = configuration.getString("ldap.groupRoot"); String connectionBind = configuration.getString("ldap.connectionBind") .replace("%USER%", userName) .replace("%USER_ROOT%", userRoot); String userSearch = configuration.getString("ldap.userSearch") .replace("%USER%", userName); String groupSearch = configuration.getString("ldap.groupSearch") .replace("%BIND%", connectionBind); // LDAP keys for values from LDAP ldapServer String userFirstName = configuration.getString("ldap.serverValues.firstName"); String userLastName = configuration.getString("ldap.serverValues.lastName"); String groupName = configuration.getString("ldap.serverValues.groupName"); String studentRole = configuration.getString("ldap.serverValues.studentRole"); String profRole = configuration.getString("ldap.serverValues.profRole"); String tutorRole = configuration.getString("ldap.serverValues.tutorRole"); LdapNetworkConnection ldapConnection; // try to connect to the LDAP ldapServer try { LdapConnectionConfig connectionConfig = new LdapConnectionConfig(); connectionConfig.setLdapHost(this.ldapServer); connectionConfig.setLdapPort(this.ldapPort); connectionConfig.setUseTls(this.ldapStartTls); connectionConfig.setCredentials(password); connectionConfig.setName(connectionBind); ldapConnection = new LdapNetworkConnection(connectionConfig); ldapConnection.bind(); } catch (InvalidConnectionException e) { e.printStackTrace(); throw new LdapConnectorException(messagesApi.get(Lang.defaultLang(), "ldap.noConnection")); } catch (LdapException e) { e.printStackTrace(); throw new LdapConnectorException(messagesApi.get(Lang.defaultLang(), "ldap.wrongCredentials")); } // login to LDAP successful, try to find the user data EntryCursor entCursor; try { entCursor = ldapConnection.search(userRoot, userSearch, SearchScope.ONELEVEL, "*"); entCursor.next(); Entry entry = entCursor.get(); this.firstName = entry.get(userFirstName).getString(); this.lastName = entry.get(userLastName).getString(); } catch (LdapException | CursorException e) { e.printStackTrace(); throw new LdapConnectorException(messagesApi.get(Lang.defaultLang(), "ldap.wrongCredentials")); } // user data successfully set, try to find the role of the user try { entCursor = ldapConnection.search(groupRoot, groupSearch, SearchScope.ONELEVEL, "*"); String role; while (entCursor.next()) { Entry entry = entCursor.get(); role = entry.get(groupName).getString(); if (role.equals(studentRole)) { this.role = AccountRole.STUDENT; } if (role.equals(profRole) || role.equals(tutorRole)) { this.role = AccountRole.TUTOR; } } } catch (LdapException | CursorException e) { e.printStackTrace(); throw new LdapConnectorException(messagesApi.get(Lang.defaultLang(), "ldap.wrongCredentials")); } // close the connection try { ldapConnection.close(); } catch (IOException e) { e.printStackTrace(); } } /** * Exception class for exceptions thrown in LdapConnector. */ public class LdapConnectorException extends Exception{ public LdapConnectorException(String message) { super(message); } private static final long serialVersionUID = 1L; } }