diff --git a/project/build.scala b/project/build.scala index 3b0cefb..c5cdd89 100644 --- a/project/build.scala +++ b/project/build.scala @@ -36,6 +36,7 @@ "org.pegdown" % "pegdown" % "1.3.0", "org.apache.commons" % "commons-compress" % "1.5", "com.typesafe.slick" %% "slick" % "1.0.1", + "com.novell.ldap" % "jldap" % "2009-10-07", "com.h2database" % "h2" % "1.3.171", "ch.qos.logback" % "logback-classic" % "1.0.6" % "runtime", "org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "container", diff --git a/src/main/scala/app/SystemSettingsController.scala b/src/main/scala/app/SystemSettingsController.scala index 0e824c4..60f3700 100644 --- a/src/main/scala/app/SystemSettingsController.scala +++ b/src/main/scala/app/SystemSettingsController.scala @@ -17,12 +17,20 @@ "gravatar" -> trim(label("Gravatar", boolean())), "notification" -> trim(label("Notification", boolean())), "smtp" -> optionalIfNotChecked("notification", mapping( - "host" -> trim(label("SMTP Host", text(required))), - "port" -> trim(label("SMTP Port", optional(number()))), - "user" -> trim(label("SMTP User", optional(text()))), - "password" -> trim(label("SMTP Password", optional(text()))), - "ssl" -> trim(label("Enable SSL", optional(boolean()))) - )(Smtp.apply)) + "host" -> trim(label("SMTP Host", text(required))), + "port" -> trim(label("SMTP Port", optional(number()))), + "user" -> trim(label("SMTP User", optional(text()))), + "password" -> trim(label("SMTP Password", optional(text()))), + "ssl" -> trim(label("Enable SSL", optional(boolean()))) + )(Smtp.apply)), + "authType" -> trim(label("Auth Type", text(required))), + "ldap" -> optional(_.get("authType") == Some("LDAP"), mapping( + "host" -> trim(label("LDAP host", text(required))), + "port" -> trim(label("LDAP port", number(required))), + "baseDN" -> trim(label("BaseDN", text(required))), + "userNameAttribute" -> trim(label("User name attribute", text(required))), + "mailAttribute" -> trim(label("Mail address attribute", text(required))) + )(Ldap.apply)) )(SystemSettings.apply) diff --git a/src/main/scala/service/SystemSettingsService.scala b/src/main/scala/service/SystemSettingsService.scala index 6837f70..d639526 100644 --- a/src/main/scala/service/SystemSettingsService.scala +++ b/src/main/scala/service/SystemSettingsService.scala @@ -19,6 +19,15 @@ smtp.ssl.foreach(x => props.setProperty(SmtpSsl, x.toString)) } } + if(settings.authType == "LDAP"){ + settings.ldap.map { ldap => + props.setProperty(LdapHost, ldap.host) + props.setProperty(LdapPort, ldap.port.toString) + props.setProperty(LdapBaseDN, ldap.baseDN) + props.setProperty(LdapUserNameAttribute, ldap.userNameAttribute) + props.setProperty(LdapMailAddressAttribute, ldap.mailAttribute) + } + } props.store(new java.io.FileOutputStream(GitBucketConf), null) } @@ -41,6 +50,17 @@ getOptionValue[Boolean](props, SmtpSsl, None))) } else { None + }, + getValue(props, AuthType, ""), + if(getValue(props, AuthType, "") == "LDAP"){ + Some(Ldap( + getValue(props, LdapHost, ""), + getValue(props, LdapPort, 389), + getValue(props, LdapBaseDN, ""), + getValue(props, LdapUserNameAttribute, "uid"), + getValue(props, LdapUserNameAttribute, "mail"))) + } else { + None } ) } @@ -54,8 +74,17 @@ allowAccountRegistration: Boolean, gravatar: Boolean, notification: Boolean, - smtp: Option[Smtp] - ) + smtp: Option[Smtp], + authType: String, + ldap: Option[Ldap]) + + case class Ldap( + host: String, + port: Int, + baseDN: String, + userNameAttribute: String, + mailAttribute: String) + case class Smtp( host: String, port: Option[Int], @@ -65,12 +94,18 @@ private val AllowAccountRegistration = "allow_account_registration" private val Gravatar = "gravatar" + private val AuthType = "auth_type" private val Notification = "notification" private val SmtpHost = "smtp.host" private val SmtpPort = "smtp.port" private val SmtpUser = "smtp.user" private val SmtpPassword = "smtp.password" private val SmtpSsl = "smtp.ssl" + private val LdapHost = "ldap.host" + private val LdapPort = "ldap.port" + private val LdapBaseDN = "ldap.baseDN" + private val LdapUserNameAttribute = "ldap.username_attribute" + private val LdapMailAddressAttribute = "ldap.mail_attribute" private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = { val value = props.getProperty(key) diff --git a/src/main/scala/util/LDAPUtil.scala b/src/main/scala/util/LDAPUtil.scala new file mode 100644 index 0000000..21454ef --- /dev/null +++ b/src/main/scala/util/LDAPUtil.scala @@ -0,0 +1,49 @@ +package util + +import service.SystemSettingsService.Ldap +import com.novell.ldap.LDAPConnection + +/** + * Utility for LDAP authentication. + */ +object LDAPUtil extends App { + + /** + * Try authentication by LDAP using given configuration. + * Returns Right(mailAddress) if authentication is successful, otherwise Left(errorMessage). + */ + def authenticate(ldapSettings: Ldap, userName: String, password: String): Either[String, String] = { + var conn: LDAPConnection = null + try { + conn = new LDAPConnection() + conn.connect(ldapSettings.host, ldapSettings.port) + val userDN = ldapSettings.userNameAttribute + "=" + userName + ",ou=Users," + ldapSettings.baseDN + conn.bind(3, userDN, password.getBytes) + if(conn.isBound){ + val results = conn.search(userDN, LDAPConnection.SCOPE_BASE, "", Array[String](ldapSettings.mailAttribute), false) + var mailAddress: String = null + while(results.hasMore){ + mailAddress = results.next.getAttribute(ldapSettings.mailAttribute).getStringValue + } + if(mailAddress != null){ + Right(mailAddress) + } else { + Left("Can't find mail address.") + } + } else { + Left("Authentication failed.") + } + } catch { + case ex: Exception => Left(ex.getMessage) + } finally { + if(conn != null){ + conn.disconnect() + } + } + } + +// val ldapSettings = Ldap("192.168.159.128", 389, "dc=unix-power,dc=net", "uid", "mail") +// +// println(authenticate(ldapSettings, "tanaka", "password")) + +} diff --git a/src/main/twirl/admin/system.scala.html b/src/main/twirl/admin/system.scala.html index 9d8c9b6..3e77d0e 100644 --- a/src/main/twirl/admin/system.scala.html +++ b/src/main/twirl/admin/system.scala.html @@ -8,6 +8,9 @@
System Settings
+ + +
+ + +
@@ -27,6 +33,63 @@ Gravatar
+ + + +
+ +
+ +
+
+ +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ + +
@@ -35,7 +98,7 @@ Send notifications
-
+
@@ -81,7 +144,12 @@ \ No newline at end of file