You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@esme.apache.org by rh...@apache.org on 2009/11/27 22:19:32 UTC

svn commit: r885021 - in /incubator/esme/trunk/server/src: main/scala/org/apache/esme/api/API2.scala main/scala/org/apache/esme/api/ApiHelper.scala test/scala/org/apache/esme/api/API2Test.scala

Author: rhirsch
Date: Fri Nov 27 21:19:30 2009
New Revision: 885021

URL: http://svn.apache.org/viewvc?rev=885021&view=rev
Log:
[ESME-14] Redesign, rework, write unit tests for, and fully document API
Patch from Ethan Jewett applied

Modified:
    incubator/esme/trunk/server/src/main/scala/org/apache/esme/api/API2.scala
    incubator/esme/trunk/server/src/main/scala/org/apache/esme/api/ApiHelper.scala
    incubator/esme/trunk/server/src/test/scala/org/apache/esme/api/API2Test.scala

Modified: incubator/esme/trunk/server/src/main/scala/org/apache/esme/api/API2.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/api/API2.scala?rev=885021&r1=885020&r2=885021&view=diff
==============================================================================
--- incubator/esme/trunk/server/src/main/scala/org/apache/esme/api/API2.scala (original)
+++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/api/API2.scala Fri Nov 27 21:19:30 2009
@@ -56,19 +56,17 @@
 	
     case Req("api2" :: "users" :: Nil, _, GetRequest) => allUsers
 // Add a method to get detail for a specific user
-
-// Document the fact that tag is no longer a parameter here                   
+                                                                          
     case Req("api2" :: "user" :: "messages" :: Nil, _, GetRequest)
  	  if S.param("timeout").isDefined => waitForMsgs
     case Req("api2" :: "user" :: "messages" :: Nil, _, GetRequest)
       if S.param("history").isDefined => allUserMsgs   
-    case Req("api2" :: "user" :: "messages" :: Nil, _, GetRequest) => getNewMsgs
-// Document the new method for getting messages belonging to a particular tag      
-    case Req("api2" :: "user" :: "messages" :: "tag" :: tag :: Nil, _, GetRequest)
-  		    => () => allUserMsgs(tag)
-// Possibly deprecate and move to api2/messages or api2/pools/poolName/messages
+    case Req("api2" :: "user" :: "messages" :: Nil, _, GetRequest) => getNewMsgs    
     case Req("api2" :: "user" :: "messages" :: Nil, _, PostRequest) => () => addMsg
 
+    case Req("api2" :: "user" :: "tags" :: tag :: "messages" :: Nil, _, GetRequest)
+  		    => () => allUserMsgs(tag)                                                 
+
     case Req("api2" :: "user" :: "followees" :: Nil, _, GetRequest) => allFollowees         
     case Req("api2" :: "user" :: "followees" :: Nil, _, PostRequest) => addFollowee
     case Req("api2" :: "user" :: "followees" :: userId :: Nil, _, DeleteRequest) 
@@ -108,53 +106,66 @@
   }
 
   def allSessions(): LiftResponse = {
-    val r: Box[Elem] = 
-		for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in"))
-    	yield { 
-			<session>{userToXml(user)}</session>
-		}
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] = 
+	  for (user <- User.currentUser)
+      yield { 
+		(200,Map(),Full(<session>{userToXml(user)}</session>))
+	  }
 
+	val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+	  if(ret.isDefined) ret else Full((404,Map(),Empty))
+	
 	r
   }      
 
   def addSession(): LiftResponse = {
-    val r: Box[Elem] = if (User.loggedIn_?) Empty else
-    for{ token <- S.param("token")
-         auth <- AuthToken.find(By(AuthToken.uniqueId, token))
-         user <- auth.user.obj
-         session <- S.session
-    } yield {
-      User.logUserIn(user)
-      val myActor = buildActor(user.id)
-      restActor(Full(myActor))
-      <session>{userToXml(user)}</session>
+	val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] = if (User.loggedIn_?) Empty else
+    for(token <- S.param("token")) yield {
+      val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] = for {
+        auth <- AuthToken.find(By(AuthToken.uniqueId, token))
+        user <- auth.user.obj 
+        val user_xml: Elem = <session>{userToXml(user)}</session>
+      } yield {
+        User.logUserIn(user)
+        val myActor = buildActor(user.id)
+        restActor(Full(myActor))
+        (200,Map(),Full(user_xml))     
+      }
+
+      ret openOr (403,Map(),Empty)   
     }
 
     r
   } 
 
   def removeSession(): LiftResponse = {
-    if (true) {
+    val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] = 
+      if (User.loggedIn_?) {
 		User.logUserOut()
-    	true
-	} else false
+    	Full((200,Map(),Empty))
+	  } else Full((404,Map(),Empty))  
+	
+	r
   } 
 
 
   def allUsers(): LiftResponse = {      	
   	val users: NodeSeq = for (user <- User.findAll) yield userToXml(user)
-    val r: Elem = <users>{users}</users>
+    val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] = 
+      Full(if (User.loggedIn_?) (200,Map(),Full(<users>{users}</users>)) else (403,Map(),Empty))
+
 	r
   }
        
   def allUserMsgs(): LiftResponse = {
-    val r: Box[Elem] = 
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
       for (user <- calcUser ?~  S.?("base_rest_api_err_param_not_found", "User");
 		val num = S.param("history").map(_.toInt) openOr 40;
         val lst = Mailbox.mostRecentMessagesFor(user.id, num))
-      yield {
-		<messages>{lst.flatMap{ case (msg, _, _) => msgToXml(msg)}}</messages>
-	  }
+      yield (200,Map(),Full(<messages>{lst.flatMap{ case (msg, reason, _) => msgToXml(msg) }}</messages>))
+
+    val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      if(ret.isDefined) ret else Full((403,Map(),Empty))
 
     r
   }
