From d872201b8e7589bc53d66299006b237181d6da0e Mon Sep 17 00:00:00 2001 From: Ash <102800515+aupn@users.noreply.github.com> Date: Tue, 26 Apr 2022 18:40:20 +0400 Subject: [PATCH 1/4] Update am.strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit могут быть некоторые допуски, исправлю со временем --- locales/am.strings | 112 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 5 deletions(-) diff --git a/locales/am.strings b/locales/am.strings index 54985e59..8f62755a 100644 --- a/locales/am.strings +++ b/locales/am.strings @@ -9,6 +9,7 @@ "home" = "Գլխավոր"; "welcome" = "Բարի գալուստ"; +"to_top" = "Վերև"; /* Login */ @@ -381,7 +382,6 @@ "left_menu_donate" = "Աջակցել"; - "footer_about_instance" = "հոսքի մասին"; "footer_blog" = "բլոգ"; "footer_help" = "օգնություն"; @@ -410,6 +410,8 @@ "style" = "Ոճ"; "default" = "Սովորական"; + +"arbitrary_avatars" = "Կամայական"; "cut" = "Կտրվածք"; "round_avatars" = "Կլոր ավատար"; @@ -519,6 +521,8 @@ "videos_many" = "$1 տեսանյութ"; "videos_other" = "$1 տեսանյութ"; +"view_video" = "Դիտում"; + /* Notifications */ "feedback" = "Հետադարձ կապ"; @@ -624,6 +628,21 @@ "receiver_not_found" = "Ստացողը չի գտնվել։"; "you_dont_have_enough_points" = "Դուք չունե՛ք բավական ձայն։"; +"increase_rating" = "Բարձրացնել վարկանիշը"; +"increase_rating_button" = "Բարձրացնել"; +"to_whom" = "Ում"; +"increase_by" = "Բարձրացնել"; +"price" = "Արժողություն"; + +"you_have_unused_votes" = "Ձեր մոտ $1 չօգտագործված ձայն կա հաշվի վրա։"; +"apply_voucher" = "Կիրառել վաուչեր"; + +"failed_to_increase_rating" = "Չհաջողվե՛ց բարձրացնել վարկանիշը"; +"rating_increase_successful" = "Դուք հաջողությամբ բարձրացրեցիք Ձեր վարկանիշը $2 $3%-ով։"; +"negative_rating_value" = "Կներե՛ք, մենք չենք կարող գողանալ ուրիշի վարկանիշը։"; + +"increased_your_rating_by" = "բարձրացրել է վարկանիշը"; + /* Gifts */ "gift" = "Նվեր"; @@ -703,6 +722,9 @@ "ticket_changed" = "Տոմսը փոփոխված է"; "ticket_changed_comment" = "Փոփոխությունները ուժի մեջ կմտնեն մի քանի վայրկյանից։"; +"banned_in_support_1" = "Կներե՛ք, $1, բայց հիմա Ձեզ թույլատրված չէ դիմումներ ստեղծել։"; +"banned_in_support_2" = "Դրա պատճառաբանությունը սա է․ $1։ Ցավո՛ք, այդ հնարավորությունը մենք Ձեզնից վերցրել ենք առհավետ։"; + /* Invite */ "invite" = "Հրավիրել"; @@ -711,9 +733,9 @@ /* Banned */ -"banned_title" = "Բլոկավորված եք"; -"banned_header" = "Ձեզ կասեցրել է կառլենի անհաջող բոցը։"; -"banned_alt" = "Օգտատերը բլոկավորված է"; +"banned_title" = "Արգելափակված եք"; +"banned_header" = "Ձեզ կասեցրել է կարլենի անհաջող բոցը։"; +"banned_alt" = "Օգտատերը արգելափակված է"; "banned_1" = "Կներե՛ք, $1, բայց Դուք կասեցված եք։"; "banned_2" = "Պատճառը հետևյալն է․ $1. Ափսոս, բայց մենք ստիպված Ձեզ հավերժ ենք կասեցրել;"; "banned_3" = "Դուք դեռ կարող եք գրել նամակ աջակցության ծառայությանը, եթե համարում եք որ դա սխալմունք է, կամ էլ կարող եք դուրս գալ։"; @@ -835,6 +857,7 @@ "captcha_error" = "Սխալ են գրված սիմվոլները"; "captcha_error_comment" = "Խնդրում ենք համոզվել, որ ճիշտ եք ներմուծել կապտչայի սիմվոլները։"; + /* Admin actions */ "login_as" = "Մտնել ինչպես $1"; @@ -843,7 +866,84 @@ "ban_user_action" = "Բլոկավորել օգտվողին"; "warn_user_action" = "Զգուշացնել օգտվողին"; -/* Paginator (subject to delete) */ + +/* Admin panel */ + +"admin" = "Ադմին-վահանակ"; + +"admin_ownerid" = "Տիրոջ ID"; +"admin_author" = "Հեղինակ"; +"admin_name" = "Անուն"; +"admin_title" = "Անվանում"; +"admin_description" = "Նկարագրություն"; +"admin_first_known_ip" = "Առաջին IP"; +"admin_shortcode" = "Կարճ հասցե"; +"admin_verification" = "Վերիֆիկացիա"; +"admin_banreason" = "Արգելափակման պատճառ"; +"admin_banned" = "արգելափակված է"; +"admin_actions" = "Գործողություններ"; +"admin_image" = "Նկար"; +"admin_image_replace" = "Փոխե՞լ նկարը"; +"admin_uses" = "Օգտագործումներ"; +"admin_uses_reset" = "Զրոյացնե՞լ օգտագործումների քանակը"; +"admin_limits" = "Սահմանափակումներ"; +"admin_limits_reset" = "Զրոյացնել օգտագործումների քանակը"; +"admin_open" = "Բացել"; +"admin_loginas" = "Մուտք գործել ինչպես..."; +"admin_commonsettings" = "Ընդհանուր կարգավորումներ"; +"admin_langsettings" = "Լեզվից կախված կարգավորումներ"; + +"admin_tab_main" = "Գլխավոր"; +"admin_tab_ban" = "Բլոկավորում"; +"admin_tab_followers" = "Մասնակիցներ"; + +"admin_overview" = "Դիտում"; +"admin_overview_summary" = "Ամփոփում"; + +"admin_content" = "Օգտատիրային կոնտենտ"; +"admin_user_search" = "Օգտատերերի որոնում"; +"admin_user_online" = "Օնլայն վիճակ"; +"admin_user_online_default" = "Ըստ նախնականի"; +"admin_user_online_incognito" = "Ինկոգնիտո"; +"admin_user_online_deceased" = "Հանգուցյալ"; +"admin_club_search" = "Խմբերի որոնում"; +"admin_club_excludeglobalfeed" = "Չ՛ցույց տալ գլոբալ ժապավենում"; + +"admin_services" = "Վճարովի ծառայություններ"; +"admin_newgift" = "Նոր նվեր"; +"admin_price" = "Գին"; +"admin_giftset" = "Նվերների հավաքախու"; +"admin_giftsets" = "Նվերների հավաքախուներ"; +"admin_giftsets_none" = "Նվերների հավաքածու չկա։ Ստեղծե՛ք հավաքածու նվեր ավելացնելու համար։"; +"admin_giftsets_create" = "Ստեղծել նվերների հավաքածու"; +"admin_giftsets_title" = "Հավաքածույի ներքին անվանում, եթե չի հաջողվում որոնել այն օգտատիրոջ լեզվով"; +"admin_giftsets_description" = "Հավաքածույի ներքին նկարագրություն, եթե չի հաջողվում որոնել այն օգտատիրոջ լեզվով"; +"admin_price_free" = "անվճար"; +"admin_voucher_rating" = "Վարկանիշ"; +"admin_voucher_serial" = "Սերիական համար"; +"admin_voucher_serial_desc" = "Համարը բաղկացած է 24 նշից։ Եթե Դուք այն սխալ գրեք, այն կտրվի ավտոմատ։"; +"admin_voucher_coins" = "Ձայների քանակ"; +"admin_voucher_rating" = "Վարկանշի քանակ"; +"admin_voucher_usages_desc" = "Վաուչերը օգտագործող ակկաունտների քանակ։ Եթե գրեք -1, ապա այն կլինի օգտագործել անվերջ։"; +"admin_voucher_status" = "Կարգավիճակ"; +"admin_voucher_status_opened" = "ակտիվ է"; +"admin_voucher_status_closed" = "վերջացել է"; + +"admin_settings" = "Կարգավորումներ"; +"admin_settings_tuning" = "Ընդհանուր"; +"admin_settings_appearance" = "Արտաքին տեսք"; +"admin_settings_security" = "Անվտանգություն"; +"admin_settings_integrations" = "Ինտեգրացիաներ"; +"admin_settings_system" = "Համակարգ"; + +"admin_about" = "OpenVK-ի մասին"; +"admin_about_version" = "Վերսիա"; +"admin_about_instance" = "Հոսք"; + +"admin_commerce_disabled" = "Коммерция отключена системным администратором"; +"admin_commerce_disabled_desc" = "Настройки ваучеров и подарков будут сохранены, но не будут оказывать никакого влияния."; + +/* Paginator (deprecated) */ "paginator_back" = "Հետ"; "paginator_page" = "$1 էջ"; @@ -857,6 +957,8 @@ "rules" = "Կանոններ"; "most_popular_groups" = "Ամենահայտնի խմբերը"; "on_this_instance_are" = "Այս հոսքում․"; +"about_links" = "Հղումներ"; +"instance_links" = "Հոսքերի հղումներ․"; "about_users_one" = "Մեկ օգտատեր"; "about_users_few" = "$1 օգտատեր"; From 57d7bf339e0ed65214ee40ed9b19cc2bb24cdc46 Mon Sep 17 00:00:00 2001 From: Ash <102800515+aupn@users.noreply.github.com> Date: Thu, 28 Apr 2022 08:38:33 +0400 Subject: [PATCH 2/4] Update am.strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit исправлены допускы в 943, 944 строках --- locales/am.strings | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/am.strings b/locales/am.strings index 8f62755a..f8140754 100644 --- a/locales/am.strings +++ b/locales/am.strings @@ -940,8 +940,8 @@ "admin_about_version" = "Վերսիա"; "admin_about_instance" = "Հոսք"; -"admin_commerce_disabled" = "Коммерция отключена системным администратором"; -"admin_commerce_disabled_desc" = "Настройки ваучеров и подарков будут сохранены, но не будут оказывать никакого влияния."; +"admin_commerce_disabled" = "Կոմմերցիան անջատված է համակարգային ադմինիստրատորի կողմից"; +"admin_commerce_disabled_desc" = "Վաուչերների և նվերների կարգավորումները կպահպանվեն, բայց ոչ մի ազդեցություն չեն ունենա։"; /* Paginator (deprecated) */ From bfa26c24d1c5251f0b961af4b8ed9a43a254476b Mon Sep 17 00:00:00 2001 From: celestora Date: Sun, 1 May 2022 17:04:59 +0300 Subject: [PATCH 3/4] Prevent deleted attachments from showing in wall.get --- VKAPI/Handlers/Wall.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/VKAPI/Handlers/Wall.php b/VKAPI/Handlers/Wall.php index 6acc9c89..f678c4ff 100644 --- a/VKAPI/Handlers/Wall.php +++ b/VKAPI/Handlers/Wall.php @@ -23,11 +23,12 @@ final class Wall extends VKAPIRequestHandler foreach ($posts->getPostsFromUsersWall((int)$owner_id, 1, $count, $offset) as $post) { $from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId(); - $attachments; - foreach($post->getChildren() as $attachment) - { - if($attachment instanceof \openvk\Web\Models\Entities\Photo) - { + $attachments = []; + foreach($post->getChildren() as $attachment) { + if($attachment instanceof \openvk\Web\Models\Entities\Photo) { + if($attachment->isDeleted()) + continue; + $attachments[] = [ "type" => "photo", "photo" => [ From 45fe2707005b19013acb75df90d23b791c88d8d8 Mon Sep 17 00:00:00 2001 From: Maxim Leshchenko Date: Fri, 6 May 2022 16:17:08 +0200 Subject: [PATCH 4/4] Users: Add ability to change email address in settings Closes #63 --- Email/change-email.eml.latte | 204 ++++++++++++++++++ .../Entities/EmailChangeVerification.php | 15 ++ Web/Models/Entities/User.php | 11 + .../Repositories/EmailChangeVerifications.php | 33 +++ Web/Presenters/UserPresenter.php | 80 ++++++- Web/Presenters/templates/User/Settings.xml | 34 ++- Web/routes.yml | 2 + install/sqls/00023-email-change.sql | 8 + locales/en.strings | 4 + locales/ru.strings | 4 + 10 files changed, 385 insertions(+), 10 deletions(-) create mode 100644 Email/change-email.eml.latte create mode 100644 Web/Models/Entities/EmailChangeVerification.php create mode 100644 Web/Models/Repositories/EmailChangeVerifications.php create mode 100644 install/sqls/00023-email-change.sql diff --git a/Email/change-email.eml.latte b/Email/change-email.eml.latte new file mode 100644 index 00000000..6cff8c11 --- /dev/null +++ b/Email/change-email.eml.latte @@ -0,0 +1,204 @@ + + + + + + Подтверждение изменения Email + + + + + + + + +
+
+ + + + +
+   +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+   +
+

Подтверждение изменения Email

+
+
+ + + + + +
+ + + + +
+
+ +
+ + + + + +
+   +
+ +
+ + + + + +
+   +
+ +

+ Здравствуйте, {$name}! Вы вероятно изменили свой адрес электронной почты в OpenVK. Чтобы изменение вступило в силу, необходимо подтвердить ваш новый Email. +

+ + + + + +
+   +
+ + + + + +
+ + + + +
+
+ Подтвердить Email! +
+
+
+ + + + + +
+   +
+ +

+ Если кнопка не работает, вы можете попробовать скопировать и вставить эту ссылку в адресную строку вашего веб-обозревателя: +

+ + + + + +
+ + http://{$_SERVER['HTTP_HOST']}/settings/change_email?key={$key} + +
+ +

+ Обратите внимание на то, что эту ссылку нельзя: +

+ +
    +
  • Передавать другим людям (даже друзьям, питомцам, соседам, любимым девушкам)
  • +
  • Использовать, если прошло более двух дней с её генерации
  • +
+ + + + + +
+

+ Ещё раз обратите внимание на то, что данную ссылку или письмо ни в коем случае нельзя передавать другим людям! Даже если они представляются службой поддержки.
+ Это письмо предназначено исключительно для одноразового, непосредственного использования владельцем аккаунта. +

+
+ + + + + +
+   +
+ +

+ С уважением, овк-тян. +

+ + + + + +
+   +
+ +
+ + + + + +
+   +
+ +

+ + Вы получили это письмо так как кто-то или вы изменили адрес электронной почты. Это не рассылка и от неё нельзя отписаться. Если вы всё равно хотите перестать получать подобные письма, деактивируйте ваш аккаунт. + +

+
+
+
+ + + + +
+   +
+
+
+ + diff --git a/Web/Models/Entities/EmailChangeVerification.php b/Web/Models/Entities/EmailChangeVerification.php new file mode 100644 index 00000000..e9b92db1 --- /dev/null +++ b/Web/Models/Entities/EmailChangeVerification.php @@ -0,0 +1,15 @@ +getRecord()->new_email; + } +} diff --git a/Web/Models/Entities/User.php b/Web/Models/Entities/User.php index 68ad6a77..ef22c700 100644 --- a/Web/Models/Entities/User.php +++ b/Web/Models/Entities/User.php @@ -877,6 +877,17 @@ class User extends RowModel return true; } + function setEmail(string $email): void + { + DatabaseConnection::i()->getContext()->table("ChandlerUsers") + ->where("id", $this->getChandlerUser()->getId())->update([ + "login" => $email + ]); + + $this->stateChanges("email", $email); + $this->save(); + } + function adminNotify(string $message): bool { $admId = OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["adminAccount"]; diff --git a/Web/Models/Repositories/EmailChangeVerifications.php b/Web/Models/Repositories/EmailChangeVerifications.php new file mode 100644 index 00000000..0e8c668b --- /dev/null +++ b/Web/Models/Repositories/EmailChangeVerifications.php @@ -0,0 +1,33 @@ +context = DatabaseConnection::i()->getContext(); + $this->verifications = $this->context->table("email_change_verifications"); + } + + function toEmailChangeVerification(?ActiveRow $ar): ?EmailChangeVerification + { + return is_null($ar) ? NULL : new EmailChangeVerification($ar); + } + + function getByToken(string $token): ?EmailChangeVerification + { + return $this->toEmailChangeVerification($this->verifications->where("key", $token)->fetch()); + } + + function getLatestByUser(User $user): ?EmailChangeVerification + { + return $this->toEmailChangeVerification($this->verifications->where("profile", $user->getId())->order("timestamp DESC")->fetch()); + } +} diff --git a/Web/Presenters/UserPresenter.php b/Web/Presenters/UserPresenter.php index b9e8b714..0f741654 100644 --- a/Web/Presenters/UserPresenter.php +++ b/Web/Presenters/UserPresenter.php @@ -9,12 +9,15 @@ use openvk\Web\Models\Repositories\Albums; use openvk\Web\Models\Repositories\Videos; use openvk\Web\Models\Repositories\Notes; use openvk\Web\Models\Repositories\Vouchers; +use openvk\Web\Models\Repositories\EmailChangeVerifications; use openvk\Web\Models\Exceptions\InvalidUserNameException; use openvk\Web\Util\Validator; use openvk\Web\Models\Entities\Notifications\{CoinsTransferNotification, RatingUpNotification}; +use openvk\Web\Models\Entities\EmailChangeVerification; use Chandler\Security\Authenticator; use lfkeitel\phptotp\{Base32, Totp}; use chillerlan\QRCode\{QRCode, QROptions}; +use Nette\Database\UniqueConstraintViolationException; final class UserPresenter extends OpenVKPresenter { @@ -132,7 +135,7 @@ final class UserPresenter extends OpenVKPresenter if(!$id) $this->notFound(); - + $user = $this->users->get($id); if($_SERVER["REQUEST_METHOD"] === "POST") { $this->willExecuteWriteAction($_GET['act'] === "status"); @@ -300,7 +303,7 @@ final class UserPresenter extends OpenVKPresenter if(!$id) $this->notFound(); - + if(in_array($this->queryParam("act"), ["finance", "finance.top-up"]) && !OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"]) $this->flashFail("err", tr("error"), tr("feature_disabled")); @@ -312,7 +315,7 @@ final class UserPresenter extends OpenVKPresenter if($this->postParam("old_pass") && $this->postParam("new_pass") && $this->postParam("repeat_pass")) { if($this->postParam("new_pass") === $this->postParam("repeat_pass")) { if($this->user->identity->is2faEnabled()) { - $code = $this->postParam("code"); + $code = $this->postParam("password_change_code"); if(!($code === (new Totp)->GenerateToken(Base32::decode($this->user->identity->get2faSecret())) || $this->user->identity->use2faBackupCode((int) $code))) $this->flashFail("err", tr("error"), tr("incorrect_2fa_code")); } @@ -323,6 +326,46 @@ final class UserPresenter extends OpenVKPresenter $this->flashFail("err", tr("error"), tr("error_new_password")); } } + + if($this->postParam("new_email")) { + if(!Validator::i()->emailValid($this->postParam("new_email"))) + $this->flashFail("err", tr("invalid_email_address"), tr("invalid_email_address_comment")); + + if(!Authenticator::verifyHash($this->postParam("email_change_pass"), $user->getChandlerUser()->getRaw()->passwordHash)) + $this->flashFail("err", tr("error"), tr("incorrect_password")); + + if($user->is2faEnabled()) { + $code = $this->postParam("email_change_code"); + if(!($code === (new Totp)->GenerateToken(Base32::decode($user->get2faSecret())) || $user->use2faBackupCode((int) $code))) + $this->flashFail("err", tr("error"), tr("incorrect_2fa_code")); + } + + if($this->postParam("new_email") !== $user->getEmail()) { + if (OPENVK_ROOT_CONF['openvk']['preferences']['security']['requireEmail']) { + $request = (new EmailChangeVerifications)->getLatestByUser($user); + if(!is_null($request) && $request->isNew()) + $this->flashFail("err", tr("forbidden"), tr("email_rate_limit_error")); + + $verification = new EmailChangeVerification; + $verification->setProfile($user->getId()); + $verification->setNew_Email($this->postParam("new_email")); + $verification->save(); + + $params = [ + "key" => $verification->getKey(), + "name" => $user->getCanonicalName(), + ]; + $this->sendmail($this->postParam("new_email"), "change-email", $params); #Vulnerability possible + $this->flashFail("succ", tr("information_-1"), tr("email_change_confirm_message")); + } + + try { + $user->setEmail($this->postParam("new_email")); + } catch(UniqueConstraintViolationException $ex) { + $this->flashFail("err", tr("error"), tr("user_already_exists")); + } + } + } if(!$user->setShortCode(empty($this->postParam("sc")) ? NULL : $this->postParam("sc"))) $this->flashFail("err", tr("error"), tr("error_shorturl_incorrect")); @@ -400,11 +443,7 @@ final class UserPresenter extends OpenVKPresenter throw $ex; } - $this->flash( - "succ", - "Изменения сохранены", - "Новые данные появятся на вашей странице." - ); + $this->flash("succ", tr("changes_saved"), tr("changes_saved_comment")); } $this->template->mode = in_array($this->queryParam("act"), [ "main", "privacy", "finance", "finance.top-up", "interface" @@ -502,6 +541,9 @@ final class UserPresenter extends OpenVKPresenter $this->assertUserLoggedIn(); $this->willExecuteWriteAction(); + if(!OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"]) + $this->flashFail("err", tr("error"), tr("feature_disabled")); + $receiverAddress = $this->postParam("receiver"); $value = (int) $this->postParam("value"); $message = $this->postParam("message"); @@ -517,7 +559,7 @@ final class UserPresenter extends OpenVKPresenter $receiver = $this->users->getByAddress($receiverAddress); if(!$receiver) - $this->flashFail("err", tr("failed_to_tranfer_points"), tr("receiver_not_found")); + $this->flashFail("err", tr("failed_to_tranfer_points"), tr("receiver_not_found")); if($this->user->identity->getCoins() < $value) $this->flashFail("err", tr("failed_to_tranfer_points"), tr("you_dont_have_enough_points")); @@ -574,4 +616,24 @@ final class UserPresenter extends OpenVKPresenter $this->flashFail("succ", tr("information_-1"), tr("rating_increase_successful", $receiver->getURL(), htmlentities($receiver->getCanonicalName()), $value)); } + + function renderEmailChangeFinish(): void + { + $request = (new EmailChangeVerifications)->getByToken(str_replace(" ", "+", $this->queryParam("key"))); + if(!$request || !$request->isStillValid()) { + $this->flash("err", tr("token_manipulation_error"), tr("token_manipulation_error_comment")); + $this->redirect("/settings"); + } else { + $request->delete(false); + + try { + $request->getUser()->setEmail($request->getNewEmail()); + } catch(UniqueConstraintViolationException $ex) { + $this->flashFail("err", tr("error"), tr("user_already_exists")); + } + + $this->flash("succ", tr("changes_saved"), tr("changes_saved_comment")); + $this->redirect("/settings"); + } + } } diff --git a/Web/Presenters/templates/User/Settings.xml b/Web/Presenters/templates/User/Settings.xml index e24c1535..03300a81 100644 --- a/Web/Presenters/templates/User/Settings.xml +++ b/Web/Presenters/templates/User/Settings.xml @@ -64,7 +64,7 @@ {_"2fa_code"} - + @@ -154,6 +154,38 @@ {$user->getEmail()} + + + {_new_email_address} + + + + + + + + {_password} + + + + + + + + {_"2fa_code"} + + + + + + + + + + + + +
diff --git a/Web/routes.yml b/Web/routes.yml index d89ce2d5..cf5aed85 100644 --- a/Web/routes.yml +++ b/Web/routes.yml @@ -73,6 +73,8 @@ routes: handler: "User->disableTwoFactorAuth" - url: "/settings/reset_theme" handler: "User->resetThemepack" + - url: "/settings/change_email" + handler: "User->emailChangeFinish" - url: "/coins_transfer" handler: "User->coinsTransfer" - url: "/increase_social_credits" diff --git a/install/sqls/00023-email-change.sql b/install/sqls/00023-email-change.sql new file mode 100644 index 00000000..70320fb2 --- /dev/null +++ b/install/sqls/00023-email-change.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS `email_change_verifications` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `profile` bigint(20) unsigned NOT NULL, + `key` char(64) COLLATE utf8mb4_unicode_520_ci NOT NULL, + `new_email` varchar(90) COLLATE utf8mb4_unicode_520_ci DEFAULT NULL, + `timestamp` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci; diff --git a/locales/en.strings b/locales/en.strings index 63fc7cce..398d14ef 100644 --- a/locales/en.strings +++ b/locales/en.strings @@ -444,6 +444,8 @@ "your_page_address" = "Your address page"; "page_address" = "Address page"; "current_email_address" = "Current email address"; +"new_email_address" = "New email address"; +"save_email_address" = "Save email address"; "page_id" = "Page ID"; "you_can_also" = "You can also"; "delete_your_page" = "delete your page"; @@ -458,6 +460,8 @@ "additional_links" = "Additional links"; "ad_poster" = "Ad poster"; +"email_change_confirm_message" = "Please confirm your new email address for the change to take effect. We have sent instructions to it."; + /* Two-factor authentication */ "two_factor_authentication" = "Two-factor authentication"; diff --git a/locales/ru.strings b/locales/ru.strings index f5fc8414..0e65c0eb 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -472,6 +472,8 @@ "your_page_address" = "Адрес Вашей страницы"; "page_address" = "Адрес страницы"; "current_email_address" = "Текущий адрес"; +"new_email_address" = "Новый адрес"; +"save_email_address" = "Сохранить адрес"; "page_id" = "ID страницы"; "you_can_also" = "Вы также можете"; "delete_your_page" = "удалить свою страницу"; @@ -486,6 +488,8 @@ "additional_links" = "Дополнительные ссылки"; "ad_poster" = "Рекламный плакат"; +"email_change_confirm_message" = "Чтобы изменение вступило в силу, подтвердите ваш новый адрес электронной почты. Мы отправили инструкции на него."; + /* Two-factor authentication */ "two_factor_authentication" = "Двухфакторная аутентификация";