mirror of
https://github.com/openvk/openvk
synced 2024-12-23 00:51:03 +03:00
Profile deactivation function (#626)
This commit is contained in:
parent
32233c34dd
commit
b1ce106e4c
18 changed files with 334 additions and 66 deletions
|
@ -84,6 +84,11 @@ class Post extends Postable
|
||||||
{
|
{
|
||||||
return ($this->getRecord()->flags & 0b01000000) > 0;
|
return ($this->getRecord()->flags & 0b01000000) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isDeactivationMessage(): bool
|
||||||
|
{
|
||||||
|
return ($this->getRecord()->flags & 0b00100000) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
function isExplicit(): bool
|
function isExplicit(): bool
|
||||||
{
|
{
|
||||||
|
|
|
@ -147,7 +147,7 @@ class User extends RowModel
|
||||||
|
|
||||||
function getFirstName(bool $pristine = false): string
|
function getFirstName(bool $pristine = false): string
|
||||||
{
|
{
|
||||||
$name = $this->getRecord()->deleted ? "DELETED" : mb_convert_case($this->getRecord()->first_name, MB_CASE_TITLE);
|
$name = ($this->isDeleted() && !$this->isDeactivated() ? "DELETED" : mb_convert_case($this->getRecord()->first_name, MB_CASE_TITLE));
|
||||||
if((($ts = tr("__transNames")) !== "@__transNames") && !$pristine)
|
if((($ts = tr("__transNames")) !== "@__transNames") && !$pristine)
|
||||||
return mb_convert_case(transliterator_transliterate($ts, $name), MB_CASE_TITLE);
|
return mb_convert_case(transliterator_transliterate($ts, $name), MB_CASE_TITLE);
|
||||||
else
|
else
|
||||||
|
@ -156,7 +156,7 @@ class User extends RowModel
|
||||||
|
|
||||||
function getLastName(bool $pristine = false): string
|
function getLastName(bool $pristine = false): string
|
||||||
{
|
{
|
||||||
$name = $this->getRecord()->deleted ? "DELETED" : mb_convert_case($this->getRecord()->last_name, MB_CASE_TITLE);
|
$name = ($this->isDeleted() && !$this->isDeactivated() ? "DELETED" : mb_convert_case($this->getRecord()->last_name, MB_CASE_TITLE));
|
||||||
if((($ts = tr("__transNames")) !== "@__transNames") && !$pristine)
|
if((($ts = tr("__transNames")) !== "@__transNames") && !$pristine)
|
||||||
return mb_convert_case(transliterator_transliterate($ts, $name), MB_CASE_TITLE);
|
return mb_convert_case(transliterator_transliterate($ts, $name), MB_CASE_TITLE);
|
||||||
else
|
else
|
||||||
|
@ -165,12 +165,12 @@ class User extends RowModel
|
||||||
|
|
||||||
function getPseudo(): ?string
|
function getPseudo(): ?string
|
||||||
{
|
{
|
||||||
return $this->getRecord()->deleted ? "DELETED" : $this->getRecord()->pseudo;
|
return ($this->isDeleted() && !$this->isDeactivated() ? "DELETED" : $this->getRecord()->pseudo);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFullName(): string
|
function getFullName(): string
|
||||||
{
|
{
|
||||||
if($this->getRecord()->deleted)
|
if($this->isDeleted() && !$this->isDeactivated())
|
||||||
return "DELETED";
|
return "DELETED";
|
||||||
|
|
||||||
$pseudo = $this->getPseudo();
|
$pseudo = $this->getPseudo();
|
||||||
|
@ -195,7 +195,7 @@ class User extends RowModel
|
||||||
|
|
||||||
function getCanonicalName(): string
|
function getCanonicalName(): string
|
||||||
{
|
{
|
||||||
if($this->getRecord()->deleted)
|
if($this->isDeleted() && !$this->isDeactivated())
|
||||||
return "DELETED";
|
return "DELETED";
|
||||||
else
|
else
|
||||||
return $this->getFirstName() . " " . $this->getLastName();
|
return $this->getFirstName() . " " . $this->getLastName();
|
||||||
|
@ -785,6 +785,27 @@ class User extends RowModel
|
||||||
$this->save();
|
$this->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deactivate(?string $reason): void
|
||||||
|
{
|
||||||
|
$this->setDeleted(1);
|
||||||
|
$this->setDeact_Date(time() + (MONTH * 7));
|
||||||
|
$this->setDeact_Reason($reason);
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
function reactivate(): void
|
||||||
|
{
|
||||||
|
$this->setDeleted(0);
|
||||||
|
$this->setDeact_Date(0);
|
||||||
|
$this->setDeact_Reason("");
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDeactivationDate(): DateTime
|
||||||
|
{
|
||||||
|
return new DateTime($this->getRecord()->deact_date);
|
||||||
|
}
|
||||||
|
|
||||||
function verifyNumber(string $code): bool
|
function verifyNumber(string $code): bool
|
||||||
{
|
{
|
||||||
$ver = $this->getPendingPhoneVerification();
|
$ver = $this->getPendingPhoneVerification();
|
||||||
|
@ -956,6 +977,14 @@ class User extends RowModel
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isDeactivated(): bool
|
||||||
|
{
|
||||||
|
if ($this->getDeactivationDate()->timestamp() > time())
|
||||||
|
return TRUE;
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0 - Default status
|
* 0 - Default status
|
||||||
* 1 - Incognito online status
|
* 1 - Incognito online status
|
||||||
|
|
|
@ -9,6 +9,7 @@ final class AboutPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
protected $banTolerant = true;
|
protected $banTolerant = true;
|
||||||
protected $activationTolerant = true;
|
protected $activationTolerant = true;
|
||||||
|
protected $deactivationTolerant = true;
|
||||||
|
|
||||||
function renderIndex(): void
|
function renderIndex(): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,6 +20,7 @@ final class AuthPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
protected $banTolerant = true;
|
protected $banTolerant = true;
|
||||||
protected $activationTolerant = true;
|
protected $activationTolerant = true;
|
||||||
|
protected $deactivationTolerant = true;
|
||||||
|
|
||||||
private $authenticator;
|
private $authenticator;
|
||||||
private $db;
|
private $db;
|
||||||
|
@ -151,7 +152,7 @@ final class AuthPresenter extends OpenVKPresenter
|
||||||
$this->flashFail("err", tr("login_failed"), tr("invalid_username_or_password"));
|
$this->flashFail("err", tr("login_failed"), tr("invalid_username_or_password"));
|
||||||
|
|
||||||
$ovkUser = new User($user->related("profiles.user")->fetch());
|
$ovkUser = new User($user->related("profiles.user")->fetch());
|
||||||
if($ovkUser->isDeleted())
|
if($ovkUser->isDeleted() && !$ovkUser->isDeactivated())
|
||||||
$this->flashFail("err", tr("login_failed"), tr("invalid_username_or_password"));
|
$this->flashFail("err", tr("login_failed"), tr("invalid_username_or_password"));
|
||||||
|
|
||||||
$secret = $user->related("profiles.user")->fetch()["2fa_secret"];
|
$secret = $user->related("profiles.user")->fetch()["2fa_secret"];
|
||||||
|
@ -321,4 +322,15 @@ final class AuthPresenter extends OpenVKPresenter
|
||||||
$this->redirect("/");
|
$this->redirect("/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderReactivatePage(): void
|
||||||
|
{
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
|
$this->user->identity->reactivate();
|
||||||
|
|
||||||
|
$this->redirect("/", 2);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
{
|
{
|
||||||
protected $banTolerant = false;
|
protected $banTolerant = false;
|
||||||
protected $activationTolerant = false;
|
protected $activationTolerant = false;
|
||||||
|
protected $deactivationTolerant = false;
|
||||||
protected $errorTemplate = "@error";
|
protected $errorTemplate = "@error";
|
||||||
protected $user = NULL;
|
protected $user = NULL;
|
||||||
|
|
||||||
|
@ -214,39 +215,28 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
$this->template->thisUser = $this->user->identity;
|
$this->template->thisUser = $this->user->identity;
|
||||||
$this->template->userTainted = $user->isTainted();
|
$this->template->userTainted = $user->isTainted();
|
||||||
|
|
||||||
if($this->user->identity->isDeleted()) {
|
if($this->user->identity->isDeleted() && !$this->deactivationTolerant) {
|
||||||
/*
|
if($this->user->identity->isDeactivated()) {
|
||||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⠶⠶⣶⠶⠶⠶⠶⠶⠶⠶⠶⠶⢶⠶⠶⠶⠤⠤⠤⠤⣄⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
header("HTTP/1.1 403 Forbidden");
|
||||||
⠀⠀⠀⠀⠀⠀⠀⠀⣠⡾⠋⠀⠀⠊⠀⠀⠀⠀⠀⠀⠀⠀⠒⠒⠒⠀⠀⠀⠀⠤⢤⣤⣄⠉⠉⠛⠛⠷⣦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
$this->getTemplatingEngine()->render(__DIR__ . "/templates/@deactivated.xml", [
|
||||||
⠀⠀⠀⠀⠀⠀⠀⣰⠟⠀⠀⠀⠀⠀⠐⠋⢑⣤⣶⣶⣤⡢⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣄⡂⠀⠀⠶⢄⠙⢷⣤⠀⠀⠀⠀⠀⠀⠀⠀
|
"thisUser" => $this->user->identity,
|
||||||
⠀⠀⠀⠀⠀⠀⣸⡿⠚⠉⡀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⢢⠀⠀⡀⣰⣿⣿⣿⣿⣦⡀⠀⠀⠡⡀⢹⡆⠀⠀⠀⠀⠀⠀⠀
|
"csrfToken" => $GLOBALS["csrfToken"],
|
||||||
⠀⠀⠀⠀⢀⣴⠏⠀⣀⣀⣀⡤⢤⣄⣠⣿⣿⣿⣿⣻⣿⣿⣷⠀⢋⣾⠈⠙⣶⠒⢿⣿⣿⣿⣿⡿⠟⠃⠀⡀⠡⠼⣧⡀⠀⠀⠀⠀⠀⠀
|
"isTimezoned" => Session::i()->get("_timezoneOffset"),
|
||||||
⠀⠀⢀⣴⣿⢃⡴⢊⢽⣶⣤⣀⠀⠊⠉⠉⡛⢿⣿⣿⣿⠿⠋⢀⡀⠁⠀⠀⢸⣁⣀⣉⣉⣉⡉⠀⠩⡡⠀⣩⣦⠀⠈⠻⣦⡀⠀⠀⠀⠀
|
]);
|
||||||
⠀⢠⡟⢡⠇⡞⢀⠆⠀⢻⣿⣿⣷⣄⠀⢀⠈⠂⠈⢁⡤⠚⡟⠉⠀⣀⣀⠀⠈⠳⣍⠓⢆⢀⡠⢀⣨⣴⣿⣿⡏⢀⡆⠀⢸⡇⠀⠀⠀⠀
|
} else {
|
||||||
⠀⣾⠁⢸⠀⠀⢸⠀⠀⠀⠹⣿⣿⣿⣿⣶⣬⣦⣤⡈⠀⠀⠇⠀⠛⠉⣩⣤⣤⣤⣿⣤⣤⣴⣾⣿⣿⣿⣿⣿⣧⠞⠀⠀⢸⡇⠀⠀⠀⠀
|
Authenticator::i()->logout();
|
||||||
⠀⢹⣆⠸⠀⠀⢸⠀⠀⠀⠀⠘⢿⣿⣿⣿⣿⣿⣿⣟⣛⠛⠛⣛⡛⠛⠛⣛⣋⡉⠉⣡⠶⢾⣿⣿⣿⣿⣿⣿⡇⠀⠀⢀⣾⠃⠀⠀⠀⠀
|
Session::i()->set("_su", NULL);
|
||||||
⠀⠀⠻⣆⡀⠀⠈⢂⠀⠀⠀⠠⡈⢻⣿⣿⣿⣿⡟⠁⠈⢧⡼⠉⠙⣆⡞⠁⠈⢹⣴⠃⠀⢸⣿⣿⣿⣿⣿⣿⠃⠀⡆⣾⠃⠀⠀⠀⠀⠀
|
$this->flashFail("err", tr("error"), tr("profile_not_found"));
|
||||||
⠀⠀⠀⠈⢻⣇⠀⠀⠀⠀⠀⠀⢡⠀⠹⣿⣿⣿⣷⡀⠀⣸⡇⠀⠀⣿⠁⠀⠀⠘⣿⠀⠀⠘⣿⣿⣿⣿⣿⣿⠀⠀⣿⡇⠀⠀⠀⠀⠀⠀
|
$this->redirect("/", static::REDIRECT_TEMPORARY);
|
||||||
⠀⠀⠀⠀⠀⠹⣇⠀⠠⠀⠀⠀⠀⠡⠐⢬⡻⣿⣿⣿⣿⣿⣷⣶⣶⣿⣦⣤⣤⣤⣿⣦⣶⣿⣿⣿⣿⣿⣿⣿⠀⠀⣿⡇⠀⠀⠀⠀⠀⠀
|
}
|
||||||
⠀⠀⠀⠀⠀⠀⠹⣧⡀⠡⡀⠀⠀⠀⠑⠄⠙⢎⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⠀⢿⡇⠀⠀⠀⠀⠀⠀
|
exit;
|
||||||
⠀⠀⠀⠀⠀⠀⠀⠈⠳⣤⡐⡄⠀⠀⠀⠈⠂⠀⠱⣌⠻⣿⣿⣿⣿⣿⣿⣿⠿⣿⠟⢻⡏⢻⣿⣿⣿⣿⣿⣿⣿⠀⢸⡇⠀⠀⠀⠀⠀⠀
|
|
||||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⢮⣦⡀⠂⠀⢀⠀⠀⠈⠳⣈⠻⣿⣿⣿⡇⠘⡄⢸⠀⠀⣇⠀⣻⣿⣿⣿⣿⣿⡏⠀⠸⡇⠀⠀⠀⠀⠀⠀
|
|
||||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢶⣤⣄⡑⠄⠀⠀⠈⠑⠢⠙⠻⢷⣶⣵⣞⣑⣒⣋⣉⣁⣻⣿⠿⠟⠱⠃⡸⠀⣧⠀⠀⠀⠀⠀⠀
|
|
||||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠻⣷⣄⡀⠐⠢⣄⣀⡀⠀⠉⠉⠉⠉⠛⠙⠭⠭⠄⠒⠈⠀⠐⠁⢀⣿⠀⠀⠀⠀⠀⠀
|
|
||||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠷⢦⣤⣤⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣒⡠⠄⣠⡾⠃⠀⠀⠀⠀⠀⠀
|
|
||||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠛⠷⠶⣦⣤⣭⣤⣬⣭⣭⣴⠶⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀
|
|
||||||
*/
|
|
||||||
Authenticator::i()->logout();
|
|
||||||
Session::i()->set("_su", NULL);
|
|
||||||
$this->flashFail("err", tr("error"), tr("profile_not_found"));
|
|
||||||
$this->redirect("/", static::REDIRECT_TEMPORARY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->user->identity->isBanned() && !$this->banTolerant) {
|
if($this->user->identity->isBanned() && !$this->banTolerant) {
|
||||||
header("HTTP/1.1 403 Forbidden");
|
header("HTTP/1.1 403 Forbidden");
|
||||||
$this->getTemplatingEngine()->render(__DIR__ . "/templates/@banned.xml", [
|
$this->getTemplatingEngine()->render(__DIR__ . "/templates/@banned.xml", [
|
||||||
"thisUser" => $this->user->identity,
|
"thisUser" => $this->user->identity,
|
||||||
"csrfToken" => $GLOBALS["csrfToken"],
|
"csrfToken" => $GLOBALS["csrfToken"],
|
||||||
"isTimezoned" => Session::i()->get("_timezoneOffset"),
|
"isTimezoned" => Session::i()->get("_timezoneOffset"),
|
||||||
]);
|
]);
|
||||||
exit;
|
exit;
|
||||||
|
@ -256,8 +246,8 @@ abstract class OpenVKPresenter extends SimplePresenter
|
||||||
if(!$this->user->identity->isActivated() && !$this->activationTolerant) {
|
if(!$this->user->identity->isActivated() && !$this->activationTolerant) {
|
||||||
header("HTTP/1.1 403 Forbidden");
|
header("HTTP/1.1 403 Forbidden");
|
||||||
$this->getTemplatingEngine()->render(__DIR__ . "/templates/@email.xml", [
|
$this->getTemplatingEngine()->render(__DIR__ . "/templates/@email.xml", [
|
||||||
"thisUser" => $this->user->identity,
|
"thisUser" => $this->user->identity,
|
||||||
"csrfToken" => $GLOBALS["csrfToken"],
|
"csrfToken" => $GLOBALS["csrfToken"],
|
||||||
"isTimezoned" => Session::i()->get("_timezoneOffset"),
|
"isTimezoned" => Session::i()->get("_timezoneOffset"),
|
||||||
]);
|
]);
|
||||||
exit;
|
exit;
|
||||||
|
|
|
@ -12,6 +12,7 @@ use Parsedown;
|
||||||
final class SupportPresenter extends OpenVKPresenter
|
final class SupportPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
protected $banTolerant = true;
|
protected $banTolerant = true;
|
||||||
|
protected $deactivationTolerant = true;
|
||||||
|
|
||||||
private $tickets;
|
private $tickets;
|
||||||
private $comments;
|
private $comments;
|
||||||
|
|
|
@ -3,6 +3,7 @@ namespace openvk\Web\Presenters;
|
||||||
use openvk\Web\Util\Sms;
|
use openvk\Web\Util\Sms;
|
||||||
use openvk\Web\Themes\Themepacks;
|
use openvk\Web\Themes\Themepacks;
|
||||||
use openvk\Web\Models\Entities\Photo;
|
use openvk\Web\Models\Entities\Photo;
|
||||||
|
use openvk\Web\Models\Entities\Post;
|
||||||
use openvk\Web\Models\Repositories\Users;
|
use openvk\Web\Models\Repositories\Users;
|
||||||
use openvk\Web\Models\Repositories\Clubs;
|
use openvk\Web\Models\Repositories\Clubs;
|
||||||
use openvk\Web\Models\Repositories\Albums;
|
use openvk\Web\Models\Repositories\Albums;
|
||||||
|
@ -22,6 +23,8 @@ use Nette\Database\UniqueConstraintViolationException;
|
||||||
final class UserPresenter extends OpenVKPresenter
|
final class UserPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
private $users;
|
private $users;
|
||||||
|
|
||||||
|
public $deactivationTolerant = false;
|
||||||
|
|
||||||
function __construct(Users $users)
|
function __construct(Users $users)
|
||||||
{
|
{
|
||||||
|
@ -34,7 +37,13 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
$user = $this->users->get($id);
|
$user = $this->users->get($id);
|
||||||
if(!$user || $user->isDeleted()) {
|
if(!$user || $user->isDeleted()) {
|
||||||
$this->template->_template = "User/deleted.xml";
|
if($user->isDeactivated()) {
|
||||||
|
$this->template->_template = "User/deactivated.xml";
|
||||||
|
|
||||||
|
$this->template->user = $user;
|
||||||
|
} else {
|
||||||
|
$this->template->_template = "User/deleted.xml";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->template->albums = (new Albums)->getUserAlbums($user);
|
$this->template->albums = (new Albums)->getUserAlbums($user);
|
||||||
$this->template->albumsCount = (new Albums)->getUserAlbumsCount($user);
|
$this->template->albumsCount = (new Albums)->getUserAlbumsCount($user);
|
||||||
|
@ -272,8 +281,7 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
$user->toggleSubscription($this->user->identity);
|
$user->toggleSubscription($this->user->identity);
|
||||||
|
|
||||||
header("HTTP/1.1 302 Found");
|
$this->redirect("/id" . $user->getId());
|
||||||
header("Location: /id" . $user->getId());
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,6 +482,33 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
$this->template->themes = Themepacks::i()->getThemeList();
|
$this->template->themes = Themepacks::i()->getThemeList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderDeactivate(): void
|
||||||
|
{
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
|
$flags = 0;
|
||||||
|
$reason = $this->postParam("deactivate_reason");
|
||||||
|
$share = $this->postParam("deactivate_share");
|
||||||
|
|
||||||
|
if($share) {
|
||||||
|
$flags |= 0b00100000;
|
||||||
|
|
||||||
|
$post = new Post;
|
||||||
|
$post->setOwner($this->user->id);
|
||||||
|
$post->setWall($this->user->id);
|
||||||
|
$post->setCreated(time());
|
||||||
|
$post->setContent($reason);
|
||||||
|
$post->setFlags($flags);
|
||||||
|
$post->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->user->identity->deactivate($reason);
|
||||||
|
|
||||||
|
$this->redirect("/");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
function renderTwoFactorAuthSettings(): void
|
function renderTwoFactorAuthSettings(): void
|
||||||
{
|
{
|
||||||
$this->assertUserLoggedIn();
|
$this->assertUserLoggedIn();
|
||||||
|
|
34
Web/Presenters/templates/@deactivated.xml
Normal file
34
Web/Presenters/templates/@deactivated.xml
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{extends "@layout.xml"}
|
||||||
|
{block title}{$thisUser->getCanonicalName()}{/block}
|
||||||
|
|
||||||
|
{block header}
|
||||||
|
{$thisUser->getCanonicalName()}
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block content}
|
||||||
|
<div class="container_gray bottom" style="margin: -10px -10px 10px;">
|
||||||
|
{tr("profile_deactivated_msg", $thisUser->getDeactivationDate()->format("%e %B %G" . tr("time_at_sp") . "%R"))|noescape}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="left_small_block">
|
||||||
|
<div>
|
||||||
|
<img src="{$thisUser->getAvatarUrl('normal')}"
|
||||||
|
alt="{$thisUser->getCanonicalName()}"
|
||||||
|
style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right_big_block">
|
||||||
|
<div class="page_info">
|
||||||
|
<div class="accountInfo clearFix">
|
||||||
|
<div class="profileName">
|
||||||
|
<h2>{$thisUser->getFullName()}</h2>
|
||||||
|
<div class="page_status" style="color: #AAA;">{_profile_deactivated_status}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<center style="color: #AAA;margin: 40px 0;font-size: 13px;">
|
||||||
|
{_profile_deactivated_info|noescape}
|
||||||
|
</center>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/block}
|
|
@ -102,29 +102,35 @@
|
||||||
<a href="/" class="home_button{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME} home_button_custom{/if}" title="{$instance_name}">{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME}{$instance_name}{/if}</a>
|
<a href="/" class="home_button{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME} home_button_custom{/if}" title="{$instance_name}">{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME}{$instance_name}{/if}</a>
|
||||||
<div n:if="isset($thisUser) ? (!$thisUser->isBanned() XOR !$thisUser->isActivated()) : true" class="header_navigation">
|
<div n:if="isset($thisUser) ? (!$thisUser->isBanned() XOR !$thisUser->isActivated()) : true" class="header_navigation">
|
||||||
{ifset $thisUser}
|
{ifset $thisUser}
|
||||||
<div class="link">
|
{if $thisUser->isDeactivated()}
|
||||||
<a href="/">{_header_home}</a>
|
<div class="link">
|
||||||
</div>
|
<a href="/logout?hash={urlencode($csrfToken)}">{_header_log_out}</a>
|
||||||
<div class="link">
|
</div>
|
||||||
<a href="/search?type=groups">{_header_groups}</a>
|
{else}
|
||||||
</div>
|
<div class="link">
|
||||||
<div class="link">
|
<a href="/">{_header_home}</a>
|
||||||
<a href="/search">{_header_search}</a>
|
</div>
|
||||||
</div>
|
<div class="link">
|
||||||
<div class="link">
|
<a href="/search?type=groups">{_header_groups}</a>
|
||||||
<a href="/invite">{_header_invite}</a>
|
</div>
|
||||||
</div>
|
<div class="link">
|
||||||
<div class="link">
|
<a href="/search">{_header_search}</a>
|
||||||
<a href="/support">{_header_help} <b n:if="$ticketAnsweredCount > 0">({$ticketAnsweredCount})</b></a>
|
</div>
|
||||||
</div>
|
<div class="link">
|
||||||
<div class="link">
|
<a href="/invite">{_header_invite}</a>
|
||||||
<a href="/logout?hash={urlencode($csrfToken)}">{_header_log_out}</a>
|
</div>
|
||||||
</div>
|
<div class="link">
|
||||||
<div class="link">
|
<a href="/support">{_header_help} <b n:if="$ticketAnsweredCount > 0">({$ticketAnsweredCount})</b></a>
|
||||||
<form action="/search" method="get">
|
</div>
|
||||||
<input type="search" name="query" placeholder="{_header_search}" style="height: 20px;background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px; background-color: #fff; padding-left: 18px;width: 120px;" title="{_header_search} [Alt+Shift+F]" accesskey="f" />
|
<div class="link">
|
||||||
</form>
|
<a href="/logout?hash={urlencode($csrfToken)}">{_header_log_out}</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="link">
|
||||||
|
<form action="/search" method="get">
|
||||||
|
<input type="search" name="query" placeholder="{_header_search}" style="height: 20px;background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px; background-color: #fff; padding-left: 18px;width: 120px;" title="{_header_search} [Alt+Shift+F]" accesskey="f" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
{else}
|
{else}
|
||||||
<div class="link">
|
<div class="link">
|
||||||
<a href="/login">{_header_login}</a>
|
<a href="/login">{_header_login}</a>
|
||||||
|
@ -142,7 +148,7 @@
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<div class="navigation">
|
<div class="navigation">
|
||||||
{ifset $thisUser}
|
{ifset $thisUser}
|
||||||
{if !$thisUser->isBanned() XOR !$thisUser->isActivated()}
|
{if !$thisUser->isBanned() XOR !$thisUser->isActivated() XOR $thisUser->isDeactivated()}
|
||||||
<a href="/edit" class="link edit-button">{_edit_button}</a>
|
<a href="/edit" class="link edit-button">{_edit_button}</a>
|
||||||
<a href="{$thisUser->getURL()}" class="link" title="{_my_page} [Alt+Shift+.]" accesskey=".">{_my_page}</a>
|
<a href="{$thisUser->getURL()}" class="link" title="{_my_page} [Alt+Shift+.]" accesskey=".">{_my_page}</a>
|
||||||
<a href="/friends{$thisUser->getId()}" class="link">{_my_friends}
|
<a href="/friends{$thisUser->getId()}" class="link">{_my_friends}
|
||||||
|
|
|
@ -220,9 +220,14 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<div class="settings_delete">
|
||||||
|
{_you_can_also} <a onClick="showProfileDeactivateDialog({$csrfToken})">{_delete_your_page}</a>.
|
||||||
|
</div>
|
||||||
|
|
||||||
{elseif $isPrivacy}
|
{elseif $isPrivacy}
|
||||||
|
|
||||||
<form action="/settings?act=privacy" method="POST" enctype="multipart/form-data">
|
<form action="/settings?act=privacy" method="POST" enctype="multipart/form-data">
|
||||||
<table cellspacing="7" cellpadding="0" width="60%" border="0" align="center">
|
<table cellspacing="7" cellpadding="0" width="60%" border="0" align="center">
|
||||||
<tr>
|
<tr>
|
||||||
|
|
30
Web/Presenters/templates/User/deactivated.xml
Normal file
30
Web/Presenters/templates/User/deactivated.xml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{extends "../@layout.xml"}
|
||||||
|
{block title}{$user->getCanonicalName()}{/block}
|
||||||
|
|
||||||
|
{block header}
|
||||||
|
{$user->getCanonicalName()}
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block content}
|
||||||
|
<div class="left_small_block">
|
||||||
|
<div>
|
||||||
|
<img src="{$user->getAvatarUrl('normal')}"
|
||||||
|
alt="{$user->getCanonicalName()}"
|
||||||
|
style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right_big_block">
|
||||||
|
<div class="page_info">
|
||||||
|
<div class="accountInfo clearFix">
|
||||||
|
<div class="profileName">
|
||||||
|
<h2>{$user->getFullName()}</h2>
|
||||||
|
<div class="page_status" style="color: #AAA;">{_profile_deactivated_status}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<center style="color: #AAA;margin: 40px 0;font-size: 13px;">
|
||||||
|
{_profile_deactivated_info|noescape}
|
||||||
|
</center>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/block}
|
|
@ -1,6 +1,11 @@
|
||||||
{var $author = $post->getOwner()}
|
{var $author = $post->getOwner()}
|
||||||
{var $comments = $post->getLastComments(3)}
|
{var $comments = $post->getLastComments(3)}
|
||||||
{var $commentsCount = $post->getCommentsCount()}
|
{var $commentsCount = $post->getCommentsCount()}
|
||||||
|
{if $post->isDeactivationMessage() && $post->getText()}
|
||||||
|
{var $deac = "post_deact"}
|
||||||
|
{else}
|
||||||
|
{var $deac = "post_deact_silent"}
|
||||||
|
{/if}
|
||||||
|
|
||||||
{var $commentTextAreaId = $post === NULL ? rand(1,300) : $post->getId()}
|
{var $commentTextAreaId = $post === NULL ? rand(1,300) : $post->getId()}
|
||||||
|
|
||||||
|
@ -17,6 +22,7 @@
|
||||||
<div class="post-author">
|
<div class="post-author">
|
||||||
<a href="{$author->getURL()}"><b>{$author->getCanonicalName()}</b></a>
|
<a href="{$author->getURL()}"><b>{$author->getCanonicalName()}</b></a>
|
||||||
<img n:if="$author->isVerified()" class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">
|
<img n:if="$author->isVerified()" class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">
|
||||||
|
{$post->isDeactivationMessage() ? ($author->isFemale() ? tr($deac . "_f") : tr($deac . "_m"))}
|
||||||
{if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
|
{if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
|
||||||
{var $wallId = $post->getTargetWall()}
|
{var $wallId = $post->getTargetWall()}
|
||||||
{var $wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
|
{var $wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
{var $author = $post->getOwner()}
|
{var $author = $post->getOwner()}
|
||||||
|
{if $post->isDeactivationMessage() && $post->getText()}
|
||||||
|
{var $deac = "post_deact"}
|
||||||
|
{else}
|
||||||
|
{var $deac = "post_deact_silent"}
|
||||||
|
{/if}
|
||||||
|
|
||||||
<table border="0" style="font-size: 11px;" n:class="post, $post->isExplicit() ? post-nsfw">
|
<table border="0" style="font-size: 11px;" n:class="post, $post->isExplicit() ? post-nsfw">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -13,7 +18,7 @@
|
||||||
<div class="post-author">
|
<div class="post-author">
|
||||||
<a href="{$author->getURL()}"><b>{$author->getCanonicalName()}</b></a>
|
<a href="{$author->getURL()}"><b>{$author->getCanonicalName()}</b></a>
|
||||||
<img n:if="$author->isVerified()" class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">
|
<img n:if="$author->isVerified()" class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">
|
||||||
{$post->isPostedOnBehalfOfGroup() ? tr("post_writes_g") : ($author->isFemale() ? tr("post_writes_f") : tr("post_writes_m"))}
|
{$post->isDeactivationMessage() ? ($author->isFemale() ? tr($deac . "_f") : tr($deac . "_m")) : ($post->isPostedOnBehalfOfGroup() ? tr("post_writes_g") : ($author->isFemale() ? tr("post_writes_f") : tr("post_writes_m")))}
|
||||||
{if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
|
{if ($onWallOf ?? false) &&!$post->isPostedOnBehalfOfGroup() && $post->getOwnerPost() !== $post->getTargetWall()}
|
||||||
{var $wallId = $post->getTargetWall()}
|
{var $wallId = $post->getTargetWall()}
|
||||||
{var $wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
|
{var $wallURL = $wallId > -1 ? "/id$wallId" : "/club" . abs($wallId)}
|
||||||
|
|
|
@ -75,6 +75,10 @@ routes:
|
||||||
handler: "User->resetThemepack"
|
handler: "User->resetThemepack"
|
||||||
- url: "/settings/change_email"
|
- url: "/settings/change_email"
|
||||||
handler: "User->emailChangeFinish"
|
handler: "User->emailChangeFinish"
|
||||||
|
- url: "/settings/deactivate"
|
||||||
|
handler: "User->deactivate"
|
||||||
|
- url: "/settings/reactivate"
|
||||||
|
handler: "Auth->reactivatePage"
|
||||||
- url: "/coins_transfer"
|
- url: "/coins_transfer"
|
||||||
handler: "User->coinsTransfer"
|
handler: "User->coinsTransfer"
|
||||||
- url: "/increase_social_credits"
|
- url: "/increase_social_credits"
|
||||||
|
|
|
@ -306,6 +306,58 @@ function ovk_proc_strtr(string, length = 0) {
|
||||||
return newString + (string !== newString ? "…" : "");
|
return newString + (string !== newString ? "…" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showProfileDeactivateDialog(hash) {
|
||||||
|
MessageBox(tr("profile_deactivate"), `
|
||||||
|
<div class="messagebox-content-header">
|
||||||
|
${tr("profile_deactivate_header")}
|
||||||
|
</div>
|
||||||
|
<form action="/settings/deactivate" method="post" id="profile_deactivate_dialog" style="margin-top: 30px">
|
||||||
|
<h4>${tr("profile_deactivate_reason_header")}</h4>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><input type="radio" name="deactivate_type" id="deactivate_r_1" data-text="${tr("profile_deactivate_reason_1_text")}"></td>
|
||||||
|
<td><label for="deactivate_r_1">${tr("profile_deactivate_reason_1")}</label></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><input type="radio" name="deactivate_type" id="deactivate_r_2" data-text="${tr("profile_deactivate_reason_2_text")}"></td>
|
||||||
|
<td><label for="deactivate_r_2">${tr("profile_deactivate_reason_2")}</label></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><input type="radio" name="deactivate_type" id="deactivate_r_3" data-text="${tr("profile_deactivate_reason_3_text")}"></td>
|
||||||
|
<td><label for="deactivate_r_3">${tr("profile_deactivate_reason_3")}</label></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><input type="radio" name="deactivate_type" id="deactivate_r_4" data-text="${tr("profile_deactivate_reason_4_text")}"></td>
|
||||||
|
<td><label for="deactivate_r_4">${tr("profile_deactivate_reason_4")}</label></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><input type="radio" name="deactivate_type" id="deactivate_r_5" data-text="${tr("profile_deactivate_reason_5_text")}"></td>
|
||||||
|
<td><label for="deactivate_r_5">${tr("profile_deactivate_reason_5")}</label></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><input type="radio" name="deactivate_type" id="deactivate_r_6" data-text=""></td>
|
||||||
|
<td><label for="deactivate_r_6">${tr("profile_deactivate_reason_6")}</label></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<textarea name="deactivate_reason" id="deactivate_reason" placeholder="${tr("gift_your_message")}"></textarea><br><br>
|
||||||
|
<input type="checkbox" name="deactivate_share" id="deactivate_share" checked>
|
||||||
|
<label for="deactivate_share">${tr("share_with_friends")}</label>
|
||||||
|
<input type="hidden" name="hash" value="${hash}" />
|
||||||
|
</form>
|
||||||
|
`, [tr("profile_deactivate_button"), tr("cancel")], [
|
||||||
|
() => {
|
||||||
|
$("#profile_deactivate_dialog").submit();
|
||||||
|
},
|
||||||
|
Function.noop
|
||||||
|
]);
|
||||||
|
|
||||||
|
$('[id^="deactivate_r_"]').on("click", function () {
|
||||||
|
$('#deactivate_reason').val($(this).data("text"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function showIncreaseRatingDialog(coinsCount, userUrl, hash) {
|
function showIncreaseRatingDialog(coinsCount, userUrl, hash) {
|
||||||
MessageBox(tr("increase_rating"), `
|
MessageBox(tr("increase_rating"), `
|
||||||
<div class="messagebox-content-header">
|
<div class="messagebox-content-header">
|
||||||
|
|
1
install/sqls/00028-deactivation.sql
Normal file
1
install/sqls/00028-deactivation.sql
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE `profiles` ADD `deact_date` bigint(20) unsigned NOT NULL DEFAULT '0' AFTER `deleted`, ADD `deact_reason` text NULL AFTER `deact_date`;
|
|
@ -149,6 +149,10 @@
|
||||||
"post_writes_m" = "wrote";
|
"post_writes_m" = "wrote";
|
||||||
"post_writes_f" = "wrote";
|
"post_writes_f" = "wrote";
|
||||||
"post_writes_g" = "published";
|
"post_writes_g" = "published";
|
||||||
|
"post_deact_m" = "deleted his profile saying:";
|
||||||
|
"post_deact_f" = "deleted her profile saying:";
|
||||||
|
"post_deact_silent_m" = "silently deleted his profile.";
|
||||||
|
"post_deact_silent_f" = "silently deleted her profile.";
|
||||||
"wall" = "Wall";
|
"wall" = "Wall";
|
||||||
"post" = "Post";
|
"post" = "Post";
|
||||||
"write" = "Write";
|
"write" = "Write";
|
||||||
|
@ -487,6 +491,28 @@
|
||||||
|
|
||||||
"email_change_confirm_message" = "Please confirm your new email address for the change to take effect. We have sent instructions to it.";
|
"email_change_confirm_message" = "Please confirm your new email address for the change to take effect. We have sent instructions to it.";
|
||||||
|
|
||||||
|
"profile_deactivate" = "Delete account";
|
||||||
|
"profile_deactivate_button" = "Delete account";
|
||||||
|
"profile_deactivate_header" = "We are sorry that you want to delete your page. Therefore, you can specify the reason for deletion and your message about it. We read your feedback and try to make the site better!";
|
||||||
|
"profile_deactivate_reason_header" = "Please select a reason why you are leaving";
|
||||||
|
"profile_deactivate_reason_1" = "I have another profile and don't need this one";
|
||||||
|
"profile_deactivate_reason_1_text" = "I created a new page and now I want to wipe my past.";
|
||||||
|
"profile_deactivate_reason_2" = "Website takes away too much of my time";
|
||||||
|
"profile_deactivate_reason_2_text" = "Even though this site is nice and beautiful, it takes away my time that I need for work and life.";
|
||||||
|
"profile_deactivate_reason_3" = "Website harbors too much inappropriate content";
|
||||||
|
"profile_deactivate_reason_3_text" = "I have found enough porn and pirated content to last me a lifetime, I'm leaving now.";
|
||||||
|
"profile_deactivate_reason_4" = "I am worried about the safety of my data";
|
||||||
|
"profile_deactivate_reason_4_text" = "I'm being watched and I'm scared to be here. I'm sorry, I have to leave.";
|
||||||
|
"profile_deactivate_reason_5" = "No one comments on my posts";
|
||||||
|
"profile_deactivate_reason_5_text" = "No one watches me here and it's sad. You will regret that I left.";
|
||||||
|
"profile_deactivate_reason_6" = "Other reason";
|
||||||
|
|
||||||
|
"profile_deactivated_msg" = "Your account has been <b>deleted</b>.<br/><br/>If you would like to start using the site again, you can <a href='/settings/reactivate'>restore your account</a> until $1.";
|
||||||
|
"profile_deactivated_status" = "Account deleted";
|
||||||
|
"profile_deactivated_info" = "The account has been deleted.<br/>The information is not available.";
|
||||||
|
|
||||||
|
"share_with_friends" = "Share with friends";
|
||||||
|
|
||||||
/* Two-factor authentication */
|
/* Two-factor authentication */
|
||||||
|
|
||||||
"two_factor_authentication" = "Two-factor authentication";
|
"two_factor_authentication" = "Two-factor authentication";
|
||||||
|
|
|
@ -155,6 +155,10 @@
|
||||||
"post_writes_m" = "написал";
|
"post_writes_m" = "написал";
|
||||||
"post_writes_f" = "написала";
|
"post_writes_f" = "написала";
|
||||||
"post_writes_g" = "опубликовали";
|
"post_writes_g" = "опубликовали";
|
||||||
|
"post_deact_m" = "удалил страницу со словами:";
|
||||||
|
"post_deact_f" = "удалила страницу со словами:";
|
||||||
|
"post_deact_silent_m" = "молча удалил свою страницу.";
|
||||||
|
"post_deact_silent_f" = "молча удалила свою страницу.";
|
||||||
"wall" = "Стена";
|
"wall" = "Стена";
|
||||||
"post" = "Запись";
|
"post" = "Запись";
|
||||||
"write" = "Написать";
|
"write" = "Написать";
|
||||||
|
@ -523,6 +527,28 @@
|
||||||
|
|
||||||
"email_change_confirm_message" = "Чтобы изменение вступило в силу, подтвердите ваш новый адрес электронной почты. Мы отправили инструкции на него.";
|
"email_change_confirm_message" = "Чтобы изменение вступило в силу, подтвердите ваш новый адрес электронной почты. Мы отправили инструкции на него.";
|
||||||
|
|
||||||
|
"profile_deactivate" = "Удаление страницы";
|
||||||
|
"profile_deactivate_button" = "Удалить страницу";
|
||||||
|
"profile_deactivate_header" = "Мы сожалеем, что Вы хотите удалить свою страницу. Поэтому, Вы можете указать причину удаления и Ваше сообщение по этому поводу. Мы читаем Ваши отзывы и пытаемся сделать сайт лучше!";
|
||||||
|
"profile_deactivate_reason_header" = "Пожалуйста, укажите причину удаления Вашей страницы";
|
||||||
|
"profile_deactivate_reason_1" = "У меня есть другая страница на сайте";
|
||||||
|
"profile_deactivate_reason_1_text" = "Я создал новую страницу и теперь хочу подтереть своё прошлое.";
|
||||||
|
"profile_deactivate_reason_2" = "Сайт отнимает у меня слишком много времени";
|
||||||
|
"profile_deactivate_reason_2_text" = "Пусть этот сайт хорош и прекрасен, но он отнимает у меня время, которое мне нужно для работы и жизни.";
|
||||||
|
"profile_deactivate_reason_3" = "Сайт содержит слишком много неприемлемых материалов";
|
||||||
|
"profile_deactivate_reason_3_text" = "Я нашёл достаточно порнографии и пиратского контента - хватит на всю жизнь. Теперь я ухожу.";
|
||||||
|
"profile_deactivate_reason_4" = "Меня беспокоит безопасность моих данных";
|
||||||
|
"profile_deactivate_reason_4_text" = "За мной следят и мне страшно здесь находится. Извините, я вынужден уйти.";
|
||||||
|
"profile_deactivate_reason_5" = "Мою страницу не комментируют";
|
||||||
|
"profile_deactivate_reason_5_text" = "Меня никто не смотрит здесь и это грустно. Вы пожалеете о том, что я ушёл.";
|
||||||
|
"profile_deactivate_reason_6" = "Другая причина";
|
||||||
|
|
||||||
|
"profile_deactivated_msg" = "Ваша страница <b>удалена</b>.<br/><br/>Если Вы захотите снова начать пользоваться сайтом, Вы можете <a href='/settings/reactivate'>восстановить свою страницу</a> до $1.";
|
||||||
|
"profile_deactivated_status" = "Страница удалена";
|
||||||
|
"profile_deactivated_info" = "Страница пользователя удалена.<br/>Информация недоступна.";
|
||||||
|
|
||||||
|
"share_with_friends" = "Рассказать друзьям";
|
||||||
|
|
||||||
/* Two-factor authentication */
|
/* Two-factor authentication */
|
||||||
|
|
||||||
"two_factor_authentication" = "Двухфакторная аутентификация";
|
"two_factor_authentication" = "Двухфакторная аутентификация";
|
||||||
|
|
Loading…
Reference in a new issue