dramatically improve user spy
This commit is contained in:
parent
86442e42fe
commit
ff73b353bf
|
@ -19,9 +19,37 @@
|
|||
</div>
|
||||
|
||||
<div class="user_spy">
|
||||
<br />
|
||||
<strong>Other usernames:</strong>
|
||||
<div class="usernames">@Html(spy.otherUsernames.map(userIdLinkMini).mkString(", "))</div>
|
||||
@if(spy.otherUsers.isEmpty) {
|
||||
<strong>No user found with same IPs</strong>
|
||||
} else {
|
||||
<strong>Shares IP addresses with @spy.otherUsers.size user(s)</strong>
|
||||
<table class="others slist">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>User</th>
|
||||
<th>Games</th>
|
||||
<th>Engine</th>
|
||||
<th>Muted</th>
|
||||
<th>IPban</th>
|
||||
<th>Closed</th>
|
||||
<th>Created</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@spy.otherUsers.map { o =>
|
||||
<tr>
|
||||
<td>@userLink(o)</td>
|
||||
<td>@o.nbGames</td>
|
||||
<td>@{o.engine.??("X")}</td>
|
||||
<td>@{o.muted.??("X")}</td>
|
||||
<td></td>
|
||||
<td>@{o.disabled.??("X")}</td>
|
||||
<td>@showDate(o.createdAt)</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
<strong>IP addresses:</strong> <ul>@spy.ips.map { ip =>
|
||||
<li>@ip</li>
|
||||
}</ul>
|
||||
|
|
|
@ -17,10 +17,12 @@ import scala.concurrent.Future
|
|||
case class UserSpy(
|
||||
ips: List[String],
|
||||
uas: List[String],
|
||||
otherUsers: Set[User])
|
||||
otherUsers: List[User])
|
||||
|
||||
object Store {
|
||||
|
||||
type IP = String
|
||||
|
||||
def save(sessionId: String, userId: String, req: RequestHeader): Funit =
|
||||
$insert(Json.obj(
|
||||
"_id" -> sessionId,
|
||||
|
@ -50,36 +52,36 @@ object Store {
|
|||
private[security] def userSpy(userId: String): Fu[UserSpy] = for {
|
||||
user ← UserRepo byId userId flatten "[spy] user not found"
|
||||
objs ← $find(selectUser(user.id))
|
||||
users ← explore(user)
|
||||
users ← explore(Set(user), Set.empty, Set(user))
|
||||
} yield UserSpy(
|
||||
ips = objs.map(_ str "ip").flatten.distinct,
|
||||
uas = objs.map(_ str "ua").flatten.distinct,
|
||||
otherUsers = users
|
||||
otherUsers = (users - user).toList.sortBy(_.createdAt)
|
||||
)
|
||||
|
||||
private def explore(user: User, withKnown: Set[User] = Set.empty): Fu[Set[User]] = {
|
||||
val known = Seq(user) ++: withKnown
|
||||
newSiblings(user.id, known) flatMap { children ⇒
|
||||
children.foldLeft(fuccess(children)) {
|
||||
case (siblings, child) ⇒ siblings flatMap { sibs ⇒
|
||||
explore(child, known ++ sibs) map (sibs ++)
|
||||
}
|
||||
private def explore(users: Set[User], ips: Set[IP], _users: Set[User]): Fu[Set[User]] = {
|
||||
nextIps(users, ips) flatMap { nIps ⇒
|
||||
nextUsers(nIps, users) flatMap { nUsers ⇒
|
||||
nUsers.isEmpty ? fuccess(users) | explore(nUsers, nIps ++: ips, nUsers ++: users)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def newSiblings(user: String, without: Set[User]): Fu[Set[User]] =
|
||||
userIps(user) flatMap { ips ⇒
|
||||
usersByIps(ips) map (_ diff without)
|
||||
private def nextIps(users: Set[User], ips: Set[IP]): Fu[Set[IP]] =
|
||||
users.nonEmpty ?? {
|
||||
$primitive(
|
||||
Json.obj("user" -> $in(users.map(_.id)), "ip" -> $nin(ips)), "ip"
|
||||
)(_.asOpt[IP]) map (_.toSet)
|
||||
}
|
||||
|
||||
private def userIps(user: String): Fu[Set[String]] =
|
||||
$primitive(selectUser(user), "ip")(_.asOpt[String]) map (_.toSet)
|
||||
|
||||
private def usersByIps(ips: Set[String]): Fu[Set[User]] =
|
||||
$primitive(
|
||||
Json.obj("ip" -> $in(ips)), "user"
|
||||
)(_.asOpt[String]) flatMap UserRepo.byIds map (_.toSet)
|
||||
private def nextUsers(ips: Set[IP], users: Set[User]): Fu[Set[User]] =
|
||||
ips.nonEmpty ?? {
|
||||
$primitive(
|
||||
Json.obj("ip" -> $in(ips), "user" -> $nin(users.map(_.id))), "user"
|
||||
)(_.asOpt[String]) flatMap { userIds ⇒
|
||||
userIds.nonEmpty ?? (UserRepo byIds userIds) map (_.toSet)
|
||||
}
|
||||
}
|
||||
|
||||
private def ip(req: RequestHeader) = req.remoteAddress
|
||||
|
||||
|
|
|
@ -84,6 +84,9 @@ div.user_show .mod_zone {
|
|||
display: none;
|
||||
margin: 1em 0 0 20px;
|
||||
}
|
||||
div.user_show .mod_zone form {
|
||||
margin: 0 25px 0 0;
|
||||
}
|
||||
div.user_show .mod_zone .usernames a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue