diff --git a/app/controllers/Clas.scala b/app/controllers/Clas.scala index 40c30e1bc14..a6ec949af47 100644 --- a/app/controllers/Clas.scala +++ b/app/controllers/Clas.scala @@ -104,7 +104,7 @@ final class Clas(env: Env, authC: Auth) extends LilaController(env): ) yield Ok(page), orDefault = _ => - isGranted(_.UserModView).so(FoundPage(env.clas.api.clas.byId(id)): clas => + isGranted(_.AccountInfo).so(FoundPage(env.clas.api.clas.byId(id)): clas => env.clas.api.student.allWithUsers(clas).flatMap { students => env.user.api.withPerfsAndEmails(students.map(_.user)).map { views.mod.search.clas(clas, _) diff --git a/app/controllers/User.scala b/app/controllers/User.scala index 7ab461d16a5..c9914f807ea 100644 --- a/app/controllers/User.scala +++ b/app/controllers/User.scala @@ -163,9 +163,9 @@ final class User( .redirect(username.value) .flatMap: case Some(url) => Redirect(url).toFuccess - case None if isGrantedOpt(_.UserModView) => ctx.useMe(modC.searchTerm(username.value)) + case None if isGrantedOpt(_.AccountInfo) => ctx.useMe(modC.searchTerm(username.value)) case None => notFound(true) - case Some(u) if u.enabled.yes || isGrantedOpt(_.UserModView) => f(u) + case Some(u) if u.enabled.yes || isGrantedOpt(_.AccountInfo) => f(u) case u => notFound(u.isEmpty) def showMini(username: UserStr) = Open: @@ -173,7 +173,7 @@ final class User( ctx.userId .so(relationApi.fetchRelation(_, user.id)) .flatMap: relation => - if user.enabled.yes || isGrantedOpt(_.UserModView) + if user.enabled.yes || isGrantedOpt(_.AccountInfo) then ( ctx.userId.so(relationApi.fetchBlocks(user.id, _)), @@ -415,7 +415,8 @@ final class User( .preloadMany(as.games.flatMap(_.userIds)) .inject(ui.assessments(user, as)) - val oauthTokens = env.oAuth.tokenApi.modRelevantTokens(user.id).map(views.user.mod.oauthTokens) + val oauthTokens = isGranted(_.AccountInfo).so: + env.oAuth.tokenApi.modRelevantTokens(user.id).map(views.user.mod.oauthTokens) val teacher = isGranted(_.AccountInfo).so: env.clas.api.clas.countOf(user).map(ui.teacher(user)) diff --git a/app/views/mod/communication.scala b/app/views/mod/communication.scala index f514c76ee61..828bebf96b1 100644 --- a/app/views/mod/communication.scala +++ b/app/views/mod/communication.scala @@ -22,7 +22,7 @@ def communication( .js(isGranted(_.UserModView).option(Esm("mod.user"))): main(id := "communication", cls := "box box-pad")( commUi.commsHeader(u, priv), - isGranted(_.UserModView).option: + isGranted(_.AccountInfo).option: frag( div(cls := "mod-zone mod-zone-full none"), views.user.mod.otherUsers(u, logins, appeals)(cls := "mod-zone communication__logins") diff --git a/app/views/user/show/header.scala b/app/views/user/show/header.scala index 6458149a4e4..f939b910c28 100644 --- a/app/views/user/show/header.scala +++ b/app/views/user/show/header.scala @@ -144,9 +144,9 @@ object header: case _ => val profile = u.profileOrDefault val hideTroll = u.marks.troll && ctx.isnt(u) - val showProfile = ctx.kid.no && u.kid.no && !hideTroll || isGranted(_.UserModView) + val showProfile = ctx.kid.no && u.kid.no && !hideTroll || isGranted(_.AccountInfo) div(id := "us_profile")( - if info.ratingChart.isDefined && (!u.lame || ctx.is(u) || isGranted(_.UserModView)) then + if info.ratingChart.isDefined && (!u.lame || ctx.is(u) || isGranted(_.AccountInfo)) then views.user.perfStat.ratingHistoryContainer else (ctx.is(u) && u.count.game < 10).option(ui.newPlayer(u)), div(cls := "profile-side")( @@ -162,7 +162,7 @@ object header: .map(strong(cls := List("name" -> true, "muted" -> hideTroll))(_)), info.publicFideId.map: id => p(a(href := routes.Fide.show(id, u.username.value))("FIDE player #" + id)), - (showLinks && showProfile || isGranted(_.UserModView)) + (showLinks && showProfile || isGranted(_.AccountInfo)) .so(profile.nonEmptyBio) .map: bio => p(cls := List("bio" -> true, "muted" -> hideTroll))(richText(bio, nl2br = true)), diff --git a/app/views/user/show/page.scala b/app/views/user/show/page.scala index 596541b1ed0..c844dfbac4c 100644 --- a/app/views/user/show/page.scala +++ b/app/views/user/show/page.scala @@ -34,7 +34,7 @@ object page: ) .js(pageModule(info)) .js(esModules()) - .js(isGranted(_.UserModView).option(esmInit("mod.autolink"))) + .js(isGranted(_.AccountInfo).option(esmInit("mod.autolink"))) .css("user.show") .css(isGranted(_.UserModView).option("mod.user")) .flag(_.noRobots, !indexable(u)): diff --git a/modules/appeal/src/main/ui/AppealUi.scala b/modules/appeal/src/main/ui/AppealUi.scala index c379d84dee9..836921a331d 100644 --- a/modules/appeal/src/main/ui/AppealUi.scala +++ b/modules/appeal/src/main/ui/AppealUi.scala @@ -12,8 +12,8 @@ final class AppealUi(helpers: Helpers): Page(title) .css("bits.form3") .css("bits.appeal") - .css(Granter.opt(_.UserModView).option("mod.user")) - .js(esmInitBit("appeal") ++ Granter.opt(_.UserModView).so(Esm("mod.user"))) + .css(Granter.opt(_.Appeals).option("mod.user")) + .js(esmInitBit("appeal") ++ Granter.opt(_.Appeals).so(Esm("mod.user"))) def renderMark(suspect: User)(using ctx: Context) = val query = Granter.opt(_.Appeals).so(ctx.req.queryString.toMap) diff --git a/modules/mod/src/main/ui/ModUserUi.scala b/modules/mod/src/main/ui/ModUserUi.scala index d8324deb2f5..5c13fbe8a15 100644 --- a/modules/mod/src/main/ui/ModUserUi.scala +++ b/modules/mod/src/main/ui/ModUserUi.scala @@ -48,154 +48,154 @@ final class ModUserUi(helpers: Helpers, modUi: ModUi, mailerEventsUrl: Url): )(using Context, Me): Frag = mzSection("actions")( div(cls := "btn-rack")( - Granter.opt(_.ModMessage).option { - postForm(action := routes.Mod.spontaneousInquiry(u.username), title := "Start an inquiry")( + Granter(_.ModMessage).option: + postForm(action := routes.Mod.spontaneousInquiry(u.username), title := "Start an inquiry"): submitButton(cls := "btn-rack__btn inquiry", title := "Hotkey: i")(i) - ) - }, - Granter.opt(_.UserEvaluate).option { + , + Granter(_.UserEvaluate).option: postForm( action := routes.Mod.refreshUserAssess(u.username), title := "Collect data and ask irwin and Kaladin", cls := "xhr" ): submitButton(cls := "btn-rack__btn")("Evaluate") - }, - Granter.opt(_.GamesModView).option { + , + Granter(_.GamesModView).option: a( cls := "btn-rack__btn", href := routes.GameMod.index(u.username), title := "View games" )("Games") - }, - Granter.opt(_.Shadowban).option { + , + Granter(_.Shadowban).option: a( cls := "btn-rack__btn", href := routes.Mod.communicationPublic(u.id), title := "View communications" )("Comms") - } ), - div(cls := "btn-rack")( - postForm( - action := routes.Mod.alt(u.username, !u.marks.alt), - title := "Preemptively close unauthorized alt.", - cls := "xhr" - ): - submitButton( - cls := List( - "btn-rack__btn" -> true, - "active" -> u.marks.alt - ), - ModUserTableUi.canCloseAlt.not.option(disabled) - )("Alt") - , - postForm( - action := routes.Mod.engine(u.username, !u.marks.engine), - title := "This user is clearly cheating.", - cls := "xhr" - ): - submitButton( - cls := List("btn-rack__btn" -> true, "active" -> u.marks.engine), - Granter.opt(_.MarkEngine).not.option(disabled) - )("Engine") - , - postForm( - action := routes.Mod.booster(u.username, !u.marks.boost), - title := "Marks the user as a booster or sandbagger.", - cls := "xhr" - ): - submitButton( - cls := List("btn-rack__btn" -> true, "active" -> u.marks.boost), - Granter.opt(_.MarkBooster).not.option(disabled) - )("Booster") - , - frag( + Granter(_.AccountInfo).option: + div(cls := "btn-rack")( postForm( - action := routes.Mod.troll(u.username, !u.marks.troll), - title := "Enable/disable communication features for this user.", + action := routes.Mod.alt(u.username, !u.marks.alt), + title := "Preemptively close unauthorized alt.", cls := "xhr" - )( + ): submitButton( - cls := List("btn-rack__btn" -> true, "active" -> u.marks.troll), - Granter.opt(_.Shadowban).not.option(disabled) - )("Shadowban") - ), - u.marks.troll.option: - frag( - postForm( - action := routes.Mod.deletePmsAndChats(u.username), - title := "Delete all PMs and public chat messages", - cls := "xhr" - ): - submitButton( - cls := "btn-rack__btn yes-no-confirm", - Granter.opt(_.Shadowban).not.option(disabled) + cls := List( + "btn-rack__btn" -> true, + "active" -> u.marks.alt + ), + ModUserTableUi.canCloseAlt.not.option(disabled) + )("Alt") + , + postForm( + action := routes.Mod.engine(u.username, !u.marks.engine), + title := "This user is clearly cheating.", + cls := "xhr" + ): + submitButton( + cls := List("btn-rack__btn" -> true, "active" -> u.marks.engine), + Granter(_.MarkEngine).not.option(disabled) + )("Engine") + , + postForm( + action := routes.Mod.booster(u.username, !u.marks.boost), + title := "Marks the user as a booster or sandbagger.", + cls := "xhr" + ): + submitButton( + cls := List("btn-rack__btn" -> true, "active" -> u.marks.boost), + Granter(_.MarkBooster).not.option(disabled) + )("Booster") + , + frag( + postForm( + action := routes.Mod.troll(u.username, !u.marks.troll), + title := "Enable/disable communication features for this user.", + cls := "xhr" + )( + submitButton( + cls := List("btn-rack__btn" -> true, "active" -> u.marks.troll), + Granter(_.Shadowban).not.option(disabled) + )("Shadowban") + ), + u.marks.troll.option: + frag( + postForm( + action := routes.Mod.deletePmsAndChats(u.username), + title := "Delete all PMs and public chat messages", + cls := "xhr" ): - "Clear PMs & chats" - , - postForm( - action := routes.Mod.isolate(u.username, !u.marks.isolate), - title := "Isolate user by preventing all PMs, follows and challenges", - cls := "xhr" - )( - submitButton( - cls := List("btn-rack__btn yes-no-confirm" -> true, "active" -> u.marks.isolate), - Granter.opt(_.Shadowban).not.option(disabled) - )("Isolate") + submitButton( + cls := "btn-rack__btn yes-no-confirm", + Granter(_.Shadowban).not.option(disabled) + ): + "Clear PMs & chats" + , + postForm( + action := routes.Mod.isolate(u.username, !u.marks.isolate), + title := "Isolate user by preventing all PMs, follows and challenges", + cls := "xhr" + )( + submitButton( + cls := List("btn-rack__btn yes-no-confirm" -> true, "active" -> u.marks.isolate), + Granter(_.Shadowban).not.option(disabled) + )("Isolate") + ) ) - ) - ), - postForm( - action := routes.Mod.kid(u.username, !u.kid.value), - title := "Activate kid mode if not already the case", - cls := "xhr" - ): - submitButton( - cls := List("btn-rack__btn yes-no-confirm" -> true, "active" -> u.kid.yes), - Granter.opt(_.SetKidMode).not.option(disabled) - )("Kid") - , - postForm( - action := routes.Mod.rankban(u.username, !u.marks.rankban), - title := "Include/exclude this user from the rankings.", - cls := "xhr" - ): - submitButton( - cls := List("btn-rack__btn" -> true, "active" -> u.marks.rankban), - Granter.opt(_.RemoveRanking).not.option(disabled) - )("Rankban") - , - postForm( - action := routes.Mod.arenaBan(u.username, !u.marks.arenaBan), - title := "Enable/disable this user from joining all arenas.", - cls := "xhr" - ): - submitButton( - cls := List("btn-rack__btn" -> true, "active" -> u.marks.arenaBan), - Granter.opt(_.ArenaBan).not.option(disabled) - )("Arena ban") - , - postForm( - action := routes.Mod.prizeban(u.username, !u.marks.prizeban), - title := "Enable/disable this user from joining prized tournaments.", - cls := "xhr" - ): - submitButton( - cls := List("btn-rack__btn" -> true, "active" -> u.marks.prizeban), - Granter.opt(_.PrizeBan).not.option(disabled) - )("Prizeban") - , - postForm( - action := routes.Mod.reportban(u.username, !u.marks.reportban), - title := "Enable/disable the report feature for this user.", - cls := "xhr" - ): - submitButton( - cls := List("btn-rack__btn" -> true, "active" -> u.marks.reportban), - Granter.opt(_.ReportBan).not.option(disabled) - )("Reportban") - ), + ), + postForm( + action := routes.Mod.kid(u.username, !u.kid.value), + title := "Activate kid mode if not already the case", + cls := "xhr" + ): + submitButton( + cls := List("btn-rack__btn yes-no-confirm" -> true, "active" -> u.kid.yes), + Granter(_.SetKidMode).not.option(disabled) + )("Kid") + , + postForm( + action := routes.Mod.rankban(u.username, !u.marks.rankban), + title := "Include/exclude this user from the rankings.", + cls := "xhr" + ): + submitButton( + cls := List("btn-rack__btn" -> true, "active" -> u.marks.rankban), + Granter(_.RemoveRanking).not.option(disabled) + )("Rankban") + , + postForm( + action := routes.Mod.arenaBan(u.username, !u.marks.arenaBan), + title := "Enable/disable this user from joining all arenas.", + cls := "xhr" + ): + submitButton( + cls := List("btn-rack__btn" -> true, "active" -> u.marks.arenaBan), + Granter(_.ArenaBan).not.option(disabled) + )("Arena ban") + , + postForm( + action := routes.Mod.prizeban(u.username, !u.marks.prizeban), + title := "Enable/disable this user from joining prized tournaments.", + cls := "xhr" + ): + submitButton( + cls := List("btn-rack__btn" -> true, "active" -> u.marks.prizeban), + Granter(_.PrizeBan).not.option(disabled) + )("Prizeban") + , + postForm( + action := routes.Mod.reportban(u.username, !u.marks.reportban), + title := "Enable/disable the report feature for this user.", + cls := "xhr" + ): + submitButton( + cls := List("btn-rack__btn" -> true, "active" -> u.marks.reportban), + Granter(_.ReportBan).not.option(disabled) + )("Reportban") + ) + , Granter .opt(_.CloseAccount) .option( @@ -219,11 +219,11 @@ final class ModUserUi(helpers: Helpers, modUi: ModUi, mailerEventsUrl: Url): cls := "xhr" )(submitButton(cls := "btn-rack__btn active")("Closed")) , - Granter.opt(_.GdprErase).option(gdprEraseForm(u)) + Granter(_.GdprErase).option(gdprEraseForm(u)) ) ) ), - (u.totpSecret.isDefined).option: + (u.totpSecret.isDefined && Granter(_.AccountInfo)).option: div(cls := "btn-rack")( postForm( action := routes.Mod.disableTwoFactor(u.username), @@ -232,7 +232,7 @@ final class ModUserUi(helpers: Helpers, modUi: ModUi, mailerEventsUrl: Url): ): submitButton( cls := "btn-rack__btn yes-no-confirm", - Granter.opt(_.DisableTwoFactor).not.option(disabled) + Granter(_.DisableTwoFactor).not.option(disabled) )( "Disable 2FA" ) @@ -249,7 +249,7 @@ final class ModUserUi(helpers: Helpers, modUi: ModUi, mailerEventsUrl: Url): ) ) }, - Granter.opt(_.SetTitle).option { + Granter(_.SetTitle).option { postForm(cls := "fide-title", action := routes.Mod.setTitle(u.username))( form3.select( lila.user.UserForm.title.fill(u.title)("title"), @@ -293,7 +293,7 @@ final class ModUserUi(helpers: Helpers, modUi: ModUi, mailerEventsUrl: Url): submitButton(cls := "btn-rack__btn yes-no-confirm")("Blank password") ) , - Granter.opt(_.FreePatron).option { + Granter(_.FreePatron).option { postForm( action := routes.Mod.freePatron(u.username), title := "Give free Patron wings for a month", diff --git a/modules/perfStat/src/main/PerfStatApi.scala b/modules/perfStat/src/main/PerfStatApi.scala index 2adf7d62f09..c5c6edf692a 100644 --- a/modules/perfStat/src/main/PerfStatApi.scala +++ b/modules/perfStat/src/main/PerfStatApi.scala @@ -40,7 +40,7 @@ final class PerfStatApi( .withPerfs(name.id) .flatMap: _.filter: u => - (u.enabled.yes && (!u.lame || me.exists(_.is(u.user)))) || me.soUse(Granter(_.UserModView)) + (u.enabled.yes && (!u.lame || me.exists(_.is(u.user)))) || me.soUse(Granter(_.AccountInfo)) .filter: u => !u.isBot || (perfKey != PerfKey.ultraBullet) .traverse: u => diff --git a/modules/team/src/main/TeamApi.scala b/modules/team/src/main/TeamApi.scala index c18ba909947..83e2297dd9e 100644 --- a/modules/team/src/main/TeamApi.scala +++ b/modules/team/src/main/TeamApi.scala @@ -126,7 +126,7 @@ final class TeamApi( .teamIdsList(of.id) .map(_.take(Team.maxJoin(of).value)) .flatMap: allIds => - if Granter(_.UserModView) then fuccess(allIds) + if Granter(_.AccountInfo) then fuccess(allIds) else allIds.nonEmpty.so: teamRepo.filterHideMembers(allIds).flatMap { hiddenIds => diff --git a/modules/title/src/main/ui/TitleModUi.scala b/modules/title/src/main/ui/TitleModUi.scala index ae6559690b4..492f97c3c41 100644 --- a/modules/title/src/main/ui/TitleModUi.scala +++ b/modules/title/src/main/ui/TitleModUi.scala @@ -32,8 +32,8 @@ final class TitleModUi(helpers: Helpers)(ui: TitleUi)(using NetDomain): Granter.opt(_.TitleRequest).option(a(href := ui.thumbnail.raw(id))(ui.thumbnail(id.some, 500))) Page(s"${user.username}'s title verification") .css("bits.titleRequest") - .css(Granter.opt(_.UserModView).option("mod.user")) - .js(esmInitBit("titleRequest") ++ Granter.opt(_.UserModView).so(Esm("mod.user"))): + .css(Granter.opt(_.AccountInfo).option("mod.user")) + .js(esmInitBit("titleRequest") ++ Granter.opt(_.AccountInfo).so(Esm("mod.user"))): main(cls := "box box-pad page title-mod")( div(cls := "box__top")( h1("Title verification by ", userLink(user), " ", showStatus(req.status)), diff --git a/modules/user/src/main/ui/UserShow.scala b/modules/user/src/main/ui/UserShow.scala index 089f5dbff6e..52bc82904d2 100644 --- a/modules/user/src/main/ui/UserShow.scala +++ b/modules/user/src/main/ui/UserShow.scala @@ -40,7 +40,7 @@ final class UserShow(helpers: Helpers, bits: UserBits): ping.map(bits.signalBars) ), realName.map(div(cls := "upt__info__realname")(_)), - if u.lame && ctx.isnt(u) && !Granter.opt(_.UserModView) + if u.lame && ctx.isnt(u) && !Granter.opt(_.AccountInfo) then div(cls := "upt__info__warning")(trans.site.thisAccountViolatedTos()) else ctx.pref.showRatings.option: @@ -80,7 +80,7 @@ final class UserShow(helpers: Helpers, bits: UserBits): div(cls := "upt__details")( span(trans.site.nbGames.plural(u.count.game, u.count.game.localize)), span(trans.site.joinedX(momentFromNow(u.createdAt))), - (Granter.opt(_.UserModView) && (u.lameOrTroll || u.enabled.no || u.marks.rankban)) + (Granter.opt(_.AccountInfo) && (u.lameOrTroll || u.enabled.no || u.marks.rankban)) .option(span(cls := "upt__details__marks")(userMarks)) ), playing diff --git a/modules/user/src/main/ui/UserShowSide.scala b/modules/user/src/main/ui/UserShowSide.scala index 4fbdc402bc2..b8778e08e77 100644 --- a/modules/user/src/main/ui/UserShowSide.scala +++ b/modules/user/src/main/ui/UserShowSide.scala @@ -72,7 +72,7 @@ final class UserShowSide(helpers: Helpers): ) div(cls := "side sub-ratings")( - (!u.lame || ctx.is(u) || Granter.opt(_.UserModView)).option( + (!u.lame || ctx.is(u) || Granter.opt(_.AccountInfo)).option( frag( showNonEmptyPerf(u.perfs.ultraBullet, PerfKey.ultraBullet), showPerf(u.perfs.bullet, PerfKey.bullet),