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