Skip to content

Commit

Permalink
implement runtime settings
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Nov 29, 2017
1 parent 48a76f7 commit bac3292
Show file tree
Hide file tree
Showing 16 changed files with 170 additions and 121 deletions.
2 changes: 1 addition & 1 deletion app/Global.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ object Global extends GlobalSettings {
if (lila.common.PlayApp.isProd) {
lila.mon.http.response.code500()
fuccess(InternalServerError(views.html.base.errorPage(ex) {
lila.api.Context(req, lila.app.Env.api.assetVersion.get, lila.i18n.defaultLang)
lila.api.Context(req, lila.common.AssetVersion(lila.app.Env.api.assetVersionSetting.get()), lila.i18n.defaultLang)
}))
} else super.onError(req, ex)
} else fuccess(InternalServerError(ex.getMessage))
Expand Down
33 changes: 18 additions & 15 deletions app/controllers/Dev.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,26 @@ import views._

object Dev extends LilaController {

def assetVersion = Secure(_.AssetVersion) { implicit ctx => me =>
Ok(html.dev.assetVersion(
Env.api.assetVersion.fromConfig,
Env.api.assetVersion.get
)).fuccess
private lazy val settingsList = List[lila.memo.SettingStore[_]](
Env.security.ugcArmedSetting,
Env.api.assetVersionSetting
)

def settings = Secure(_.Settings) { implicit ctx => me =>
Ok(html.dev.settings(settingsList)).fuccess
}

def assetVersionPost = SecureBody(_.AssetVersion) { implicit ctx => me =>
implicit val req = ctx.body
Form(single(
"version" -> number(min = 0)
)).bindFromRequest.fold(
err => funit,
v => Env.api.assetVersion.set(
lila.common.AssetVersion(v)
) inject Redirect(routes.Dev.assetVersion)
) inject Redirect(routes.Dev.assetVersion)
def settingsPost(id: String) = SecureBody(_.Settings) { implicit ctx => me =>
~(for {
setting <- settingsList.find(_.id == id)
form <- setting.form
} yield {
implicit val req = ctx.body
form.bindFromRequest.fold(
err => BadRequest(html.dev.settings(settingsList)).fuccess,
v => setting.setString(v.toString) inject Redirect(routes.Dev.settings)
)
})
}

private val commandForm = Form(single(
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/LilaController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ private[controllers] trait LilaController
}
}

private def getAssetVersion = Env.api.assetVersion.get
protected def getAssetVersion = lila.common.AssetVersion(Env.api.assetVersionSetting.get())

private def blindMode(implicit ctx: UserContext) =
ctx.req.cookies.get(Env.api.Accessibility.blindCookieName) ?? { c =>
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/Tv.scala
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ object Tv extends LilaController {
Pov first game,
get("bg", req) | "light",
lila.pref.Theme(~get("theme", req)).cssClass,
assetVersion = Env.api.assetVersion.get
assetVersion = getAssetVersion
))
}
}
Expand Down
44 changes: 0 additions & 44 deletions app/views/dev/assetVersion.scala.html

This file was deleted.

38 changes: 38 additions & 0 deletions app/views/dev/settings.scala.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
@(settings: List[lila.memo.SettingStore[_]])(implicit ctx: Context)

@title = @{ "Settings" }

@mod.layout(title = title, active = "setting") {

<style type="text/css">
#settings form {
margin-top: 10px;
border-top: 1px solid rgba(120, 120, 120, 0.3);
padding-top: 10px;
}
#settings form label p {
width: 50%;
text-align: right;
display: inline-block;
vertical-align: middle;
margin-right: 10px;
}
</style>

