diff --git a/src/main/scala/app/IndexController.scala b/src/main/scala/app/IndexController.scala index 2925e8c..1959463 100644 --- a/src/main/scala/app/IndexController.scala +++ b/src/main/scala/app/IndexController.scala @@ -59,6 +59,10 @@ session.setAttribute(Keys.Session.LoginAccount, account) updateLastLoginDate(account.userName) + if(AccountUtil.hasLdapDummyMailAddress(account)) { + redirect("/" + account.userName + "/_edit") + } + flash.get(Keys.Flash.Redirect).asInstanceOf[Option[String]].map { redirectUrl => if(redirectUrl.stripSuffix("/") == request.getContextPath){ redirect("/") diff --git a/src/main/scala/app/SystemSettingsController.scala b/src/main/scala/app/SystemSettingsController.scala index da30699..c5cf523 100644 --- a/src/main/scala/app/SystemSettingsController.scala +++ b/src/main/scala/app/SystemSettingsController.scala @@ -41,8 +41,9 @@ "bindPassword" -> trim(label("Bind Password", optional(text()))), "baseDN" -> trim(label("Base DN", text(required))), "userNameAttribute" -> trim(label("User name attribute", text(required))), + "additionalFilterCondition"-> trim(label("Additional filter condition", optional(text()))), "fullNameAttribute" -> trim(label("Full name attribute", optional(text()))), - "mailAttribute" -> trim(label("Mail address attribute", text(required))), + "mailAttribute" -> trim(label("Mail address attribute", optional(text()))), "tls" -> trim(label("Enable TLS", optional(boolean()))), "keystore" -> trim(label("Keystore", optional(text()))) )(Ldap.apply)) diff --git a/src/main/scala/service/AccountService.scala b/src/main/scala/service/AccountService.scala index 7472738..ad0d363 100644 --- a/src/main/scala/service/AccountService.scala +++ b/src/main/scala/service/AccountService.scala @@ -39,7 +39,11 @@ // Create or update account by LDAP information getAccountByUserName(ldapUserInfo.userName, true) match { case Some(x) if(!x.isRemoved) => { - updateAccount(x.copy(mailAddress = ldapUserInfo.mailAddress, fullName = ldapUserInfo.fullName)) + if(settings.ldap.get.mailAttribute.getOrElse("").isEmpty) { + updateAccount(x.copy(fullName = ldapUserInfo.fullName)) + } else { + updateAccount(x.copy(mailAddress = ldapUserInfo.mailAddress, fullName = ldapUserInfo.fullName)) + } getAccountByUserName(ldapUserInfo.userName) } case Some(x) if(x.isRemoved) => { diff --git a/src/main/scala/service/SystemSettingsService.scala b/src/main/scala/service/SystemSettingsService.scala index 42f3a75..2d8f1d3 100644 --- a/src/main/scala/service/SystemSettingsService.scala +++ b/src/main/scala/service/SystemSettingsService.scala @@ -37,8 +37,9 @@ ldap.bindPassword.foreach(x => props.setProperty(LdapBindPassword, x)) props.setProperty(LdapBaseDN, ldap.baseDN) props.setProperty(LdapUserNameAttribute, ldap.userNameAttribute) + ldap.additionalFilterCondition.foreach(x => props.setProperty(LdapAdditionalFilterCondition, x)) ldap.fullNameAttribute.foreach(x => props.setProperty(LdapFullNameAttribute, x)) - props.setProperty(LdapMailAddressAttribute, ldap.mailAttribute) + ldap.mailAttribute.foreach(x => props.setProperty(LdapMailAddressAttribute, x.toString)) ldap.tls.foreach(x => props.setProperty(LdapTls, x.toString)) ldap.keystore.foreach(x => props.setProperty(LdapKeystore, x)) } @@ -85,8 +86,9 @@ getOptionValue(props, LdapBindPassword, None), getValue(props, LdapBaseDN, ""), getValue(props, LdapUserNameAttribute, ""), + getOptionValue(props, LdapAdditionalFilterCondition, None), getOptionValue(props, LdapFullNameAttribute, None), - getValue(props, LdapMailAddressAttribute, ""), + getOptionValue(props, LdapMailAddressAttribute, None), getOptionValue[Boolean](props, LdapTls, None), getOptionValue(props, LdapKeystore, None))) } else { @@ -125,8 +127,9 @@ bindPassword: Option[String], baseDN: String, userNameAttribute: String, + additionalFilterCondition: Option[String], fullNameAttribute: Option[String], - mailAttribute: String, + mailAttribute: Option[String], tls: Option[Boolean], keystore: Option[String]) @@ -163,6 +166,7 @@ private val LdapBindPassword = "ldap.bind_password" private val LdapBaseDN = "ldap.baseDN" private val LdapUserNameAttribute = "ldap.username_attribute" + private val LdapAdditionalFilterCondition = "ldap.additional_filter_condition" private val LdapFullNameAttribute = "ldap.fullname_attribute" private val LdapMailAddressAttribute = "ldap.mail_attribute" private val LdapTls = "ldap.tls" diff --git a/src/main/scala/util/AccountUtil.scala b/src/main/scala/util/AccountUtil.scala new file mode 100644 index 0000000..e6da429 --- /dev/null +++ b/src/main/scala/util/AccountUtil.scala @@ -0,0 +1,18 @@ +package util + +import model.Account + +/** + * Utility for account model. + */ +object AccountUtil { + private val LDAP_DUMMY_MAL = "@ldap-devnull" + + def hasLdapDummyMailAddress(account: Account): Boolean = { + account.mailAddress.endsWith(LDAP_DUMMY_MAL) + } + + def getLdapDummyMailAddress(userName: String): String = { + userName + LDAP_DUMMY_MAL + } +} diff --git a/src/main/scala/util/LDAPUtil.scala b/src/main/scala/util/LDAPUtil.scala index d107b96..621fbd5 100644 --- a/src/main/scala/util/LDAPUtil.scala +++ b/src/main/scala/util/LDAPUtil.scala @@ -30,7 +30,7 @@ keystore = ldapSettings.keystore.getOrElse(""), error = "System LDAP authentication failed." ){ conn => - findUser(conn, userName, ldapSettings.baseDN, ldapSettings.userNameAttribute) match { + findUser(conn, userName, ldapSettings.baseDN, ldapSettings.userNameAttribute, ldapSettings.additionalFilterCondition) match { case Some(userDN) => userAuthentication(ldapSettings, userDN, userName, password) case None => Left("User does not exist.") } @@ -47,14 +47,23 @@ keystore = ldapSettings.keystore.getOrElse(""), error = "User LDAP Authentication Failed." ){ conn => - findMailAddress(conn, userDN, ldapSettings.userNameAttribute, userName, ldapSettings.mailAttribute) match { - case Some(mailAddress) => Right(LDAPUserInfo( - userName = getUserNameFromMailAddress(userName), + if(ldapSettings.mailAttribute.getOrElse("").isEmpty) { + Right(LDAPUserInfo( + userName = userName, fullName = ldapSettings.fullNameAttribute.flatMap { fullNameAttribute => findFullName(conn, userDN, ldapSettings.userNameAttribute, userName, fullNameAttribute) }.getOrElse(userName), - mailAddress = mailAddress)) - case None => Left("Can't find mail address.") + mailAddress = AccountUtil.getLdapDummyMailAddress(userName))) + } else { + findMailAddress(conn, userDN, ldapSettings.userNameAttribute, userName, ldapSettings.mailAttribute.get) match { + case Some(mailAddress) => Right(LDAPUserInfo( + userName = getUserNameFromMailAddress(userName), + fullName = ldapSettings.fullNameAttribute.flatMap { fullNameAttribute => + findFullName(conn, userDN, ldapSettings.userNameAttribute, userName, fullNameAttribute) + }.getOrElse(userName), + mailAddress = mailAddress)) + case None => Left("Can't find mail address.") + } } } } @@ -112,7 +121,7 @@ /** * Search a specified user and returns userDN if exists. */ - private def findUser(conn: LDAPConnection, userName: String, baseDN: String, userNameAttribute: String): Option[String] = { + private def findUser(conn: LDAPConnection, userName: String, baseDN: String, userNameAttribute: String, additionalFilterCondition: Option[String]): Option[String] = { @tailrec def getEntries(results: LDAPSearchResults, entries: List[Option[LDAPEntry]] = Nil): List[LDAPEntry] = { if(results.hasMore){ @@ -125,7 +134,13 @@ entries.flatten } } - getEntries(conn.search(baseDN, LDAPConnection.SCOPE_SUB, userNameAttribute + "=" + userName, null, false)).collectFirst { + + val filterCond = additionalFilterCondition.getOrElse("") match { + case "" => userNameAttribute + "=" + userName + case x => "(&(" + x + ")(" + userNameAttribute + "=" + userName + "))" + } + + getEntries(conn.search(baseDN, LDAPConnection.SCOPE_SUB, filterCond, null, false)).collectFirst { case x => x.getDN } } diff --git a/src/main/scala/util/Notifier.scala b/src/main/scala/util/Notifier.scala index e1bd50b..e218800 100644 --- a/src/main/scala/util/Notifier.scala +++ b/src/main/scala/util/Notifier.scala @@ -28,7 +28,7 @@ ) .distinct .withFilter ( _ != context.loginAccount.get.userName ) // the operation in person is excluded - .foreach ( getAccountByUserName(_) filterNot (_.isGroupAccount) foreach (x => notify(x.mailAddress)) ) + .foreach ( getAccountByUserName(_) filterNot (_.isGroupAccount) filterNot (AccountUtil.hasLdapDummyMailAddress(_)) foreach (x => notify(x.mailAddress)) ) } diff --git a/src/main/twirl/account/edit.scala.html b/src/main/twirl/account/edit.scala.html index d92c708..a441f09 100644 --- a/src/main/twirl/account/edit.scala.html +++ b/src/main/twirl/account/edit.scala.html @@ -1,6 +1,7 @@ @(account: model.Account, info: Option[Any])(implicit context: app.Context) @import context._ @import view.helpers._ +@import util.AccountUtil @html.main("Edit your profile"){