Skip to content

Commit

Permalink
no longer mix cookies and oauth on any endpoint
Browse files Browse the repository at this point in the history
With an exception for /games/export/:username.

This endpoint works without any auth, with cookie auth, and with oauth.
The only difference is in throttling.
  • Loading branch information
ornicar committed Apr 26, 2018
1 parent 9a2dd5f commit 8724766
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 69 deletions.
46 changes: 24 additions & 22 deletions app/controllers/Account.scala
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,20 @@ object Account extends LilaController {
Env.security.forms.changeEmail(user, _)
}

def email = AuthOrScoped(_.Email.Read)(
auth = implicit ctx => me =>
if (getBool("check")) Ok(renderCheckYourEmail).fuccess
else emailForm(me) map { form =>
Ok(html.account.email(me, form))
},
scoped = _ => me =>
UserRepo email me.id map {
_ ?? { email =>
Ok(Json.obj("email" -> email.value))
}
def email = Auth { implicit ctx => me =>
if (getBool("check")) Ok(renderCheckYourEmail).fuccess
else emailForm(me) map { form =>
Ok(html.account.email(me, form))
}
}

def apiEmail = Scoped(_.Email.Read) { _ => me =>
UserRepo email me.id map {
_ ?? { email =>
Ok(Json.obj("email" -> email.value))
}
)
}
}

def renderCheckYourEmail(implicit ctx: Context) =
html.auth.checkYourEmail(lila.security.EmailConfirm.cookie get ctx.req)
Expand Down Expand Up @@ -169,22 +170,23 @@ object Account extends LilaController {
}
}

def kid = AuthOrScoped(_.Preference.Read)(
auth = implicit ctx => me => Ok(html.account.kid(me)).fuccess,
scoped = _ => me => Ok(Json.obj("kid" -> me.kid)).fuccess
)
def kid = Auth { implicit ctx => me =>
Ok(html.account.kid(me)).fuccess
}
def apiKid = Scoped(_.Preference.Read) { _ => me =>
Ok(Json.obj("kid" -> me.kid)).fuccess
}

// App BC
def kidToggle = Auth { ctx => me =>
UserRepo.setKid(me, !me.kid) inject Ok
}

