Skip to content

Commit

Permalink
Merge branch 'master' into refactor-css-direction
Browse files Browse the repository at this point in the history
* master:
  Remove chess24 (lichess-org#14962)
  preload the broadcast group name
  tweak hcaptcha skip condition
  better log hcaptcha result type
  rotate oauth token on creation - closes lichess-org#14946
  Add comments for NewTree.toBranch function
  fixes for ios safari < 15
  fix error preventing pure javascript engine when none other are available
  • Loading branch information
ornicar committed Mar 25, 2024
2 parents ecec086 + 824bc46 commit 334c5be
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 38 deletions.
2 changes: 1 addition & 1 deletion app/views/relay/show.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ object show:
div(cls := "box relay-tour")(
div(cls := "relay-tour__header")(
div(cls := "relay-tour__header__content")(
h1(rt.tour.name),
h1(data.group.fold(rt.tour.name.value)(_.value)),
div(cls := "relay-tour__header__selectors"):
div(cls := "mselect relay-tour__mselect"):
label(cls := "mselect__label"):
Expand Down
29 changes: 21 additions & 8 deletions modules/oauth/src/main/AccessTokenApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,24 @@ final class AccessTokenApi(
import OAuthScope.given
import AccessToken.{ BSONFields as F, given }

private def create(token: AccessToken): Fu[AccessToken] = coll.insert.one(token).inject(token)
private def createAndRotate(token: AccessToken): Fu[AccessToken] = for
oldIds <- coll
.find($doc(F.userId -> token.userId, F.clientOrigin -> token.clientOrigin), $doc(F.id -> true).some)
.sort($doc(F.usedAt -> -1, F.createdAt -> -1))
.skip(30)
.cursor[Bdoc]()
.listAll()
.dmap:
_.flatMap { _.getAsOpt[AccessToken.Id](F.id) }
_ <- oldIds.nonEmpty.so:
coll.delete.one($doc(F.id.$in(oldIds))).void
_ <- coll.insert.one(token)
yield token

def create(setup: OAuthTokenForm.Data, me: User, isStudent: Boolean): Fu[AccessToken] =
(fuccess(isStudent) >>| userRepo.isManaged(me.id)) flatMap { noBot =>
(fuccess(isStudent) >>| userRepo.isManaged(me.id)).flatMap { noBot =>
val plain = Bearer.randomPersonal()
create:
createAndRotate:
AccessToken(
id = AccessToken.Id.from(plain),
plain = plain,
Expand All @@ -42,7 +54,7 @@ final class AccessTokenApi(

def create(granted: AccessTokenRequest.Granted): Fu[AccessToken] =
val plain = Bearer.random()
create:
createAndRotate:
AccessToken(
id = AccessToken.Id.from(plain),
plain = plain,
Expand Down Expand Up @@ -73,7 +85,7 @@ final class AccessTokenApi(
)
.getOrElse:
val plain = Bearer.randomPersonal()
create:
createAndRotate:
AccessToken(
id = AccessToken.Id.from(plain),
plain = plain,
Expand Down Expand Up @@ -158,7 +170,8 @@ final class AccessTokenApi(
F.id -> id,
F.userId -> user.id
)
.void.andDo(onRevoke(id))
.void
.andDo(onRevoke(id))

def revokeByClientOrigin(clientOrigin: String, user: User): Funit =
coll
Expand Down Expand Up @@ -190,11 +203,11 @@ final class AccessTokenApi(
def test(bearers: List[Bearer]): Fu[Map[Bearer, Option[AccessToken]]] =
coll
.optionsByOrderedIds[AccessToken, AccessToken.Id](
bearers map AccessToken.Id.from,
bearers.map(AccessToken.Id.from),
readPref = _.sec
)(_.id)
.flatMap: tokens =>
userRepo.filterDisabled(tokens.flatten.map(_.userId)) map { closedUserIds =>
userRepo.filterDisabled(tokens.flatten.map(_.userId)).map { closedUserIds =>
val openTokens = tokens.map(_.filter(token => !closedUserIds(token.userId)))
bearers.zip(openTokens).toMap
}
Expand Down
5 changes: 3 additions & 2 deletions modules/relay/src/main/JsonView.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,13 @@ final class JsonView(
.add("isSubscribed" -> isSubscribed)
.add("videoUrls" -> videoUrls),
study = studyData.study,
analysis = studyData.analysis
analysis = studyData.analysis,
group = group.map(_.group.name)
)

object JsonView:

case class JsData(relay: JsObject, study: JsObject, analysis: JsObject)
case class JsData(relay: JsObject, study: JsObject, analysis: JsObject, group: Option[RelayGroup.Name])

given OWrites[SyncLog.Event] = Json.writes

Expand Down
45 changes: 26 additions & 19 deletions modules/security/src/main/Hcaptcha.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ trait Hcaptcha:
object Hcaptcha:

enum Result(val ok: Boolean):
case Valid extends Result(true)
case Skip extends Result(true)
case Pass extends Result(true)
case Fail extends Result(false)
case Valid extends Result(true)
case Disabled extends Result(true)
case IpFirst extends Result(true)
case Mobile extends Result(true)
case Fail extends Result(false)

val field = "h-captcha-response" -> optional(nonEmptyText)
val form = Form(single(field))
Expand All @@ -50,6 +51,7 @@ final class HcaptchaSkip(config: HcaptchaPublicConfig) extends Hcaptcha:
def verify(response: String)(using RequestHeader) = fuccess(Hcaptcha.Result.Valid)

final class HcaptchaReal(
ipTrust: IpTrust,
ws: StandaloneWSClient,
netDomain: NetDomain,
config: Hcaptcha.Config
Expand All @@ -68,23 +70,25 @@ final class HcaptchaReal(
override def toString = `error-codes`.mkString(",")
private given Reads[BadResponse] = Json.reads[BadResponse]

private object skip:
private object skipIp:
private val memo = lila.memo.HashCodeExpireSetMemo[IpAddress](24 hours)

def get(using req: RequestHeader): Boolean = !memo.get(HTTPRequest.ipAddress(req))
def getFu(using RequestHeader): Fu[Boolean] = fuccess(get)
def get(using req: RequestHeader): Fu[Boolean] =
val ip = HTTPRequest.ipAddress(req)
(!memo.get(ip)).so:
ipTrust.isSuspicious(ip).not

def record(using req: RequestHeader) = memo.put(HTTPRequest.ipAddress(req))

def form[A](form: Form[A])(using req: RequestHeader): Fu[HcaptchaForm[A]] =
skip.getFu.map: skip =>
skipIp.get.map: skip =>
lila.mon.security.hCaptcha
.form(HTTPRequest.clientName(req), if skip then "skip" else "show")
.increment()
HcaptchaForm(form, config.public, skip)

def verify(response: String)(using req: RequestHeader): Fu[Result] =
val client = HTTPRequest.clientName(req)
val client = HTTPRequest.clientName(req)
given Conversion[Result, Fu[Result]] = fuccess
ws.url(config.endpoint)
.post(
Map(
Expand All @@ -94,7 +98,7 @@ final class HcaptchaReal(
"sitekey" -> config.publicKey
)
)
.map {
.flatMap {
case res if res.status == 200 =>
res.body[JsValue].validate[GoodResponse] match
case JsSuccess(res, _) =>
Expand All @@ -106,15 +110,18 @@ final class HcaptchaReal(
case Some(err) if err.missingInput =>
if HTTPRequest.apiVersion(req).isDefined then
lila.mon.security.hCaptcha.hit(client, "api").increment()
Result.Pass
else if skip.get then
lila.mon.security.hCaptcha.hit(client, "skip").increment()
skip.record
Result.Skip
Result.Mobile
else
logger.info(s"hcaptcha missing ${HTTPRequest.printClient(req)}")
lila.mon.security.hCaptcha.hit(client, "missing").increment()
Result.Fail
skipIp.get.map:
if _
then
lila.mon.security.hCaptcha.hit(client, "skip").increment()
skipIp.record
Result.IpFirst
else
logger.info(s"hcaptcha missing ${HTTPRequest.printClient(req)}")
lila.mon.security.hCaptcha.hit(client, "missing").increment()
Result.Fail
case Some(err) =>
lila.mon.security.hCaptcha.hit(client, err.toString).increment()
Result.Fail
Expand Down
5 changes: 2 additions & 3 deletions modules/security/src/main/Signup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ final class Signup(
suspIp <- ipTrust.isSuspicious(ip)
ipData <- ipTrust.data(ip)
result <- hcaptcha.verify().flatMap {
case Hcaptcha.Result.Fail => fuccess(Signup.Result.MissingCaptcha)
case Hcaptcha.Result.Pass if !blind => fuccess(Signup.Result.MissingCaptcha)
case Hcaptcha.Result.Fail => fuccess(Signup.Result.MissingCaptcha)
case hcaptchaResult =>
signupRateLimit(
data.username.id,
Expand Down Expand Up @@ -146,7 +145,7 @@ final class Signup(
val mustConfirm = MustConfirmEmail.YesBecauseMobile
monitor(
data,
captcha = Hcaptcha.Result.Skip,
captcha = Hcaptcha.Result.Mobile,
mustConfirm,
ipData,
suspIp,
Expand Down
3 changes: 3 additions & 0 deletions modules/study/src/test/Helpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ object Helpers:
)

extension (newTree: NewTree)
// We lost variations here
// newTree.toBranch == newTree.withoutVariations.toBranch
def toBranch: Branch = newTree.value.toBranch(newTree.child)

def toBranches: Branches =
val variations = newTree.variations.map(_.toNode.toBranch)
Branches(newTree.value.toBranch(newTree.child) :: variations)
Expand Down
4 changes: 2 additions & 2 deletions modules/study/src/test/newTreeTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class NewTreeTest extends munit.ScalaCheckSuite:
val oldRoot = x.root.toNewRoot.cleanup
assertEquals(y.root.cleanup, oldRoot)

test("conversion check"):
test("Root conversion check"):
forAll: (root: NewRoot) =>
val oldRoot = root.toRoot
val newRoot = oldRoot.toNewRoot
Expand Down Expand Up @@ -149,7 +149,7 @@ class NewTreeTest extends munit.ScalaCheckSuite:
val (root, path) = rp

oTree.isDefined && path.nonEmpty ==> {
val tree = oTree.get.clearVariations
val tree = oTree.get.withoutVariations
val oldRoot = root.toRoot.withChildren(_.addNodeAt(tree.toBranch, path))
val x = oldRoot.map(_.toNewRoot)
val y = root.addNodeAt(path, tree)
Expand Down
2 changes: 0 additions & 2 deletions modules/user/src/main/Links.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ object Link:
case GitHub extends Site("GitHub", List("github.com"))
case VKontakte extends Site("VKontakte", List("vk.com"))
case ChessCom extends Site("Chess.com", List("chess.com"))
case Chess24 extends Site("Chess24", List("chess24.com"))
case ChessMonitor extends Site("ChessMonitor", List("chessmonitor.com"))
case ChessTempo extends Site("ChessTempo", List("chesstempo.com"))
case Other(domain: String) extends Site(domain, List(domain))
Expand All @@ -68,7 +67,6 @@ object Link:
GitHub,
VKontakte,
ChessCom,
Chess24,
ChessMonitor,
ChessTempo
)
Expand Down
3 changes: 2 additions & 1 deletion ui/ceval/src/engines/engines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ export class Engines {
tech: 'HCE',
minThreads: 1,
maxThreads: 1,
requires: [],
obsoletedBy: 'wasm',
assets: {
version: 'a022fa',
Expand All @@ -211,7 +212,7 @@ export class Engines {
]
.filter(
e =>
e.info.requires?.every((req: Requires) => this.browserSupport.includes(req)) &&
e.info.requires.every((req: Requires) => this.browserSupport.includes(req)) &&
!(e.info.obsoletedBy && this.browserSupport.includes(e.info.obsoletedBy as Feature)),
)
.map(e => [e.info.id, { info: withDefaults(e.info as BrowserEngineInfo), make: e.make }]),
Expand Down
1 change: 1 addition & 0 deletions ui/ceval/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface ExternalEngineInfo extends EngineInfo {
export interface BrowserEngineInfo extends EngineInfo {
minMem?: number;
assets: { root?: string; js?: string; wasm?: string; version?: string; nnue?: string };
requires: Requires[];
obsoletedBy?: Feature;
}

Expand Down

0 comments on commit 334c5be

Please sign in to comment.