Return-Path: Delivered-To: apmail-incubator-esme-commits-archive@minotaur.apache.org Received: (qmail 42724 invoked from network); 2 May 2009 23:36:57 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 2 May 2009 23:36:57 -0000 Received: (qmail 49815 invoked by uid 500); 2 May 2009 23:36:57 -0000 Delivered-To: apmail-incubator-esme-commits-archive@incubator.apache.org Received: (qmail 49790 invoked by uid 500); 2 May 2009 23:36:57 -0000 Mailing-List: contact esme-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: esme-dev@incubator.apache.org Delivered-To: mailing list esme-commits@incubator.apache.org Received: (qmail 49780 invoked by uid 99); 2 May 2009 23:36:57 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 02 May 2009 23:36:57 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 02 May 2009 23:36:49 +0000 Received: by eris.apache.org (Postfix, from userid 510) id 206D52388A7D; Sat, 2 May 2009 23:36:29 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r770989 - in /incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme: actor/ api/ comet/ external/ model/ snippet/ Date: Sat, 02 May 2009 23:36:28 -0000 To: esme-commits@incubator.apache.org From: vdichev@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090502233629.206D52388A7D@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: vdichev Date: Sat May 2 22:28:43 2009 New Revision: 770989 URL: http://svn.apache.org/viewvc?rev=770989&view=rev Log: ESME-55 Efficient sending of messages to a pool from RestAPI and hiding from public timeline; control of tracking depending on pool. Modified: incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/actor/Distributor.scala incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/actor/UserActor.scala incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/api/RestAPI.scala incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/comet/PublicTimeline.scala incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/external/Feed.scala incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/external/TwitterFeed.scala incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/model/Action.scala incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/model/Privilege.scala incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala Modified: incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/actor/Distributor.scala URL: http://svn.apache.org/viewvc/incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/actor/Distributor.scala?rev=770989&r1=770988&r2=770989&view=diff ============================================================================== --- incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/actor/Distributor.scala (original) +++ incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/actor/Distributor.scala Sat May 2 22:28:43 2009 @@ -51,10 +51,11 @@ case UserCreatedMessage(user, text, tags, when, metaData, source, - inReplyTo) => + inReplyTo, + pool) => findOrCreateUser(user) ! UserActor.CreateMessage(text, tags, - when, metaData, source, inReplyTo) + when, metaData, source, inReplyTo, pool) case AddMessageToMailbox(user, message, reason) => findOrCreateUser(user) ! UserActor.AddToMailbox(message, reason) @@ -85,6 +86,9 @@ case PublicTimelineUnlisteners(who) => listeners = listeners.filter(_ ne who) + + case AllowUserInPool(userId, poolId) => + findOrCreateUser(userId) ! UserActor.AllowPool(poolId) case _ => } @@ -96,7 +100,8 @@ when: Long, metaData: Box[Elem], source: String, - replyTo: Box[Long]) + replyTo: Box[Long], + pool: Box[Long]) case class AddMessageToMailbox(user: Long, message: Message, reason: MailboxReason) case class Listen(user: Long, who: Actor) case class Unlisten(user: Long, who: Actor) @@ -106,6 +111,7 @@ case class UserUpdated(userId: Long) case class PublicTimelineListeners(who: Actor) case class PublicTimelineUnlisteners(who: Actor) + case class AllowUserInPool(userId: Long, poolId: Long) sealed trait TrackingType case object PerformTrackingType extends TrackingType case object TrackTrackingType extends TrackingType Modified: incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/actor/UserActor.scala URL: http://svn.apache.org/viewvc/incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/actor/UserActor.scala?rev=770989&r1=770988&r2=770989&view=diff ============================================================================== --- incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/actor/UserActor.scala (original) +++ incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/actor/UserActor.scala Sat May 2 22:28:43 2009 @@ -42,13 +42,15 @@ private[actor] case class CreateMessage(text: String, tags: List[String], when: Long, metaData: Box[Elem], source: String, - replyTo: Box[Long]) + replyTo: Box[Long], + pool: Box[Long]) private[actor] case class AddToMailbox(msg: Message, reason: MailboxReason) private[actor] case class Listen(who: Actor) private[actor] case class Unlisten(who: Actor) private[actor] case class LatestMessages(cnt: Int) private[actor] case class TestForTracking(msg: Message) private[actor] case class UpdateTracking(ttype: Distributor.TrackingType) + private[actor] case class AllowPool(poolId: Long) case class MessageReceived(msg: Message, reason: MailboxReason) @@ -69,8 +71,12 @@ private var perform: List[PerformMatcher] = Nil private var _mailbox: Array[Long] = Array() + + private var pools: List[Long] = List() private def followers: List[Long] = User.followerIdsForUserId(userId) + + private def canReadPool_?(poolId: Long) = pools contains poolId private case class RunFunc(f: () => Unit) @@ -89,23 +95,38 @@ _mailbox = Mailbox.mostRecentMessagesFor(userId, 500). map(_._1.id.is).toArray + + pools = Privilege.findViewablePools(userId) this ! UpdateTracking(Distributor.TrackTrackingType) this ! UpdateTracking(Distributor.PerformTrackingType) case RunFunc(f) => f() - case CreateMessage(text, tags, when, metaData, source, replyTo) => - val tagLst = tags.removeDuplicates.map(Tag.findOrCreate) + case CreateMessage(text, tags, when, metaData, source, replyTo, pool) => + val tagLst = if (pool == None) + tags.removeDuplicates.map(Tag.findOrCreate) + else Nil Message.create.author(userId).when(when). source(source). - setTextAndTags(text, tagLst, metaData).map{msg => + setTextAndTags(text, tagLst, metaData).filter{ m => + pool match { + case Full(p) => + m.pool(p) + Privilege.hasPermission(userId, p, Permission.Write) + case _ => true + } + }.map{msg => // do some security... only reply to messages // that are in our mailbox for (rt <- replyTo; mb <- Mailbox.find(By(Mailbox.message, rt), - By(Mailbox.user, userId))) msg.replyTo(rt) + By(Mailbox.user, userId)); + rtm <- Message.find(mb.message.is)) + if (rtm.pool == msg.pool) msg.replyTo(rt) + // workaround for compiler bug: + else null msg.saveMe @@ -130,12 +151,14 @@ } case AddToMailbox(msg, reason) => - addToMailbox(msg, reason) + if (!msg.pool.defined_? || canReadPool_?(msg.pool.is)) + addToMailbox(msg, reason) case TestForTracking(msg) => - for (t <- tracking.find(_.doesMatch_?(msg))) - this ! AddToMailbox(msg, TrackReason(t.trackId)) + if (!msg.pool.defined_? || canReadPool_?(msg.pool.is)) + for (t <- tracking.find(_.doesMatch_?(msg))) + this ! AddToMailbox(msg, TrackReason(t.trackId)) case UpdateTracking(ttype) => @@ -158,6 +181,8 @@ case Unlisten(who) => listeners = listeners.filter(_ ne who) case LatestMessages(cnt) => reply(_mailbox.take(cnt).toList) + + case AllowPool(poolId) => pools ::= poolId } } Modified: incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/api/RestAPI.scala URL: http://svn.apache.org/viewvc/incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/api/RestAPI.scala?rev=770989&r1=770988&r2=770989&view=diff ============================================================================== --- incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/api/RestAPI.scala (original) +++ incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/api/RestAPI.scala Sat May 2 22:28:43 2009 @@ -293,6 +293,10 @@ msg <- params.param("message") ?~ "Message not included") yield { val from: String = params.param("via") openOr "api" + val pool = for (poolName <- params.param("pool"); + p <- AccessPool.findPool(poolName, + params.param("realm") openOr "Native") + ) yield p.id.is val xml: Box[Elem] = params.param("metadata").flatMap(md => tryo(XML.loadString(md))) @@ -304,7 +308,8 @@ millis, xml, from, - params.param("replyto").map(toLong)) + params.param("replyto").map(toLong), + pool) true } r @@ -363,14 +368,15 @@ poolName <- S.param("pool") ?~ "Pool not specified"; realm <- (S.param("realm") or Full("Native")); pool <- AccessPool.findPool(poolName, realm) ?~ "Pool not found"; - _ <- Privilege.find(By(Privilege.pool, pool), - By(Privilege.user, adminUser), - By(Privilege.permission, Permission.Admin)) ?~ "User has no permission to administer pool"; userName <- S.param("user") ?~ "User to add to pool not specified"; user <- User.findFromWeb(userName) ?~ "User not found"; permissionName <- (S.param("permission") or Full("Write")); permission <- Box(Permission.valueOf(permissionName)) ?~ "Unknown permission type" - ) yield Privilege.create.user(user).pool(pool).permission(permission).save + ) yield if(Privilege.hasPermission(adminUser.id.is, pool.id.is, Permission.Admin)) { + val result = Privilege.create.user(user).pool(pool).permission(permission).save + if (result) Distributor ! Distributor.AllowUserInPool(user.id.is, pool.id.is) + result + } else false // "User has no permission to administer pool" r } Modified: incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/comet/PublicTimeline.scala URL: http://svn.apache.org/viewvc/incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/comet/PublicTimeline.scala?rev=770989&r1=770988&r2=770989&view=diff ============================================================================== --- incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/comet/PublicTimeline.scala (original) +++ incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/comet/PublicTimeline.scala Sat May 2 22:28:43 2009 @@ -45,7 +45,8 @@ override def localSetup() { super.localSetup() Distributor ! Distributor.PublicTimelineListeners(this) - messages = Message.findAll(OrderBy(Message.id, Descending), + messages = Message.findAll(By(Message.pool, Empty), + OrderBy(Message.id, Descending), MaxRows(40)).map(_.id.is) } @@ -71,7 +72,8 @@ reRender(false) case Distributor.NewMessage(msg) => - messages = (msg.id.is :: messages).take(40) + if (!msg.pool.defined_?) + messages = (msg.id.is :: messages).take(40) if ((millis - lastRender) < 30000L) { if (!scheduled) { Modified: incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/external/Feed.scala URL: http://svn.apache.org/viewvc/incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/external/Feed.scala?rev=770989&r1=770988&r2=770989&view=diff ============================================================================== --- incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/external/Feed.scala (original) +++ incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/external/Feed.scala Sat May 2 22:28:43 2009 @@ -52,7 +52,8 @@ getDate(node), Empty, source, - Empty + Empty, + None ) ).toList } Modified: incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/external/TwitterFeed.scala URL: http://svn.apache.org/viewvc/incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/external/TwitterFeed.scala?rev=770989&r1=770988&r2=770989&view=diff ============================================================================== --- incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/external/TwitterFeed.scala (original) +++ incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/external/TwitterFeed.scala Sat May 2 22:28:43 2009 @@ -53,7 +53,8 @@ tf.parse(node \ "created_at" text).getTime, Empty, "twiiter", - Empty + Empty, + None )).toList } Modified: incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/model/Action.scala URL: http://svn.apache.org/viewvc/incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/model/Action.scala?rev=770989&r1=770988&r2=770989&view=diff ============================================================================== --- incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/model/Action.scala (original) +++ incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/model/Action.scala Sat May 2 22:28:43 2009 @@ -155,7 +155,7 @@ val lastMsg = if (msgList.isEmpty) None else { val m = msgList.first - Some(Distributor.UserCreatedMessage(user, m.getText, m.tags, m.when, Empty, m.source, Full(m.replyTo))) + Some(Distributor.UserCreatedMessage(user, m.getText, m.tags, m.when, Empty, m.source, Full(m.replyTo), None)) } val feed = a match { Modified: incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/model/Privilege.scala URL: http://svn.apache.org/viewvc/incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/model/Privilege.scala?rev=770989&r1=770988&r2=770989&view=diff ============================================================================== --- incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/model/Privilege.scala (original) +++ incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/model/Privilege.scala Sat May 2 22:28:43 2009 @@ -34,6 +34,10 @@ By(user, in.user)). foreach(_.delete_!) } + + def findViewablePools(userId: Long) = Privilege.findMap( + By(Privilege.user, userId) + )(p => Full(p.pool.is)) } class Privilege extends LongKeyedMapper[Privilege] { @@ -45,6 +49,10 @@ object user extends MappedLongForeignKey(this, User) object permission extends MappedEnum(this, Permission) + def hasPermission(userId: Long, poolId: Long, permission: Permission.Value) = Privilege.find( + By(user, userId), + By(pool, poolId) + ).map(_.permission.is >= permission).getOrElse(false) } object Permission extends Enumeration { Modified: incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala URL: http://svn.apache.org/viewvc/incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala?rev=770989&r1=770988&r2=770989&view=diff ============================================================================== --- incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala (original) +++ incubator/esme/branches/access-pools/server/src/main/scala/org/apache/esme/snippet/UserSnip.scala Sat May 2 22:28:43 2009 @@ -54,7 +54,8 @@ millis, Empty, "web", - replyTo) + replyTo, + None) } Noop