protect users coach data: only accessible by friends for now
This commit is contained in:
parent
1f3bd0a8d3
commit
407be57ec7
|
@ -1,7 +1,8 @@
|
|||
package controllers
|
||||
|
||||
import lila.api.Context
|
||||
import lila.app._
|
||||
import lila.user.UserRepo
|
||||
import play.api.mvc.Result
|
||||
import views._
|
||||
|
||||
object Coach extends LilaController {
|
||||
|
@ -9,30 +10,42 @@ object Coach extends LilaController {
|
|||
private def env = Env.coach
|
||||
|
||||
def raw(username: String) = Open { implicit ctx =>
|
||||
OptionFuOk(UserRepo named username) { user =>
|
||||
Accessible(username) { user =>
|
||||
env.statApi.fetch(user.id) map { stat =>
|
||||
html.coach.raw.index(user, stat)
|
||||
Ok(html.coach.raw.index(user, stat))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def json(username: String) = Open { implicit ctx =>
|
||||
JsonOptionFuOk(UserRepo named username) { user =>
|
||||
env.statApi.fetchOrCompute(user.id) flatMap env.jsonView.apply
|
||||
Accessible(username) { user =>
|
||||
env.statApi.fetchOrCompute(user.id) flatMap env.jsonView.apply map { json =>
|
||||
Ok(json) as JSON
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def opening(username: String) = Open { implicit ctx =>
|
||||
OptionFuOk(UserRepo named username) { user =>
|
||||
Accessible(username) { user =>
|
||||
env.statApi.fetch(user.id) map { stat =>
|
||||
html.coach.opening(user, stat)
|
||||
Ok(html.coach.opening(user, stat))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def refresh(username: String) = Open { implicit ctx =>
|
||||
OptionFuRedirect(UserRepo named username) { user =>
|
||||
env.statApi.computeIfOld(user.id) inject routes.Coach.raw(user.username)
|
||||
Accessible(username) { user =>
|
||||
env.statApi.computeIfOld(user.id) inject
|
||||
Redirect(routes.Coach.raw(user.username))
|
||||
}
|
||||
}
|
||||
|
||||
private def Accessible(username: String)(f: lila.user.User => Fu[Result])(implicit ctx: Context) =
|
||||
lila.user.UserRepo named username flatMap {
|
||||
case None => notFound
|
||||
case Some(u) => env.share.grant(u, ctx.me) flatMap {
|
||||
case true => f(u)
|
||||
case false => fuccess(Forbidden(html.coach.forbidden(u)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,10 @@
|
|||
<h2>@trans.letOtherPlayersChallengeYou()</h2>
|
||||
@base.radios(form("challenge"), translatedChallengeChoices)
|
||||
</li>
|
||||
<li>
|
||||
<h2>Share your coach data</h2>
|
||||
@base.radios(form("coachShare"), lila.pref.Pref.CoachShare.choices)
|
||||
</li>
|
||||
</ul>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
|
|
6
app/views/coach/forbidden.scala.html
Normal file
6
app/views/coach/forbidden.scala.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
@(u: User)(implicit ctx: Context)
|
||||
|
||||
@coach.layout(title = s"${u.username} coach data is protected") {
|
||||
|
||||
You cannot see @userLink(u) coach data!
|
||||
}
|
|
@ -8,6 +8,8 @@ import lila.common.PimpedConfig._
|
|||
|
||||
final class Env(
|
||||
config: Config,
|
||||
getPref: String => Fu[lila.pref.Pref],
|
||||
areFriends: (String, String) => Fu[Boolean],
|
||||
db: lila.db.Env) {
|
||||
|
||||
private val settings = new {
|
||||
|
@ -15,6 +17,8 @@ final class Env(
|
|||
}
|
||||
import settings._
|
||||
|
||||
lazy val share = new Share(getPref, areFriends)
|
||||
|
||||
lazy val jsonView = new JsonView
|
||||
|
||||
lazy val statApi = new StatApi(coll = db(CollectionStat))
|
||||
|
@ -24,5 +28,7 @@ object Env {
|
|||
|
||||
lazy val current: Env = "[boot] coach" describes new Env(
|
||||
config = lila.common.PlayApp loadConfig "coach",
|
||||
getPref = lila.pref.Env.current.api.getPrefById,
|
||||
areFriends = lila.relation.Env.current.api.areFriends,
|
||||
db = lila.db.Env.current)
|
||||
}
|
||||
|
|
18
modules/coach/src/main/Share.scala
Normal file
18
modules/coach/src/main/Share.scala
Normal file
|
@ -0,0 +1,18 @@
|
|||
package lila.coach
|
||||
|
||||
import lila.pref.Pref
|
||||
import lila.user.User
|
||||
|
||||
final class Share(
|
||||
getPref: String => Fu[Pref],
|
||||
areFriends: (String, String) => Fu[Boolean]) {
|
||||
|
||||
def grant(coached: User, to: Option[User]): Fu[Boolean] = getPref(coached.id) flatMap { pref =>
|
||||
pref.coachShare match {
|
||||
case _ if to.contains(coached) => fuccess(true)
|
||||
case Pref.CoachShare.EVERYBODY => fuccess(true)
|
||||
case Pref.CoachShare.FRIENDS => to ?? { t => areFriends(coached.id, t.id) }
|
||||
case Pref.CoachShare.NOBODY => fuccess(false)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ private[pref] final class DataForm {
|
|||
"premove" -> number.verifying(Set(0, 1) contains _),
|
||||
"animation" -> number.verifying(Set(0, 1, 2, 3) contains _),
|
||||
"submitMove" -> number.verifying(Set(0, 1, 2) contains _),
|
||||
"coachShare" -> number.verifying(Set(0, 1, 2) contains _),
|
||||
"captured" -> number.verifying(Set(0, 1) contains _)
|
||||
)(PrefData.apply)(PrefData.unapply))
|
||||
|
||||
|
@ -44,6 +45,7 @@ private[pref] final class DataForm {
|
|||
premove: Int,
|
||||
animation: Int,
|
||||
submitMove: Int,
|
||||
coachShare: Int,
|
||||
captured: Int) {
|
||||
|
||||
def apply(pref: Pref) = pref.copy(
|
||||
|
@ -63,6 +65,7 @@ private[pref] final class DataForm {
|
|||
premove = premove == 1,
|
||||
animation = animation,
|
||||
submitMove = submitMove,
|
||||
coachShare = coachShare,
|
||||
captured = captured == 1)
|
||||
}
|
||||
|
||||
|
@ -84,6 +87,7 @@ private[pref] final class DataForm {
|
|||
premove = pref.premove.fold(1, 0),
|
||||
animation = pref.animation,
|
||||
submitMove = pref.submitMove,
|
||||
coachShare = pref.coachShare,
|
||||
captured = pref.captured.fold(1, 0))
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ case class Pref(
|
|||
coordColor: Int,
|
||||
puzzleDifficulty: Int,
|
||||
submitMove: Int,
|
||||
coachShare: Int,
|
||||
tags: Map[String, String] = Map.empty) {
|
||||
|
||||
import Pref._
|
||||
|
@ -143,6 +144,17 @@ object Pref {
|
|||
ALWAYS -> "Always")
|
||||
}
|
||||
|
||||
object CoachShare {
|
||||
val NOBODY = 0
|
||||
val FRIENDS = 1
|
||||
val EVERYBODY = 2
|
||||
|
||||
val choices = Seq(
|
||||
NOBODY -> "With nobody",
|
||||
FRIENDS -> "With friends",
|
||||
EVERYBODY -> "With everybody")
|
||||
}
|
||||
|
||||
object Blindfold {
|
||||
val NO = 0
|
||||
val YES = 1
|
||||
|
@ -275,6 +287,7 @@ object Pref {
|
|||
coordColor = Color.RANDOM,
|
||||
puzzleDifficulty = Difficulty.NORMAL,
|
||||
submitMove = SubmitMove.CORRESPONDENCE,
|
||||
coachShare = CoachShare.FRIENDS,
|
||||
tags = Map.empty)
|
||||
|
||||
import ornicar.scalalib.Zero
|
||||
|
|
|
@ -54,6 +54,7 @@ final class PrefApi(
|
|||
coordColor = r.getD("coordColor", Pref.default.coordColor),
|
||||
puzzleDifficulty = r.getD("puzzleDifficulty", Pref.default.puzzleDifficulty),
|
||||
submitMove = r.getD("submitMove", Pref.default.submitMove),
|
||||
coachShare = r.getD("coachShare", Pref.default.coachShare),
|
||||
tags = r.getD("tags", Pref.default.tags))
|
||||
|
||||
def writes(w: BSON.Writer, o: Pref) = BSONDocument(
|
||||
|
@ -86,6 +87,7 @@ final class PrefApi(
|
|||
"coordColor" -> o.coordColor,
|
||||
"puzzleDifficulty" -> o.puzzleDifficulty,
|
||||
"submitMove" -> o.submitMove,
|
||||
"coachShare" -> o.coachShare,
|
||||
"tags" -> o.tags)
|
||||
}
|
||||
|
||||
|
@ -95,7 +97,8 @@ final class PrefApi(
|
|||
BSONDocument("$set" -> BSONDocument(s"tags.$name" -> value)),
|
||||
upsert = true).void >>- { cache remove user.id }
|
||||
|
||||
def getPref(id: String): Fu[Pref] = cache(id) map (_ getOrElse Pref.create(id))
|
||||
def getPrefById(id: String): Fu[Pref] = cache(id) map (_ getOrElse Pref.create(id))
|
||||
val getPref = getPrefById _
|
||||
def getPref(user: User): Fu[Pref] = getPref(user.id)
|
||||
def getPref(user: Option[User]): Fu[Pref] = user.fold(fuccess(Pref.default))(getPref)
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ object ApplicationBuild extends Build {
|
|||
libraryDependencies ++= provided(play.api, RM, PRM)
|
||||
)
|
||||
|
||||
lazy val coach = project("coach", Seq(common, chess, game, user, analyse)).settings(
|
||||
lazy val coach = project("coach", Seq(common, chess, game, user, analyse, relation, pref)).settings(
|
||||
libraryDependencies ++= provided(play.api, RM, PRM)
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue