You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@esme.apache.org by le...@apache.org on 2011/04/24 02:02:42 UTC

svn commit: r1096261 - in /esme/trunk/server/src/main: resources/props/default.props scala/bootstrap/liftweb/Boot.scala scala/org/apache/esme/model/UserAuth.scala

Author: lester
Date: Sun Apr 24 00:02:42 2011
New Revision: 1096261

URL: http://svn.apache.org/viewvc?rev=1096261&view=rev
Log:
Completed ESME-135: Add LDAP to ESME

Modified:
    esme/trunk/server/src/main/resources/props/default.props
    esme/trunk/server/src/main/scala/bootstrap/liftweb/Boot.scala
    esme/trunk/server/src/main/scala/org/apache/esme/model/UserAuth.scala

Modified: esme/trunk/server/src/main/resources/props/default.props
URL: http://svn.apache.org/viewvc/esme/trunk/server/src/main/resources/props/default.props?rev=1096261&r1=1096260&r2=1096261&view=diff
==============================================================================
--- esme/trunk/server/src/main/resources/props/default.props (original)
+++ esme/trunk/server/src/main/resources/props/default.props Sun Apr 24 00:02:42 2011
@@ -51,4 +51,6 @@ ldap.server.initial_context_factory=com.
 ;Prefix for user to whom additional LDAP attributes belong, for example 'uid' or 'sAMAccountName'
 ldap.uidPrefix=uid
 ;User base DN for user to whom additional LDAP attributes belong
-ldap.userBase=ou=Users,ou=esme,dc=lester,dc=org
\ No newline at end of file
+ldap.userBase=ou=Users,ou=esme,dc=lester,dc=org
+;Group base DN to check whether user has specific role
+ldap.groupBase=ou=Groups,ou=esme,dc=lester,dc=org

Modified: esme/trunk/server/src/main/scala/bootstrap/liftweb/Boot.scala
URL: http://svn.apache.org/viewvc/esme/trunk/server/src/main/scala/bootstrap/liftweb/Boot.scala?rev=1096261&r1=1096260&r2=1096261&view=diff
==============================================================================
--- esme/trunk/server/src/main/scala/bootstrap/liftweb/Boot.scala (original)
+++ esme/trunk/server/src/main/scala/bootstrap/liftweb/Boot.scala Sun Apr 24 00:02:42 2011
@@ -166,6 +166,7 @@ class Boot extends Loggable {
     UserAuth.register(UserPwdAuthModule)
     UserAuth.register(OpenIDAuthModule)  
     UserAuth.register(ContainerManagedAuthModule)
+    UserAuth.register(LDAPAuthModule)
 
     def ifIsLoggedIn = If(User.loggedIn_? _, strFuncToFailMsg(() => S.?("base_error_not_logged_in")))
 

Modified: esme/trunk/server/src/main/scala/org/apache/esme/model/UserAuth.scala
URL: http://svn.apache.org/viewvc/esme/trunk/server/src/main/scala/org/apache/esme/model/UserAuth.scala?rev=1096261&r1=1096260&r2=1096261&view=diff
==============================================================================
--- esme/trunk/server/src/main/scala/org/apache/esme/model/UserAuth.scala (original)
+++ esme/trunk/server/src/main/scala/org/apache/esme/model/UserAuth.scala Sun Apr 24 00:02:42 2011
@@ -20,6 +20,7 @@
 package org.apache.esme.model
 
 import net.liftweb._
+import common.Logger._
 import mapper._
 import openid._
 import util._
@@ -274,28 +275,29 @@ object OpenIDAuthModule extends AuthModu
   } yield user
 }
 