@@ -165,11 +176,14 @@
     def waitForAnswer: Box[List[(Message, MailboxReason)]] = 
       future.get(60L * 1000L)
 
-    val r: Box[NodeSeq] = 
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] = 
       for (act <- restActor.is ?~ "No REST actor";
 		   val ignore = act ! ListenFor(future, 0 seconds);
            answer <- waitForAnswer ?~ "Didn't get an answer")
-      yield answer.flatMap{ case (msg, reason) => msgToXml(msg) }
+      yield (200,Map(),Full(<messages>{answer.flatMap{ case (msg, reason) => msgToXml(msg) }}</messages>))
+
+    val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      if(ret.isDefined) ret else Full((403,Map(),Empty))
 
     r
   } 
@@ -180,225 +194,321 @@
     def waitForAnswer: Box[List[(Message, MailboxReason)]] = 
       future.get(6L * 60L * 1000L)
 
-    var r: Box[NodeSeq] = 
-    for (act <- restActor.is ?~ "No REST actor";
-		 length <- S.param("timeout").map(_.toInt * 1000);
-         val ignore = act ! ListenFor(future, TimeSpan(length));
-         answer <- waitForAnswer ?~ "Didn't get an answer")
-    yield answer.flatMap{ case (msg, reason) => msgToXml(msg) }
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =  
+      for (act <- restActor.is ?~ "No REST actor";
+		length <- S.param("timeout").map(_.toInt * 1000);
+        val ignore = act ! ListenFor(future, TimeSpan(length));
+        answer <- waitForAnswer ?~ "Didn't get an answer")
+      yield (200,Map(),Full(<messages>{answer.flatMap{ case (msg, reason) => msgToXml(msg) }}</messages>))
+
+    val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      if(ret.isDefined) ret else Full((403,Map(),Empty))
 
     r
   }
 
   def allUserMsgs(tag: String): LiftResponse = {
-	val r: Box[Elem] =
-      for (tagName <- Box(List(tag));
-        tag <- Tag.find(By(Tag.name, tagName)))
-      yield {
-	    <tag>
-		  <name>{tag.name}</name>
-		  <messages>{tag.findMessages.map(msgToXml(_))}</messages>
-	    </tag>
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =  
+      for (user <- User.currentUser;
+           tagName <- Box(List(tag));
+           tag <- Tag.find(By(Tag.name, tagName)))
+      yield {
+	    val tag_xml = <tag><name>{tag.name}</name><messages>{tag.findMessages.map(msgToXml(_))}</messages></tag>
+	    (200,Map(),Full(tag_xml))
 	  }
 	
-	r  	
+    val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+    r	
   } 
 
   def addMsg(): LiftResponse = {
 // Should return the created message
 
-    val r: Box[Boolean] =
-    for (user <- calcUser.map(_.id.is) ?~ S.?("base_rest_api_err_param_not_found", "User");
-         msg <- S.param("message") ?~ S.?("base_rest_api_err_missing_param", "message"))
-    yield {
-      val from: String = S.param("via") openOr "api"
-      val pool = for (poolName <- S.param("pool");
-                      p <- AccessPool.findPool(poolName,
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] = 
+      for (user <- calcUser.map(_.id.is) ?~ S.?("base_rest_api_err_param_not_found", "User");
+        msg <- S.param("message") ?~ S.?("base_rest_api_err_missing_param", "message"))
+      yield {
+        val from: String = S.param("via") openOr "api"
+        val pool = for (poolName <- S.param("pool");
+                        p <- AccessPool.findPool(poolName,
                         S.param("realm") openOr AccessPool.Native)
-                      ) yield p.id.is
+                        ) yield p.id.is
 
-      val xml: Box[Elem] = S.param("metadata").flatMap(md =>
-        tryo(XML.loadString(md)))
+        val xml: Box[Elem] = 
+          S.param("metadata").flatMap(md =>
+            tryo(XML.loadString(md)))
+
+        Distributor !
+        Distributor.UserCreatedMessage(user, msg,
+                                       Tag.split(S.param("tags")
+                                                 openOr ""),
+                                       millis,
+                                       xml,
+                                       from,
+                                       S.param("replyto").map(toLong),
+                                       pool)
+        (200,Map(),Empty)
+      }
+
+    val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      if(ret.isDefined) ret else Full((403,Map(),Empty))
 
-      Distributor !
-      Distributor.UserCreatedMessage(user, msg,
-                                     Tag.split(S.param("tags")
-                                               openOr ""),
-                                     millis,
-                                     xml,
-                                     from,
-                                     S.param("replyto").map(toLong),
-                                     pool)
-      true
-    }
     r
   }      
 
 
   def allFollowees(): LiftResponse = {
-    val followees: NodeSeq = calcUser.map(_.following)
-		.map(_.map(userToXml(_)))
-		.openOr(<no_followees/>)
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      for(user <- User.currentUser)
+      yield {
+        val followees: NodeSeq = 
+          calcUser.map(_.following)
+		                .map(_.map(userToXml(_)))
+		                .openOr(<no_followees/>)
+		(200,Map(),Full(<followees>{followees}</followees>))
+	  }
+
+    val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      if(ret.isDefined) ret else Full((403,Map(),Empty))
 
-    <followees>{followees}</followees>
+    r
   }         
 
   def addFollowee(): LiftResponse = {
-    val r: Box[Node] =
-    for (user <- User.currentUser;
-         userName <- S.param("userId");
-         other <- User.findFromWeb(userName)
-    ) yield { 	
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      for (user <- User.currentUser;
+        userName <- S.param("userId");
+        other <- User.findFromWeb(userName))
+      yield { 	
 		user.follow(other)
-		userToXml(other)
-    }
+		(200,Map(),Full(userToXml(other)))
+      }
     
-	r
+    val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+    r
   }   
 
   
   def removeFollow(userName: Box[String])(): LiftResponse = {
-    val r: Box[Boolean] =
-    for (user <- User.currentUser;
-         userName <- userName;
-         other <- User.findFromWeb(userName)
-    ) yield user.unfollow(other)
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] = 
+      for (user <- User.currentUser;
+        userName <- userName;
+        other <- User.findFromWeb(userName))
+      yield {
+        user.unfollow(other)        
+        (200,Map(),Empty)
+      }
     
+    val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      if(ret.isDefined) ret else Full((403,Map(),Empty))
+
     r
   }
 
   def allFollowers(): LiftResponse = {
-  	val followers: NodeSeq = calcUser.map(_.followers)
-		.map(_.map(userToXml(_)))
-		.openOr(<no_followers/>)
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      for(user <- User.currentUser)
+      yield {
+        val followees: NodeSeq = 
+          calcUser.map(_.following)
+		                .map(_.map(userToXml(_)))
+		                .openOr(<no_followees/>)
+		(200,Map(),Full(<followees>{followees}</followees>))
+	  }
+
+    val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      if(ret.isDefined) ret else Full((403,Map(),Empty))
 
-  	<followers>{followers}</followers>
+    r
   }     
 
   def allTracking(): LiftResponse = {
-    val tracks: Box[NodeSeq] =
-    for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in"))
-    yield Tracking.findAll(By(Tracking.user, user)).flatMap(_.toXml)
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in"))
+      yield {
+        val track_lst = Tracking.findAll(By(Tracking.user, user)).flatMap(_.toXml)
+        (200,Map(),Full(<tracks>{track_lst}</tracks>))
+      }
     
-	<tracks>{tracks}</tracks>
+    val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+    r
   }   
 
   def addTracking(): LiftResponse = {
-    val ret: Box[Boolean] =
-    for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in");
-         toTrack <- (S.param("track") ?~ S.?("base_rest_api_err_missing_param", "track")) if toTrack.trim.length > 0)
-    yield
-    Tracking.create.user(user).regex(toTrack).save
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] = 
+      for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in");
+           toTrack <- (S.param("track") ?~ S.?("base_rest_api_err_missing_param", "track")) if toTrack.trim.length > 0)
+      yield
+        (200,Map(),Full(<track>{Tracking.create.user(user).regex(toTrack).save}</track>))
 
