let players erase their own forum posts - closes #8420

pull/8432/head
Thibault Duplessis 2021-03-20 15:41:30 +01:00
parent ca3970720e
commit e0a03df87f
8 changed files with 59 additions and 29 deletions

View File

@ -78,8 +78,15 @@ final class ForumPost(env: Env) extends LilaController(env) with ForumController
def delete(categSlug: String, id: String) =
Auth { implicit ctx => me =>
CategGrantMod(categSlug) {
postApi.delete(categSlug, id, me) map { Ok(_) }
postApi getPost id flatMap {
_ ?? { post =>
if (me.id == ~post.userId)
postApi.erasePost(id) inject Redirect(routes.ForumPost.redirect(id))
else
isGrantedMod(categSlug) flatMap { granted =>
(granted | isGranted(_.ModerateForum)) ?? postApi.delete(categSlug, id, me) map { Ok(_) }
}
}
}
}

View File

@ -34,8 +34,5 @@ trait ForumHelper { self: UserHelper with StringHelper with HasEnv =>
modIcon: Boolean = false
)(implicit lang: Lang): Frag =
if (post.erased) span(cls := "author")("<erased>")
else
post.userId.fold(frag(lila.user.User.anonymous)) { userId =>
userIdLink(userId.some, cssClass = cssClass, withOnline = withOnline, modIcon = modIcon)
}
else userIdLink(post.userId, cssClass = cssClass, withOnline = withOnline, modIcon = modIcon)
}

View File

@ -87,7 +87,7 @@ trait UserHelper { self: I18nHelper with StringHelper with NumberHelper =>
def isStreaming(userId: String) = env.streamer.liveStreamApi isStreaming userId
def userIdLink(
userIdOption: Option[String],
userIdOption: Option[User.ID],
cssClass: Option[String] = None,
withOnline: Boolean = true,
withTitle: Boolean = true,

View File

@ -41,7 +41,7 @@ object post {
)(implicit ctx: Context) = {
st.article(cls := List("forum-post" -> true, "erased" -> post.erased), id := post.number)(
div(cls := "forum-post__metas")(
div(
!post.erased option div(
authorLink(post = post, cssClass = "author".some, modIcon = post.displayModIcon),
a(href := url)(
post.updatedAt
@ -55,23 +55,33 @@ object post {
momentFromNow(post.createdAt)
}
),
ctx.userId.fold(false)(post.shouldShowEditForm(_)) option
ctx.userId.exists(post.shouldShowEditForm) option
a(cls := "mod edit button button-empty text", dataIcon := "m")("Edit"),
canModCateg option a(
cls := "mod delete button button-empty button-red",
href := routes.ForumPost.delete(categ.slug, post.id),
dataIcon := "q",
title := "Delete"
)
if (ctx.userId.has(~post.userId))
postForm(action := routes.ForumPost.delete(categ.slug, post.id))(
submitButton(
cls := "mod delete button button-empty confirm",
dataIcon := "q",
title := "Delete"
)
)
else if (canModCateg)
a(
cls := "mod delete button button-empty",
href := routes.ForumPost.delete(categ.slug, post.id),
dataIcon := "q",
title := "Delete"
)
else emptyFrag
),
a(cls := "anchor", href := url)(s"#${post.number}")
),
p(cls := "forum-post__message")(
if (post.erased) "<erased>"
if (post.erased) "<Comment deleted by user>"
else richText(post.text)
),
reactions(post, canReact),
ctx.userId.exists(post.shouldShowEditForm(_)) option
!post.erased option reactions(post, canReact),
ctx.userId.exists(post.shouldShowEditForm) option
postForm(cls := "edit-post-form", action := routes.ForumPost.edit(post.id))(
textarea(
bits.dataTopic := topic.id,

View File

@ -35,7 +35,7 @@ object games {
) {
main(cls := "mod-games box")(
div(cls := "box__top")(
h1(userLink(user), " games"),
h1(userLink(user, params = "?mod"), " games"),
div(cls := "box__top__actions")(
form(method := "get", action := routes.GameMod.index(user.id), cls := "mod-games__filter-form")(
form3.input(filterForm("opponents"))(placeholder := "Opponents"),

View File

@ -66,6 +66,6 @@ final class Env(
lila.common.Bus.subscribeFun("team", "gdprErase") {
case CreateTeam(id, name, _) => categApi.makeTeam(id, name).unit
case lila.user.User.GDPRErase(user) => postApi.erase(user).unit
case lila.user.User.GDPRErase(user) => postApi.eraseAllOf(user).unit
}
}

View File

@ -113,12 +113,15 @@ final class PostApi(
}
def get(postId: String): Fu[Option[(Topic, Post)]] =
env.postRepo.coll.byId[Post](postId) flatMap {
getPost(postId) flatMap {
_ ?? { post =>
env.topicRepo.coll.byId[Topic](post.topicId) dmap2 { _ -> post }
}
}
def getPost(postId: String): Fu[Option[Post]] =
env.postRepo.coll.byId[Post](postId)
def react(postId: String, me: User, reaction: String, v: Boolean): Fu[Option[Post]] =
Post.Reaction.set(reaction) ?? {
if (v) lila.mon.forum.reaction(reaction).increment()
@ -246,7 +249,10 @@ final class PostApi(
ReadPreference.secondaryPreferred
)
def erase(user: User): Funit =
def erasePost(id: Post.ID) =
env.postRepo.coll.updateField($id(id), "erasedAt", DateTime.now).void
def eraseAllOf(user: User): Funit =
env.postRepo.coll.update
.one(
$doc("userId" -> user.id),

View File

@ -25,6 +25,14 @@
color: $c-link-dim;
font-weight: bold;
}
.delete {
color: $c-font;
margin-left: 1em;
&:hover {
color: $c-bad;
}
}
}
.mod {
@ -56,14 +64,16 @@
}
&.erased {
background: $c-shade;
opacity: 0.6;
}
color: $c-font-dimmer;
&.erased .forum-post__message {
font-style: italic;
text-align: center;
margin: 0;
.forum-post__message {
font-style: italic;
text-align: center;
margin-bottom: 2em;
}
.forum-post__metas {
justify-content: flex-end;
}
}
&__message {