Skip to content

Commit

Permalink
improve, compress and sign the javascript
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Oct 20, 2012
1 parent af56365 commit 110e2a8
Show file tree
Hide file tree
Showing 18 changed files with 94 additions and 28 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ logs
project/project
project/target
public/trans
public/compiled
serve/
serve/README
target
Expand Down
3 changes: 3 additions & 0 deletions app/controllers/LilaController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ trait LilaController

protected def JsonIOk(map: IO[Map[String, Any]]) = JsonOk(map.unsafePerformIO)

protected def JsIOk(js: IO[String], headers: (String, String)*) =
Ok(js.unsafePerformIO) as JAVASCRIPT withHeaders (headers: _*)

protected def ValidOk(valid: Valid[Unit]) = valid.fold(
e BadRequest(e.shows),
_ Ok("ok")
Expand Down
17 changes: 12 additions & 5 deletions app/controllers/Round.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ object Round extends LilaController with TheftPrevention with RoundEventPerforme
private def userRepo = env.user.userRepo
private def analyser = env.analyse.analyser
private def tournamentRepo = env.tournament.repo
private def gameJs = env.game.gameJs

def websocketWatcher(gameId: String, color: String) = WebSocket.async[JsValue] { req
implicit val ctx = reqToCtx(req)
Expand All @@ -32,16 +33,22 @@ object Round extends LilaController with TheftPrevention with RoundEventPerforme
color,
getInt("version"),
get("sri"),
get("tk"),
ctx).unsafePerformIO
}

def websocketPlayer(fullId: String) = WebSocket.async[JsValue] { req
implicit val ctx = reqToCtx(req)
socket.joinPlayer(
fullId,
getInt("version"),
get("sri"),
ctx).unsafePerformIO
socket.joinPlayer(
fullId,
getInt("version"),
get("sri"),
get("tk"),
ctx).unsafePerformIO
}

def signedJs(gameId: String) = Open { implicit ctx
JsIOk(gameRepo token gameId map gameJs.sign, CACHE_CONTROL -> "max-age=3600")
}

