mirror of
https://github.com/openvk/openvk
synced 2025-01-22 07:44:27 +03:00
Merge branch 'master' of https://github.com/openvk/openvk into ton-integration
This commit is contained in:
commit
13bc1b877d
12 changed files with 498 additions and 20 deletions
204
Email/change-email.eml.latte
Normal file
204
Email/change-email.eml.latte
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<title>Подтверждение изменения Email</title>
|
||||||
|
<link rel="stylesheet" href="foundation.css" />
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
border-top: 5px solid pink;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table class="body" data-made-with-foundation="">
|
||||||
|
<tr>
|
||||||
|
<td class="float-center" align="center" valign="top">
|
||||||
|
<center>
|
||||||
|
<table class="spacer">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<table class="container">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table class="row header">
|
||||||
|
<tr>
|
||||||
|
<th class="small-12 large-12 columns first last">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<table class="spacer">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h4 class="text-center">Подтверждение изменения Email</h4>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table class="row">
|
||||||
|
<tr>
|
||||||
|
<th class="small-12 large-12 columns first last">
|
||||||
|
<table class="row">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<img src="pictures/lock.jpeg" align="center" class="float-center" width=128 height=128 />
|
||||||
|
</center>
|
||||||
|
|
||||||
|
<table class="spacer">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<table class="spacer">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="text-left">
|
||||||
|
Здравствуйте, {$name}! Вы вероятно изменили свой адрес электронной почты в OpenVK. Чтобы изменение вступило в силу, необходимо подтвердить ваш новый Email.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table class="spacer">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table class="button large expand success">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<center>
|
||||||
|
<a href="http://{$_SERVER['HTTP_HOST']}/settings/change_email?key={rawurlencode($key)}" align="center" class="float-center">Подтвердить Email!</a>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table class="spacer">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="text-left">
|
||||||
|
Если кнопка не работает, вы можете попробовать скопировать и вставить эту ссылку в адресную строку вашего веб-обозревателя:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table class="callout">
|
||||||
|
<tr>
|
||||||
|
<th class="callout-inner primary">
|
||||||
|
<a href="http://{$_SERVER['HTTP_HOST']}/settings/change_email?key={$key}" style="color: #000; text-decoration: none;">
|
||||||
|
http://{$_SERVER['HTTP_HOST']}/settings/change_email?key={$key}
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="text-left">
|
||||||
|
Обратите внимание на то, что эту ссылку нельзя:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Передавать другим людям (даже друзьям, питомцам, соседам, любимым девушкам)</li>
|
||||||
|
<li>Использовать, если прошло более двух дней с её генерации</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<table class="callout">
|
||||||
|
<tr>
|
||||||
|
<th class="callout-inner alert">
|
||||||
|
<p>
|
||||||
|
Ещё раз <b>обратите внимание</b> на то, что данную ссылку или письмо <b>ни в коем случае нельзя</b> передавать другим людям! Даже если они представляются службой поддержки.<br/>
|
||||||
|
Это письмо предназначено исключительно для одноразового, <b>непосредственного</b> использования владельцем аккаунта.
|
||||||
|
</p>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table class="spacer">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="text-right">
|
||||||
|
С уважением, овк-тян.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table class="spacer">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<table class="spacer">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="text-left">
|
||||||
|
<small>
|
||||||
|
Вы получили это письмо так как кто-то или вы изменили адрес электронной почты. Это не рассылка и от неё нельзя отписаться. Если вы всё равно хотите перестать получать подобные письма, деактивируйте ваш аккаунт.
|
||||||
|
</small>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<table class="spacer">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -23,11 +23,12 @@ final class Wall extends VKAPIRequestHandler
|
||||||
foreach ($posts->getPostsFromUsersWall((int)$owner_id, 1, $count, $offset) as $post) {
|
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();
|
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
|
||||||
|
|
||||||
$attachments;
|
$attachments = [];
|
||||||
foreach($post->getChildren() as $attachment)
|
foreach($post->getChildren() as $attachment) {
|
||||||
{
|
if($attachment instanceof \openvk\Web\Models\Entities\Photo) {
|
||||||
if($attachment instanceof \openvk\Web\Models\Entities\Photo)
|
if($attachment->isDeleted())
|
||||||
{
|
continue;
|
||||||
|
|
||||||
$attachments[] = [
|
$attachments[] = [
|
||||||
"type" => "photo",
|
"type" => "photo",
|
||||||
"photo" => [
|
"photo" => [
|
||||||
|
|
15
Web/Models/Entities/EmailChangeVerification.php
Normal file
15
Web/Models/Entities/EmailChangeVerification.php
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
namespace openvk\Web\Models\Entities;
|
||||||
|
use openvk\Web\Models\Repositories\Users;
|
||||||
|
use openvk\Web\Models\RowModel;
|
||||||
|
use openvk\Web\Util\DateTime;
|
||||||
|
|
||||||
|
class EmailChangeVerification extends PasswordReset
|
||||||
|
{
|
||||||
|
protected $tableName = "email_change_verifications";
|
||||||
|
|
||||||
|
function getNewEmail(): string
|
||||||
|
{
|
||||||
|
return $this->getRecord()->new_email;
|
||||||
|
}
|
||||||
|
}
|
|
@ -877,6 +877,17 @@ class User extends RowModel
|
||||||
return true;
|
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
|
function adminNotify(string $message): bool
|
||||||
{
|
{
|
||||||
$admId = OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["adminAccount"];
|
$admId = OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["adminAccount"];
|
||||||
|
|
33
Web/Models/Repositories/EmailChangeVerifications.php
Normal file
33
Web/Models/Repositories/EmailChangeVerifications.php
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
namespace openvk\Web\Models\Repositories;
|
||||||
|
use Chandler\Database\DatabaseConnection;
|
||||||
|
use openvk\Web\Models\Entities\EmailChangeVerification;
|
||||||
|
use openvk\Web\Models\Entities\User;
|
||||||
|
use Nette\Database\Table\ActiveRow;
|
||||||
|
|
||||||
|
class EmailChangeVerifications
|
||||||
|
{
|
||||||
|
private $context;
|
||||||
|
private $verifications;
|
||||||
|
|
||||||
|
function __construct()
|
||||||
|
{
|
||||||
|
$this->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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,12 +9,15 @@ use openvk\Web\Models\Repositories\Albums;
|
||||||
use openvk\Web\Models\Repositories\Videos;
|
use openvk\Web\Models\Repositories\Videos;
|
||||||
use openvk\Web\Models\Repositories\Notes;
|
use openvk\Web\Models\Repositories\Notes;
|
||||||
use openvk\Web\Models\Repositories\Vouchers;
|
use openvk\Web\Models\Repositories\Vouchers;
|
||||||
|
use openvk\Web\Models\Repositories\EmailChangeVerifications;
|
||||||
use openvk\Web\Models\Exceptions\InvalidUserNameException;
|
use openvk\Web\Models\Exceptions\InvalidUserNameException;
|
||||||
use openvk\Web\Util\Validator;
|
use openvk\Web\Util\Validator;
|
||||||
use openvk\Web\Models\Entities\Notifications\{CoinsTransferNotification, RatingUpNotification};
|
use openvk\Web\Models\Entities\Notifications\{CoinsTransferNotification, RatingUpNotification};
|
||||||
|
use openvk\Web\Models\Entities\EmailChangeVerification;
|
||||||
use Chandler\Security\Authenticator;
|
use Chandler\Security\Authenticator;
|
||||||
use lfkeitel\phptotp\{Base32, Totp};
|
use lfkeitel\phptotp\{Base32, Totp};
|
||||||
use chillerlan\QRCode\{QRCode, QROptions};
|
use chillerlan\QRCode\{QRCode, QROptions};
|
||||||
|
use Nette\Database\UniqueConstraintViolationException;
|
||||||
|
|
||||||
final class UserPresenter extends OpenVKPresenter
|
final class UserPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
|
@ -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("old_pass") && $this->postParam("new_pass") && $this->postParam("repeat_pass")) {
|
||||||
if($this->postParam("new_pass") === $this->postParam("repeat_pass")) {
|
if($this->postParam("new_pass") === $this->postParam("repeat_pass")) {
|
||||||
if($this->user->identity->is2faEnabled()) {
|
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)))
|
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"));
|
$this->flashFail("err", tr("error"), tr("incorrect_2fa_code"));
|
||||||
}
|
}
|
||||||
|
@ -324,6 +327,46 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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")))
|
if(!$user->setShortCode(empty($this->postParam("sc")) ? NULL : $this->postParam("sc")))
|
||||||
$this->flashFail("err", tr("error"), tr("error_shorturl_incorrect"));
|
$this->flashFail("err", tr("error"), tr("error_shorturl_incorrect"));
|
||||||
} else if($_GET['act'] === "privacy") {
|
} else if($_GET['act'] === "privacy") {
|
||||||
|
@ -400,11 +443,7 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
throw $ex;
|
throw $ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->flash(
|
$this->flash("succ", tr("changes_saved"), tr("changes_saved_comment"));
|
||||||
"succ",
|
|
||||||
"Изменения сохранены",
|
|
||||||
"Новые данные появятся на вашей странице."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
$this->template->mode = in_array($this->queryParam("act"), [
|
$this->template->mode = in_array($this->queryParam("act"), [
|
||||||
"main", "privacy", "finance", "finance.top-up", "interface"
|
"main", "privacy", "finance", "finance.top-up", "interface"
|
||||||
|
@ -502,6 +541,9 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
$this->assertUserLoggedIn();
|
$this->assertUserLoggedIn();
|
||||||
$this->willExecuteWriteAction();
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
|
if(!OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"])
|
||||||
|
$this->flashFail("err", tr("error"), tr("feature_disabled"));
|
||||||
|
|
||||||
$receiverAddress = $this->postParam("receiver");
|
$receiverAddress = $this->postParam("receiver");
|
||||||
$value = (int) $this->postParam("value");
|
$value = (int) $this->postParam("value");
|
||||||
$message = $this->postParam("message");
|
$message = $this->postParam("message");
|
||||||
|
@ -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));
|
$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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
<span class="nobold">{_"2fa_code"}</span>
|
<span class="nobold">{_"2fa_code"}</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="code" style="width: 100%;" />
|
<input type="text" name="password_change_code" style="width: 100%;" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -154,6 +154,38 @@
|
||||||
{$user->getEmail()}
|
{$user->getEmail()}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="120" valign="top">
|
||||||
|
<span class="nobold">{_new_email_address}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="email" name="new_email" style="width: 100%;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="120" valign="top">
|
||||||
|
<span class="nobold">{_password}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="password" name="email_change_pass" style="width: 100%;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr n:if="$user->is2faEnabled()">
|
||||||
|
<td width="120" valign="top">
|
||||||
|
<span class="nobold">{_"2fa_code"}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="email_change_code" style="width: 100%;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="submit" value="{_save_email_address}" class="button" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
|
@ -73,6 +73,8 @@ routes:
|
||||||
handler: "User->disableTwoFactorAuth"
|
handler: "User->disableTwoFactorAuth"
|
||||||
- url: "/settings/reset_theme"
|
- url: "/settings/reset_theme"
|
||||||
handler: "User->resetThemepack"
|
handler: "User->resetThemepack"
|
||||||
|
- url: "/settings/change_email"
|
||||||
|
handler: "User->emailChangeFinish"
|
||||||
- url: "/coins_transfer"
|
- url: "/coins_transfer"
|
||||||
handler: "User->coinsTransfer"
|
handler: "User->coinsTransfer"
|
||||||
- url: "/increase_social_credits"
|
- url: "/increase_social_credits"
|
||||||
|
|
8
install/sqls/00023-email-change.sql
Normal file
8
install/sqls/00023-email-change.sql
Normal file
|
@ -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;
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
"home" = "Գլխավոր";
|
"home" = "Գլխավոր";
|
||||||
"welcome" = "Բարի գալուստ";
|
"welcome" = "Բարի գալուստ";
|
||||||
|
"to_top" = "Վերև";
|
||||||
|
|
||||||
/* Login */
|
/* Login */
|
||||||
|
|
||||||
|
@ -381,7 +382,6 @@
|
||||||
|
|
||||||
"left_menu_donate" = "Աջակցել";
|
"left_menu_donate" = "Աջակցել";
|
||||||
|
|
||||||
|
|
||||||
"footer_about_instance" = "հոսքի մասին";
|
"footer_about_instance" = "հոսքի մասին";
|
||||||
"footer_blog" = "բլոգ";
|
"footer_blog" = "բլոգ";
|
||||||
"footer_help" = "օգնություն";
|
"footer_help" = "օգնություն";
|
||||||
|
@ -410,6 +410,8 @@
|
||||||
"style" = "Ոճ";
|
"style" = "Ոճ";
|
||||||
|
|
||||||
"default" = "Սովորական";
|
"default" = "Սովորական";
|
||||||
|
|
||||||
|
"arbitrary_avatars" = "Կամայական";
|
||||||
"cut" = "Կտրվածք";
|
"cut" = "Կտրվածք";
|
||||||
"round_avatars" = "Կլոր ավատար";
|
"round_avatars" = "Կլոր ավատար";
|
||||||
|
|
||||||
|
@ -519,6 +521,8 @@
|
||||||
"videos_many" = "$1 տեսանյութ";
|
"videos_many" = "$1 տեսանյութ";
|
||||||
"videos_other" = "$1 տեսանյութ";
|
"videos_other" = "$1 տեսանյութ";
|
||||||
|
|
||||||
|
"view_video" = "Դիտում";
|
||||||
|
|
||||||
/* Notifications */
|
/* Notifications */
|
||||||
|
|
||||||
"feedback" = "Հետադարձ կապ";
|
"feedback" = "Հետադարձ կապ";
|
||||||
|
@ -624,6 +628,21 @@
|
||||||
"receiver_not_found" = "Ստացողը չի գտնվել։";
|
"receiver_not_found" = "Ստացողը չի գտնվել։";
|
||||||
"you_dont_have_enough_points" = "Դուք չունե՛ք բավական ձայն։";
|
"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" = "Դուք հաջողությամբ բարձրացրեցիք Ձեր վարկանիշը <b><a href=\"$1\">$2</a></b> <b>$3%</b>-ով։";
|
||||||
|
"negative_rating_value" = "Կներե՛ք, մենք չենք կարող գողանալ ուրիշի վարկանիշը։";
|
||||||
|
|
||||||
|
"increased_your_rating_by" = "բարձրացրել է վարկանիշը";
|
||||||
|
|
||||||
/* Gifts */
|
/* Gifts */
|
||||||
|
|
||||||
"gift" = "Նվեր";
|
"gift" = "Նվեր";
|
||||||
|
@ -703,6 +722,9 @@
|
||||||
"ticket_changed" = "Տոմսը փոփոխված է";
|
"ticket_changed" = "Տոմսը փոփոխված է";
|
||||||
"ticket_changed_comment" = "Փոփոխությունները ուժի մեջ կմտնեն մի քանի վայրկյանից։";
|
"ticket_changed_comment" = "Փոփոխությունները ուժի մեջ կմտնեն մի քանի վայրկյանից։";
|
||||||
|
|
||||||
|
"banned_in_support_1" = "Կներե՛ք, <b>$1</b>, բայց հիմա Ձեզ թույլատրված չէ դիմումներ ստեղծել։";
|
||||||
|
"banned_in_support_2" = "Դրա պատճառաբանությունը սա է․ <b>$1</b>։ Ցավո՛ք, այդ հնարավորությունը մենք Ձեզնից վերցրել ենք առհավետ։";
|
||||||
|
|
||||||
/* Invite */
|
/* Invite */
|
||||||
|
|
||||||
"invite" = "Հրավիրել";
|
"invite" = "Հրավիրել";
|
||||||
|
@ -711,9 +733,9 @@
|
||||||
|
|
||||||
/* Banned */
|
/* Banned */
|
||||||
|
|
||||||
"banned_title" = "Բլոկավորված եք";
|
"banned_title" = "Արգելափակված եք";
|
||||||
"banned_header" = "Ձեզ կասեցրել է կառլենի անհաջող բոցը։";
|
"banned_header" = "Ձեզ կասեցրել է կարլենի անհաջող բոցը։";
|
||||||
"banned_alt" = "Օգտատերը բլոկավորված է";
|
"banned_alt" = "Օգտատերը արգելափակված է";
|
||||||
"banned_1" = "Կներե՛ք, <b>$1</b>, բայց Դուք կասեցված եք։";
|
"banned_1" = "Կներե՛ք, <b>$1</b>, բայց Դուք կասեցված եք։";
|
||||||
"banned_2" = "Պատճառը հետևյալն է․ <b>$1</b>. Ափսոս, բայց մենք ստիպված Ձեզ հավերժ ենք կասեցրել;";
|
"banned_2" = "Պատճառը հետևյալն է․ <b>$1</b>. Ափսոս, բայց մենք ստիպված Ձեզ հավերժ ենք կասեցրել;";
|
||||||
"banned_3" = "Դուք դեռ կարող եք <a href=\"/support?act=new\">գրել նամակ աջակցության ծառայությանը</a>, եթե համարում եք որ դա սխալմունք է, կամ էլ կարող եք <a href=\"/logout?hash=$1\">դուրս գալ</a>։";
|
"banned_3" = "Դուք դեռ կարող եք <a href=\"/support?act=new\">գրել նամակ աջակցության ծառայությանը</a>, եթե համարում եք որ դա սխալմունք է, կամ էլ կարող եք <a href=\"/logout?hash=$1\">դուրս գալ</a>։";
|
||||||
|
@ -835,6 +857,7 @@
|
||||||
"captcha_error" = "Սխալ են գրված սիմվոլները";
|
"captcha_error" = "Սխալ են գրված սիմվոլները";
|
||||||
"captcha_error_comment" = "Խնդրում ենք համոզվել, որ ճիշտ եք ներմուծել կապտչայի սիմվոլները։";
|
"captcha_error_comment" = "Խնդրում ենք համոզվել, որ ճիշտ եք ներմուծել կապտչայի սիմվոլները։";
|
||||||
|
|
||||||
|
|
||||||
/* Admin actions */
|
/* Admin actions */
|
||||||
|
|
||||||
"login_as" = "Մտնել ինչպես $1";
|
"login_as" = "Մտնել ինչպես $1";
|
||||||
|
@ -843,7 +866,84 @@
|
||||||
"ban_user_action" = "Բլոկավորել օգտվողին";
|
"ban_user_action" = "Բլոկավորել օգտվողին";
|
||||||
"warn_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_back" = "Հետ";
|
||||||
"paginator_page" = "$1 էջ";
|
"paginator_page" = "$1 էջ";
|
||||||
|
@ -857,6 +957,8 @@
|
||||||
"rules" = "Կանոններ";
|
"rules" = "Կանոններ";
|
||||||
"most_popular_groups" = "Ամենահայտնի խմբերը";
|
"most_popular_groups" = "Ամենահայտնի խմբերը";
|
||||||
"on_this_instance_are" = "Այս հոսքում․";
|
"on_this_instance_are" = "Այս հոսքում․";
|
||||||
|
"about_links" = "Հղումներ";
|
||||||
|
"instance_links" = "Հոսքերի հղումներ․";
|
||||||
|
|
||||||
"about_users_one" = "<b>Մեկ</b> օգտատեր";
|
"about_users_one" = "<b>Մեկ</b> օգտատեր";
|
||||||
"about_users_few" = "<b>$1</b> օգտատեր";
|
"about_users_few" = "<b>$1</b> օգտատեր";
|
||||||
|
|
|
@ -444,6 +444,8 @@
|
||||||
"your_page_address" = "Your address page";
|
"your_page_address" = "Your address page";
|
||||||
"page_address" = "Address page";
|
"page_address" = "Address page";
|
||||||
"current_email_address" = "Current email address";
|
"current_email_address" = "Current email address";
|
||||||
|
"new_email_address" = "New email address";
|
||||||
|
"save_email_address" = "Save email address";
|
||||||
"page_id" = "Page ID";
|
"page_id" = "Page ID";
|
||||||
"you_can_also" = "You can also";
|
"you_can_also" = "You can also";
|
||||||
"delete_your_page" = "delete your page";
|
"delete_your_page" = "delete your page";
|
||||||
|
@ -458,6 +460,8 @@
|
||||||
"additional_links" = "Additional links";
|
"additional_links" = "Additional links";
|
||||||
"ad_poster" = "Ad poster";
|
"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" = "Two-factor authentication";
|
"two_factor_authentication" = "Two-factor authentication";
|
||||||
|
|
|
@ -472,6 +472,8 @@
|
||||||
"your_page_address" = "Адрес Вашей страницы";
|
"your_page_address" = "Адрес Вашей страницы";
|
||||||
"page_address" = "Адрес страницы";
|
"page_address" = "Адрес страницы";
|
||||||
"current_email_address" = "Текущий адрес";
|
"current_email_address" = "Текущий адрес";
|
||||||
|
"new_email_address" = "Новый адрес";
|
||||||
|
"save_email_address" = "Сохранить адрес";
|
||||||
"page_id" = "ID страницы";
|
"page_id" = "ID страницы";
|
||||||
"you_can_also" = "Вы также можете";
|
"you_can_also" = "Вы также можете";
|
||||||
"delete_your_page" = "удалить свою страницу";
|
"delete_your_page" = "удалить свою страницу";
|
||||||
|
@ -486,6 +488,8 @@
|
||||||
"additional_links" = "Дополнительные ссылки";
|
"additional_links" = "Дополнительные ссылки";
|
||||||
"ad_poster" = "Рекламный плакат";
|
"ad_poster" = "Рекламный плакат";
|
||||||
|
|
||||||
|
"email_change_confirm_message" = "Чтобы изменение вступило в силу, подтвердите ваш новый адрес электронной почты. Мы отправили инструкции на него.";
|
||||||
|
|
||||||
/* Two-factor authentication */
|
/* Two-factor authentication */
|
||||||
|
|
||||||
"two_factor_authentication" = "Двухфакторная аутентификация";
|
"two_factor_authentication" = "Двухфакторная аутентификация";
|
||||||
|
|
Loading…
Reference in a new issue