diff --git a/endpoints/account/confirm-delete.php b/endpoints/account/confirm-delete.php new file mode 100644 index 00000000..b5d0b6b9 --- /dev/null +++ b/endpoints/account/confirm-delete.php @@ -0,0 +1,128 @@ + [FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => '/^[a-zA-Z0-9]{40}$/']] + ); + protected array $expectedPOST = array( + 'submit' => [FILTER_UNSAFE_RAW ], + 'cancel' => [FILTER_UNSAFE_RAW ], + 'confirm' => [FILTER_CALLBACK, 'options' => [self::class, 'checkEmptySet'] ], + 'key' => [FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => '/^[a-zA-Z0-9]{40}$/']] + ); + + public bool $confirm = true; // just to select the correct localized brick + public string $username = ''; + public string $deleteFormTarget = '?account=confirm-delete'; + public ?array $inputbox = null; + public string $key = ''; + + private bool $success = false; + + public function __construct(string $pageParam) + { + if (Cfg::get('ACC_AUTH_MODE') != AUTH_MODE_SELF) + $this->generateError(); + + parent::__construct($pageParam); + } + + protected function generate() : void + { + array_unshift($this->title, Lang::account('accDelete')); + + $this->username = User::$username; + + parent::generate(); + + $msg = Lang::account('inputbox', 'error', 'purgeTokenUsed'); + + // display default confirm template + if ($this->assertGET('key') && DB::Aowow()->selectCell('SELECT 1 FROM ?_account WHERE `status` = ?d AND `statusTimer` > UNIX_TIMESTAMP() AND `token` = ?', ACC_STATUS_PURGING, $this->_get['key'])) + { + $this->key = $this->_get['key']; + return; + } + + // perform action and display status + if ($this->assertPOST('key') && ($userId = DB::Aowow()->selectCell('SELECT `id` FROM ?_account WHERE `status` = ?d AND `statusTimer` > UNIX_TIMESTAMP() AND `token` = ?', ACC_STATUS_PURGING, $this->_post['key']))) + { + if ($this->_post['cancel']) + $msg = $this->cancel($userId); + else if ($this->_post['submit'] && $this->_post['confirm']) + $msg = $this->purge($userId); + } + + // throw error and display in status + $this->inputbox = ['inputbox-status', array( + 'head' => Lang::account('inputbox', 'head', $this->success ? 'success' : 'error'), + 'message' => $this->success ? $msg : '', + 'error' => $this->success ? '' : $msg + )]; + } + + private function cancel(int $userId) : string + { + if (DB::Aowow()->query('UPDATE ?_account SET `status` = ?d, `statusTimer` = 0, `token` = "" WHERE `id` = ?d', ACC_STATUS_NONE, $userId)) + { + $this->success = true; + return Lang::account('inputbox', 'message', 'deleteCancel'); + } + + return Lang::main('intError'); + } + + private function purge(int $userId) : string + { + // empty all user settings and cookies + DB::Aowow()->query('DELETE FROM ?_account_cookies WHERE `userId` = ?d', $userId); + DB::Aowow()->query('DELETE FROM ?_account_avatars WHERE `userId` = ?d', $userId); + DB::Aowow()->query('DELETE FROM ?_account_excludes WHERE `userId` = ?d', $userId); + DB::Aowow()->query('DELETE FROM ?_account_favorites WHERE `userId` = ?d', $userId); + DB::Aowow()->query('DELETE FROM ?_account_reputation WHERE `userId` = ?d', $userId); + DB::Aowow()->query('DELETE FROM ?_account_weightscales WHERE `userId` = ?d', $userId); // cascades to aowow_account_weightscale_data + + // delete profiles, unlink chars + DB::Aowow()->query('DELETE pp FROM ?_profiler_profiles pp JOIN ?_account_profiles ap ON ap.`profileId` = pp.`id` WHERE ap.`accountId` = ?d', $userId); + // DB::Aowow()->query('DELETE FROM ?_account_profiles WHERE `accountId` = ?d', $userId); // already deleted via FK? + + // delete all sessions and bans + DB::Aowow()->query('DELETE FROM ?_account_banned WHERE `userId` = ?d', $userId); + DB::Aowow()->query('DELETE FROM ?_account_sessions WHERE `userId` = ?d', $userId); + + // delete forum posts (msg: This post was from a user who has deleted their account. (no translations at src); comments/replies are unaffected) + // ... + + // replace username with userId and empty fields + DB::Aowow()->query( + 'UPDATE ?_account SET + `login` = "", `passHash` = "", `username` = `id`, `email` = NULL, `userGroups` = 0, `userPerms` = 0, + `curIp` = "", `prevIp` = "", `curLogin` = 0, `prevLogin` = 0, + `locale` = 0, `debug` = 0, `avatar` = 0, `wowicon` = "", `title` = "", `description` = "", `excludeGroups` = 0, + `status` = ?d, `statusTimer` = 0, `token` = "", `updateValue` = "", `renameCooldown` = 0 + WHERE `id` = ?d', + ACC_STATUS_DELETED, $userId + ); + + $this->success = true; + return Lang::account('inputbox', 'message', 'deleteOk'); + } +} + +?> diff --git a/endpoints/account/delete.php b/endpoints/account/delete.php new file mode 100644 index 00000000..34da70e2 --- /dev/null +++ b/endpoints/account/delete.php @@ -0,0 +1,71 @@ + ['filter' => FILTER_UNSAFE_RAW] + ); + + public string $username = ''; + public string $deleteFormTarget = '?account=delete'; + public ?array $inputbox = null; + + public function __construct(string $pageParam) + { + if (Cfg::get('ACC_AUTH_MODE') != AUTH_MODE_SELF) + $this->generateError(); + + parent::__construct($pageParam); + } + + protected function generate() : void + { + array_unshift($this->title, Lang::account('accDelete')); + + parent::generate(); + + $this->username = User::$username; + + if ($this->_post['proceed']) + { + $error = false; + if (!DB::Aowow()->selectCell('SELECT 1 FROM ?_account WHERE `status` NOT IN (?a) AND `statusTimer` > UNIX_TIMESTAMP() AND `id` = ?d', [ACC_STATUS_NEW, ACC_STATUS_NONE, ACC_STATUS_PURGING], User::$id)) + { + $token = Util::createHash(40); + + DB::Aowow()->query('UPDATE ?_account SET `status` = ?d, `statusTimer` = UNIX_TIMESTAMP() + ?d, `token` = ? WHERE `id` = ?d', + ACC_STATUS_PURGING, Cfg::get('ACC_RECOVERY_DECAY'), $token, User::$id); + + Util::sendMail(User::$email, 'delete-account', [$token, User::$email, User::$username]); + } + else + $error = true; + + $this->inputbox = ['inputbox-status', array( + 'head' => Lang::account('inputbox', 'head', $error ? 'error' : 'success'), + 'message' => $error ? '' : Lang::account('inputbox', 'message', 'deleteAccSent', [User::$email]), + 'error' => $error ? Lang::account('inputbox', 'error', 'isRecovering') : '' + )]; + } + } +} + +?> diff --git a/includes/components/response/templateresponse.class.php b/includes/components/response/templateresponse.class.php index bef62121..bc2cda60 100644 --- a/includes/components/response/templateresponse.class.php +++ b/includes/components/response/templateresponse.class.php @@ -472,14 +472,16 @@ class TemplateResponse extends BaseResponse 'viError' => $_SESSION['error']['vi'] ?? null ); + // we cannot blanket NUMERIC_CHECK the data as usernames of deleted users are their id which does not support String.lower() + if ($this->contribute & CONTRIBUTE_CO) - $community['co'] = Util::toJSON(CommunityContent::getComments($this->type, $this->typeId)); + $community['co'] = Util::toJSON(CommunityContent::getComments($this->type, $this->typeId), JSON_UNESCAPED_UNICODE); if ($this->contribute & CONTRIBUTE_SS) - $community['ss'] = Util::toJSON(CommunityContent::getScreenshots($this->type, $this->typeId)); + $community['ss'] = Util::toJSON(CommunityContent::getScreenshots($this->type, $this->typeId), JSON_UNESCAPED_UNICODE); if ($this->contribute & CONTRIBUTE_VI) - $community['vi'] = Util::toJSON(CommunityContent::getVideos($this->type, $this->typeId)); + $community['vi'] = Util::toJSON(CommunityContent::getVideos($this->type, $this->typeId), JSON_UNESCAPED_UNICODE); unset($_SESSION['error']); diff --git a/includes/defines.php b/includes/defines.php index 29900e2e..eb18180f 100644 --- a/includes/defines.php +++ b/includes/defines.php @@ -69,7 +69,8 @@ define('ACC_STATUS_RECOVER_PASS', 3); // currently recover define('ACC_STATUS_CHANGE_EMAIL', 4); // currently changing contact email define('ACC_STATUS_CHANGE_PASS', 5); // currently changing password define('ACC_STATUS_CHANGE_USERNAME', 6); // currently changing username -define('ACC_STATUS_DELETED', 7); // is deleted - only a stub remains +define('ACC_STATUS_PURGING', 7); // deletion is pending +define('ACC_STATUS_DELETED', 99); // is deleted - only a stub remains // Session Status define('SESSION_ACTIVE', 1); diff --git a/includes/user.class.php b/includes/user.class.php index ebf180af..e310239f 100644 --- a/includes/user.class.php +++ b/includes/user.class.php @@ -280,10 +280,11 @@ class User 'SELECT a.`id`, a.`passHash`, BIT_OR(ab.`typeMask`) AS "bans", a.`status` FROM ?_account a LEFT JOIN ?_account_banned ab ON a.`id` = ab.`userId` AND ab.`end` > UNIX_TIMESTAMP() - WHERE { a.`email` = ? } { a.`login` = ? } + WHERE { a.`email` = ? } { a.`login` = ? } AND `status` <> ?d GROUP BY a.`id`', $email ?: DBSIMPLE_SKIP, - !$email ? $nameOrEmail : DBSIMPLE_SKIP + !$email ? $nameOrEmail : DBSIMPLE_SKIP, + ACC_STATUS_DELETED ); if (!$query) diff --git a/localization/locale_dede.php b/localization/locale_dede.php index c1e1e179..3004a8d5 100644 --- a/localization/locale_dede.php +++ b/localization/locale_dede.php @@ -1035,6 +1035,7 @@ $lang = array( 'passChangeOk' => "Ihr Kennwort wurde erfolgreich geändert.", 'deleteAccSent' => "Eine E-Mail mit einem Bestätigungslink wurde an %s gesendet.", 'deleteOk' => "Ihr Konto wurde erfolgreich entfernt. Wir hoffen, Sie bald wiederzusehen!

