Skip to content

Commit

Permalink
Merge branch 'master' into display-cases-explorer
Browse files Browse the repository at this point in the history
  • Loading branch information
johndoknjas authored Jan 26, 2025
2 parents e7fe89c + fb6d816 commit 46bc286
Show file tree
Hide file tree
Showing 34 changed files with 111 additions and 104 deletions.
24 changes: 10 additions & 14 deletions app/controllers/Challenge.scala
Original file line number Diff line number Diff line change
Expand Up @@ -140,21 +140,17 @@ final class Challenge(env: Env) extends LilaController(env):
res: Result
)(using Context): Fu[Result] =
cond
.so {
env.game.gameRepo.game(c.id.into(GameId)).map {
_.map { game =>
env.security.lilaCookie.cookie(
AnonCookie.name,
game.player(if owner then c.finalColor else !c.finalColor).id.value,
maxAge = AnonCookie.maxAge.some,
httpOnly = false.some
)
}
.so:
env.game.gameRepo.game(c.id.into(GameId)).map2 { game =>
env.security.lilaCookie.cookie(
AnonCookie.name,
game.player(if owner then c.finalColor else !c.finalColor).id.value,
maxAge = AnonCookie.maxAge.some,
httpOnly = false.some
)
}
}
.map { cookieOption =>
cookieOption.foldLeft(res)(_.withCookies(_))
}
.map:
_.foldLeft(res)(_.withCookies(_))

def decline(id: ChallengeId) = AuthBody { ctx ?=> _ ?=>
Found(api.byId(id)): c =>
Expand Down
65 changes: 44 additions & 21 deletions bin/mongodb/fix-normalized-emails.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,48 @@
function gmailNormalize(email) {
const dry = false;
const gmailOrProton = [
'protonmail.com',
'protonmail.ch',
'pm.me',
'proton.me',
'gmail.com',
'googlemail.com',
];

function normalize(email) {
let [name, domain] = email.toLowerCase().split('@');
[name] = name.split('+');
return name.replace(/\./g, '') + '@' + domain;

if (gmailOrProton.includes(domain)) name = name.replace(/\./g, '');

return name + '@' + domain;
}

db.user4
.find({ email: /[^+.]+[+.].*@(protonmail\.com|protonmail\.ch|pm\.me|gmail\.com|googlemail\.com)$/i })
.forEach(user => {
const normalized = gmailNormalize(user.email);
const verbatim = user.verbatimEmail || user.email;
print(user.username, ': ', verbatim, '->', normalized);

db.user4.update(
{
_id: user._id,
},
{
$set: {
email: normalized,
verbatimEmail: verbatim,
},
},
);
});
let nbUpdates = 0;
let nbDups = 0;

db.user4.find({ email: /^[^+]+\+.*@.+$/ }, { email: 1, verbatimEmail: 1, username: 1 }).forEach(user => {
const normalized = normalize(user.email);
const verbatim = user.verbatimEmail || user.email;
print(user.username, ': ', verbatim, '->', normalized);

const updates = {};
if (normalized != user.email) updates.email = normalized;
if (verbatim != user.email) updates.verbatimEmail = verbatim;

if (!dry && Object.keys(updates).length) {
try {
db.user4.updateOne({ _id: user._id }, { $set: updates });
db.user_email_backup.update(
{ _id: user._id },
{ $set: { email: user.email, verbatimEmail: user.verbatimEmail } },
{ upsert: true },
);
nbUpdates++;
} catch (e) {
if (e.code == 11000) nbDups++;
}
}
});

print('updated:', nbUpdates);
print('skiped duplicates:', nbDups);
4 changes: 2 additions & 2 deletions bin/mongodb/indexes.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ db.note.createIndex(
);
db.irwin_report.createIndex({ date: -1 });
db.user4.createIndex({ 'count.game': -1 });
db.user4.createIndex({ title: 1 }, { sparse: true });
db.user4.createIndex({ email: 1 }, { unique: true, sparse: 1 });
db.user4.createIndex({ title: 1 }, { partialFilterExpression: { title: { $exists: 1 } } });
db.user4.createIndex({ email: 1 }, { unique: true, partialFilterExpression: { email: { $exists: 1 } } });
db.user4.createIndex({ roles: 1 }, { background: 1, partialFilterExpression: { roles: { $exists: 1 } } });
db.user4.createIndex({ prevEmail: 1 }, { sparse: 1, background: 1 });
db.user4.createIndex(
Expand Down
2 changes: 1 addition & 1 deletion modules/common/src/main/MarkdownRender.scala
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ object MarkdownRender:

case class PgnSourceExpand(domain: NetDomain, getPgn: PgnSourceId => Option[LpvEmbed])

private val rel = "nofollow noopener noreferrer"
private val rel = "nofollow noreferrer"

private object WhitelistedImage:

Expand Down
2 changes: 1 addition & 1 deletion modules/common/src/main/RawHtml.scala
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ object RawHtml:
if (end < sArr.length && sArr(end) == '"') || !expandImg then None
else imgUrl(url)
}.getOrElse {
s"""<a rel="nofollow noopener noreferrer" href="$url" target="_blank">$text</a>"""
s"""<a rel="nofollow noreferrer" href="$url" target="_blank">$text</a>"""
}
}

Expand Down
9 changes: 5 additions & 4 deletions modules/core/src/main/email.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ object email:
def normalize = NormalizedEmailAddress: // changing normalization requires database migration!
val lower = e.toLowerCase
lower.split('@') match
case Array(name, domain) if EmailAddress.gmailLikeNormalizedDomains(domain) =>
val normalizedName = name
.replace(".", "") // remove all dots
.takeWhile('+' != _) // skip everything after the first '+'
case Array(name, domain) =>
val skipAfterPlus = name.takeWhile('+' != _)
val normalizedName =
if EmailAddress.gmailLikeNormalizedDomains(domain) then skipAfterPlus.replace(".", "")
else skipAfterPlus
if normalizedName.isEmpty then lower else s"$normalizedName@$domain"
case _ => lower

Expand Down
10 changes: 10 additions & 0 deletions modules/core/src/test/EmailTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ class EmailTest extends munit.FunSuite:
NormalizedEmailAddress("[email protected]")
)

test("normalize other"):
assertEquals(
EmailAddress("[email protected]").normalize,
NormalizedEmailAddress("[email protected]")
)
assertEquals(
EmailAddress("[email protected]").normalize,
NormalizedEmailAddress("[email protected]")
)

test("not similar emails"):
assert(!EmailAddress("[email protected]").similarTo(EmailAddress("[email protected]")))
assert(!EmailAddress("[email protected]").similarTo(EmailAddress("[email protected]")))
Expand Down
4 changes: 3 additions & 1 deletion modules/study/src/main/JsonView.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import lila.common.Json.{ *, given }
import lila.core.i18n.Translate
import lila.core.socket.Sri
import lila.tree.Node.Shape
import lila.core.pref.Pref

final class JsonView(
studyRepo: StudyRepo,
Expand All @@ -21,7 +22,7 @@ final class JsonView(
previews: Option[ChapterPreview.AsJsons],
fedNames: Option[JsObject],
withMembers: Boolean
)(using me: Option[Me]) =
)(using me: Option[Me], pref: Pref) =

def allowed(selection: Settings => Settings.UserSelection): Boolean =
Settings.UserSelection.allows(selection(study.settings), study, me.map(_.userId))
Expand Down Expand Up @@ -66,6 +67,7 @@ final class JsonView(
.add("chapters", previews)
.add("description", study.description)
.add("federations", fedNames)
.add("showRatings", pref.showRatings)

def chapterConfig(c: Chapter) =
Json
Expand Down
8 changes: 1 addition & 7 deletions modules/ui/src/main/scalatags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,7 @@ trait ScalatagsExtensions:
def empty: Frag = emptyFrag
def combine(x: Frag, y: Frag): Frag = frag(x, y)

val targetBlank: Modifier = (t: Builder) =>
// Prevent tab nabbing when opening untrusted links. Apply also to trusted
// links, because there can be a small performance advantage and lila does
// not use window.opener anywhere. Will not be overwritten by additional
// rels.
t.setAttr("rel", Builder.GenericAttrValueSource("noopener"))
t.setAttr("target", Builder.GenericAttrValueSource("_blank"))
val targetBlank: Modifier = (t: Builder) => t.setAttr("target", Builder.GenericAttrValueSource("_blank"))

val noFollow = rel := "nofollow"
val relMe = rel := "me"
Expand Down
2 changes: 2 additions & 0 deletions modules/web/src/main/CtrlExtensions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import lila.common.HTTPRequest
import lila.core.config.BaseUrl
import lila.core.i18n.Translate
import lila.core.perf.UserWithPerfs
import lila.core.pref.Pref
import lila.ui.Context

trait CtrlExtensions extends play.api.mvc.ControllerHelpers with ResponseHeaders:
Expand All @@ -16,6 +17,7 @@ trait CtrlExtensions extends play.api.mvc.ControllerHelpers with ResponseHeaders
given (using ctx: Context): Lang = ctx.lang
given (using ctx: Context): Translate = ctx.translate
given (using ctx: Context): RequestHeader = ctx.req
given (using ctx: Context): Pref = ctx.pref

given Conversion[UserWithPerfs, User] = _.user

Expand Down
6 changes: 3 additions & 3 deletions modules/web/src/test/common/MarkdownTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class MarkdownTest extends munit.FunSuite:
assertEquals(
render(md),
Html(
"""<p><a href="https://example.com" target="_blank" rel="nofollow noopener noreferrer">https://example.com</a></p>
"""<p><a href="https://example.com" target="_blank" rel="nofollow noreferrer">https://example.com</a></p>
"""
)
)
Expand All @@ -25,7 +25,7 @@ class MarkdownTest extends munit.FunSuite:
assertEquals(
render(md),
Html(
"""<p><a href="https://example.com" target="_blank" rel="nofollow noopener noreferrer">Example</a></p>
"""<p><a href="https://example.com" target="_blank" rel="nofollow noreferrer">Example</a></p>
"""
)
)
Expand Down Expand Up @@ -81,7 +81,7 @@ class MarkdownTest extends munit.FunSuite:
assertEquals(
render(Markdown("![image](https://evil.com/image.png)")),
Html(
"""<p><a href="https://evil.com/image.png" target="_blank" rel="nofollow noopener noreferrer">image</a></p>
"""<p><a href="https://evil.com/image.png" target="_blank" rel="nofollow noreferrer">image</a></p>
"""
)
)
Expand Down
16 changes: 8 additions & 8 deletions modules/web/src/test/common/RawHtmlTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,21 @@ class RawHtmlTest extends munit.FunSuite:
val url = "http://zombo.com"
assertEquals(
addLinks(s"""link to $url here"""),
s"""link to <a rel="nofollow noopener noreferrer" href="$url" target="_blank">$url</a> here"""
s"""link to <a rel="nofollow noreferrer" href="$url" target="_blank">$url</a> here"""
)
}
test("hide https >> text") {
val url = "zombo.com"
assertEquals(
addLinks(s"""link to https://$url here"""),
s"""link to <a rel="nofollow noopener noreferrer" href="https://$url" target="_blank">$url</a> here"""
s"""link to <a rel="nofollow noreferrer" href="https://$url" target="_blank">$url</a> here"""
)
}
test("default to https") {
val url = "zombo.com"
assertEquals(
addLinks(s"""link to $url here"""),
s"""link to <a rel="nofollow noopener noreferrer" href="https://$url" target="_blank">$url</a> here"""
s"""link to <a rel="nofollow noreferrer" href="https://$url" target="_blank">$url</a> here"""
)
}
test("skip buggy url like http://foo@bar") {
Expand All @@ -46,7 +46,7 @@ class RawHtmlTest extends munit.FunSuite:
val url = "http://zombo.com/pic.jpg"
assertEquals(
addLinks(s"""link to $url here"""),
s"""link to <a rel="nofollow noopener noreferrer" href="$url" target="_blank">$url</a> here"""
s"""link to <a rel="nofollow noreferrer" href="$url" target="_blank">$url</a> here"""
)
}
test("detect direct giphy gif URL") {
Expand Down Expand Up @@ -85,14 +85,14 @@ class RawHtmlTest extends munit.FunSuite:
val url = "http://i.imgur.com/Cku31nh.png"
assertEquals(
addLinks(s"""img to "$url" here"""),
s"""img to &quot;<a rel="nofollow noopener noreferrer" href="$url" target="_blank">$url</a>&quot; here"""
s"""img to &quot;<a rel="nofollow noreferrer" href="$url" target="_blank">$url</a>&quot; here"""
)
}
test("ignore imgur gallery URL") {
val url = "http://imgur.com/gallery/pMtTE"
assertEquals(
addLinks(s"""link to $url here"""),
s"""link to <a rel="nofollow noopener noreferrer" href="$url" target="_blank">$url</a> here"""
s"""link to <a rel="nofollow noreferrer" href="$url" target="_blank">$url</a> here"""
)
}

Expand All @@ -118,7 +118,7 @@ class RawHtmlTest extends munit.FunSuite:
)
assertEquals(
addLinks("b foo.com blah lichess.org"),
"""b <a rel="nofollow noopener noreferrer" href="https://foo.com" target="_blank">foo.com</a> blah <a href="/">lichess.org</a>"""
"""b <a rel="nofollow noreferrer" href="https://foo.com" target="_blank">foo.com</a> blah <a href="/">lichess.org</a>"""
)
}