def kidPost = AuthOrScopedTupple(_.Preference.Write) {
def set(me: UserModel, req: RequestHeader) = UserRepo.setKid(me, getBool("v", req))
(
ctx => me => set(me, ctx.req) inject Redirect(routes.Account.kid),
req => me => set(me, req) inject jsonOkResult
)
def kidPost = Auth { implicit ctx => me =>
UserRepo.setKid(me, getBool("v")) inject Redirect(routes.Account.kid)
}
def apiKidPost = Scoped(_.Preference.Write) { req => me =>
UserRepo.setKid(me, getBool("v", req)) inject jsonOkResult
}

private def currentSessionId(implicit ctx: Context) =
Expand Down
24 changes: 14 additions & 10 deletions app/controllers/Challenge.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ object Challenge extends LilaController {
private def isForMe(challenge: ChallengeModel)(implicit ctx: Context) =
challenge.destUserId.fold(true)(ctx.userId.contains)

def accept(id: String) = OpenOrScoped()(
open = implicit ctx => OptionFuResult(env.api byId id) { c =>
def accept(id: String) = Open { implicit ctx =>
OptionFuResult(env.api byId id) { c =>
isForMe(c) ?? env.api.accept(c, ctx.me).flatMap {
case Some(pov) => negotiate(
html = Redirect(routes.Round.watcher(pov.gameId, "white")).fuccess,
Expand All @@ -71,16 +71,18 @@ object Challenge extends LilaController {
api = _ => notFoundJson("Someone else accepted the challenge")
)
}
},
scoped = _ => me => env.api.onlineByIdFor(id, me) flatMap {
}
}
def apiAccept(id: String) = Scoped() { _ => me =>
env.api.onlineByIdFor(id, me) flatMap {
_ ?? { env.api.accept(_, me.some) }
} flatMap { res =>
if (res.isDefined) jsonOkResult.fuccess
else Env.bot.player.rematchAccept(id, me) flatMap {
_.fold(jsonOkResult.fuccess, notFoundJson())
}
}
)
}

private def withChallengeAnonCookie(cond: Boolean, c: ChallengeModel, owner: Boolean)(res: Result)(implicit ctx: Context): Fu[Result] =
cond ?? {
Expand All @@ -99,18 +101,20 @@ object Challenge extends LilaController {
cookieOption.fold(res) { res.withCookies(_) }
}

def decline(id: String) = AuthOrScoped()(
auth = implicit ctx => me => OptionFuResult(env.api byId id) { c =>
def decline(id: String) = Auth { implicit ctx => me =>
OptionFuResult(env.api byId id) { c =>
if (isForMe(c)) env.api decline c
else notFound
},
scoped = _ => me => env.api.activeByIdFor(id, me) flatMap {
}
}
def apiDecline(id: String) = Scoped() { _ => me =>
env.api.activeByIdFor(id, me) flatMap {
case None => Env.bot.player.rematchDecline(id, me) flatMap {
_.fold(jsonOkResult.fuccess, notFoundJson())
}
case Some(c) => env.api.decline(c) inject jsonOkResult
}
)
}

def cancel(id: String) = Open { implicit ctx =>
OptionFuResult(env.api byId id) { c =>
Expand Down
8 changes: 4 additions & 4 deletions app/controllers/Game.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ object Game extends LilaController {
}

def export(username: String) = OpenOrScoped()(
open = ctx => handleExport(username, ctx.me, ctx.req),
scoped = req => me => handleExport(username, me.some, req)
open = ctx => handleExport(username, ctx.me, ctx.req, oauth = false),
scoped = req => me => handleExport(username, me.some, req, oauth = true)
)

private def handleExport(username: String, me: Option[lila.user.User], req: RequestHeader) =
private def handleExport(username: String, me: Option[lila.user.User], req: RequestHeader, oauth: Boolean) =
lila.user.UserRepo named username flatMap {
_ ?? { user =>
RequireHttp11(req) {
Expand All @@ -54,7 +54,7 @@ object Game extends LilaController {
perSecond = MaxPerSecond(me match {
case None => 10
case Some(m) if m is user.id => 50
case Some(_) => 20
case Some(_) if oauth => 20 // bonus for oauth logged in only (not to XSRF)
})
)
val date = (DateTimeFormat forPattern "yyyy-MM-dd") print new DateTime
Expand Down
35 changes: 5 additions & 30 deletions app/controllers/LilaController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,7 @@ private[controllers] trait LilaController
protected def OpenOrScoped(selectors: OAuthScope.Selector*)(
open: Context => Fu[Result],
scoped: RequestHeader => UserModel => Fu[Result]
): Action[Unit] = OpenOrScoped(BodyParsers.parse.empty)(selectors)(open, scoped)

protected def OpenOrScoped[A](parser: BodyParser[A])(selectors: Seq[OAuthScope.Selector])(
open: Context => Fu[Result],
scoped: RequestHeader => UserModel => Fu[Result]
): Action[A] = Action.async(parser) { req =>
): Action[Unit] = Action.async(BodyParsers.parse.empty) { req =>
if (HTTPRequest isOAuth req) handleScoped(selectors, scoped)(req)
else handleOpen(open, req)
}
Expand All @@ -91,30 +86,10 @@ private[controllers] trait LilaController

protected def Auth[A](parser: BodyParser[A])(f: Context => UserModel => Fu[Result]): Action[A] =
Action.async(parser) { req =>
handleAuth(f, req)
}

protected def AuthOrScoped(selectors: OAuthScope.Selector*)(
auth: Context => UserModel => Fu[Result],
scoped: RequestHeader => UserModel => Fu[Result]
): Action[Unit] = AuthOrScoped(BodyParsers.parse.empty)(selectors)(auth, scoped)

protected def AuthOrScopedTupple(selectors: OAuthScope.Selector*)(
handlers: (Context => UserModel => Fu[Result], RequestHeader => UserModel => Fu[Result])
): Action[Unit] = AuthOrScoped(BodyParsers.parse.empty)(selectors)(handlers._1, handlers._2)

protected def AuthOrScoped[A](parser: BodyParser[A])(selectors: Seq[OAuthScope.Selector])(
auth: Context => UserModel => Fu[Result],
scoped: RequestHeader => UserModel => Fu[Result]
): Action[A] = Action.async(parser) { req =>
if (HTTPRequest isOAuth req) handleScoped(selectors, scoped)(req)
else handleAuth(auth, req)
}

private def handleAuth(f: Context => UserModel => Fu[Result], req: RequestHeader): Fu[Result] =
CSRF(req) {
reqToCtx(req) flatMap { ctx =>
ctx.me.fold(authenticationFailed(ctx))(f(ctx))
CSRF(req) {
reqToCtx(req) flatMap { ctx =>
ctx.me.fold(authenticationFailed(ctx))(f(ctx))
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/Pref.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ object Pref extends LilaController {
private def api = Env.pref.api
private def forms = lila.pref.DataForm

def get = Scoped(_.Preference.Read) { _ => me =>
def apiGet = Scoped(_.Preference.Read) { _ => me =>
Env.pref.api.getPref(me) map { prefs =>
Ok {
import play.api.libs.json._
Expand Down
9 changes: 7 additions & 2 deletions conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,6 @@ GET /fishnet/status controllers.Fishnet.status
# Pref
POST /pref/zoom controllers.Pref.setZoom
POST /pref/:name controllers.Pref.set(name: String)
GET /account/preferences controllers.Pref.get
GET /account/preferences/:categ controllers.Pref.form(categ: String)
POST /account/preferences controllers.Pref.formApply
POST /account/preferences/tag/:name/:value controllers.Pref.saveTag(name: String, value: String)
Expand Down Expand Up @@ -503,6 +502,13 @@ GET /api/users/status controllers.Api.usersStatus
GET /api/crosstable/:u1/:u2 controllers.Api.crosstable(u1: String, u2: String)
POST /api/stream/games-by-users controllers.Api.gamesByUsersStream
GET /api/stream/event controllers.Api.eventStream
GET /api/account controllers.Account.me
GET /api/account/email controllers.Account.apiEmail
GET /api/account/kid controllers.Account.apiKid
POST /api/account/kid controllers.Account.apiKidPost
GET /api/account/preferences controllers.Pref.apiGet
POST /api/challenge/$id<\w{8}>/accept controllers.Challenge.apiAccept(id: String)
POST /api/challenge/$id<\w{8}>/decline controllers.Challenge.apiDecline(id: String)

# Bot API
GET /bot/game/stream/:id controllers.Bot.gameStream(id: String)
Expand All @@ -528,7 +534,6 @@ GET /account/security controllers.Account.security
POST /account/signout/:sessionId controllers.Account.signout(sessionId: String)
GET /account/info controllers.Account.info
GET /account/now-playing controllers.Account.nowPlaying
GET /account/me controllers.Account.me

# OAuth
GET /account/oauth/token controllers.OAuthToken.index
Expand Down

0 comments on commit 8724766

Please sign in to comment.