-    ret
+	val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+	  if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+	r
   }      
 
   def removeTracking(trackId: Box[String]): LiftResponse = {
-    val ret: Box[Boolean] =
-    for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in");
-         id <- trackId ?~ S.?("base_rest_api_err_missing_param", "id");
-         track <- Tracking.find(By(Tracking.id, id.toLong),
-                                By(Tracking.user, user)) ?~ "Couldn't find tracking item"
-    ) yield track.removed(true).save
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in");
+           id <- trackId ?~ S.?("base_rest_api_err_missing_param", "id");
+           track <- Tracking.find(By(Tracking.id, id.toLong),
+                                  By(Tracking.user, user)) ?~ "Couldn't find tracking item")
+      yield {
+        track.removed(true).save
+        (200,Map(),Empty)
+      }
 
-    ret
+	val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+	  if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+	r
   } 
 
   def allActions(): LiftResponse = {
-    val ret: Box[NodeSeq] =
-    for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in"))
-    yield user.performing.flatMap(_.toXml)
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =       
+      for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in"))
+      yield (200,Map(),Full(<actions>{user.performing.flatMap(_.toXml)}</actions>))
 
-    ret
+	val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+	  if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+	r
   }     
 
   def addAction(): LiftResponse = {
-    val ret: Box[NodeSeq] =
-    for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in");
-         name <- S.param("name") ?~ S.?("base_rest_api_err_missing_param", "name");
-         test <- S.param("test") ?~ S.?("base_rest_api_err_missing_param", "test");
-         action <- S.param("action") ?~ S.?("base_rest_api_err_missing_param", "action");
-         val a = Action.create.user(user).name(name);
-         a2 <- a.setTest(test);
-         a3 <- a.setAction(action)) yield a3.saveMe.toXml
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in");
+           name <- S.param("name") ?~ S.?("base_rest_api_err_missing_param", "name");
+           test <- S.param("test") ?~ S.?("base_rest_api_err_missing_param", "test");
+           action <- S.param("action") ?~ S.?("base_rest_api_err_missing_param", "action");
+           val a = Action.create.user(user).name(name);
+           a2 <- a.setTest(test);
+           a3 <- a.setAction(action))
+       yield {
+         (200,Map(),Full(a3.saveMe.toXml))
+       }
 