Expand Down Expand Up @@ -159,7 +159,7 @@ class RawHtmlTest extends munit.FunSuite:
val clean = "example.com/"
assertEquals(
addLinks(url),
s"""<a rel="nofollow noopener noreferrer" href="https://$clean" target="_blank">$clean</a>"""
s"""<a rel="nofollow noreferrer" href="https://$clean" target="_blank">$clean</a>"""
)
}

Expand Down
4 changes: 2 additions & 2 deletions modules/web/src/test/common/StringTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class StringTest extends munit.FunSuite:
assertEquals(
String.html.richText(s"link to $url here\n"),
raw:
s"""link to <a rel="nofollow noopener noreferrer" href="$url" target="_blank">$url</a> here<br>"""
s"""link to <a rel="nofollow noreferrer" href="$url" target="_blank">$url</a> here<br>"""
)

assertEquals(String.html.richText(s"link\n", false), raw("link\n"))
Expand All @@ -29,7 +29,7 @@ class StringTest extends munit.FunSuite:
assertEquals(
String.html.richText("a https://example.com/foo--. b"),
raw:
"""a <a rel="nofollow noopener noreferrer" href="https://example.com/foo--" target="_blank">example.com/foo--</a>. b"""
"""a <a rel="nofollow noreferrer" href="https://example.com/foo--" target="_blank">example.com/foo--</a>. b"""
)
}

