allow login through TOR

This commit is contained in:
Thibault Duplessis 2016-06-20 17:31:53 +02:00
parent bdaadca26d
commit f7e56a0270
5 changed files with 45 additions and 51 deletions

View file

@ -46,7 +46,6 @@ object Auth extends LilaController {
}
private def authRecovery(implicit ctx: Context): PartialFunction[Throwable, Fu[Result]] = {
case lila.security.Api.AuthFromTorExitNode => noTorResponse
case lila.security.Api.MustConfirmEmail(userId) => UserRepo byId userId map {
case Some(user) => BadRequest(html.auth.checkYourEmail(user))
case None => BadRequest
@ -54,12 +53,8 @@ object Auth extends LilaController {
}
def login = Open { implicit ctx =>
if (Env.security.tor isExitNode ctx.req.remoteAddress)
Unauthorized(html.auth.tor()).fuccess
else {
val referrer = get("referrer")
Ok(html.auth.login(api.loginForm, referrer)).fuccess
}
val referrer = get("referrer")
Ok(html.auth.login(api.loginForm, referrer)).fuccess
}
def authenticate = OpenBody { implicit ctx =>
@ -94,9 +89,7 @@ object Auth extends LilaController {
}
def signup = Open { implicit ctx =>
if (Env.security.tor isExitNode ctx.req.remoteAddress)
Unauthorized(html.auth.tor()).fuccess
else {
NoTor {
forms.signup.websiteWithCaptcha map {
case (form, captcha) => Ok(html.auth.signup(form, captcha, env.RecaptchaPublicKey))
}
@ -105,38 +98,40 @@ object Auth extends LilaController {
def signupPost = OpenBody { implicit ctx =>
implicit val req = ctx.body
Firewall {
negotiate(
html = forms.signup.website.bindFromRequest.fold(
err => forms.anyCaptcha map { captcha =>
BadRequest(html.auth.signup(err, captcha, env.RecaptchaPublicKey))
},
data => env.recaptcha.verify(~data.recaptchaResponse, req).flatMap {
case false => forms.signup.websiteWithCaptcha map {
case (form, captcha) => BadRequest(html.auth.signup(form fill data, captcha, env.RecaptchaPublicKey))
}
case true =>
lila.mon.user.register.website()
val email = env.emailAddress.validate(data.email) err s"Invalid email ${data.email}"
UserRepo.create(data.username, data.password, email.some, ctx.blindMode, none)
.flatten(s"No user could be created for ${data.username}")
.map(_ -> email).flatMap {
case (user, email) => env.emailConfirm.send(user, email) >> {
if (env.emailConfirm.effective) Redirect(routes.Auth.checkYourEmail(user.username)).fuccess
else saveAuthAndRedirect(user)
NoTor {
Firewall {
negotiate(
html = forms.signup.website.bindFromRequest.fold(
err => forms.anyCaptcha map { captcha =>
BadRequest(html.auth.signup(err, captcha, env.RecaptchaPublicKey))
},
data => env.recaptcha.verify(~data.recaptchaResponse, req).flatMap {
case false => forms.signup.websiteWithCaptcha map {
case (form, captcha) => BadRequest(html.auth.signup(form fill data, captcha, env.RecaptchaPublicKey))
}
case true =>
lila.mon.user.register.website()
val email = env.emailAddress.validate(data.email) err s"Invalid email ${data.email}"
UserRepo.create(data.username, data.password, email.some, ctx.blindMode, none)
.flatten(s"No user could be created for ${data.username}")
.map(_ -> email).flatMap {
case (user, email) => env.emailConfirm.send(user, email) >> {
if (env.emailConfirm.effective) Redirect(routes.Auth.checkYourEmail(user.username)).fuccess
else saveAuthAndRedirect(user)
}
}
}
}),
api = apiVersion => forms.signup.mobile.bindFromRequest.fold(
err => fuccess(BadRequest(jsonError(errorsAsJson(err)))),
data => {
lila.mon.user.register.mobile()
val email = data.email flatMap env.emailAddress.validate
UserRepo.create(data.username, data.password, email, false, apiVersion.some)
.flatten(s"No user could be created for ${data.username}") flatMap authenticateUser
}
}),
api = apiVersion => forms.signup.mobile.bindFromRequest.fold(
err => fuccess(BadRequest(jsonError(errorsAsJson(err)))),
data => {
lila.mon.user.register.mobile()
val email = data.email flatMap env.emailAddress.validate
UserRepo.create(data.username, data.password, email, false, apiVersion.some)
.flatten(s"No user could be created for ${data.username}") flatMap authenticateUser
}
)
)
)
}
}
}

View file

@ -140,6 +140,11 @@ private[controllers] trait LilaController
})
}
protected def NoTor(res: => Fu[Result])(implicit ctx: Context) =
if (Env.security.tor isExitNode ctx.req.remoteAddress)
Unauthorized(views.html.auth.tor()).fuccess
else res
protected def NoEngine[A <: Result](a: => Fu[A])(implicit ctx: Context): Fu[Result] =
ctx.me.??(_.engine).fold(Forbidden(views.html.site.noEngine()).fuccess, a)

View file

@ -5,15 +5,12 @@ title = "Tor exit node",
zen = true) {
<div class="content_box small_box signup">
<div class="signup_box">
<h1 class="lichess_title text" data-icon="2">Cannot log in from your IP</h1>
<h1 class="lichess_title text" data-icon="2">Ooops</h1>
<p>
We have detected that you are using Tor to remain anonymous on the Internet.
Sorry, you can't signup to lichess through TOR!
<br />
<br />
It's a great idea, and we'll make sure you stay Anonymous on lichess as well.
<br />
<br />
As an Anonymous user, you can play, train, and use all lichess features. Enjoy!
As an Anonymous user, you can play, train, and use all lichess features.
</p>
</div>
</div>

View file

@ -14,7 +14,6 @@ import lila.user.{ User, UserRepo }
final class Api(
coll: Coll,
firewall: Firewall,
tor: Tor,
geoIP: GeoIP,
emailAddress: EmailAddress) {
@ -48,8 +47,7 @@ final class Api(
candidate ?? { _(password) }
def saveAuthentication(userId: String, apiVersion: Option[Int])(implicit req: RequestHeader): Fu[String] =
if (tor isExitNode req.remoteAddress) fufail(Api.AuthFromTorExitNode)
else UserRepo mustConfirmEmail userId flatMap {
UserRepo mustConfirmEmail userId flatMap {
case true => fufail(Api MustConfirmEmail userId)
case false =>
val sessionId = Random nextStringUppercase 12
@ -123,6 +121,5 @@ final class Api(
object Api {
case object AuthFromTorExitNode extends Exception
case class MustConfirmEmail(userId: String) extends Exception
}

View file

@ -107,7 +107,7 @@ final class Env(
scheduler.once(30 seconds)(tor.refresh(_ => funit))
scheduler.effect(TorRefreshDelay, "Refresh Tor exit nodes")(tor.refresh(firewall.unblockIps))
lazy val api = new Api(storeColl, firewall, tor, geoIP, emailAddress)
lazy val api = new Api(storeColl, firewall, geoIP, emailAddress)
def cli = new Cli