Sie können dieses Fenster jetzt schließen.", + 'deleteCancel' => "Die Kontolöschung wurde abgebrochen.", 'createAccSent' => 'Eine Nachricht wurde soeben an %s versandt. Folgt einfach den darin enthaltenen Anweisungen, um Euer Konto zu erstellen.

Falls du keine Bestätigungsnachricht erhalten hast klicke hier um eine neue zu senden.', 'recovUserSent' => "Eine Nachricht wurde soeben an %s versandt. Folgt einfach den darin enthaltenen Anweisungen, um euren Benutzernamen zu erhalten.", 'recovPassSent' => "Eine Nachricht wurde soeben an %s versandt. Folgt einfach den darin enthaltenen Anweisungen, um euer Kennwort zurückzusetzen.", @@ -1042,6 +1043,7 @@ $lang = array( 'error' => array( 'mailTokenUsed' => 'Dieser Schlüssel zur Änderung der E-Mail-Adresse wurde entweder bereits verwendet oder ist ungültig. Besuchen Sie Ihre Kontoeinstellungen, um es erneut zu versuchen.', 'passTokenUsed' => 'Dieser Schlüssel zur Änderung des Kennworts wurde entweder bereits verwendet oder ist ungültig. Besuchen Sie Ihre Kontoeinstellungen, um es erneut zu versuchen.', + 'purgeTokenUsed' => 'Dieser Schlüssel zum Löschen des Kontos wurde entweder bereits verwendet oder ist ungültig. Besuchen Sie Ihre Kontoeinstellungen, um es erneut zu versuchen.', 'passTokenLost' => "Kein Token wurde bereitgestellt. Wenn Sie in einer E-Mail einen Link zum Zurücksetzen des Kennworts erhalten haben, kopieren Sie die gesamte URL (einschließlich des Tokens am Ende) in die Adressleiste Ihres Browsers.", 'isRecovering' => "Dieses Konto wird bereits wiederhergestellt. Folgt den Anweisungen in der Nachricht oder wartet %s bis das Token verfällt.", 'loginExceeded' => "Die maximale Anzahl an Anmelde-Versuchen von dieser IP wurde überschritten. Bitte versucht es in %s erneut.", diff --git a/localization/locale_enus.php b/localization/locale_enus.php index 9ec1ff02..9c239530 100644 --- a/localization/locale_enus.php +++ b/localization/locale_enus.php @@ -1035,6 +1035,7 @@ $lang = array( 'passChangeOk' => "Your password has been changed successfully.", 'deleteAccSent' => "An email has been sent to %s with confirmation link attached.", 'deleteOk' => "Your account has been successfully removed. We hope to see you again soon!