-    ret
+	val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+	  if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+	r
   } 
 
   def changeAction(actionId: Box[String]): LiftResponse = {
-    val ret: Box[Boolean] =
-    for (action <- findAction(actionId);
-         enabled <- S.param("enabled").map(toBoolean) ?~ S.?("base_rest_api_err_missing_param", "enable"))
-    yield action.disabled(!enabled).save
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+      for (user <- User.currentUser;
+           action <- findAction(actionId);
+           enabled <- S.param("enabled").map(toBoolean) ?~ S.?("base_rest_api_err_missing_param", "enable"))
+      yield {
+        action.disabled(!enabled).save
+        (200,Map(),Full(action.toXml))
+      }
   
-    ret
+	val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+	  if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+	r
   }
 
   def removeAction(actionId: Box[String]): LiftResponse = {
-    val ret: Box[Boolean] =
-    for (action <- findAction(actionId)) 
-    yield action.removed(true).save
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =  
+      for (user <- User.currentUser;
+           action <- findAction(actionId)) 
+      yield {
+        action.removed(true).save
+        (200,Map(),Empty)
+      }
     
-    ret
+	val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+	  if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+	r
   }              
 
   def allPools(): LiftResponse = {
-    val ret: Box[NodeSeq] =
-    for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in"))
-    yield AccessPool.findAll(In(AccessPool.id, Privilege.pool, By(Privilege.user, user)),
-                             OrderBy(AccessPool.id, Descending),
-                             MaxRows(20)).
-          flatMap(_.toXml)
-    ret
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =  
+      for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in"))
+      yield {
+        val pools_lst = AccessPool.findAll(In(AccessPool.id,
+                                              Privilege.pool,
+                                              By(Privilege.user, user)),
+                                           OrderBy(AccessPool.id, Descending),
+                                           MaxRows(20)).flatMap(_.toXml)
+        (200,Map(),Full(<pools>{pools_lst}</pools>))
+      }
+
+	val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+	  if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+	r
   }      
 
   def addPool(): LiftResponse = {
-    val r: Box[Boolean] =
-    for (user <- User.currentUser;
-         pool <- AccessPool.create.realm(AccessPool.Native).setName(S.param("poolName").openOr(""));
-         privilegeSaved = Privilege.create.pool(pool.saveMe).user(user).
-           permission(Permission.Admin).save
-    ) yield {
-      if (privilegeSaved) Distributor ! Distributor.AllowUserInPool(user.id.is, pool.id.is)
-      privilegeSaved
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =   
+      for (user <- User.currentUser;
+           pool <- AccessPool.create.realm(AccessPool.Native).setName(S.param("poolName").openOr(""));
+           privilegeSaved = Privilege.create.pool(pool.saveMe)
+                                     .user(user)
+                                     .permission(Permission.Admin)
+                                     .save)
+      yield {
+        if (privilegeSaved) Distributor ! Distributor.AllowUserInPool(user.id.is, pool.id.is)
+        (200,Map(),Full(pool.toXml))
     }
     
-    r
+	val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+	  if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+	r
   } 
 
   def addUserToPool(poolId: Box[String]): LiftResponse = {
-    val r: Box[Boolean] = 
-    for (adminUser <- User.currentUser;
-         poolName <- poolId ?~ S.?("base_rest_api_err_missing_param", "pool");
-         realm <- (S.param("realm") or Full(AccessPool.Native));
-         pool <- AccessPool.findPool(poolName, realm) ?~  S.?("base_rest_api_err_param_not_found", "Pool");
-         userName <- S.param("userId") ?~ S.?("base_rest_api_err_missing_param", "user");
-         user <- User.findFromWeb(userName) ?~  S.?("base_rest_api_err_param_not_found", "User");
-         permissionName <- (S.param("permission") or Full("Write"));
-         permission <- Box(Permission.valueOf(permissionName)) ?~ S.?("base_rest_api_err_param_not_found", "Permission")
-    ) yield if(Privilege.hasPermission(adminUser.id.is, pool.id.is, Permission.Admin)) {
-      val result = try {
-        Privilege.create.user(user).pool(pool).permission(permission).save
-      } catch {
-        case _: Exception => false
-      }
-      if (result) Distributor ! Distributor.AllowUserInPool(user.id.is, pool.id.is)
-      result
-    } else false // "User has no permission to administer pool"
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] = 
+      for (adminUser <- User.currentUser;
+           poolName <- poolId ?~ S.?("base_rest_api_err_missing_param", "pool");
+           realm <- (S.param("realm") or Full(AccessPool.Native));
+           pool <- AccessPool.findPool(poolName, realm) ?~  S.?("base_rest_api_err_param_not_found", "Pool");
+           userName <- S.param("userId") ?~ S.?("base_rest_api_err_missing_param", "user");
+           user <- User.findFromWeb(userName) ?~  S.?("base_rest_api_err_param_not_found", "User");
+           permissionName <- (S.param("permission") or Full("Write"));
+           permission <- Box(Permission.valueOf(permissionName)) ?~ S.?("base_rest_api_err_param_not_found", "Permission"))
+      yield
+        if(Privilege.hasPermission(adminUser.id.is, pool.id.is, Permission.Admin)) {
+          val result = try {
+            Privilege.create.user(user).pool(pool).permission(permission).save
+          } catch {
+            case _: Exception => false
+          }
+
+          if (result) Distributor ! Distributor.AllowUserInPool(user.id.is, pool.id.is)
+            (200,Map(),Full(userToXml(user)))
+        } else (403,Map(),Empty) // "User has no permission to administer pool"
     
-    r
+	val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+	  if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+	r
   }  
 
   def getConversation(conversationId: Box[String]): LiftResponse = {
-    val ret: Box[NodeSeq] =
-    for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in");
-         id <- conversationId.map(toLong) ?~ S.?("base_rest_api_err_missing_param", "id")
-    ) yield <conversation id={id.toString}>{
+    val ret: Box[Tuple3[Int,Map[String,String],Box[Elem]]] = 
+      for (user <- User.currentUser ?~ S.?("base_rest_api_err_not_logged_in");
+           id <- conversationId.map(toLong) ?~ S.?("base_rest_api_err_missing_param", "id"))
+      yield (200,Map(),Full(<conversation id={id.toString}>{
         Message.findAndPrime(By(Message.conversation, id),
                              OrderBy(Message.id, Ascending)).map(_.toXml)
-      }</conversation>
+      }</conversation>))
 
