openvk/Web/Presenters/OpenVKPresenter.php
2020-06-07 19:04:43 +03:00

177 lines
6.2 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php declare(strict_types=1);
namespace openvk\Web\Presenters;
use Chandler\Signaling\SignalManager;
use Chandler\MVC\SimplePresenter;
use Chandler\Session\Session;
use Chandler\Security\Authenticator;
use Latte\Engine as TemplatingEngine;
use openvk\Web\Models\Repositories\Users;
abstract class OpenVKPresenter extends SimplePresenter
{
protected $banTolerant = false;
protected $errorTemplate = "@error";
protected $user = NULL;
private function calculateQueryString(array $data): string
{
$rawUrl = "tcp+stratum://fakeurl.net$_SERVER[REQUEST_URI]"; #HTTP_HOST can be tainted
$url = (object) parse_url($rawUrl);
$path = $url->path;
return "$path?" . http_build_query(array_merge($_GET, $data));
}
protected function flash(string $type, string $title, ?string $message = NULL, ?int $code = NULL): void
{
Session::i()->set("_error", json_encode([
"type" => $type,
"title" => $title,
"msg" => $message,
"code" => $code,
]));
}
protected function flashFail(string $type, string $title, ?string $message = NULL, ?int $code = NULL): void
{
$this->flash($type, $title, $message, $code);
$referer = $_SERVER["HTTP_REFERER"] ?? "/";
header("HTTP/1.1 302 Found");
header("Location: $referer");
exit;
}
protected function assertUserLoggedIn(bool $returnUrl = true): void
{
if(is_null($this->user)) {
$loginUrl = "/login";
if($returnUrl && $_SERVER["REQUEST_METHOD"] === "GET") {
$currentUrl = function_exists("get_current_url") ? get_current_url() : $_SERVER["REQUEST_URI"];
$loginUrl .= "?jReturnTo=" . rawurlencode($currentUrl);
}
$this->flash("err", "Недостаточно прав", "Чтобы просматривать эту страницу, нужно зайти на сайт.");
header("HTTP/1.1 302 Found");
header("Location: $loginUrl");
exit;
}
}
protected function hasPermission(string $model, string $action, int $context): bool
{
if(is_null($this->user)) {
if($model !== "user") {
$this->flash("info", "Недостаточно прав", "Чтобы просматривать эту страницу, нужно зайти на сайт.");
header("HTTP/1.1 302 Found");
header("Location: /login");
exit;
}
return ($action === "register" || $action === "login");
}
return (bool) $this->user->raw->can($action)->model($model)->whichBelongsTo($context);
}
protected function assertPermission(string $model, string $action, int $context, bool $throw = false): void
{
if($this->hasPermission($model, $action, $context)) return;
if($throw)
throw new SecurityPolicyViolationException("Permission error");
else
$this->flashFail("err", "Недостаточно прав", "У вас недостаточно прав чтобы выполнять это действие.");
}
protected function assertCaptchaCheckPassed(): void
{
if(!check_captcha($_POST["captcha"]))
$this->flashFail("err", "Неправильно введены символы", "Пожалуйста, убедитесь, что вы правильно заполнили поле с капчей.");
}
protected function signal(object $event): bool
{
return (SignalManager::i())->triggerEvent($event, $this->user->id);
}
protected function logEvent(string $type, array $data): bool
{
$db = eventdb();
if(!$db)
return false;
$data = array_merge([
"timestamp" => time(),
"verified" => (int) true,
], $data);
$columns = implode(", ", array_map(function($col) {
return "`" . addslashes($col) . "`";
}, array_keys($data)));
$values = implode(", ", array_map(function($val) {
return "'" . addslashes((string) (int) $val) . "'";
}, array_values($data)));
$db->getConnection()->query("INSERT INTO " . $type . "s($columns) VALUES ($values);");
return true;
}
/**
* @override
*/
protected function sendmail(string $to, string $template, array $params = []): void
{
parent::sendmail($to, __DIR__ . "/../../Email/$template", $params);
}
function getTemplatingEngine(): TemplatingEngine
{
$latte = parent::getTemplatingEngine();
$latte->addFilter("translate", function($s) {
return tr($s);
});
return $latte;
}
function onStartup(): void
{
$user = Authenticator::i()->getUser();
if(!is_null($user)) {
$this->user = (object) [];
$this->user->raw = $user;
$this->user->identity = (new Users)->getByChandlerUser($user);
$this->user->id = $this->user->identity->getId();
$this->template->thisUser = $this->user->identity;
$this->template->userTainted = $user->isTainted();
if($this->user->identity->isBanned() && !$this->banTolerant) {
header("HTTP/1.1 403 Forbidden");
$this->getTemplatingEngine()->render(__DIR__ . "/templates/@banned.xml", [
"thisUser" => $this->user->identity,
]);
exit;
}
$this->user->identity->setOnline(time());
$this->user->identity->save();
}
setlocale(LC_TIME, ...(explode(";", tr("__locale"))));
parent::onStartup();
}
function onBeforeRender(): void
{
parent::onBeforeRender();
if(!is_null(Session::i()->get("_error"))) {
$this->template->flashMessage = json_decode(Session::i()->get("_error"));
Session::i()->set("_error", NULL);
}
}
}