+trait LDAPBase {
 
-object ContainerManagedAuthModule extends AuthModule {
+  this : AuthModule =>
 
   object myLdapVendor extends LDAPVendor
 
   def myLdap : LDAPVendor = {
     val ldapSrvHost = Props.get("ldap.server.host") openOr ""
-    info("LDAP server host: %s".format(ldapSrvHost))
+    debug("LDAP server host: %s".format(ldapSrvHost))
     val ldapSrvPort = Props.get("ldap.server.port") openOr ""
-    info("LDAP server port: %s".format(ldapSrvPort))
+    debug("LDAP server port: %s".format(ldapSrvPort))
     val ldapSrvBase = Props.get("ldap.server.base") openOr ""
-    info("LDAP server base: %s".format(ldapSrvBase))
+    debug("LDAP server base: %s".format(ldapSrvBase))
     val ldapSrvUsrName = Props.get("ldap.server.userName") openOr ""
-    info("LDAP server username: %s".format(ldapSrvUsrName))
+    debug("LDAP server username: %s".format(ldapSrvUsrName))
     val ldapSrvPwd = Props.get("ldap.server.password") openOr ""
-    info("LDAP server password: %s".format(ldapSrvPwd))
+    debug("LDAP server password: %s".format(ldapSrvPwd))
     val ldapSrvAuthType = Props.get("ldap.server.authType") openOr ""
-    info("LDAP server authentication type: %s".format(ldapSrvAuthType))
+    debug("LDAP server authentication type: %s".format(ldapSrvAuthType))
     val ldapSrvReferral= Props.get("ldap.server.referral") openOr ""
-    info("LDAP server referral: %s".format(ldapSrvReferral))
+    debug("LDAP server referral: %s".format(ldapSrvReferral))
     val ldapSrvCtxFactory = Props.get("ldap.server.initial_context_factory") openOr ""
-    info("LDAP server initial context factory class: %s".format(ldapSrvCtxFactory))
+    debug("LDAP server initial context factory class: %s".format(ldapSrvCtxFactory))
 
 
     myLdapVendor.configure(Map("ldap.url" -> "ldap://%s:%s".format(ldapSrvHost, ldapSrvPort),
@@ -308,15 +310,8 @@ object ContainerManagedAuthModule extend
     myLdapVendor
   }
 
-  def getAttrs(who : String) : Map[String, List[String]] = {
-    val uidPrefix = Props.get("ldap.uidPrefix") openOr ""
-    info("LDAP uid prefix: %s".format(uidPrefix))
-    val userBase = Props.get("ldap.userBase") openOr ""
-    info("LDAP user base: %s".format(userBase))
-
+  def getAttrs(dn : String) : Map[String, List[String]] = {
     var attrsMap = Map.empty[String, List[String]]
-    val dn = "%s=%s,%s".format(uidPrefix, who, userBase)
-    info("Distinguished name: %s".format(dn))
     val attrs : Attributes = myLdap.attributesFromDn(dn)
     if (attrs != null) {
       val allAttrs = attrs.getAll();
@@ -336,6 +331,31 @@ object ContainerManagedAuthModule extend
     attrsMap
   }
 
+  def constructDistinguishedName(who : String, isGroup : Boolean = false) = {
+    val base = Props.get( if(isGroup) {"ldap.groupBase"} else {"ldap.userBase"} )  openOr ""
+     debug("LDAP base: %s".format(base))
+
+     val dn = "%s,%s".format(constructNameWithPrefix(who, isGroup), base)
+     debug("Distinguished name: %s".format(dn))
+     dn
+  }
+
+  def constructNameWithPrefix(username: String, isGroup: Boolean = false) = {
+    val prefix = if(isGroup) {"cn"} else {Props.get("ldap.uidPrefix") openOr ""}
+    val nameWithPrefix = "%s=%s".format(prefix, username)
+    debug("Name with prefix: '%s'".format(nameWithPrefix))
+    nameWithPrefix
+  }
+
+  def logInUser(who: User) {
+    User.logUserIn(who)
+    //TODO: save role for user
+    S.notice(S.?("base_user_msg_welcome", who.niceName))
+  }
+}
+
+object ContainerManagedAuthModule extends AuthModule with LDAPBase {
+
   // It's possible to get roles list from some external source
   // for example from LDAP via Lift API
   val rolesToCheck = List(
@@ -363,9 +383,9 @@ object ContainerManagedAuthModule extend
             debug("Username: '%s'".format(username))
             if(username!=null){
               val currentRoles = rolesToCheck.filter(hsr.isUserInRole(_))
-              info("User from HTTP Request: %s has following roles=%s".format(username, currentRoles))
+              debug("User from HTTP Request: %s has following roles=%s".format(username, currentRoles))
               if(currentRoles.size == 0) {
-                info("No roles have been found")
+                debug("No roles have been found")
                 S.error(S.?("base_user_err_unknown_creds"))
               } else {
                 currentRoles.map(cr => {
@@ -375,7 +395,7 @@ object ContainerManagedAuthModule extend
                     User.find(By(User.nickname, username))
                   } yield user) match {
                     case Full(user) => {
-                      info("User: '%s' has been found".format(user.niceName))
+                      debug("User: '%s' has been found".format(user.niceName))
                       logInUser(user)
                     }
                     case _ => {
@@ -383,11 +403,11 @@ object ContainerManagedAuthModule extend
                       //find and save additional attributes in LDAP if it's enabled
                       val ldapEnabled = Props.getBool("ldap.enabled") openOr false
                       if(ldapEnabled) {
-                        val ldapAttrs = getAttrs(username)
+                        val ldapAttrs = getAttrs(constructDistinguishedName(username))
                         val firstName = ldapAttrs("givenName").head
                         val lastName = ldapAttrs("sn").head
                         val mail = ldapAttrs("mail").head
-                        info("Attributes from LDAP for user '%s'. Firstname: '%s', lastname: '%s', email: '%s'".format(username, firstName, lastName, mail))
+                        debug("Attributes from LDAP for user '%s'. Firstname: '%s', lastname: '%s', email: '%s'".format(username, firstName, lastName, mail))
                         usr.firstName(firstName).lastName(lastName).save
                       }
                       UserAuth.create.authType(moduleName).user(usr).authKey(username).save
@@ -424,6 +444,77 @@ object ContainerManagedAuthModule extend
   }
 }
 
+object LDAPAuthModule extends AuthModule with LDAPBase {
+
+  // It's possible to get roles list from some external source
+  // for example from LDAP via Lift API
+  val rolesToCheck = List(
+    "esme-users"
+  )
+
+  override def isDefault = false
+
+  def loginPresentation: Box[NodeSeq] = TemplateFinder.findAnyTemplate("templates-hidden" :: "ldap_login_form" :: Nil)
+
+  def moduleName: String = "ldap"
+
+  def performInit(): Unit = {
+    LiftRules.dispatch.append {
+      case Req("ldap" :: "login" :: Nil, _, PostRequest) =>
+        val from = S.referer openOr "/"
+
+      val ldapEnabled = Props.getBool("ldap.enabled") openOr false
+      if(ldapEnabled) {
+        val name = S.param("username").map(_.trim.toLowerCase) openOr ""
+        val pwd = S.param("password").map(_.trim) openOr ""
+        if(myLdap.bindUser(constructNameWithPrefix(name), pwd) && checkRoles(constructDistinguishedName(name))) {
+          (for {
+              user <- UserAuth.find(By(UserAuth.authKey, name),
+                                    By(UserAuth.authType, moduleName)).flatMap(_.user.obj) or
+              User.find(By(User.nickname, name))
+            } yield user) match {
+            case Full(user) =>
+              debug("User: '%s' has been found".format(user.niceName))
+              logInUser(user)
+            case Empty =>
+              val usr = User.createAndPopulate.nickname(name).saveMe
+              //find and save additional attributes in LDAP if it's enabled
+              val ldapAttrs = getAttrs(constructDistinguishedName(name))
+              val firstName = ldapAttrs("givenName").head
+              val lastName = ldapAttrs("sn").head
+              val mail = ldapAttrs("mail").head
+              debug("Attributes from LDAP for user '%s'. Firstname: '%s', lastname: '%s', email: '%s'".format(name, firstName, lastName, mail))
+              usr.firstName(firstName).lastName(lastName).save
+              UserAuth.create.authType(moduleName).user(usr).authKey(name).save
+              logInUser(usr)
+          }
+        } else {
+          S.error(S.?("base_user_err_unknown_creds"))
+        }
+      }
+
+      S.redirectTo(from)
+    }
+  }
+
+  def checkRoles(who : String) : Boolean = {
+    for (role <-rolesToCheck) {
+      val ldapAttrs = getAttrs(constructDistinguishedName(role, true))
+      val uniqueMember = ldapAttrs("uniqueMember").head
+      debug("'uniqueMember' attribute value: '%s'".format(uniqueMember))
+      if(who == uniqueMember) return true
+    }
+    debug("No roles have been found")
+    return false;
+  }
+
+  def createHolder(): FieldSet = new FieldSet {
+    def toForm: NodeSeq = NodeSeq.Empty
+    def validate: List[FieldError] = Nil
+    def save(user: User): Unit = {}
+  }
+}
+
 object ESMEOpenIDVendor extends OpenIDVendor {
   type UserType = User
   type ConsumerType = ESMEOpenIDConsumer