-    ret
+	val r: Box[Tuple3[Int,Map[String,String],Box[Elem]]] =
+	  if(ret.isDefined) ret else Full((403,Map(),Empty))
+
+	r
   }
 
   private def findAction(actionId: Box[String]): Box[Action] =

Modified: incubator/esme/trunk/server/src/main/scala/org/apache/esme/api/ApiHelper.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/main/scala/org/apache/esme/api/ApiHelper.scala?rev=885021&r1=885020&r2=885021&view=diff
==============================================================================
--- incubator/esme/trunk/server/src/main/scala/org/apache/esme/api/ApiHelper.scala (original)
+++ incubator/esme/trunk/server/src/main/scala/org/apache/esme/api/ApiHelper.scala Fri Nov 27 21:19:30 2009
@@ -42,56 +42,31 @@
 import scala.xml.{NodeSeq, Text, Elem, UnprefixedAttribute, Null, Node}  
   
 trait ApiHelper {  
-  implicit def boolToResponse(in: Boolean): LiftResponse =  
-  buildResponse(in, Empty, Text(""))  
-  
-  implicit def canBoolToResponse(in: Box[Boolean]): LiftResponse =  
-  buildResponse(in openOr false, in match {  
-      case Failure(msg, _, _) => Full(Text(msg))  
-      case _ => Empty  
-    }, Text(""))  
-  
-  implicit def pairToResponse(in: (Boolean, String)): LiftResponse =  
-  buildResponse(in._1, Full(Text(in._2)), Text(""))  
-  
-  implicit def nodeSeqToResponse(in: NodeSeq): LiftResponse =  
-  buildResponse(true, Empty, in)  
-  
-  implicit def listElemToResponse(in: Seq[Node]): LiftResponse =  
-  buildResponse(true, Empty, in)
+  /**
+   * This method converts from Rack/WSGI response format into the correct Lift response
+   */
 
-  implicit def elemToResponse(in: Elem): LiftResponse =
-  buildResponseFromElem(true, Empty, in)
-  
-  implicit def canNodeToResponse(in: Box[NodeSeq]): LiftResponse = in match {  
-    case Full(n) => buildResponse(true, Empty, n)  
-    case Failure(msg, _, _) => buildResponse(false, Full(Text(msg)), Text(""))  
-    case _ => buildResponse(false, Empty, Text(""))  
+  implicit def rackResponse(in: Box[Tuple3[Int,Map[String,String],Box[Elem]]]): LiftResponse = in match {
+    case Full((200,_,xml)) => buildResponse(true, Empty, xml openOr Text(""))
+    case Full((403,_,_)) => ForbiddenResponse()
+    case Full((404,_,_)) => NotFoundResponse()
+    case _ => InternalServerErrorResponse()   
   }  
   
   implicit def putResponseInBox(in: LiftResponse): Box[LiftResponse] = Full(in)
 
-  implicit def takeResponseOutOfBox(in: Box[LiftResponse]): LiftResponse =
-	in openOr false                                                   
-  
   /** 
    * The method that wraps the outer-most tag around the body 
-   */  
+   */   
+
   def createTag(in: NodeSeq): Elem  
   
   /** 
    * Build the Response based on the body 
    */  
+
   protected def buildResponse(success: Boolean, msg: Box[NodeSeq],  
-                            body: NodeSeq): LiftResponse = {
-    if(success) {
-      XmlResponse(createTag(body))
-    } else {
-      XmlResponse(createTag(body))  // Need to return a 401 response here
-    }
-  }  
-  
-  protected def buildResponseFromElem(success: Boolean, msg: Box[NodeSeq], body: Elem): LiftResponse = {
-  	XmlResponse(createTag(body))                                                                                   
-  }
+                            body: NodeSeq): LiftResponse = 
+    XmlResponse(createTag(body))
+
 }