Expand Down
2 changes: 1 addition & 1 deletion ui/analyse/src/explorer/explorerView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ function openGame(ctrl: AnalyseCtrl, gameId: string) {
fenParam = ctrl.node.ply > 0 ? '?fen=' + ctrl.node.fen : '';
let url = '/' + gameId + '/' + orientation + fenParam;
if (ctrl.explorer.db() === 'masters') url = '/import/master' + url;
window.open(url, '_blank', 'noopener');
window.open(url, '_blank');
}

function gameActions(ctrl: AnalyseCtrl, game: OpeningGame): VNode {
Expand Down
3 changes: 1 addition & 2 deletions ui/analyse/src/study/relay/relayManagerView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ function renderLog(ctrl: RelayCtrl) {
.reverse()
.map(e => {
const err =
e.error &&
h('a', url ? { attrs: { href: url, target: '_blank', rel: 'noopener nofollow' } } : {}, e.error);
e.error && h('a', url ? { attrs: { href: url, target: '_blank', rel: 'nofollow' } } : {}, e.error);
return h(
'div' + (err ? '.err' : ''),
{ key: e.at, attrs: dataIcon(err ? licon.CautionCircle : licon.Checkmark) },
Expand Down
6 changes: 1 addition & 5 deletions ui/analyse/src/study/relay/relayTourView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,7 @@ const showInfo = (i: RelayTourInfo, dates?: RelayTourDates) => {
h('div.relay-tour__info__' + key, [
icon && h('img', { attrs: { src: site.asset.flairSrc(icon) } }),
linkName
? h(
'a',
{ attrs: { href: value, target: '_blank', rel: 'nofollow noopener noreferrer' } },
linkName,
)
? h('a', { attrs: { href: value, target: '_blank', rel: 'nofollow noreferrer' } }, linkName)
: value,
]),
)
Expand Down
1 change: 0 additions & 1 deletion ui/analyse/src/study/studyShare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ export function view(ctrl: StudyShare): VNode {
attrs: {
href: '/developers#embed-study',
target: '_blank',
rel: 'noopener',
...dataIcon(licon.InfoCircle),
},
},
Expand Down
2 changes: 1 addition & 1 deletion ui/analyse/src/view/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ export function renderControls(ctrl: AnalyseCtrl) {
else if (action === 'practice') ctrl.togglePractice();
else if (action === 'menu') ctrl.actionMenu.toggle();
else if (action === 'analysis' && ctrl.studyPractice)
window.open(ctrl.studyPractice.analysisUrl(), '_blank', 'noopener');
window.open(ctrl.studyPractice.analysisUrl(), '_blank');
}, ctrl.redraw),
),
},
Expand Down
2 changes: 1 addition & 1 deletion ui/bits/src/bits.lpv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ function toGamebook(lpv: PgnViewer) {
const href = lpv.game.metadata.externalLink;
$(lpv.div)
.addClass('lpv--gamebook')
.append($(`<a href="${href}" target="_blank" rel="noopener" class="button lpv__gamebook">Start</a>`));
.append($(`<a href="${href}" target="_blank" class="button lpv__gamebook">Start</a>`));
}
2 changes: 1 addition & 1 deletion ui/common/src/richText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const userPattern: RegExp = /(^|[^\w@#/])@([a-z0-9_-]{2,30})/gi;
export const isMoreThanText = (str: string): boolean => /(\n|(@|#|\.)\w{2,}|(board|game) \d)/i.test(str);

const linkHtml = (href: string, content: string): string =>
`<a target="_blank" rel="nofollow noopener noreferrer" href="${href}">${content}</a>`;
`<a target="_blank" rel="nofollow noreferrer" href="${href}">${content}</a>`;

export function toLink(url: string): string {
if (!url.match(/^[A-Za-z]+:\/\//)) url = 'https://' + url;
Expand Down
Loading

0 comments on commit 46bc286

Please sign in to comment.