You may now close this window.", + 'deleteCancel' => "Account deletion was canceled.", 'createAccSent' => 'An email was sent to %s. Simply follow the instructions to create your account.

If you don\'t receive the verification email, click here to send another one.', 'recovUserSent' => "An email was sent to %s. Simply follow the instructions to recover your username.", 'recovPassSent' => "An email was sent to %s. Simply follow the instructions to reset your password." @@ -1042,6 +1043,7 @@ $lang = array( 'error' => array( 'mailTokenUsed' => 'Either that email change key has already been used, or it\'s not a valid key. Visit your Account Settings page to try again.', 'passTokenUsed' => 'Either that password change key has already been used, or it\'s not a valid key. Visit your Account Settings page to try again.', + 'purgeTokenUsed' => 'Either that account delete key has already been used, or it\'s not a valid key. Visit your Account Settings page to try again.', 'passTokenLost' => "No token was provided. If you received a reset password link in an email, please copy and paste the entire URL (including the token at the end) into your browser's location bar.", 'isRecovering' => "This account is already recovering. Follow the instructions in your email or wait %s for the token to expire.", 'loginExceeded' => "The maximum number of logins from this IP has been exceeded. Please try again in %s.", diff --git a/localization/locale_eses.php b/localization/locale_eses.php index e281220a..0b178b77 100644 --- a/localization/locale_eses.php +++ b/localization/locale_eses.php @@ -1035,6 +1035,7 @@ $lang = array( 'passChangeOk' => "Tu contraseña ha sido cambiada correctamente.", 'deleteAccSent' => "Se ha enviado un correo electrónico a %s con el enlace de confirmación adjunto.", 'deleteOk' => "Tu cuenta ha sido eliminada correctamente. ¡Esperamos verte de nuevo pronto!

Ahora puedes cerrar esta ventana.", + 'deleteCancel' => "La eliminación de la cuenta fue cancelada.", 'createAccSent' => 'Un correo fue enviado a %s. Sigue las instrucciones para crear tu cuenta.

Si no recibes el correo de verificación, haz clic aquí para enviar otro.', 'recovUserSent' => "Un correo fue enviado a %s. Sigue las instrucciones para recuperar tu nombre de usuario.", 'recovPassSent' => "Un correo fue enviado a %s. Sigue las instrucciones para restablecer tu contraseña." @@ -1042,6 +1043,7 @@ $lang = array( 'error' => array( 'mailTokenUsed' => 'Ese código de cambio de correo electrónico ya ha sido usado, o no es válido. Visita tu página de configuración de cuenta para intentarlo de nuevo.', 'passTokenUsed' => 'Ese código de cambio de contraseña ya ha sido usado, o no es válido. Visita tu página de configuración de cuenta para intentarlo de nuevo.', + 'purgeTokenUsed' => 'Esa clave de eliminación de cuenta ya ha sido usada, o no es válida. Visita tu página de configuración de cuenta para intentarlo de nuevo.', 'passTokenLost' => "No se recibió ningún código de petición. Si recibiste un enlace para restablecer tu contraseña por correo, por favor copia y pega la dirección completa (incluyendo el código del final) en la barra de dirección de tu navegador.", 'isRecovering' => "Esta cuenta ya se encuentra en proceso de recuperación. Sigue las instrucciones en tu correo o espera %s para que el token expire.", 'loginExceeded' => "Has excedido la cantidad de inicios de sesión con esta IP. Por favor intenta en %s.", diff --git a/localization/locale_frfr.php b/localization/locale_frfr.php index 2d19e8cb..ffa2d017 100644 --- a/localization/locale_frfr.php +++ b/localization/locale_frfr.php @@ -1035,6 +1035,7 @@ $lang = array( 'passChangeOk' => "Votre mot de passe a été changé avec succès.", 'deleteAccSent' => "Un courriel a été envoyé à %s avec le lien de confirmation.", 'deleteOk' => "Votre compte a été supprimé avec succès. Nous espérons vous revoir bientôt !

Vous pouvez maintenant fermer cette fenêtre.", + 'deleteCancel' => "La suppression du compte a été annulée.", 'createAccSent' => 'Un courriel vous a été envoyé à %s. Veuillez suivre les instructions qu\'il contient pour créer votre compte.

Si vous ne recevez pas l\'email de vérification, cliquez ici pour en envoyer un autre.', 'recovUserSent' => "Un courriel vous a été envoyé à %s. Veuillez suivre les instructions qu'il contient pour récupérer votre nom d'utilisateur.", 'recovPassSent' => "Un courriel vous a été envoyé à %s. Veuillez suivre les instructions qu'il contient pour réinitialiser votre mot de passe." @@ -1042,6 +1043,7 @@ $lang = array( 'error' => array( 'mailTokenUsed' => "Cette clé de changement d'adresse courriel a déjà été utilisée ou n'est pas valide. Visitez votre page de paramètres du compte pour réessayer.", 'passTokenUsed' => "Cette clé de changement de mot de passe a déjà été utilisée ou n'est pas valide. Visitez votre page de paramètres du compte pour réessayer.", + 'purgeTokenUsed' => "Cette clé de suppression de compte a déjà été utilisée ou n'est pas valide. Visitez votre page de paramètres du compte pour réessayer.", 'passTokenLost' => "Aucun jeton n'a été fourni. Si vous avez reçu un lien de réinitialisation du mot de passe dans un courriel, merci de copier et coller l'URL entière (y compris le jeton à la fin) dans la barre d'adresse de votre navigateur.", 'isRecovering' => "Ce compte est déjà en train d'être récupéré. Suivez les instruction dans l'email reçu ou attendez %s pour que le token expire.", 'loginExceeded' => "Le nombre maximum de connections depuis cette IP a été dépassé. Essayez de nouevau dans %s.", diff --git a/localization/locale_ruru.php b/localization/locale_ruru.php index 9238b977..72e8a01c 100644 --- a/localization/locale_ruru.php +++ b/localization/locale_ruru.php @@ -1035,6 +1035,7 @@ $lang = array( 'passChangeOk' => "Ваш пароль был успешно изменен.", 'deleteAccSent' => "Письмо с подтверждением было отправлено на %s.", 'deleteOk' => "Ваша учетная запись была успешно удалена. Надеемся увидеть вас снова!

Теперь вы можете закрыть это окно.", + 'deleteCancel' => "Удаление учетной записи было отменено.", 'createAccSent' => 'Письмо с инструкциями для активации учетной записи было отправлено на адрес %s/b>. Следуйте инструкциям, для продолжения регистрации.

Если вы не получили письмо для подтверждения, нажмите здесь, чтобы отправить его повторно.', 'recovUserSent' => "Письмо с инструкциями для активации учетной записи было отправлено на адрес %s/b>. Просто следуйте инструкциям для восстановления имени пользователя.", 'recovPassSent' => "Письмо с инструкциями для активации учетной записи было отправлено на адрес %s/b>. Просто следуйте инструкциям для сброса пароля." @@ -1042,6 +1043,7 @@ $lang = array( 'error' => array( 'mailTokenUsed' => 'Этот ключ для смены email уже был использован или недействителен. Посетите вашу страницу настроек учетной записи, чтобы попробовать снова.', 'passTokenUsed' => 'Этот ключ для смены пароля уже был использован или недействителен. Посетите вашу страницу настроек учетной записи, чтобы попробовать снова.', + 'purgeTokenUsed' => 'Этот ключ для удаления учетной записи уже был использован или недействителен. Посетите вашу страницу настроек учетной записи, чтобы попробовать снова.', 'passTokenLost' => "Ключ не был получен. Если вы сбросили пароль по ссылке из письма, отправленного на email, пожалуйста, скопируйте URL целиком и вставьте в адресную строку (включая ключ, указанный в конце ссылки).", 'isRecovering' => "Эта учетная запись уже восстанавливается. Следуйте инструкциям в письме или дождитесь истечения срока действия токена через %s.", 'loginExceeded' => "Достигнуто максимальное количество попыток входа с этого IP. Пожалуйста, попробуйте снова через %s.", diff --git a/localization/locale_zhcn.php b/localization/locale_zhcn.php index c72151a8..34b40587 100644 --- a/localization/locale_zhcn.php +++ b/localization/locale_zhcn.php @@ -1035,6 +1035,7 @@ $lang = array( 'passChangeOk' => "您的密码已成功更改。", 'deleteAccSent' => "已向 %s 发送了一封带有确认链接的邮件。", 'deleteOk' => "您的账户已成功删除。希望不久后能再次见到您!

您现在可以关闭此窗口。", + 'deleteCancel' => "账户删除已取消。", 'createAccSent' => '电子邮件发送到%s。只请按照说明创建您的账户。

如果您没有收到验证邮件,点击这里重新发送。', 'recovUserSent' => "电子邮件发送到%s。只请按照说明恢复您的用户名。", 'recovPassSent' => "电子邮件发送到%s。只请按照说明重置您的密码。" @@ -1042,6 +1043,7 @@ $lang = array( 'error' => array( 'mailTokenUsed' => '该邮箱更改密钥已被使用,或不是有效密钥。请访问您的账户设置页面重新尝试。', 'passTokenUsed' => '该密码更改密钥已被使用,或不是有效密钥。请访问您的账户设置页面重新尝试。', + 'purgeTokenUsed' => '该账户删除密钥已被使用,或不是有效密钥。请访问您的账户设置页面重新尝试。', 'passTokenLost' => "未提供令牌。如果您在邮件中收到重置密码链接,请将整个网址(包括最后的令牌)复制并粘贴到浏览器地址栏中。", 'isRecovering' => "此帐户已恢复。按照电子邮件中的说明或等待%s后令牌过期。", 'loginExceeded' => "这个IP最大登录次数已超过。请在%s后再次尝试。", diff --git a/static/css/delete.css b/static/css/delete.css new file mode 100644 index 00000000..257d8d12 --- /dev/null +++ b/static/css/delete.css @@ -0,0 +1,42 @@ +.account-delete-box { + background: #161616; + border-radius: 3px; + box-sizing: border-box; + line-height: 1.7em; + margin: 0 auto; + max-width: 100%; + padding: 15px; + width: 34em; +} + +.account-delete-box [class^="heading-size-"] { + margin-top: 0; + text-align: center; +} + +.account-delete-box-warning, +.account-delete-box-alternative { + font-size: 175%; + line-height: 1.2; +} + +.account-delete-box-warning, +.account-delete-box-warning * { + color: #ff4040 !important +} + +.account-delete-box-warning b { + display: block; + font-size: 200%; + font-weight: 900; + text-align: center; +} + +.account-delete-box-confirm { + text-align: center; +} + +/* from global.css */ +.text p { + margin: 10px 0px; +} diff --git a/template/localized/confirm-delete-account_0.tpl.php b/template/localized/confirm-delete-account_0.tpl.php new file mode 100644 index 00000000..db78173a --- /dev/null +++ b/template/localized/confirm-delete-account_0.tpl.php @@ -0,0 +1,26 @@ + diff --git a/template/localized/confirm-delete-account_2.tpl.php b/template/localized/confirm-delete-account_2.tpl.php new file mode 100644 index 00000000..74e8b617 --- /dev/null +++ b/template/localized/confirm-delete-account_2.tpl.php @@ -0,0 +1,26 @@ + diff --git a/template/localized/confirm-delete-account_3.tpl.php b/template/localized/confirm-delete-account_3.tpl.php new file mode 100644 index 00000000..637f018f --- /dev/null +++ b/template/localized/confirm-delete-account_3.tpl.php @@ -0,0 +1,26 @@ + diff --git a/template/localized/confirm-delete-account_4.tpl.php b/template/localized/confirm-delete-account_4.tpl.php new file mode 100644 index 00000000..e4c023c3 --- /dev/null +++ b/template/localized/confirm-delete-account_4.tpl.php @@ -0,0 +1,26 @@ + diff --git a/template/localized/confirm-delete-account_6.tpl.php b/template/localized/confirm-delete-account_6.tpl.php new file mode 100644 index 00000000..18f58f57 --- /dev/null +++ b/template/localized/confirm-delete-account_6.tpl.php @@ -0,0 +1,26 @@ + diff --git a/template/localized/confirm-delete-account_8.tpl.php b/template/localized/confirm-delete-account_8.tpl.php new file mode 100644 index 00000000..af869141 --- /dev/null +++ b/template/localized/confirm-delete-account_8.tpl.php @@ -0,0 +1,26 @@ + diff --git a/template/localized/delete-account_0.tpl.php b/template/localized/delete-account_0.tpl.php new file mode 100644 index 00000000..633484f0 --- /dev/null +++ b/template/localized/delete-account_0.tpl.php @@ -0,0 +1,15 @@ + diff --git a/template/localized/delete-account_2.tpl.php b/template/localized/delete-account_2.tpl.php new file mode 100644 index 00000000..5f34b9b5 --- /dev/null +++ b/template/localized/delete-account_2.tpl.php @@ -0,0 +1,15 @@ + diff --git a/template/localized/delete-account_3.tpl.php b/template/localized/delete-account_3.tpl.php new file mode 100644 index 00000000..15db9de0 --- /dev/null +++ b/template/localized/delete-account_3.tpl.php @@ -0,0 +1,15 @@ + diff --git a/template/localized/delete-account_4.tpl.php b/template/localized/delete-account_4.tpl.php new file mode 100644 index 00000000..987545c9 --- /dev/null +++ b/template/localized/delete-account_4.tpl.php @@ -0,0 +1,15 @@ + diff --git a/template/localized/delete-account_6.tpl.php b/template/localized/delete-account_6.tpl.php new file mode 100644 index 00000000..12544c3f --- /dev/null +++ b/template/localized/delete-account_6.tpl.php @@ -0,0 +1,15 @@ + diff --git a/template/localized/delete-account_8.tpl.php b/template/localized/delete-account_8.tpl.php new file mode 100644 index 00000000..b8b84244 --- /dev/null +++ b/template/localized/delete-account_8.tpl.php @@ -0,0 +1,15 @@ + diff --git a/template/mails/delete-account_0.tpl b/template/mails/delete-account_0.tpl new file mode 100644 index 00000000..7bbef9db --- /dev/null +++ b/template/mails/delete-account_0.tpl @@ -0,0 +1,21 @@ +# 2025 +Please verify your request to be forgotten +Greetings, + +We’ve just received a request to exercise the “right to be forgotten” from the following email address %2$s in accordance with our Privacy Policy. + +Please click on following link HOST_URL?account=confirm-delete&key=%1$s to confirm your selection. You will get one last chance to review your choices once you are back on the site. + +Should you choose to proceed with this process, we will permanently delete or anonymize any Personal Data linked to your account. + +This information will include, but is not limited to: + + * Your Identity %3$s, and the email address associated with this login. + * Your current Premium status and data, should you be a Premium member. + * Your profile information and preferences. + * In some cases, content that you've authored, including comments, guides and forum posts. + * Note that game data connected to your gaming identities will re-appear when other users request data updates, unless you delete that data at the source. + +Once we receive your final confirmation, we will be removing your Personal Data. + +If you have any questions or need further assistance, please contact CONTACT_EMAIL. diff --git a/template/mails/delete-account_2.tpl b/template/mails/delete-account_2.tpl new file mode 100644 index 00000000..7ccda5d2 --- /dev/null +++ b/template/mails/delete-account_2.tpl @@ -0,0 +1,21 @@ +# GPTed from 2025 source +Veuillez vérifier votre demande de droit à l'oubli +Bonjour, + +Nous venons de recevoir une demande d'exercice du « droit à l'oubli » de l'adresse e-mail suivante %2$s conformément à notre politique de confidentialité. + +Veuillez cliquer sur le lien suivant HOST_URL?account=confirm-delete&key=%1$s pour confirmer votre choix. Vous aurez une dernière chance de revoir vos choix une fois de retour sur le site. + +Si vous choisissez de poursuivre ce processus, nous supprimerons ou anonymiserons définitivement toutes les données personnelles liées à votre compte. + +Ces informations incluront, sans s'y limiter : + + * Votre identité %3$s, et l'adresse e-mail associée à cette connexion. + * Votre statut Premium actuel et les données, si vous êtes membre Premium. + * Vos informations de profil et préférences. + * Dans certains cas, le contenu que vous avez créé, y compris les commentaires, guides et messages sur le forum. + * Notez que les données de jeu liées à vos identités de jeu réapparaîtront lorsque d'autres utilisateurs demanderont des mises à jour de données, sauf si vous supprimez ces données à la source. + +Une fois que nous aurons reçu votre confirmation finale, nous supprimerons vos données personnelles. + +Si vous avez des questions ou besoin d'aide supplémentaire, veuillez contacter CONTACT_EMAIL. diff --git a/template/mails/delete-account_3.tpl b/template/mails/delete-account_3.tpl new file mode 100644 index 00000000..b8ce03a4 --- /dev/null +++ b/template/mails/delete-account_3.tpl @@ -0,0 +1,21 @@ +# GPTed from 2025 source +Bitte bestätigen Sie Ihre Anfrage auf Vergessenwerden +Hallo, + +Wir haben gerade eine Anfrage zum "Recht auf Vergessenwerden" von der folgenden E-Mail-Adresse %2$s gemäß unserer Datenschutzrichtlinie erhalten. + +Bitte klicken Sie auf den folgenden Link HOST_URL?account=confirm-delete&key=%1$s, um Ihre Auswahl zu bestätigen. Sie erhalten eine letzte Gelegenheit, Ihre Auswahl zu überprüfen, sobald Sie wieder auf der Website sind. + +Wenn Sie sich entscheiden, diesen Prozess fortzusetzen, werden wir alle mit Ihrem Konto verknüpften personenbezogenen Daten dauerhaft löschen oder anonymisieren. + +Diese Informationen umfassen unter anderem: + + * Ihre Identität %3$s und die mit diesem Login verknüpfte E-Mail-Adresse. + * Ihren aktuellen Premium-Status und Daten, falls Sie ein Premium-Mitglied sind. + * Ihre Profilinformationen und Präferenzen. + * In einigen Fällen von Ihnen erstellte Inhalte, einschließlich Kommentare, Guides und Forenbeiträge. + * Beachten Sie, dass Spieldaten, die mit Ihren Spielidentitäten verbunden sind, wieder erscheinen, wenn andere Nutzer Datenaktualisierungen anfordern, es sei denn, Sie löschen diese Daten an der Quelle. + +Sobald wir Ihre endgültige Bestätigung erhalten haben, werden wir Ihre personenbezogenen Daten entfernen. + +Wenn Sie Fragen haben oder weitere Unterstützung benötigen, kontaktieren Sie bitte CONTACT_EMAIL. diff --git a/template/mails/delete-account_4.tpl b/template/mails/delete-account_4.tpl new file mode 100644 index 00000000..a1738dfe --- /dev/null +++ b/template/mails/delete-account_4.tpl @@ -0,0 +1,21 @@ +# GPTed from 2025 source +请验证您的被遗忘权请求 +您好, + +我们刚刚收到来自以下电子邮件地址 %2$s 的“被遗忘权”请求,依据我们的隐私政策。 + +请点击以下链接 HOST_URL?account=confirm-delete&key=%1$s 以确认您的选择。返回网站后,您将有最后一次机会审查您的选择。 + +如果您选择继续此流程,我们将永久删除或匿名化与您的账户相关的所有个人数据。 + +这些信息包括但不限于: + + * 您的身份 %3$s,以及与此登录关联的电子邮件地址。 + * 您当前的高级会员状态和数据(如适用)。 + * 您的个人资料信息和偏好设置。 + * 在某些情况下,您创作的内容,包括评论、指南和论坛帖子。 + * 请注意,与您的游戏身份相关的游戏数据在其他用户请求数据更新时会重新出现,除非您在源头删除这些数据。 + +一旦我们收到您的最终确认,我们将删除您的个人数据。 + +如有任何疑问或需要进一步帮助,请联系 CONTACT_EMAIL。 diff --git a/template/mails/delete-account_6.tpl b/template/mails/delete-account_6.tpl new file mode 100644 index 00000000..421351f6 --- /dev/null +++ b/template/mails/delete-account_6.tpl @@ -0,0 +1,21 @@ +# GPTed from 2025 source +Por favor, verifique su solicitud de derecho al olvido +Saludos, + +Acabamos de recibir una solicitud para ejercer el "derecho al olvido" desde la siguiente dirección de correo electrónico %2$s de acuerdo con nuestra Política de Privacidad. + +Por favor, haga clic en el siguiente enlace HOST_URL?account=confirm-delete&key=%1$s para confirmar su selección. Tendrá una última oportunidad de revisar sus opciones una vez que regrese al sitio. + +Si decide continuar con este proceso, eliminaremos o anonimizaremos permanentemente cualquier dato personal vinculado a su cuenta. + +Esta información incluirá, pero no se limitará a: + + * Su identidad %3$s y la dirección de correo electrónico asociada a este inicio de sesión. + * Su estado Premium actual y datos, si es miembro Premium. + * Su información de perfil y preferencias. + * En algunos casos, contenido que haya creado, incluyendo comentarios, guías y publicaciones en foros. + * Tenga en cuenta que los datos de juego conectados a sus identidades de juego volverán a aparecer cuando otros usuarios soliciten actualizaciones de datos, a menos que elimine esos datos en la fuente. + +Una vez que recibamos su confirmación final, eliminaremos sus datos personales. + +Si tiene alguna pregunta o necesita más ayuda, por favor contacte a CONTACT_EMAIL. diff --git a/template/mails/delete-account_8.tpl b/template/mails/delete-account_8.tpl new file mode 100644 index 00000000..f9f916c4 --- /dev/null +++ b/template/mails/delete-account_8.tpl @@ -0,0 +1,21 @@ +# GPTed from 2025 source +Пожалуйста, подтвердите ваш запрос на удаление данных +Здравствуйте, + +Мы только что получили запрос на реализацию "права быть забытым" с адреса электронной почты %2$s в соответствии с нашей Политикой конфиденциальности. + +Пожалуйста, перейдите по следующей ссылке HOST_URL?account=confirm-delete&key=%1$s, чтобы подтвердить свой выбор. После возвращения на сайт у вас будет последний шанс пересмотреть свое решение. + +Если вы решите продолжить процесс, мы навсегда удалим или анонимизируем все персональные данные, связанные с вашей учетной записью. + +Эта информация будет включать, но не ограничиваться: + + * Вашу личность %3$s и адрес электронной почты, связанный с этим входом. + * Ваш текущий статус и данные Premium, если вы являетесь Premium-участником. + * Вашу информацию профиля и предпочтения. + * В некоторых случаях созданный вами контент, включая комментарии, руководства и сообщения на форуме. + * Обратите внимание, что игровые данные, связанные с вашими игровыми идентификаторами, появятся снова, когда другие пользователи запросят обновление данных, если только вы не удалите эти данные у источника. + +После получения вашего окончательного подтверждения мы удалим ваши персональные данные. + +Если у вас есть вопросы или вам нужна дополнительная помощь, пожалуйста, свяжитесь с CONTACT_EMAIL. diff --git a/template/pages/delete.tpl.php b/template/pages/delete.tpl.php new file mode 100644 index 00000000..77753488 --- /dev/null +++ b/template/pages/delete.tpl.php @@ -0,0 +1,26 @@ +brick('header'); +?> +
+
+
+brick('announcement'); + + $this->brick('pageTemplate'); + +if ($this->inputbox): + $this->brick(...$this->inputbox); // $templateName, [$templateVars] +elseif ($this->confirm): + $this->localizedBrick('confirm-delete-account'); +else: + $this->localizedBrick('delete-account'); +endif; +?> +
+
+ + +brick('footer'); ?>