def player(fullId: String) = Open { implicit ctx
Expand Down
1 change: 1 addition & 0 deletions app/core/Settings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ final class Settings(config: Config, val IsDev: Boolean) {
val GamePaginatorMaxPerPage = getInt("game.paginator.max_per_page")
val GameCollectionGame = getString("game.collection.game")
val GameCollectionPgn = getString("game.collection.pgn")
val GameJsPath = getString("game.js_path")

val SearchESHost = getString("search.elasticsearch.host")
val SearchESPort = getInt("search.elasticsearch.port")
Expand Down
7 changes: 7 additions & 0 deletions app/game/DbGame.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import scala.math.min

case class DbGame(
id: String,
token: String,
whitePlayer: DbPlayer,
blackPlayer: DbPlayer,
status: Status,
Expand Down Expand Up @@ -322,6 +323,7 @@ case class DbGame(

def encode = RawDbGame(
id = id,
tk = token.some filter (DbGame.defaultToken !=),
p = players map (_.encode),
s = status.id,
t = turns,
Expand Down Expand Up @@ -366,6 +368,8 @@ object DbGame {
val gameIdSize = 8
val playerIdSize = 4
val fullIdSize = 12
val tokenSize = 4
val defaultToken = "-tk-"

def abandonedDate = DateTime.now - 10.days

Expand All @@ -380,6 +384,7 @@ object DbGame {
mode: Mode,
variant: Variant): DbGame = DbGame(
id = IdGenerator.game,
token = IdGenerator.token,
whitePlayer = whitePlayer withEncodedPieces game.allPieces,
blackPlayer = blackPlayer withEncodedPieces game.allPieces,
status = Status.Created,
Expand All @@ -398,6 +403,7 @@ object DbGame {

case class RawDbGame(
@Key("_id") id: String,
tk: Option[String] = None,
p: List[RawDbPlayer],
s: Int,
t: Int,
Expand All @@ -423,6 +429,7 @@ case class RawDbGame(
trueStatus Status(s)
} yield DbGame(
id = id,
token = tk | DbGame.defaultToken,
whitePlayer = whitePlayer,
blackPlayer = blackPlayer,
status = trueStatus,
Expand Down
2 changes: 2 additions & 0 deletions app/game/GameEnv.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@ final class GameEnv(
lazy val listMenu = ListMenu(cached) _

lazy val rewind = new Rewind

lazy val gameJs = new GameJs(settings.GameJsPath)
}
14 changes: 14 additions & 0 deletions app/game/GameJs.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package lila
package game

final class GameJs(path: String) {

lazy val unsigned: String = {
val source = scala.io.Source fromFile path
source.mkString ~ { _ => source.close }
}

val placeholder = "--tkph--"

def sign(token: String) = unsigned.replace(placeholder, token)
}
4 changes: 4 additions & 0 deletions app/game/GameRepo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ final class GameRepo(collection: MongoCollection)

def pov(ref: PovRef): IO[Option[Pov]] = pov(ref.gameId, ref.color)

def token(id: String): IO[String] = io {
primitiveProjection[String](idSelector(id), "tk") | DbGame.defaultToken
}

def save(game: DbGame): IO[Unit] = io {
update(idSelector(game), _grater asDBObject game.encode)
}
Expand Down
2 changes: 2 additions & 0 deletions app/game/IdGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ object IdGenerator {

def game = Random nextString DbGame.gameIdSize

def token = Random nextString DbGame.tokenSize

def player = Random nextString DbGame.playerIdSize
}
17 changes: 11 additions & 6 deletions app/round/Socket.scala
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,17 @@ final class Socket(
colorName: String,
version: Option[Int],
uid: Option[String],
token: Option[String],
ctx: Context): IO[SocketPromise] =
getWatcherPov(gameId, colorName) map { join(_, false, version, uid, ctx) }
getWatcherPov(gameId, colorName) map { join(_, false, version, uid, token, ctx) }

def joinPlayer(
fullId: String,
version: Option[Int],
uid: Option[String],
token: Option[String],
ctx: Context): IO[SocketPromise] =
getPlayerPov(fullId) map { join(_, true, version, uid, ctx) }
getPlayerPov(fullId) map { join(_, true, version, uid, token, ctx) }

private def parseMove(event: JsValue) = for {
d event obj "d"
Expand All @@ -136,20 +138,23 @@ final class Socket(
owner: Boolean,
versionOption: Option[Int],
uidOption: Option[String],
tokenOption: Option[String],
ctx: Context): SocketPromise =
((povOption |@| uidOption |@| versionOption) apply {
(pov: Pov, uid: String, version: Int)
((povOption |@| uidOption |@| tokenOption |@| versionOption) apply {
(pov: Pov, uid: String, token: String, version: Int)
(for {
hub hubMaster ? GetHub(pov.gameId) mapTo manifest[ActorRef]
socket hub ? Join(
uid = uid,
user = ctx.me,
version = version,
color = pov.color,
owner = owner
owner = owner && token == pov.game.token
) map {
case Connected(enumerator, member) {
if (owner && !member.owner) println("Websocket hijacking detected (%s) %s".format(pov.gameId, ctx.toString))
if (owner && !member.owner) {
println("Websocket hijacking detected %s %s".format(pov.gameId, ctx.toString))
}
(Iteratee.foreach[JsValue](
controller(hub, uid, member, PovRef(pov.gameId, member.color))
) mapDone { _
Expand Down
11 changes: 7 additions & 4 deletions app/templating/AssetHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import play.api.templates.Html

trait AssetHelper {

val assetVersion = 4
val assetVersion = 6

def cssTag(name: String) = css("stylesheets/" + name)

Expand All @@ -20,10 +20,13 @@ trait AssetHelper {

def jsTag(name: String) = js("javascripts/" + name)

def jsTagC(name: String) = js("compiled/" + name)

def jsVendorTag(name: String) = js("vendor/" + name)

def js(path: String) = Html {
"""<script src="%s?v=%d"></script>"""
.format(routes.Assets.at(path), assetVersion)
private def js(path: String) = jsAt(routes.Assets.at(path).toString)

def jsAt(path: String) = Html {
"""<script src="%s?v=%d"></script>""".format(path, assetVersion)
}
}
4 changes: 2 additions & 2 deletions app/views/base/layout.scala.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@(title: String, active: Option[ui.SiteMenu.Elem] = None, baseline: Option[Html] = None, goodies: Option[Html] = None, menu: Option[Html] = None, chat: Option[Html] = None, underchat: Option[Html] = None, robots: Boolean = true, moreCss: Html = Html(""), moreJs: Html = Html(""))(body: Html)(implicit ctx: Context)
@(title: String, active: Option[ui.SiteMenu.Elem] = None, baseline: Option[Html] = None, goodies: Option[Html] = None, menu: Option[Html] = None, chat: Option[Html] = None, underchat: Option[Html] = None, robots: Boolean = true, moreCss: Html = Html(""), moreJs: Html = Html(""), signedJs: Option[String] = None)(body: Html)(implicit ctx: Context)

<!doctype html>
<html lang="@lang.language">
Expand Down Expand Up @@ -105,7 +105,7 @@ <h1>
</div>
</div>
@jsTag("deps.min.js")
@jsTag("big.js")
@signedJs.fold(jsAt, jsTagC("big.js"))
@moreJs
@if(lang.language != "en") {
<script src="@routes.Assets.at("trans/" + lang.language + ".js")?v=@assetVersion"></script>
Expand Down
6 changes: 4 additions & 2 deletions app/views/round/layout.scala.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
@(title: String, goodies: Html, chat: Option[Html] = None, underchat: Option[Html] = None, robots: Boolean = true)(body: Html)(implicit ctx: Context)
@(title: String, goodies: Html, chat: Option[Html] = None, underchat: Option[Html] = None, robots: Boolean = true, signedJs: Option[String] = None)(body: Html)(implicit ctx: Context)

@base.layout(
title = title,
goodies = goodies.some,
active = siteMenu.play.some,
chat = chat,
underchat = underchat,
robots = robots)(body)
robots = robots,
signedJs = signedJs)(body)
3 changes: 2 additions & 1 deletion app/views/round/player.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
title = title,
goodies = views.html.game.infoBox(pov, tour),
chat = roomHtml.map(round.room(_, false)),
underchat = underchat.some) {
underchat = underchat.some,
signedJs = routes.Round.signedJs(pov.gameId).toString.some) {
<div class="lichess_game clearfix lichess_player_@color not_spectator"
data-socket-url="@routes.Round.websocketPlayer(fullId)"
data-table-url="@routes.Round.tablePlayer(fullId)"
Expand Down
7 changes: 7 additions & 0 deletions bin/closure
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh
. bin/lilarc

lilalog "Compiling javascript"

mkdir -p public/compiled
closure --js public/javascripts/big.js --js_output_file public/compiled/big.js
1 change: 1 addition & 0 deletions bin/prod/deploy
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ if [ -z $1 ]; then
elif [ $1 = "main" ]; then
REMOTE="balrog"
REMOTE_DIR="/home/lila"
bin/closure
elif [ $1 = "ai" ]; then
REMOTE="marty"
REMOTE_DIR="/home/lila3"
Expand Down
1 change: 1 addition & 0 deletions conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ GET /$gameId<[\w\-]{8}> controllers.Round.watcher(g
GET /$gameId<[\w\-]{8}>/$color<white|black> controllers.Round.watcher(gameId: String, color: String)
GET /$fullId<[\w\-]{12}> controllers.Round.player(fullId: String)
GET /$gameId<[\w\-]{8}>/$color<white|black>/socket controllers.Round.websocketWatcher(gameId: String, color: String)
GET /$gameId<[\w\-]{8}>/signed.js controllers.Round.signedJs(gameId: String)
GET /$fullId<[\w\-]{12}>/socket controllers.Round.websocketPlayer(fullId: String)
GET /$fullId<[\w\-]{12}>/abort controllers.Round.abort(fullId: String)
GET /$fullId<[\w\-]{12}>/resign controllers.Round.resign(fullId: String)
Expand Down
21 changes: 13 additions & 8 deletions public/javascripts/big.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @externs_url https://closure-compiler.googlecode.com/svn/trunk/contrib/externs/jquery-1.7.js
// ==/ClosureCompiler==
if (typeof console == "undefined" || typeof console.log == "undefined") console = {
log: function() {}
};
Expand Down Expand Up @@ -512,7 +516,7 @@ $.widget("lichess.game", {
self.options.tableUrl = self.element.data('table-url');
self.options.playersUrl = self.element.data('players-url');
self.options.socketUrl = self.element.data('socket-url');
self.socketAckTimeout;
self.socketAckTimeout = null;

$("div.game_tournament .clock").each(function() {
$(this).clock({time: $(this).data("time")}).clock("start");
Expand Down Expand Up @@ -567,6 +571,7 @@ $.widget("lichess.game", {
options: {
name: "game"
},
params: { tk: "--tkph--"},
events: {
ack: function() {
clearTimeout(self.socketAckTimeout);
Expand Down Expand Up @@ -871,12 +876,12 @@ $.widget("lichess.game", {
moveData.promotion = "queen";
sendMoveRequest(moveData);
} else {
var $choices = $('<div class="lichess_promotion_choice">').appendTo(self.$board).html('\
<div data-piece="queen" class="lichess_piece queen ' + color + '"></div>\
<div data-piece="knight" class="lichess_piece knight ' + color + '"></div>\
<div data-piece="rook" class="lichess_piece rook ' + color + '"></div>\
<div data-piece="bishop" class="lichess_piece bishop ' + color + '"></div>').fadeIn(self.options.animation_delay).find('div.lichess_piece').click(function() {
moveData.promotion = $(this).attr('data-piece');
var $choices = $('<div class="lichess_promotion_choice">')
.appendTo(self.$board)
.html('<div data-piece="queen" class="lichess_piece queen ' + color + '"></div><div data-piece="knight" class="lichess_piece knight ' + color + '"></div><div data-piece="rook" class="lichess_piece rook ' + color + '"></div><div data-piece="bishop" class="lichess_piece bishop ' + color + '"></div>')
.fadeIn(self.options.animation_delay)
.find('div.lichess_piece')
.click(function() { moveData.promotion = $(this).attr('data-piece');
sendMoveRequest(moveData);
$choices.fadeOut(self.options.animation_delay, function() {
$choices.remove();
Expand Down Expand Up @@ -1169,7 +1174,7 @@ $.widget("lichess.chat", {
},
append: function(msg) {
var self = this;
self.$msgs.append(urlToLink(msg))[0];
self.$msgs.append(urlToLink(msg));
$('body').trigger('lichess.content_loaded');
self.$msgs[0].scrollTop = 9999999;
}
Expand Down

0 comments on commit 110e2a8

Please sign in to comment.