<div id="settings" class="content_box">
<h1 data-icon="%" class="text">@title</h1>
<br /><br />
<p>
Tread lightly.
</p>
@settings.map { s =>
<form action="@routes.Dev.settingsPost(s.id)" method="POST">
<label>
<p>@s.text.getOrElse(s.id)</p>
<input name="v" value="@s.get()" />
</label>
<button type="submit" class="submit button text" data-icon="E"></button>
</form>
}
</div>
}
4 changes: 2 additions & 2 deletions app/views/mod/menu.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
Chat Panic <strong>@if(isChatPanicEnabled){ON}else{OFF}</strong>
</a>
}
@if(isGranted(_.AssetVersion)) {
<a class="@active.active("asset")" href="@routes.Dev.assetVersion">Asset version @ctx.pageData.assetVersion</a>
@if(isGranted(_.Settings)) {
<a class="@active.active("setting")" href="@routes.Dev.settings">Settings</a>
}
@if(isGranted(_.Cli)) {
<a class="@active.active("cli")" href="@routes.Dev.cli">CLI</a>
Expand Down
6 changes: 4 additions & 2 deletions conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -520,11 +520,13 @@ GET /mobile controllers.Main.mobile
GET /lag controllers.Main.lag
GET /fpmenu controllers.Main.fpmenu
GET /get-fishnet controllers.Main.getFishnet
GET /dev/asset-version controllers.Dev.assetVersion
POST /dev/asset-version controllers.Dev.assetVersionPost

# Dev
GET /dev/cli controllers.Dev.cli
POST /dev/cli controllers.Dev.cliPost
POST /cli controllers.Dev.command
GET /dev/settings controllers.Dev.settings
POST /dev/settings/:id controllers.Dev.settingsPost(id: String)

# Mobile Push
POST /mobile/register/:platform/:deviceId controllers.Main.mobileRegister(platform: String, deviceId: String)
Expand Down
28 changes: 0 additions & 28 deletions modules/api/src/main/AssetVersionApi.scala

This file was deleted.

13 changes: 7 additions & 6 deletions modules/api/src/main/Env.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import lila.simul.Simul

final class Env(
config: Config,
db: lila.db.Env,
settingStore: lila.memo.SettingStore.Builder,
renderer: ActorSelection,
system: ActorSystem,
scheduler: lila.common.Scheduler,
Expand Down Expand Up @@ -53,10 +53,11 @@ final class Env(
private val InfluxEventEndpoint = config getString "api.influx_event.endpoint"
private val InfluxEventEnv = config getString "api.influx_event.env"

val assetVersion = new AssetVersionApi(
fromConfig = lila.common.AssetVersion(config getInt "net.asset.version"),
coll = db("flag")
)(system)
val assetVersionSetting = settingStore[Int](
"assetVersion",
default = config getInt "net.asset.version",
text = "Assets version. Increment to force all clients to load a new version of static assets. Decrement to serve a previous revision of static assets.".some
)

object Accessibility {
val blindCookieName = config getString "accessibility.blind.cookie.name"
Expand Down Expand Up @@ -135,7 +136,7 @@ object Env {

lazy val current = "api" boot new Env(
config = lila.common.PlayApp.loadConfig,
db = lila.db.Env.current,
settingStore = lila.memo.Env.current.settingStore,
renderer = lila.hub.Env.current.actor.renderer,
userEnv = lila.user.Env.current,
analyseEnv = lila.analyse.Env.current,
Expand Down
6 changes: 5 additions & 1 deletion modules/memo/src/main/Env.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ final class Env(
private val CollectionCache = config getString "collection.cache"
private val CollectionConfig = config getString "collection.config"

private val configColl = db(CollectionConfig)

lazy val mongoCache: MongoCache.Builder = new MongoCache.Builder(db(CollectionCache))

lazy val configStore: ConfigStore.Builder = new ConfigStore.Builder(db(CollectionConfig))
lazy val configStore: ConfigStore.Builder = new ConfigStore.Builder(configColl)

lazy val settingStore: SettingStore.Builder = new SettingStore.Builder(configColl)

lazy val asyncCache: AsyncCache.Builder = new AsyncCache.Builder()(system)
}
Expand Down
66 changes: 66 additions & 0 deletions modules/memo/src/main/SettingStore.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package lila.memo

import lila.db.dsl._
import play.api.data._, Forms._

final class SettingStore[A: BSONValueHandler: SettingStore.StringReader] private (
coll: Coll,
val id: String,
val default: A,
val text: Option[String]
) {

import SettingStore.dbField

private var value: A = default

def get(): A = value

def set(v: A): Funit = {
value = v
coll.updateField(dbId, dbField, v).void
}

def form: Option[Form[_]] = SettingStore formOf this

def setString(str: String): Funit = (implicitly[SettingStore.StringReader[A]] read str) ?? set

override def toString = s"SettingStore(id: $id, default: $default, value: $value)"

private val dbId = $id(id)

coll.primitiveOne[A](dbId, dbField) map2 { (v: A) =>
value = v
}
}

object SettingStore {

final class Builder(coll: Coll) {
def apply[A: BSONValueHandler: StringReader](
id: String,
default: A,
text: Option[String] = None
) = new SettingStore[A](coll, id, default, text)
}

private final class StringReader[A](val read: String => Option[A])

private object StringReader {
implicit val booleanReader = new StringReader[Boolean](v =>
if (Set("on", "yes", "true", "1")(v)) true.some
else if (Set("off", "no", "false", "0")(v)) false.some
else none)
implicit val intReader = new StringReader[Int](parseIntOption)
implicit val stringReader = new StringReader[String](some)
}

def formOf(s: SettingStore[_]): Option[Form[_]] = s.value match {
case v: Boolean => Form(single("v" -> boolean)) fill v some
case v: Int => Form(single("v" -> number)) fill v some
case v: String => Form(single("v" -> text)) fill v some
case _ => none
}

private val dbField = "setting"
}
10 changes: 9 additions & 1 deletion modules/security/src/main/Env.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ final class Env(
authenticator: lila.user.Authenticator,
slack: lila.slack.SlackApi,
asyncCache: lila.memo.AsyncCache.Builder,
settingStore: lila.memo.SettingStore.Builder,
system: akka.actor.ActorSystem,
scheduler: lila.common.Scheduler,
db: lila.db.Env
Expand Down Expand Up @@ -82,11 +83,17 @@ final class Env(

lazy val ipIntel = new IpIntel(asyncCache, NetEmail)

lazy val ugcArmedSetting = settingStore[Boolean](
"ugcArmed",
default = true,
text = "Enable the user garbage collector".some
)

lazy val garbageCollector = new GarbageCollector(
userSpyApi,
ipIntel,
slack,
db("flag"),
ugcArmedSetting.get,
system
)

Expand Down Expand Up @@ -159,6 +166,7 @@ object Env {
authenticator = lila.user.Env.current.authenticator,
slack = lila.slack.Env.current.api,
asyncCache = lila.memo.Env.current.asyncCache,
settingStore = lila.memo.Env.current.settingStore,
system = lila.common.PlayApp.system,
scheduler = lila.common.PlayApp.scheduler,
captcher = lila.hub.Env.current.actor.captcher
Expand Down
Loading

0 comments on commit bac3292

Please sign in to comment.