Modified: incubator/esme/trunk/server/src/test/scala/org/apache/esme/api/API2Test.scala
URL: http://svn.apache.org/viewvc/incubator/esme/trunk/server/src/test/scala/org/apache/esme/api/API2Test.scala?rev=885021&r1=885020&r2=885021&view=diff
==============================================================================
--- incubator/esme/trunk/server/src/test/scala/org/apache/esme/api/API2Test.scala (original)
+++ incubator/esme/trunk/server/src/test/scala/org/apache/esme/api/API2Test.scala Fri Nov 27 21:19:30 2009
@@ -47,44 +47,414 @@
 object Api2Specs extends Specification with TestKit {
   JettyTestServer.start
 
-  val baseUrl = JettyTestServer.urlFor("")
+  val baseUrl = JettyTestServer.urlFor("/api2/")
   
   val theUser = User.createAndPopulate.nickname("api_test").saveMe
   val token = {
     val toke = AuthToken.create.user(theUser).saveMe
     toke.uniqueId.is
-  }                
+  }     
+
+  val post_session = post("session", "token" -> token)
   
   "API2" should {
-	"Login with a valid token results in a 200 response and a proper response body" in {
-      for{
-        session <- post("/api2/session", "token" -> token)    
-      } {
-        (session.xml \ "session" \ "user" \ "id").text must be equalTo(theUser.id.toString)
-		session.code must be equalTo(200)
+	"/session POST" in {  
+	  "Attempt to log in with a valid token should succeed with a 200 response" in {
+	    for{
+	      session <- post_session    
+	    } {
+	      (session.xml \ "session" \ "user" \ "id").text must be equalTo(theUser.id.toString)
+		  session.code must be equalTo 200
+	    } 
+	  }
+
+	  "Attempt to create session with an invalid token returns 403 response" in {
+	    for{
+	      session <- post("session", "token" -> "000000")
+	    } {                  
+          session.code must be equalTo 403
+	    } 
+	  }
+	}
+	
+	"/session GET" in {
+	  "with valid session" in {
+	    for {
+	      session <- post_session
+          session_response <- session.get("session")
+	    } {
+	      session_response.code must be equalTo 200
+	      ( session_response.xml \ "session" \ "user" \ "id").text must be equalTo(theUser.id.toString)
+	    }
+	  }
+	
+	  "with no session returns 404 (not found)" in {
+	    for(session_res <- get("session")) {
+	      session_res.code must be equalTo 404
+	    }
+	  }  
+    }
+
+    "/session DELETE" in {
+      "with valid session" in {
+        for {
+          session <- post_session
+          session_del_response <- session.delete("session")
+          //session_response <- session.get("session")
+        } {
+          session_del_response.code must be equalTo 200
+          //session_response.code must be equalTo(404)
+        }
+      }
+
+	  "with no session returns 404 (not found)" in {
+	    for(session_res <- delete("session")) {
+	      session_res.code must be equalTo 404
+	    }
+	  }
+    }	
+
+    "/users GET" in {
+      "with valid session" in {     
+        for {
+          session <- post_session
+          users <- session.get("users")
+        } {
+          users.code must be equalTo 200
+        }
+      }
+
+	  "with no session returns 403 (forbidden)" in {
+	    for(session_res <- get("users")) {
+	      session_res.code must be equalTo 403
+	    }
+	  }
+    }
+
+    "/user/messages GET" in {
+      "with valid session" in {
+        for {
+          session <- post_session
+          mess_res <- session.get("user/messages")
+        } {
+          mess_res.code must be equalTo 200
+        }
       }
+
+	  "with no session returns 403 (forbidden)" in {
+	    for(session_res <- get("user/messages")) {
+	      session_res.code must be equalTo 403
+	    }
+	  }
     }
 
-	"Attempt to create session with an invalid token returns 400 response" in {
-      for{
-        session <- post("/api2/session", "token" -> "0000000")
-      } {                   
-		session.code must be equalTo(400)
+    "/user/messages?history=10 GET" in {
+      "with valid session" in {
+        for {
+          session <- post_session
+          res <- session.get("user/messages?history=10")
+        } {
+          res.code must be equalTo 200
+        }                     
       }
+
+      "with no session returns 403 (forbidden)" in {
+	    for(session_res <- get("user/messages?history=10")) {
+	      session_res.code must be equalTo 403
+	    }
+	  }
     }
 
-    "/users" in {
-      "Valid session" in {     
-        "have a response code of 200" in {
-          for {
-            session <- post("/api2/session", "token" -> token)
-            users <- session.get("/api2/users")
-          } {
-            users.code must be equalTo(200)
-          }
+    "/user/messages?timeout=2 GET" in {
+      "with valid session" in {
+        for {
+          sess <- post_session
+          res <- sess.get("user/messages?timeout=2")
+        } {
+          res.code must be equalTo 200
+        }          
+      }
+
+      "with no session returns 403 (forbidden)" in {
+	    for(session_res <- get("user/messages?timeout=2")) {
+	      session_res.code must be equalTo 403
+	    }
+	  }
+    } 
+
+    "/user/messages POST" in {
+      "with valid session" in {
+        for {
+          session <- post_session
+          mess_res <- session.post("user/messages","message"->"test message")
+        } {
+          mess_res.code must be equalTo 200
         }
-	  }                
+      }
+
+	  "with no session returns 403 (forbidden)" in {
+	    for(session_res <- post("user/messages","message"->"test message")) {
+	      session_res.code must be equalTo 403
+	    }
+	  }
+    }
+
+    "/user/followees GET" in {
+      "with valid session" in {
+        for {
+          sess <- post_session
+          res <- sess.get("user/followees")
+        } {
+          res.code must be equalTo 200
+        }          
+      }
+
+      "with no session returns 403 (forbidden)" in {
+	    for(session_res <- get("user/followees")) {
+	      session_res.code must be equalTo 403
+	    }
+	  }
+    }
+
+    "/user/followees POST" in {
+      "with valid session" in {
+        for {
+          sess <- post_session
+          res <- sess.post("user/followees", "userId" -> "1")
+        } {
+          res.code must be equalTo 200
+        }          
+      }
+
+      "with no session returns 403 (forbidden)" in {
+	    for(res <- post("user/followees", "userId" -> "1")) {
+	      res.code must be equalTo 403
+	    }
+	  }
+    } 
+
+    "/user/followers GET" in {
+      "with valid session" in {
+        for {
+          sess <- post_session
+          res <- sess.get("user/followers")
+        } {
+          res.code must be equalTo 200
+        }          
+      }
+
+      "with no session returns 403 (forbidden)" in {
+	    for(session_res <- get("user/followers")) {
+	      session_res.code must be equalTo 403
+	    }
+	  }
     }
-  }                                    
-}
- 
\ No newline at end of file
+
+    "/user/tracks GET" in {
+      "with valid session" in {
+        for {
+          sess <- post_session
+          res <- sess.get("user/tracks")
+        } {
+          res.code must be equalTo 200
+        }          
+      }
+
+      "with no session returns 403 (forbidden)" in {
+	    for(session_res <- get("user/tracks")) {
+	      session_res.code must be equalTo 403
+	    }
+	  }
+    }
+
+    "/user/tracks POST" in {
+      "with valid session" in {
+        for {
+          sess <- post_session
+          res <- sess.post("user/tracks","track" -> ".*")
+        } {
+          res.code must be equalTo 200
+        }          
+      }
+
+      "with no session returns 403 (forbidden)" in {
+	    for(session_res <- post("user/tracks","track" -> ".*")) {
+	      session_res.code must be equalTo 403
+	    }
+	  }
+    }
+
+/*
+ *   "/user/tracks/TRACKID DELETE" in {
+ *     "with valid session" in {
+ *       for {
+ *         sess <- post_session
+ *         create_track <- sess.post("user/tracks","track"->".*")
+ *         res <- sess.delete("user/tracks/1")
+ *       } {
+ *         res.code must be equalTo 200
+ *       }          
+ *     }
+ *
+ *     "with no session returns 403 (forbidden)" in {
+ *       for(session_res <- delete("user/tracks/1")) {
+ *         session_res.code must be equalTo 403
+ *       }
+ *     }
+ *   } 
+ */
+
+    "/user/actions GET" in {
+      "with valid session" in {
+        for {
+          sess <- post_session
+          res <- sess.get("user/actions")
+        } {
+          res.code must be equalTo 200
+        }          
+      }
+
+      "with no session returns 403 (forbidden)" in {
+	    for(res <- get("user/actions")) {
+	      res.code must be equalTo 403
+	    }
+	  }
+    }
+
+    "/user/actions POST" in {
+      "with valid session" in {
+        for {
+          sess <- post_session
+          res <- sess.post("user/actions",
+                           "name"->"Test action",
+                           "test"->"every 5 mins",
+                           "action"->"rss:http://blog.com/feed.rss")
+        } {
+          res.code must be equalTo 200
+        }          
+      }
+
+      "with no session returns 403 (forbidden)" in {
+	    for(res <- post("user/actions",
+	                    "name"->"Test action",
+	                    "test"->"every 5 mins",
+	                    "action"->"rss:http://blog.com/feed.rss")) {
+	      res.code must be equalTo 403
+	    }
+	  }
+    }   
+
+/*
+ *    "/user/actions/ACTIONID PUT" in {
+ *     "with valid session" in {
+ *       for {
+ *         sess <- post_session
+ *         res <- sess.put("user/actions/1","enabled"->0)
+ *       } {
+ *         res.code must be equalTo 200
+ *       }          
+ *     }
+ *
+ *     "with no session returns 403 (forbidden)" in {
+ *       for(res <- post("user/actions/1","enabled"->0)) {
+ *         res.code must be equalTo 403
+ *       }
+ *     }
+ *   }
+ */
+
+/*
+ *   "/user/actions/ACTIONID DELETE" in {
+ *     "with valid session" in {
+ *       for {
+ *         sess <- post_session
+ *         res <- sess.delete("user/actions/1")
+ *       } {
+ *         res.code must be equalTo 200
+ *       }          
+ *     }
+ *
+ *     "with no session returns 403 (forbidden)" in {
+ *       for(res <- delete("user/actions/1")) {
+ *         res.code must be equalTo 403
+ *       }
+ *     }
+ *   } 
+ */
+
+    "conversations/CONVERSATIONID GET" in {
+      "with valid session" in {
+        for {
+          sess <- post_session
+          res <- sess.get("conversations/1")
+        } {
+          res.code must be equalTo 200
+        }          
+      }
+
+      "with no session returns 403 (forbidden)" in {
+	    for(res <- get("conversations/1")) {
+	      res.code must be equalTo 403
+	    }
+	  }
+    }
+
+    "/pools GET" in {
+      "with valid session" in {
+        for {
+          sess <- post_session
+          res <- sess.get("pools")
+        } {
+          res.code must be equalTo 200
+        }          
+      }
+
+      "with no session returns 403 (forbidden)" in {
+	    for(res <- get("pools")) {
+	      res.code must be equalTo 403
+	    }
+	  }
+    }
+
+    "/pools POST" in {
+      "with valid session" in {
+        for {
+          sess <- post_session
+          res <- sess.post("pools","poolName"->"test_pool")
+        } {
+          res.code must be equalTo 200
+        }          
+      }
+
+      "with no session returns 403 (forbidden)" in {
+	    for(res <- post("pools","poolName"->"test_pool")) {
+	      res.code must be equalTo 403
+	    }
+	  }
+    }  
+
+    "/pools/POOLID/users POST" in {
+
+/*
+ *     "with valid session" in {
+ *       for {
+ *         sess <- post_session
+ *         res <- sess.post("pools/1/users",{"realm"->"test_realm";
+ *                                                "userId"->1;
+ *                                                "permission"->"Write"})
+ *       } {
+ *         res.code must be equalTo 200
+ *       }          
+ *     }
+ */
+
+      "with no session returns 403 (forbidden)" in {
+	    for(res <- post("pools/1/users",{"realm"->"test_realm";
+                                                 "userId"->2;
+                                                 "permission"->"Write"})) {
+	      res.code must be equalTo 403
+	    }
+	  }
+    }        
+  }  
+}
\ No newline at end of file