2020-06-07 19:04:43 +03:00
|
|
|
|
<?php declare(strict_types=1);
|
|
|
|
|
namespace openvk\Web\Presenters;
|
|
|
|
|
use openvk\Web\Util\Sms;
|
2020-06-11 23:21:49 +03:00
|
|
|
|
use openvk\Web\Themes\Themepacks;
|
2020-06-07 19:04:43 +03:00
|
|
|
|
use openvk\Web\Models\Entities\Photo;
|
|
|
|
|
use openvk\Web\Models\Repositories\Users;
|
2021-11-10 11:45:06 +03:00
|
|
|
|
use openvk\Web\Models\Repositories\Clubs;
|
2020-06-07 19:04:43 +03:00
|
|
|
|
use openvk\Web\Models\Repositories\Albums;
|
|
|
|
|
use openvk\Web\Models\Repositories\Videos;
|
|
|
|
|
use openvk\Web\Models\Repositories\Notes;
|
2021-10-07 11:47:30 +03:00
|
|
|
|
use openvk\Web\Models\Repositories\Vouchers;
|
2022-02-05 21:09:37 +03:00
|
|
|
|
use openvk\Web\Models\Exceptions\InvalidUserNameException;
|
2021-12-08 21:06:05 +03:00
|
|
|
|
use openvk\Web\Util\Validator;
|
2021-12-19 15:34:33 +03:00
|
|
|
|
use openvk\Web\Models\Entities\Notifications\CoinsTransferNotification;
|
2021-12-02 18:31:32 +03:00
|
|
|
|
use Chandler\Security\Authenticator;
|
|
|
|
|
use lfkeitel\phptotp\{Base32, Totp};
|
2021-12-02 19:12:45 +03:00
|
|
|
|
use chillerlan\QRCode\{QRCode, QROptions};
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
final class UserPresenter extends OpenVKPresenter
|
|
|
|
|
{
|
|
|
|
|
private $users;
|
|
|
|
|
|
|
|
|
|
function __construct(Users $users)
|
|
|
|
|
{
|
|
|
|
|
$this->users = $users;
|
|
|
|
|
|
|
|
|
|
parent::__construct();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderView(int $id): void
|
|
|
|
|
{
|
|
|
|
|
$user = $this->users->get($id);
|
|
|
|
|
if(!$user || $user->isDeleted())
|
|
|
|
|
$this->notFound();
|
|
|
|
|
else {
|
2021-12-28 13:54:20 +03:00
|
|
|
|
/* ActivityPub quirks :DDDD */
|
|
|
|
|
if($this->isActivityPubClient()) {
|
|
|
|
|
$objUser = array(
|
|
|
|
|
"type" => "Person",
|
|
|
|
|
"id" => $user->getFullURL(true),
|
|
|
|
|
"name" => $user->getFullName(),
|
|
|
|
|
"summary" => $user->getDescription(),
|
|
|
|
|
"url" => $user->getFullURL(),
|
2022-02-13 00:37:20 +03:00
|
|
|
|
"preferredUsername" => "id" . $user->getId(), // Костыль, но рабочий
|
2021-12-28 13:54:20 +03:00
|
|
|
|
"inbox" => $user->getFullURL() . "/inbox",
|
|
|
|
|
"outbox" => $user->getFullURL() . "/outbox",
|
2022-01-06 15:57:00 +03:00
|
|
|
|
"followers" => ovk_scheme(true) . $_SERVER['SERVER_NAME'] . "/friends" . $user->getId() . '?act=incoming',
|
|
|
|
|
"following" => ovk_scheme(true) . $_SERVER['SERVER_NAME'] . "/friends" . $user->getId() . '?act=outcoming',
|
2022-02-13 12:49:03 +03:00
|
|
|
|
"endpoints" => ["sharedInbox" => ovk_scheme(true) . $_SERVER['SERVER_NAME'] . "/activitypub/sharedInbox"],
|
|
|
|
|
"publicKey" => [
|
2021-12-28 17:21:26 +03:00
|
|
|
|
"id" => $user->getFullURL(true) . "#main-key",
|
|
|
|
|
"owner" => $user->getFullURL(true),
|
|
|
|
|
"publicKeyPem" => $this->getKey()
|
2022-02-13 12:49:03 +03:00
|
|
|
|
],
|
2021-12-28 13:54:20 +03:00
|
|
|
|
"wall" => ovk_scheme(true) . $_SERVER['SERVER_NAME'] . "/wall" . $user->getId(),
|
|
|
|
|
"firstName" => $user->getFirstName(),
|
|
|
|
|
"lastName" => $user->getLastName(),
|
|
|
|
|
"middleName" => $user->getPseudo(), // Unlike Smithereen, the Middle name in OpenVK is a Nickname
|
2021-12-28 17:56:09 +03:00
|
|
|
|
"vcard:bday" => $user->getBirthday()->format('%Y-%m-%d'),
|
2021-12-28 13:54:20 +03:00
|
|
|
|
"gender" => "http://schema.org#" . $user->isFemale() ? "Male" : "Female",
|
|
|
|
|
"supportsFriendRequests" => true,
|
|
|
|
|
"friends" => ovk_scheme(true) . $_SERVER['SERVER_NAME'] . "/friends" . $user->getId(),
|
2021-12-28 21:00:23 +03:00
|
|
|
|
"groups" => ovk_scheme(true) . $_SERVER['SERVER_NAME'] . "/groups" . $user->getId()
|
2021-12-28 13:54:20 +03:00
|
|
|
|
);
|
2021-12-28 21:00:23 +03:00
|
|
|
|
|
|
|
|
|
if($user->getAvatarUrl(true) !== null) {
|
2021-12-28 21:02:07 +03:00
|
|
|
|
$objUser['icon'] = array(
|
2021-12-28 21:00:23 +03:00
|
|
|
|
"type" => "Image",
|
|
|
|
|
"mediaType" => "image/jpg",
|
|
|
|
|
"url" => $user->getAvatarUrl(true)
|
|
|
|
|
);
|
|
|
|
|
}
|
2022-01-06 15:57:00 +03:00
|
|
|
|
|
|
|
|
|
$objUser['@context'] = $this->getPersonContext();
|
2021-12-28 13:54:20 +03:00
|
|
|
|
|
2022-01-06 15:37:40 +03:00
|
|
|
|
$this->returnJson($objUser, CT_AP);
|
2021-12-28 13:54:20 +03:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-07 19:04:43 +03:00
|
|
|
|
if($user->getShortCode())
|
|
|
|
|
if(parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH) !== "/" . $user->getShortCode())
|
|
|
|
|
$this->redirect("/" . $user->getShortCode(), static::REDIRECT_TEMPORARY_PRESISTENT);
|
|
|
|
|
|
|
|
|
|
$this->template->albums = (new Albums)->getUserAlbums($user);
|
|
|
|
|
$this->template->albumsCount = (new Albums)->getUserAlbumsCount($user);
|
|
|
|
|
$this->template->videos = (new Videos)->getByUser($user, 1, 2);
|
|
|
|
|
$this->template->videosCount = (new Videos)->getUserVideosCount($user);
|
|
|
|
|
$this->template->notes = (new Notes)->getUserNotes($user, 1, 4);
|
|
|
|
|
$this->template->notesCount = (new Notes)->getUserNotesCount($user);
|
2021-11-04 14:45:30 +03:00
|
|
|
|
|
2020-06-07 19:04:43 +03:00
|
|
|
|
$this->template->user = $user;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderFriends(int $id): void
|
|
|
|
|
{
|
|
|
|
|
$this->assertUserLoggedIn();
|
|
|
|
|
|
|
|
|
|
$user = $this->users->get($id);
|
|
|
|
|
$page = abs($this->queryParam("p") ?? 1);
|
|
|
|
|
if(!$user)
|
|
|
|
|
$this->notFound();
|
2021-12-14 16:00:12 +03:00
|
|
|
|
elseif (!$user->getPrivacyPermission('friends.read', $this->user->identity ?? NULL))
|
|
|
|
|
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
2020-06-07 19:04:43 +03:00
|
|
|
|
else
|
|
|
|
|
$this->template->user = $user;
|
|
|
|
|
|
|
|
|
|
$this->template->mode = in_array($this->queryParam("act"), [
|
|
|
|
|
"incoming", "outcoming", "friends"
|
|
|
|
|
]) ? $this->queryParam("act")
|
|
|
|
|
: "friends";
|
|
|
|
|
$this->template->page = $page;
|
|
|
|
|
|
|
|
|
|
if(!is_null($this->user)) {
|
|
|
|
|
if($this->template->mode !== "friends" && $this->user->id !== $id) {
|
|
|
|
|
$name = $user->getFullName();
|
|
|
|
|
$this->flash("err", "Ошибка доступа", "Вы не можете просматривать полный список подписок $name.");
|
|
|
|
|
|
|
|
|
|
$this->redirect("/id$id", static::REDIRECT_TEMPORARY_PRESISTENT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderGroups(int $id): void
|
|
|
|
|
{
|
|
|
|
|
$this->assertUserLoggedIn();
|
|
|
|
|
|
|
|
|
|
$user = $this->users->get($id);
|
2021-12-14 16:00:12 +03:00
|
|
|
|
if(!$user)
|
2020-06-07 19:04:43 +03:00
|
|
|
|
$this->notFound();
|
2021-12-14 16:00:12 +03:00
|
|
|
|
elseif (!$user->getPrivacyPermission('groups.read', $this->user->identity ?? NULL))
|
|
|
|
|
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
|
|
|
|
else {
|
2020-06-07 19:04:43 +03:00
|
|
|
|
$this->template->user = $user;
|
2021-12-24 23:17:05 +03:00
|
|
|
|
$this->template->page = (int) ($this->queryParam("p") ?? 1);
|
2021-11-20 13:47:59 +03:00
|
|
|
|
$this->template->admin = $this->queryParam("act") == "managed";
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-11-10 11:45:06 +03:00
|
|
|
|
|
|
|
|
|
function renderPinClub(): void
|
|
|
|
|
{
|
|
|
|
|
$this->assertUserLoggedIn();
|
|
|
|
|
|
|
|
|
|
$club = (new Clubs)->get((int) $this->queryParam("club"));
|
|
|
|
|
if(!$club)
|
|
|
|
|
$this->notFound();
|
|
|
|
|
|
|
|
|
|
if(!$club->canBeModifiedBy($this->user->identity ?? NULL))
|
2021-12-25 19:03:21 +03:00
|
|
|
|
$this->flashFail("err", "Ошибка доступа", "У вас недостаточно прав, чтобы изменять этот ресурс.", NULL, true);
|
2021-11-10 11:45:06 +03:00
|
|
|
|
|
|
|
|
|
$isClubPinned = $this->user->identity->isClubPinned($club);
|
|
|
|
|
if(!$isClubPinned && $this->user->identity->getPinnedClubCount() > 10)
|
2021-12-25 19:03:21 +03:00
|
|
|
|
$this->flashFail("err", "Ошибка", "Находится в левом меню могут максимум 10 групп", NULL, true);
|
2021-11-10 11:45:06 +03:00
|
|
|
|
|
|
|
|
|
if($club->getOwner()->getId() === $this->user->identity->getId()) {
|
|
|
|
|
$club->setOwner_Club_Pinned(!$isClubPinned);
|
|
|
|
|
$club->save();
|
|
|
|
|
} else {
|
|
|
|
|
$manager = $club->getManager($this->user->identity);
|
|
|
|
|
if(!is_null($manager)) {
|
|
|
|
|
$manager->setClub_Pinned(!$isClubPinned);
|
|
|
|
|
$manager->save();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-25 19:03:21 +03:00
|
|
|
|
$this->returnJson([
|
|
|
|
|
"success" => true
|
|
|
|
|
]);
|
2021-11-10 11:45:06 +03:00
|
|
|
|
}
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
function renderEdit(): void
|
|
|
|
|
{
|
|
|
|
|
$this->assertUserLoggedIn();
|
|
|
|
|
|
|
|
|
|
$id = $this->user->id; #TODO: when ACL'll be done, allow admins to edit users via ?GUID=(chandler guid)
|
|
|
|
|
|
|
|
|
|
if(!$id)
|
|
|
|
|
$this->notFound();
|
2020-06-11 23:21:49 +03:00
|
|
|
|
|
2021-12-13 20:19:53 +03:00
|
|
|
|
$user = $this->users->get($id);
|
|
|
|
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
2021-12-25 20:47:18 +03:00
|
|
|
|
$this->willExecuteWriteAction($_GET['act'] === "status");
|
2021-12-13 20:19:53 +03:00
|
|
|
|
|
|
|
|
|
if($_GET['act'] === "main" || $_GET['act'] == NULL) {
|
2022-02-05 21:09:37 +03:00
|
|
|
|
try {
|
|
|
|
|
$user->setFirst_Name(empty($this->postParam("first_name")) ? $user->getFirstName() : $this->postParam("first_name"));
|
|
|
|
|
$user->setLast_Name(empty($this->postParam("last_name")) ? "" : $this->postParam("last_name"));
|
|
|
|
|
} catch(InvalidUserNameException $ex) {
|
|
|
|
|
$this->flashFail("err", tr("error"), tr("invalid_real_name"));
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-13 20:19:53 +03:00
|
|
|
|
$user->setPseudo(empty($this->postParam("pseudo")) ? NULL : $this->postParam("pseudo"));
|
|
|
|
|
$user->setStatus(empty($this->postParam("status")) ? NULL : $this->postParam("status"));
|
2022-02-07 20:07:03 +03:00
|
|
|
|
$user->setHometown(empty($this->postParam("hometown")) ? NULL : $this->postParam("hometown"));
|
|
|
|
|
|
|
|
|
|
|
2021-12-13 20:19:53 +03:00
|
|
|
|
if (strtotime($this->postParam("birthday")) < time())
|
|
|
|
|
$user->setBirthday(strtotime($this->postParam("birthday")));
|
2021-09-13 19:34:02 +03:00
|
|
|
|
|
2021-12-13 20:19:53 +03:00
|
|
|
|
if ($this->postParam("marialstatus") <= 8 && $this->postParam("marialstatus") >= 0)
|
|
|
|
|
$user->setMarital_Status($this->postParam("marialstatus"));
|
|
|
|
|
|
|
|
|
|
if ($this->postParam("politViews") <= 9 && $this->postParam("politViews") >= 0)
|
|
|
|
|
$user->setPolit_Views($this->postParam("politViews"));
|
|
|
|
|
|
|
|
|
|
if ($this->postParam("gender") <= 1 && $this->postParam("gender") >= 0)
|
|
|
|
|
$user->setSex($this->postParam("gender"));
|
|
|
|
|
|
|
|
|
|
if(!empty($this->postParam("phone")) && $this->postParam("phone") !== $user->getPhone()) {
|
|
|
|
|
if(!OPENVK_ROOT_CONF["openvk"]["credentials"]["smsc"]["enable"])
|
|
|
|
|
$this->flashFail("err", tr("error_segmentation"), "котлетки");
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
2021-12-13 20:19:53 +03:00
|
|
|
|
$code = $user->setPhoneWithVerification($this->postParam("phone"));
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
2021-12-13 20:19:53 +03:00
|
|
|
|
if(!Sms::send($this->postParam("phone"), "OPENVK - Your verification code is: $code"))
|
|
|
|
|
$this->flashFail("err", tr("error_segmentation"), "котлетки: Remote err!");
|
|
|
|
|
}
|
|
|
|
|
} elseif($_GET['act'] === "contacts") {
|
|
|
|
|
if(empty($this->postParam("email_contact")) || Validator::i()->emailValid($this->postParam("email_contact")))
|
|
|
|
|
$user->setEmail_Contact(empty($this->postParam("email_contact")) ? NULL : $this->postParam("email_contact"));
|
|
|
|
|
else
|
|
|
|
|
$this->flashFail("err", tr("invalid_email_address"), tr("invalid_email_address_comment"));
|
2021-12-08 21:06:05 +03:00
|
|
|
|
|
2021-12-13 20:19:53 +03:00
|
|
|
|
$telegram = $this->postParam("telegram");
|
|
|
|
|
if(empty($telegram) || Validator::i()->telegramValid($telegram))
|
|
|
|
|
if(strpos($telegram, "t.me/") === 0)
|
|
|
|
|
$user->setTelegram(empty($telegram) ? NULL : substr($telegram, 5));
|
2021-11-12 19:56:41 +03:00
|
|
|
|
else
|
2021-12-13 20:19:53 +03:00
|
|
|
|
$user->setTelegram(empty($telegram) ? NULL : ltrim($telegram, "@"));
|
|
|
|
|
else
|
|
|
|
|
$this->flashFail("err", tr("invalid_telegram_name"), tr("invalid_telegram_name_comment"));
|
2021-11-25 23:10:53 +03:00
|
|
|
|
|
2021-12-13 20:19:53 +03:00
|
|
|
|
$user->setCity(empty($this->postParam("city")) ? NULL : $this->postParam("city"));
|
|
|
|
|
$user->setAddress(empty($this->postParam("address")) ? NULL : $this->postParam("address"));
|
2022-02-07 20:07:03 +03:00
|
|
|
|
|
2021-12-13 20:19:53 +03:00
|
|
|
|
$website = $this->postParam("website") ?? "";
|
|
|
|
|
if(empty($website))
|
|
|
|
|
$user->setWebsite(NULL);
|
|
|
|
|
else
|
|
|
|
|
$user->setWebsite((!parse_url($website, PHP_URL_SCHEME) ? "https://" : "") . $website);
|
|
|
|
|
} elseif($_GET['act'] === "interests") {
|
|
|
|
|
$user->setInterests(empty($this->postParam("interests")) ? NULL : ovk_proc_strtr($this->postParam("interests"), 300));
|
|
|
|
|
$user->setFav_Music(empty($this->postParam("fav_music")) ? NULL : ovk_proc_strtr($this->postParam("fav_music"), 300));
|
|
|
|
|
$user->setFav_Films(empty($this->postParam("fav_films")) ? NULL : ovk_proc_strtr($this->postParam("fav_films"), 300));
|
|
|
|
|
$user->setFav_Shows(empty($this->postParam("fav_shows")) ? NULL : ovk_proc_strtr($this->postParam("fav_shows"), 300));
|
|
|
|
|
$user->setFav_Books(empty($this->postParam("fav_books")) ? NULL : ovk_proc_strtr($this->postParam("fav_books"), 300));
|
|
|
|
|
$user->setFav_Quote(empty($this->postParam("fav_quote")) ? NULL : ovk_proc_strtr($this->postParam("fav_quote"), 300));
|
|
|
|
|
$user->setAbout(empty($this->postParam("about")) ? NULL : ovk_proc_strtr($this->postParam("about"), 300));
|
|
|
|
|
} elseif($_GET['act'] === "status") {
|
|
|
|
|
if(mb_strlen($this->postParam("status")) > 255) {
|
|
|
|
|
$statusLength = (string) mb_strlen($this->postParam("status"));
|
2021-12-25 20:47:18 +03:00
|
|
|
|
$this->flashFail("err", "Ошибка", "Статус слишком длинный ($statusLength символов вместо 255 символов)", NULL, true);
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
2021-12-13 20:19:53 +03:00
|
|
|
|
|
|
|
|
|
$user->setStatus(empty($this->postParam("status")) ? NULL : $this->postParam("status"));
|
|
|
|
|
$user->save();
|
|
|
|
|
|
2021-12-25 20:47:18 +03:00
|
|
|
|
$this->returnJson([
|
|
|
|
|
"success" => true
|
|
|
|
|
]);
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
|
|
|
|
|
2021-12-13 20:19:53 +03:00
|
|
|
|
try {
|
|
|
|
|
$user->save();
|
|
|
|
|
} catch(\PDOException $ex) {
|
|
|
|
|
if($ex->getCode() == 23000)
|
|
|
|
|
$this->flashFail("err", tr("error"), tr("error_shorturl"));
|
|
|
|
|
else
|
|
|
|
|
throw $ex;
|
|
|
|
|
}
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
2021-12-13 20:19:53 +03:00
|
|
|
|
$this->flash("succ", tr("changes_saved"), tr("changes_saved_comment"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->template->mode = in_array($this->queryParam("act"), [
|
|
|
|
|
"main", "contacts", "interests", "avatar"
|
|
|
|
|
]) ? $this->queryParam("act")
|
|
|
|
|
: "main";
|
|
|
|
|
|
|
|
|
|
$this->template->user = $user;
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderVerifyPhone(): void
|
|
|
|
|
{
|
|
|
|
|
$this->assertUserLoggedIn();
|
2021-01-01 00:18:53 +03:00
|
|
|
|
$this->willExecuteWriteAction();
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
$user = $this->user->identity;
|
|
|
|
|
if(!$user->hasPendingNumberChange())
|
|
|
|
|
exit;
|
|
|
|
|
else
|
|
|
|
|
$this->template->change = $user->getPendingPhoneVerification();
|
|
|
|
|
|
|
|
|
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
|
|
|
|
if(!$user->verifyNumber($this->postParam("code") ?? 0))
|
|
|
|
|
$this->flashFail("err", "Ошибка", "Не удалось подтвердить номер телефона: неверный код.");
|
|
|
|
|
|
2020-08-20 17:05:00 +03:00
|
|
|
|
$this->flash("succ", tr("changes_saved"), tr("changes_saved_comment"));
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderSub(): void
|
|
|
|
|
{
|
|
|
|
|
$this->assertUserLoggedIn();
|
2021-01-01 00:18:53 +03:00
|
|
|
|
$this->willExecuteWriteAction();
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
if($_SERVER["REQUEST_METHOD"] !== "POST") exit("Invalid state");
|
|
|
|
|
|
|
|
|
|
$user = $this->users->get((int) $this->postParam("id"));
|
|
|
|
|
if(!$user) exit("Invalid state");
|
|
|
|
|
|
|
|
|
|
$user->toggleSubscription($this->user->identity);
|
|
|
|
|
|
|
|
|
|
header("HTTP/1.1 302 Found");
|
|
|
|
|
header("Location: /id" . $user->getId());
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderSetAvatar(): void
|
|
|
|
|
{
|
|
|
|
|
$this->assertUserLoggedIn();
|
2021-01-01 00:18:53 +03:00
|
|
|
|
$this->willExecuteWriteAction();
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
|
|
|
|
$photo = new Photo;
|
|
|
|
|
try {
|
|
|
|
|
$photo->setOwner($this->user->id);
|
|
|
|
|
$photo->setDescription("Profile image");
|
|
|
|
|
$photo->setFile($_FILES["blob"]);
|
|
|
|
|
$photo->setCreated(time());
|
|
|
|
|
$photo->save();
|
|
|
|
|
} catch(ISE $ex) {
|
|
|
|
|
$name = $album->getName();
|
2020-08-20 17:05:00 +03:00
|
|
|
|
$this->flashFail("err", tr("error"), tr("error_upload_failed"));
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(new Albums)->getUserAvatarAlbum($this->user->identity)->addPhoto($photo);
|
2020-08-20 17:05:00 +03:00
|
|
|
|
$this->flashFail("succ", tr("photo_saved"), tr("photo_saved_comment"));
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderSettings(): void
|
|
|
|
|
{
|
|
|
|
|
$this->assertUserLoggedIn();
|
|
|
|
|
|
|
|
|
|
$id = $this->user->id; #TODO: when ACL'll be done, allow admins to edit users via ?GUID=(chandler guid)
|
|
|
|
|
|
|
|
|
|
if(!$id)
|
|
|
|
|
$this->notFound();
|
2020-06-11 23:21:49 +03:00
|
|
|
|
|
2021-10-12 12:15:55 +03:00
|
|
|
|
if(in_array($this->queryParam("act"), ["finance", "finance.top-up"]) && !OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"])
|
|
|
|
|
$this->flashFail("err", tr("error"), tr("feature_disabled"));
|
|
|
|
|
|
2020-06-11 23:21:49 +03:00
|
|
|
|
$user = $this->users->get($id);
|
|
|
|
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
2021-01-01 00:18:53 +03:00
|
|
|
|
$this->willExecuteWriteAction();
|
|
|
|
|
|
2020-06-11 23:21:49 +03:00
|
|
|
|
if($_GET['act'] === "main" || $_GET['act'] == NULL) {
|
|
|
|
|
if($this->postParam("old_pass") && $this->postParam("new_pass") && $this->postParam("repeat_pass")) {
|
|
|
|
|
if($this->postParam("new_pass") === $this->postParam("repeat_pass")) {
|
2021-12-02 18:31:32 +03:00
|
|
|
|
if($this->user->identity->is2faEnabled()) {
|
|
|
|
|
$code = $this->postParam("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"));
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-11 23:21:49 +03:00
|
|
|
|
if(!$this->user->identity->getChandlerUser()->updatePassword($this->postParam("new_pass"), $this->postParam("old_pass")))
|
2020-08-20 17:05:00 +03:00
|
|
|
|
$this->flashFail("err", tr("error"), tr("error_old_password"));
|
2020-06-11 23:21:49 +03:00
|
|
|
|
} else {
|
2020-08-20 17:05:00 +03:00
|
|
|
|
$this->flashFail("err", tr("error"), tr("error_new_password"));
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-11 23:21:49 +03:00
|
|
|
|
if(!$user->setShortCode(empty($this->postParam("sc")) ? NULL : $this->postParam("sc")))
|
2020-08-20 17:05:00 +03:00
|
|
|
|
$this->flashFail("err", tr("error"), tr("error_shorturl_incorrect"));
|
2021-10-07 11:47:30 +03:00
|
|
|
|
} else if($_GET['act'] === "privacy") {
|
2020-06-11 23:21:49 +03:00
|
|
|
|
$settings = [
|
|
|
|
|
"page.read",
|
|
|
|
|
"page.info.read",
|
|
|
|
|
"groups.read",
|
|
|
|
|
"photos.read",
|
|
|
|
|
"videos.read",
|
|
|
|
|
"notes.read",
|
|
|
|
|
"friends.read",
|
|
|
|
|
"friends.add",
|
|
|
|
|
"wall.write",
|
2021-12-28 12:40:14 +03:00
|
|
|
|
"messages.write",
|
2020-06-11 23:21:49 +03:00
|
|
|
|
];
|
|
|
|
|
foreach($settings as $setting) {
|
|
|
|
|
$input = $this->postParam(str_replace(".", "_", $setting));
|
|
|
|
|
$user->setPrivacySetting($setting, min(3, abs($input ?? $user->getPrivacySetting($setting))));
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
2021-10-07 11:47:30 +03:00
|
|
|
|
} else if($_GET['act'] === "finance.top-up") {
|
|
|
|
|
$token = $this->postParam("key0") . $this->postParam("key1") . $this->postParam("key2") . $this->postParam("key3");
|
|
|
|
|
$voucher = (new Vouchers)->getByToken($token);
|
|
|
|
|
if(!$voucher)
|
|
|
|
|
$this->flashFail("err", tr("invalid_voucher"), tr("voucher_bad"));
|
|
|
|
|
|
|
|
|
|
$perm = $voucher->willUse($user);
|
|
|
|
|
if(!$perm)
|
|
|
|
|
$this->flashFail("err", tr("invalid_voucher"), tr("voucher_bad"));
|
|
|
|
|
|
|
|
|
|
$user->setCoins($user->getCoins() + $voucher->getCoins());
|
|
|
|
|
$user->setRating($user->getRating() + $voucher->getRating());
|
|
|
|
|
$user->save();
|
|
|
|
|
|
|
|
|
|
$this->flashFail("succ", tr("voucher_good"), tr("voucher_redeemed"));
|
|
|
|
|
} else if($_GET['act'] === "interface") {
|
2020-06-11 23:21:49 +03:00
|
|
|
|
if (isset(Themepacks::i()[$this->postParam("style")]) || $this->postParam("style") === Themepacks::DEFAULT_THEME_ID)
|
2021-11-06 23:43:48 +03:00
|
|
|
|
{
|
2022-01-17 19:01:30 +03:00
|
|
|
|
if ($this->postParam("theme_for_session") != "1") $user->setStyle($this->postParam("style"));
|
2022-01-16 23:15:33 +03:00
|
|
|
|
$this->setSessionTheme($this->postParam("style"));
|
2021-11-06 23:43:48 +03:00
|
|
|
|
}
|
2020-06-07 19:04:43 +03:00
|
|
|
|
|
2020-06-11 23:21:49 +03:00
|
|
|
|
if ($this->postParam("style_avatar") <= 2 && $this->postParam("style_avatar") >= 0)
|
|
|
|
|
$user->setStyle_Avatar((int)$this->postParam("style_avatar"));
|
|
|
|
|
|
|
|
|
|
if (in_array($this->postParam("rating"), [0, 1]))
|
|
|
|
|
$user->setShow_Rating((int) $this->postParam("rating"));
|
2021-01-04 20:33:25 +03:00
|
|
|
|
|
|
|
|
|
if (in_array($this->postParam("microblog"), [0, 1]))
|
|
|
|
|
$user->setMicroblog((int) $this->postParam("microblog"));
|
2021-01-07 19:19:36 +03:00
|
|
|
|
|
|
|
|
|
if(in_array($this->postParam("nsfw"), [0, 1, 2]))
|
|
|
|
|
$user->setNsfwTolerance((int) $this->postParam("nsfw"));
|
2021-10-07 11:47:30 +03:00
|
|
|
|
} else if($_GET['act'] === "lMenu") {
|
2020-06-11 23:21:49 +03:00
|
|
|
|
$settings = [
|
2022-01-03 22:13:53 +03:00
|
|
|
|
"menu_bildoj" => "photos",
|
|
|
|
|
"menu_filmetoj" => "videos",
|
|
|
|
|
"menu_mesagoj" => "messages",
|
|
|
|
|
"menu_notatoj" => "notes",
|
|
|
|
|
"menu_grupoj" => "groups",
|
|
|
|
|
"menu_novajoj" => "news",
|
|
|
|
|
"menu_ligiloj" => "links",
|
|
|
|
|
"menu_standardo" => "poster",
|
2020-06-11 23:21:49 +03:00
|
|
|
|
];
|
|
|
|
|
foreach($settings as $checkbox => $setting)
|
|
|
|
|
$user->setLeftMenuItemStatus($setting, $this->checkbox($checkbox));
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
2020-06-11 23:21:49 +03:00
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
$user->save();
|
|
|
|
|
} catch(\PDOException $ex) {
|
|
|
|
|
if($ex->getCode() == 23000)
|
2020-08-20 17:05:00 +03:00
|
|
|
|
$this->flashFail("err", tr("error"), tr("error_shorturl"));
|
2020-06-11 23:21:49 +03:00
|
|
|
|
else
|
|
|
|
|
throw $ex;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-06 23:43:48 +03:00
|
|
|
|
$this->flash(
|
2020-06-11 23:21:49 +03:00
|
|
|
|
"succ",
|
|
|
|
|
"Изменения сохранены",
|
2021-11-06 23:43:48 +03:00
|
|
|
|
"Новые данные появятся на вашей странице."
|
2020-06-11 23:21:49 +03:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
$this->template->mode = in_array($this->queryParam("act"), [
|
2021-10-07 11:47:30 +03:00
|
|
|
|
"main", "privacy", "finance", "finance.top-up", "interface"
|
2020-06-11 23:21:49 +03:00
|
|
|
|
]) ? $this->queryParam("act")
|
|
|
|
|
: "main";
|
|
|
|
|
$this->template->user = $user;
|
|
|
|
|
$this->template->themes = Themepacks::i()->getThemeList();
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|
2021-12-02 18:31:32 +03:00
|
|
|
|
|
|
|
|
|
function renderTwoFactorAuthSettings(): void
|
|
|
|
|
{
|
|
|
|
|
$this->assertUserLoggedIn();
|
|
|
|
|
|
|
|
|
|
if($this->user->identity->is2faEnabled()) {
|
|
|
|
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
|
|
|
|
if(!Authenticator::verifyHash($this->postParam("password"), $this->user->identity->getChandlerUser()->getRaw()->passwordHash))
|
|
|
|
|
$this->flashFail("err", tr("error"), tr("incorrect_password"));
|
|
|
|
|
|
|
|
|
|
$this->user->identity->generate2faBackupCodes();
|
|
|
|
|
$this->template->_template = "User/TwoFactorAuthCodes.xml";
|
|
|
|
|
$this->template->codes = $this->user->identity->get2faBackupCodes();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->redirect("/settings");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$secret = Base32::encode(Totp::GenerateSecret(16));
|
|
|
|
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
|
|
|
|
$this->willExecuteWriteAction();
|
|
|
|
|
|
|
|
|
|
if(!Authenticator::verifyHash($this->postParam("password"), $this->user->identity->getChandlerUser()->getRaw()->passwordHash))
|
|
|
|
|
$this->flashFail("err", tr("error"), tr("incorrect_password"));
|
|
|
|
|
|
|
|
|
|
$secret = $this->postParam("secret");
|
|
|
|
|
$code = $this->postParam("code");
|
|
|
|
|
|
|
|
|
|
if($code === (new Totp)->GenerateToken(Base32::decode($secret))) {
|
|
|
|
|
$this->user->identity->set2fa_secret($secret);
|
|
|
|
|
$this->user->identity->save();
|
|
|
|
|
|
2021-12-02 19:12:45 +03:00
|
|
|
|
$this->flash("succ", tr("two_factor_authentication_enabled_message"), tr("two_factor_authentication_enabled_message_description"));
|
2021-12-02 18:31:32 +03:00
|
|
|
|
$this->redirect("/settings");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->template->secret = $secret;
|
|
|
|
|
$this->flash("err", tr("error"), tr("incorrect_code"));
|
|
|
|
|
} else {
|
|
|
|
|
$this->template->secret = $secret;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-06 01:31:21 +03:00
|
|
|
|
// Why are these crutch? For some reason, the QR code is not displayed if you just pass the render output to the view
|
|
|
|
|
|
|
|
|
|
$issuer = OPENVK_ROOT_CONF["openvk"]["appearance"]["name"];
|
|
|
|
|
$email = $this->user->identity->getEmail();
|
|
|
|
|
$qrCode = explode("base64,", (new QRCode(new QROptions([
|
2021-12-02 19:12:45 +03:00
|
|
|
|
"imageTransparent" => false
|
2022-01-06 01:31:21 +03:00
|
|
|
|
])))->render("otpauth://totp/$issuer:$email?secret=$secret&issuer=$issuer"));
|
|
|
|
|
|
|
|
|
|
$this->template->qrCodeType = substr($qrCode[0], 5);
|
|
|
|
|
$this->template->qrCodeData = $qrCode[1];
|
2021-12-02 18:31:32 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderDisableTwoFactorAuth(): void
|
|
|
|
|
{
|
|
|
|
|
$this->assertUserLoggedIn();
|
|
|
|
|
$this->willExecuteWriteAction();
|
|
|
|
|
|
|
|
|
|
if(!Authenticator::verifyHash($this->postParam("password"), $this->user->identity->getChandlerUser()->getRaw()->passwordHash))
|
|
|
|
|
$this->flashFail("err", tr("error"), tr("incorrect_password"));
|
|
|
|
|
|
|
|
|
|
$this->user->identity->set2fa_secret(NULL);
|
|
|
|
|
$this->user->identity->save();
|
|
|
|
|
$this->flashFail("succ", tr("information_-1"), tr("two_factor_authentication_disabled_message"));
|
|
|
|
|
}
|
2021-12-19 15:34:33 +03:00
|
|
|
|
|
|
|
|
|
function renderCoinsTransfer(): void
|
|
|
|
|
{
|
|
|
|
|
$this->assertUserLoggedIn();
|
|
|
|
|
$this->willExecuteWriteAction();
|
|
|
|
|
|
|
|
|
|
$receiverAddress = $this->postParam("receiver");
|
|
|
|
|
$value = (int) $this->postParam("value");
|
|
|
|
|
$message = $this->postParam("message");
|
|
|
|
|
|
|
|
|
|
if(!$receiverAddress || !$value)
|
|
|
|
|
$this->flashFail("err", tr("failed_to_tranfer_points"), tr("not_all_information_has_been_entered"));
|
|
|
|
|
|
|
|
|
|
if($value < 0)
|
|
|
|
|
$this->flashFail("err", tr("failed_to_tranfer_points"), tr("negative_transfer_value"));
|
|
|
|
|
|
|
|
|
|
if(iconv_strlen($message) > 255)
|
|
|
|
|
$this->flashFail("err", tr("failed_to_tranfer_points"), tr("message_is_too_long"));
|
|
|
|
|
|
|
|
|
|
$receiver = $this->users->getByAddress($receiverAddress);
|
|
|
|
|
if(!$receiver)
|
|
|
|
|
$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"));
|
|
|
|
|
|
|
|
|
|
if($this->user->id !== $receiver->getId()) {
|
|
|
|
|
$this->user->identity->setCoins($this->user->identity->getCoins() - $value);
|
|
|
|
|
$this->user->identity->save();
|
|
|
|
|
|
|
|
|
|
$receiver->setCoins($receiver->getCoins() + $value);
|
|
|
|
|
$receiver->save();
|
|
|
|
|
|
|
|
|
|
(new CoinsTransferNotification($receiver, $this->user->identity, $value, $message))->emit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->flashFail("succ", tr("information_-1"), tr("points_transfer_successful", tr("points_amount", $value), $receiver->getURL(), htmlentities($receiver->getCanonicalName())));
|
|
|
|
|
}
|
2020-06-07 19:04:43 +03:00
|
|
|
|
}
|