diff --git a/app/controllers/ForumController.scala b/app/controllers/ForumController.scala index e5c175ea9cc1f..54eba522ac7c5 100644 --- a/app/controllers/ForumController.scala +++ b/app/controllers/ForumController.scala @@ -16,9 +16,10 @@ private[controllers] trait ForumController { self: LilaController => protected def teamCache = env.team.cached protected def CategGrantWrite[A <: Result]( - categSlug: String + categSlug: String, + tryingToPostAsMod: Boolean = false )(a: => Fu[A])(implicit ctx: Context): Fu[Result] = - access.isGrantedWrite(categSlug) flatMap { granted => + access.isGrantedWrite(categSlug, tryingToPostAsMod) flatMap { granted => if (granted) a else fuccess(Forbidden("You cannot post to this category")) } diff --git a/app/controllers/ForumPost.scala b/app/controllers/ForumPost.scala index 1069a26f32f4d..35da3ee3b91eb 100644 --- a/app/controllers/ForumPost.scala +++ b/app/controllers/ForumPost.scala @@ -27,18 +27,18 @@ final class ForumPost(env: Env) extends LilaController(env) with ForumController def create(categSlug: String, slug: String, page: Int) = AuthBody { implicit ctx => me => NoBot { - CategGrantWrite(categSlug) { - implicit val req = ctx.body - OptionFuResult(topicApi.show(categSlug, slug, page, ctx.me)) { case (categ, topic, posts) => - if (topic.closed) fuccess(BadRequest("This topic is closed")) - else if (topic.isOld) fuccess(BadRequest("This topic is archived")) - else - categ.team.?? { env.team.cached.isLeader(_, me.id) } flatMap { inOwnTeam => - forms - .post(me, inOwnTeam) - .bindFromRequest() - .fold( - err => + implicit val req = ctx.body + OptionFuResult(topicApi.show(categSlug, slug, page, ctx.me)) { case (categ, topic, posts) => + if (topic.closed) fuccess(BadRequest("This topic is closed")) + else if (topic.isOld) fuccess(BadRequest("This topic is archived")) + else + categ.team.?? { env.team.cached.isLeader(_, me.id) } flatMap { inOwnTeam => + forms + .post(me, inOwnTeam) + .bindFromRequest() + .fold( + err => + CategGrantWrite(categSlug, tryingToPostAsMod = true) { for { captcha <- forms.anyCaptcha unsub <- env.timeline.status(s"forum:${topic.id}")(me.id) @@ -46,16 +46,18 @@ final class ForumPost(env: Env) extends LilaController(env) with ForumController } yield BadRequest( html.forum.topic .show(categ, topic, posts, Some(err -> captcha), unsub, canModCateg = canModCateg) - ), - data => + ) + }, + data => + CategGrantWrite(categSlug, tryingToPostAsMod = ~data.modIcon) { CreateRateLimit(ctx.ip) { postApi.makePost(categ, topic, data, me) map { post => Redirect(routes.ForumPost.redirect(post.id)) } }(rateLimitedFu) - ) - } - } + } + ) + } } } } diff --git a/app/controllers/ForumTopic.scala b/app/controllers/ForumTopic.scala index 5c49403a16ddd..99934b24b02a1 100644 --- a/app/controllers/ForumTopic.scala +++ b/app/controllers/ForumTopic.scala @@ -62,7 +62,7 @@ final class ForumTopic(env: Env) extends LilaController(env) with ForumControlle for { unsub <- ctx.userId ?? env.timeline.status(s"forum:${topic.id}") canRead <- access.isGrantedRead(categ.slug) - canWrite <- access.isGrantedWrite(categ.slug) + canWrite <- access.isGrantedWrite(categ.slug, tryingToPostAsMod = true) canModCateg <- access.isGrantedMod(categ.slug) inOwnTeam <- ~(categ.team, ctx.me).mapN { case (teamId, me) => env.team.cached.isLeader(teamId, me.id) diff --git a/modules/api/src/main/ForumAccess.scala b/modules/api/src/main/ForumAccess.scala index ed9e7df354ac0..a560c1ec7e506 100644 --- a/modules/api/src/main/ForumAccess.scala +++ b/modules/api/src/main/ForumAccess.scala @@ -13,10 +13,10 @@ final class ForumAccess(teamApi: lila.team.TeamApi, teamCached: lila.team.Cached case object Read extends Operation case object Write extends Operation - def isGranted(categSlug: String, op: Operation)(implicit ctx: UserContext): Fu[Boolean] = + private def isGranted(categSlug: String, op: Operation)(implicit ctx: UserContext): Fu[Boolean] = Categ.slugToTeamId(categSlug).fold(fuTrue) { teamId => ctx.me ?? { me => - fuccess(Granter(Permission.ModerateForum)(me)) >>| teamCached.forumAccess.get(teamId).flatMap { + teamCached.forumAccess.get(teamId).flatMap { case Team.Access.NONE => fuFalse case Team.Access.EVERYONE => op match { @@ -34,10 +34,14 @@ final class ForumAccess(teamApi: lila.team.TeamApi, teamCached: lila.team.Cached } def isGrantedRead(categSlug: String)(implicit ctx: UserContext): Fu[Boolean] = - isGranted(categSlug, Read) - - def isGrantedWrite(categSlug: String)(implicit ctx: UserContext): Fu[Boolean] = - ctx.me.exists(canWriteInAnyForum) ?? isGranted(categSlug, Write) + if (ctx.me ?? Granter(Permission.Shusher)) fuTrue + else isGranted(categSlug, Read) + + def isGrantedWrite(categSlug: String, tryingToPostAsMod: Boolean = false)(implicit + ctx: UserContext + ): Fu[Boolean] = + if (tryingToPostAsMod && ctx.me ?? Granter(Permission.Shusher)) fuTrue + else ctx.me.exists(canWriteInAnyForum) ?? isGranted(categSlug, Write) private def canWriteInAnyForum(u: User) = !u.isBot && {