diff --git a/backend/routes/auth/discord.go b/backend/routes/auth/discord.go index 63a08c1..f0f37c7 100644 --- a/backend/routes/auth/discord.go +++ b/backend/routes/auth/discord.go @@ -43,8 +43,10 @@ type discordCallbackResponse struct { Ticket string `json:"ticket,omitempty"` RequireInvite bool `json:"require_invite"` // require an invite for signing up - IsDeleted bool `json:"is_deleted"` - DeletedAt *time.Time `json:"deleted_at,omitempty"` + IsDeleted bool `json:"is_deleted"` + DeletedAt *time.Time `json:"deleted_at,omitempty"` + SelfDelete *bool `json:"self_delete,omitempty"` + DeleteReason *string `json:"delete_reason,omitempty"` } func (s *Server) discordCallback(w http.ResponseWriter, r *http.Request) error { @@ -81,7 +83,7 @@ func (s *Server) discordCallback(w http.ResponseWriter, r *http.Request) error { u, err := s.DB.DiscordUser(ctx, du.ID) if err == nil { - if u.DeletedAt != nil && *u.SelfDelete { + if u.DeletedAt != nil { // store cancel delete token token := undeleteToken() err = s.saveUndeleteToken(ctx, u.ID, token) @@ -91,11 +93,13 @@ func (s *Server) discordCallback(w http.ResponseWriter, r *http.Request) error { } render.JSON(w, r, discordCallbackResponse{ - HasAccount: true, - Token: token, - User: dbUserToUserResponse(u, []db.Field{}), - IsDeleted: true, - DeletedAt: u.DeletedAt, + HasAccount: true, + Token: token, + User: dbUserToUserResponse(u, []db.Field{}), + IsDeleted: true, + DeletedAt: u.DeletedAt, + SelfDelete: u.SelfDelete, + DeleteReason: u.DeleteReason, }) return nil } diff --git a/backend/routes/auth/fedi_mastodon.go b/backend/routes/auth/fedi_mastodon.go index 581fa32..0f40d4d 100644 --- a/backend/routes/auth/fedi_mastodon.go +++ b/backend/routes/auth/fedi_mastodon.go @@ -31,8 +31,10 @@ type fediCallbackResponse struct { Ticket string `json:"ticket,omitempty"` RequireInvite bool `json:"require_invite"` // require an invite for signing up - IsDeleted bool `json:"is_deleted"` - DeletedAt *time.Time `json:"deleted_at,omitempty"` + IsDeleted bool `json:"is_deleted"` + DeletedAt *time.Time `json:"deleted_at,omitempty"` + SelfDelete *bool `json:"self_delete,omitempty"` + DeleteReason *string `json:"delete_reason,omitempty"` } type partialMastodonAccount struct { @@ -102,7 +104,7 @@ func (s *Server) mastodonCallback(w http.ResponseWriter, r *http.Request) error u, err := s.DB.FediverseUser(ctx, mu.ID, app.ID) if err == nil { - if u.DeletedAt != nil && *u.SelfDelete { + if u.DeletedAt != nil { // store cancel delete token token := undeleteToken() err = s.saveUndeleteToken(ctx, u.ID, token) @@ -112,11 +114,13 @@ func (s *Server) mastodonCallback(w http.ResponseWriter, r *http.Request) error } render.JSON(w, r, fediCallbackResponse{ - HasAccount: true, - Token: token, - User: dbUserToUserResponse(u, []db.Field{}), - IsDeleted: true, - DeletedAt: u.DeletedAt, + HasAccount: true, + Token: token, + User: dbUserToUserResponse(u, []db.Field{}), + IsDeleted: true, + DeletedAt: u.DeletedAt, + SelfDelete: u.SelfDelete, + DeleteReason: u.DeleteReason, }) return nil } diff --git a/backend/routes/auth/undelete.go b/backend/routes/auth/undelete.go index 236b4ce..6bc2314 100644 --- a/backend/routes/auth/undelete.go +++ b/backend/routes/auth/undelete.go @@ -27,6 +27,16 @@ func (s *Server) cancelDelete(w http.ResponseWriter, r *http.Request) error { return server.APIError{Code: server.ErrNotFound} // assume invalid token } + // only self deleted users can undelete themselves + u, err := s.DB.User(ctx, id) + if err != nil { + log.Errorf("getting user: %v", err) + return errors.Wrap(err, "getting user") + } + if !*u.SelfDelete { + return server.APIError{Code: server.ErrForbidden} + } + err = s.DB.UndoDeleteUser(ctx, id) if err != nil { log.Errorf("executing undelete query: %v", err) diff --git a/backend/routes/mod/resolve_report.go b/backend/routes/mod/resolve_report.go index f9a91a9..bf7730c 100644 --- a/backend/routes/mod/resolve_report.go +++ b/backend/routes/mod/resolve_report.go @@ -77,6 +77,11 @@ func (s *Server) resolveReport(w http.ResponseWriter, r *http.Request) error { } if req.Delete { + err = s.DB.InvalidateAllTokens(ctx, tx, report.UserID) + if err != nil { + return errors.Wrap(err, "invalidating tokens") + } + err = s.DB.CleanUser(ctx, report.UserID) if err != nil { log.Errorf("cleaning user data: %v", err) diff --git a/frontend/src/routes/auth/login/CallbackPage.svelte b/frontend/src/routes/auth/login/CallbackPage.svelte index b20f111..efc80a0 100644 --- a/frontend/src/routes/auth/login/CallbackPage.svelte +++ b/frontend/src/routes/auth/login/CallbackPage.svelte @@ -5,6 +5,7 @@ import ErrorAlert from "$lib/components/ErrorAlert.svelte"; import { userStore } from "$lib/store"; import { addToast } from "$lib/toast"; + import { DateTime } from "luxon"; import { onMount } from "svelte"; import { Alert, @@ -26,6 +27,8 @@ export let token: string | undefined; export let user: MeUser | undefined; export let deletedAt: string | undefined; + export let selfDelete: boolean | undefined; + export let deleteReason: string | undefined; onMount(() => { if (!isDeleted && token && user) { @@ -136,8 +139,12 @@ -{:else if isDeleted && token} -
Your account is pending deletion since {deletedAt}.
+{:else if isDeleted && token && selfDelete && deletedAt} ++ Your account is pending deletion since {DateTime.fromISO(deletedAt) + .toLocal() + .toLocaleString(DateTime.DATETIME_MED)}. +
If you wish to cancel deletion, press the button below.
-
- If you want to delete your account, type your username below:
-
-
- This is irreversible! Your account cannot be recovered after you press "Force delete
- account".
-
-
- -
- {#if deleteError} -+ Your account is pending deletion since {DateTime.fromISO(deletedAt) + .toLocal() + .toLocaleString(DateTime.DATETIME_MED)}. +
++ Your account was deactivated by a moderator. You cannot cancel deletion. The moderator + gave the following reason: +
++ {deleteReason} ++
+ Your account will be fully deleted 180 days after being deactivated. If you want your data wiped + immediately instead, press the force delete link below. +
+
+
+ If you want to delete your account, type your username ({user.name}
) below:
+
+
+ This is irreversible! Your account cannot be recovered after you press "Force delete account".
+
+
+ +
+ {#if deleteError} +