Skip to content

Commit

Permalink
account delete WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Dec 18, 2024
1 parent c3cb44b commit d82b1a7
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 10 deletions.
28 changes: 24 additions & 4 deletions app/controllers/Account.scala
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,11 @@ final class Account(
}

def close = Auth { _ ?=> me ?=>
env.clas.api.student.isManaged(me).flatMap { managed =>
env.security.forms.closeAccount.flatMap: form =>
Ok.page(pages.close(form, managed))
}
for
managed <- env.clas.api.student.isManaged(me)
form <- env.security.forms.closeAccount
res <- Ok.page(pages.close(form, managed))
yield res
}

def closeConfirm = AuthBody { ctx ?=> me ?=>
Expand All @@ -257,6 +258,25 @@ final class Account(
Redirect(routes.User.show(me.username)).withCookies(env.security.lilaCookie.newSession)
}

def delete = Auth { _ ?=> me ?=>
for
managed <- env.clas.api.student.isManaged(me)
form <- env.security.forms.deleteAccount
res <- Ok.page(pages.delete(form, managed))
yield res
}

def deleteConfirm = AuthBody { ctx ?=> me ?=>
NotManaged:
auth.HasherRateLimit:
env.security.forms.deleteAccount.flatMap: form =>
FormFuResult(form)(err => renderPage(pages.delete(err, managed = false))): _ =>
env.api.accountClosure
.close(me.value)
.inject:
Redirect(routes.User.show(me.username)).withCookies(env.security.lilaCookie.newSession)
}

def kid = Auth { _ ?=> me ?=>
for
managed <- env.clas.api.student.isManaged(me)
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/LilaController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -351,4 +351,4 @@ abstract private[controllers] class LilaController(val env: Env)
def anyCaptcha = env.game.captcha.any

def bindForm[T, R](form: Form[T])(error: Form[T] => R, success: T => R)(using Request[?], FormBinding): R =
form.bindFromRequest().fold(error, success)
form.bindFromRequest().pp.fold(error, success)
4 changes: 2 additions & 2 deletions bin/mongodb/recap-notif.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ function sendToRandomOfflinePlayers() {
}
db.user4.find({
enabled: true,
createdAt: { $lt: new Date(year, 9, 1) },
createdAt: { $lt: new Date(year, 10, 1) },
seenAt: {
$gt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 30 * 3),
$gt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 30 * 4),
// $lt: new Date(Date.now() - 1000 * 60 * 20) // avoid the lila notif cache!
},
marks: { $nin: ['boost', 'engine', 'troll'] }
Expand Down
2 changes: 2 additions & 0 deletions conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,8 @@ GET /contact/email-confirm/help controllers.Account.emailConfirmHelp
GET /account/email/confirm/:token controllers.Account.emailConfirm(token)
GET /account/close controllers.Account.close
POST /account/closeConfirm controllers.Account.closeConfirm
GET /account/delete controllers.Account.delete
POST /account/deleteConfirm controllers.Account.deleteConfirm
GET /account/profile controllers.Account.profile
POST /account/profile controllers.Account.profileApply
GET /account/username controllers.Account.username
Expand Down
11 changes: 10 additions & 1 deletion modules/api/src/main/AccountClosure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ package lila.api
import lila.common.Bus
import lila.core.perm.Granter

/* There are 3 stages to account eradication.
* - close:
* - disable the account; the user can reopen it later on
* - close all open sessions
* - cancel patron sub
* - leave teams and tournaments
* - unfollow everyone
* -
*/
final class AccountClosure(
userRepo: lila.user.UserRepo,
playbanApi: lila.playban.PlaybanApi,
Expand Down Expand Up @@ -78,5 +87,5 @@ final class AccountClosure(
def closeThenErase(username: UserStr)(using Me): Fu[Either[String, String]] =
userRepo.byId(username).flatMap {
case None => fuccess(Left("No such user."))
case Some(u) => (u.enabled.yes.so(close(u))) >> eraseClosed(u.id)
case Some(u) => u.enabled.yes.so(close(u)) >> eraseClosed(u.id)
}
2 changes: 1 addition & 1 deletion modules/gathering/src/main/Quote.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1374,7 +1374,7 @@ object Quote:
"Garry Kasparov"
),
Quote(
"For me, chess is at the same time a game, a sport, a science and an art. And perhaps even more than that,. There is something hard to explain to those who do not know the game well. One must first learn to play it correctly in order to savor its richness.",
"For me, chess is at the same time a game, a sport, a science and an art. And perhaps even more than that. There is something hard to explain to those who do not know the game well. One must first learn to play it correctly in order to savor its richness.",
"Bent Larsen"
),
Quote(
Expand Down
4 changes: 4 additions & 0 deletions modules/oauth/src/main/AccessTokenApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ final class AccessTokenApi(
for _ <- coll.delete.one($doc(F.id -> id, F.userId -> me))
yield onRevoke(id)

def revokeAllByUser(using me: MyId): Funit =
for _ <- coll.delete.one($doc(F.id -> id, F.userId -> me))
yield onRevoke(id)

def revokeByClientOrigin(clientOrigin: String)(using me: MyId): Funit =
coll
.find(
Expand Down
28 changes: 28 additions & 0 deletions modules/pref/src/main/ui/AccountPages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ final class AccountPages(helpers: Helpers, ui: AccountUi, flagApi: lila.core.use
if managed then p(trs.managedAccountCannotBeClosed())
else
postForm(cls := "form3", action := routes.Account.closeConfirm)(
div(cls := "form-group")(h2("We're sorry to see you go.")),
div(cls := "form-group")(trs.closeAccountExplanation()),
div(cls := "form-group")(trs.cantOpenSimilarAccount()),
form3.passwordModified(form("passwd"), trans.site.password())(autofocus, autocomplete := "off"),
Expand All @@ -35,6 +36,33 @@ final class AccountPages(helpers: Helpers, ui: AccountUi, flagApi: lila.core.use
)
)

def delete(form: Form[?], managed: Boolean)(using Context)(using me: Me) =
AccountPage(s"${me.username} - Delete your account", "delete"):
div(cls := "box box-pad")(
boxTop(h1(cls := "text", dataIcon := Icon.CautionCircle)("Delete your account")),
if managed then p(trs.managedAccountCannotBeClosed())
else
postForm(cls := "form3", action := routes.Account.deleteConfirm)(
div(cls := "form-group")(h2("We're sorry to see you go.")),
div(cls := "form-group")(
"Once you delete your account, your profile and username are permanently removed from Lichess and your posts, comments, and game are disassociated (not deleted) from your account."
),
form3.passwordModified(form("passwd"), trans.site.password())(autofocus, autocomplete := "off"),
form3.checkbox(form("understand"), "I understand that deleted accounts aren't recoverable"),
form3.errors(form("understand")),
form3.actions(
frag(
a(href := routes.User.show(me.username))(trans.site.cancel()),
form3.submit(
"Delete my account",
icon = Icon.CautionCircle.some,
confirm = trs.closingIsDefinitive.txt().some
)(cls := "button-red")
)
)
)
)

private def linksHelp()(using Translate) = frag(
"Mastodon, Facebook, GitHub, Chess.com, ...",
br,
Expand Down
8 changes: 8 additions & 0 deletions modules/security/src/main/SecurityForm.scala
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,14 @@ final class SecurityForm(
)(Reopen.apply)(_ => None)
)

def deleteAccount(using Me) =
authenticator.loginCandidate.map: candidate =>
Form:
mapping(
"passwd" -> passwordMapping(candidate),
"understand" -> boolean.verifying("It's an important point.", identity[Boolean])
)((pass, _) => pass)(_ => None)

private def passwordMapping(candidate: LoginCandidate) =
text.verifying("incorrectPassword", p => candidate.check(ClearPassword(p)))

Expand Down
2 changes: 1 addition & 1 deletion modules/ui/src/main/helper/Form3.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ final class Form3(formHelper: FormHelper & I18nHelper & AssetHelper, flairApi: F
private def groupLabel(field: Field) = label(cls := "form-label", `for` := id(field))
private val helper = small(cls := "form-help")

def errors(field: Field)(using Translate): Frag = errors(field.errors)
private def errors(errs: Seq[FormError])(using Translate): Frag = errs.distinct.map(error)
private def errors(field: Field)(using Translate): Frag = errors(field.errors)
private def error(err: FormError)(using Translate): Frag =
p(cls := "error")(transKey(trans(err.message), err.args))

Expand Down

0 comments on commit d82b1a7

Please sign in to comment.