diff --git a/README.md b/README.md index d91f3d4c..56211045 100644 --- a/README.md +++ b/README.md @@ -31,17 +31,23 @@ If you want, you can add your instance to the list above so that people can regi ### Installation procedure 1. Install PHP 7.4, web-server, Composer, Node.js, Yarn and [Chandler](https://github.com/openvk/chandler) - * PHP 8 has **not** yet been tested, so you should not expect it to work. + +* PHP 8 has **not** yet been tested, so you should not expect it to work. + 2. Install [commitcaptcha](https://github.com/openvk/commitcaptcha) and OpenVK as Chandler extensions like this: -``` + +```bash git clone https://github.com/openvk/openvk /path/to/chandler/extensions/available/openvk git clone https://github.com/openvk/commitcaptcha /path/to/chandler/extensions/available/commitcaptcha ``` + 3. And enable them: -``` + +```bash ln -s /path/to/chandler/extensions/available/commitcaptcha /path/to/chandler/extensions/enabled/ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions/enabled/ ``` + 4. Import `install/init-static-db.sql` to **same database** you installed Chandler to 5. Import `install/init-event-db.sql` to **separate database** 6. Copy `openvk-example.yml` to `openvk.yml` and change options @@ -50,11 +56,12 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions 9. Set `openvk` as your root app in `chandler.yml` Once you are done, you can login as a system administrator on the network itself (no registration required): + * **Login**: `admin@localhost.localdomain6` * **Password**: `admin` - * It is recommended to change the password before using the built-in account. + * It is recommended to change the password before using the built-in account. -Full example installation instruction for CentOS 8 is also available [here](docs/centos8_install.md). +Full example installation instruction for CentOS 8 is also available [here](https://docs.openvk.su/openvk_engine/centos8_installation/). ### If my website uses OpenVK, should I publish it's sources? @@ -65,6 +72,7 @@ You also not required to publish source texts of your themepacks and plugins. ## Where can I get assistance? You may reach out to us via: + * [Bug-tracker](https://github.com/openvk/openvk/projects/1) * [Ticketing system](https://openvk.su/support?act=new) * Telegram chat: Go to [our channel](https://t.me/openvkch) and open discussion in our channel menu. diff --git a/README_RU.md b/README_RU.md index a87dd1d5..2ed13a7b 100644 --- a/README_RU.md +++ b/README_RU.md @@ -31,17 +31,23 @@ _[English](README.md)_ ### Процедура установки 1. Установите PHP 7.4, веб-сервер, Composer, Node.js, Yarn и [Chandler](https://github.com/openvk/chandler) - * PHP 8 еще **не** тестировался, поэтому не стоит ожидать, что он будет работать. + +* PHP 8 еще **не** тестировался, поэтому не стоит ожидать, что он будет работать. + 2. Установите [commitcaptcha](https://github.com/openvk/commitcaptcha) и OpenVK в качестве расширений Chandler следующим образом: -``` + +```bash git clone https://github.com/openvk/openvk /path/to/chandler/extensions/available/openvk git clone https://github.com/openvk/commitcaptcha /path/to/chandler/extensions/available/commitcaptcha ``` + 3. И включите их: -``` + +```bash ln -s /path/to/chandler/extensions/available/commitcaptcha /path/to/chandler/extensions/enabled/ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions/enabled/ ``` + 4. Импортируйте `install/init-static-db.sql` в **ту же базу данных**, в которую вы установили Chandler 5. Импортируйте `install/init-event-db.sql` в **отдельную базу данных** 6. Скопируйте `openvk-example.yml` в `openvk.yml` и измените параметры @@ -50,11 +56,12 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions 9. Установите `openvk` в качестве корневого приложения в файле `chandler.yml` После этого вы можете войти как системный администратор в саму сеть (регистрация не требуется): + * **Логин**: `admin@localhost.localdomain6` * **Пароль**: `admin` - * Перед использованием встроенной учетной записи рекомендуется сменить пароль. + * Перед использованием встроенной учетной записи рекомендуется сменить пароль. -Полный пример инструкции по установке CentOS 8 также доступен [здесь](docs/centos8_install.md). +Полный пример инструкции по установке CentOS 8 также доступен [здесь](https://docs.openvk.su/openvk_engine/centos8_installation/). ### Если мой сайт использует OpenVK, должен ли я публиковать его исходные тексты? @@ -65,6 +72,7 @@ ln -s /path/to/chandler/extensions/available/openvk /path/to/chandler/extensions ## Где я могу получить помощь? Вы можете связаться с нами через: + * [Баг-трекер](https://github.com/openvk/openvk/projects/1) * [Помощь в OVK](https://openvk.su/support?act=new) * Telegram-чат: Перейдите на [наш канал](https://t.me/openvkch) и откройте обсуждение в меню нашего канала. diff --git a/Web/Models/Entities/Note.php b/Web/Models/Entities/Note.php index e15a838c..b33f1238 100644 --- a/Web/Models/Entities/Note.php +++ b/Web/Models/Entities/Note.php @@ -94,4 +94,9 @@ class Note extends Postable return $cached; } + + function getSource(): string + { + return $this->getRecord()->source; + } } diff --git a/Web/Models/Entities/TicketComment.php b/Web/Models/Entities/TicketComment.php index 0801c39f..a9fb684a 100644 --- a/Web/Models/Entities/TicketComment.php +++ b/Web/Models/Entities/TicketComment.php @@ -127,5 +127,10 @@ class TicketComment extends RowModel return $mark === 1; } + function isDeleted(): bool + { + return (bool) $this->getRecord()->deleted; + } + use Traits\TRichText; } diff --git a/Web/Models/Repositories/TicketComments.php b/Web/Models/Repositories/TicketComments.php index 94360aec..4d3c5316 100644 --- a/Web/Models/Repositories/TicketComments.php +++ b/Web/Models/Repositories/TicketComments.php @@ -4,7 +4,6 @@ namespace openvk\Web\Models\Repositories; // use openvk\Web\Models\Entities\User; // use openvk\Web\Models\Repositories\Users; use openvk\Web\Models\Entities\TicketComment; -use Nette\Database\Table\ActiveRow; use Chandler\Database\DatabaseConnection; class TicketComments @@ -20,7 +19,7 @@ class TicketComments function getCommentsById(int $ticket_id): \Traversable { - foreach($this->comments->where(['ticket_id' => $ticket_id]) as $comment) yield new TicketComment($comment); + foreach($this->comments->where(['ticket_id' => $ticket_id, 'deleted' => 0]) as $comment) yield new TicketComment($comment); } // private function toTicket(?ActiveRow $ar): ?Ticket diff --git a/Web/Models/Repositories/Users.php b/Web/Models/Repositories/Users.php index e99611b2..e0893a6d 100644 --- a/Web/Models/Repositories/Users.php +++ b/Web/Models/Repositories/Users.php @@ -39,7 +39,7 @@ class Users function find(string $query): Util\EntityStream { $query = "%$query%"; - $result = $this->users->where("CONCAT_WS(' ', first_name, last_name) LIKE ?", $query); + $result = $this->users->where("CONCAT_WS(' ', first_name, last_name) LIKE ?", $query)->where("deleted", 0); return new Util\EntityStream("User", $result); } diff --git a/Web/Presenters/AboutPresenter.php b/Web/Presenters/AboutPresenter.php index f7131772..bd84efbc 100644 --- a/Web/Presenters/AboutPresenter.php +++ b/Web/Presenters/AboutPresenter.php @@ -63,7 +63,7 @@ final class AboutPresenter extends OpenVKPresenter $this->template->usersStats = (new Users)->getStatistics(); $this->template->clubsCount = (new Clubs)->getCount(); $this->template->postsCount = (new Posts)->getCount(); - $this->template->popularClubs = (new Clubs)->getPopularClubs(); + $this->template->popularClubs = iterator_to_array((new Clubs)->getPopularClubs()); $this->template->admins = iterator_to_array((new Users)->getInstanceAdmins()); } diff --git a/Web/Presenters/AuthPresenter.php b/Web/Presenters/AuthPresenter.php index 0d43315b..9123f12a 100644 --- a/Web/Presenters/AuthPresenter.php +++ b/Web/Presenters/AuthPresenter.php @@ -126,6 +126,10 @@ final class AuthPresenter extends OpenVKPresenter if(!$this->authenticator->verifyCredentials($user->id, $this->postParam("password"))) $this->flashFail("err", tr("login_failed"), tr("invalid_username_or_password")); + $ovkUser = new User($user->related("profiles.user")->fetch()); + if($ovkUser->isDeleted()) + $this->flashFail("err", tr("login_failed"), tr("invalid_username_or_password")); + $secret = $user->related("profiles.user")->fetch()["2fa_secret"]; $code = $this->postParam("code"); if(!is_null($secret)) { @@ -136,7 +140,6 @@ final class AuthPresenter extends OpenVKPresenter if(is_null($code)) return; - $ovkUser = new User($user->related("profiles.user")->fetch()); if(!($code === (new Totp)->GenerateToken(Base32::decode($secret)) || $ovkUser->use2faBackupCode((int) $code))) { $this->flash("err", tr("login_failed"), tr("incorrect_2fa_code")); return; @@ -229,7 +232,7 @@ final class AuthPresenter extends OpenVKPresenter } $user = $this->users->getByChandlerUser(new ChandlerUser($uRow)); - if(!$user) + if(!$user || $user->isDeleted()) $this->flashFail("err", tr("error"), tr("password_reset_error")); $request = $this->restores->getLatestByUser($user); diff --git a/Web/Presenters/GroupPresenter.php b/Web/Presenters/GroupPresenter.php index 4ad9f849..65d3640f 100644 --- a/Web/Presenters/GroupPresenter.php +++ b/Web/Presenters/GroupPresenter.php @@ -207,6 +207,7 @@ final class GroupPresenter extends OpenVKPresenter $club->setShortcode(empty($this->postParam("shortcode")) ? NULL : $this->postParam("shortcode")); $club->setWall(empty($this->postParam("wall")) ? 0 : 1); $club->setAdministrators_List_Display(empty($this->postParam("administrators_list_display")) ? 0 : $this->postParam("administrators_list_display")); + $club->setEveryone_Can_Create_Topics(empty($this->postParam("everyone_can_create_topics")) ? 0 : 1); $club->setDisplay_Topics_Above_Wall(empty($this->postParam("display_topics_above_wall")) ? 0 : 1); $club->setHide_From_Global_Feed(empty($this->postParam("hide_from_global_feed")) ? 0 : 1); diff --git a/Web/Presenters/NotesPresenter.php b/Web/Presenters/NotesPresenter.php index 443a484a..d88c6365 100644 --- a/Web/Presenters/NotesPresenter.php +++ b/Web/Presenters/NotesPresenter.php @@ -67,6 +67,35 @@ final class NotesPresenter extends OpenVKPresenter $note->setCreated(time()); $note->setName($this->postParam("name")); $note->setSource($this->postParam("html")); + $note->setEdited(time()); + $note->save(); + + $this->redirect("/note" . $this->user->id . "_" . $note->getVirtualId()); + } + } + + function renderEdit(int $owner, int $note_id): void + { + $this->assertUserLoggedIn(); + $this->willExecuteWriteAction(); + + $note = $this->notes->getNoteById($owner, $note_id); + + if(!$note || $note->getOwner()->getId() !== $owner || $note->isDeleted()) + $this->notFound(); + if(is_null($this->user) || !$note->canBeModifiedBy($this->user->identity)) + $this->flashFail("err", "Ошибка доступа", "Недостаточно прав для модификации данного ресурса."); + $this->template->note = $note; + + if($_SERVER["REQUEST_METHOD"] === "POST") { + if(empty($this->postParam("name"))) { + $this->flashFail("err", tr("error"), tr("error_segmentation")); + } + + $note->setName($this->postParam("name")); + $note->setSource($this->postParam("html")); + $note->setCached_Content(NULL); + $note->setEdited(time()); $note->save(); $this->redirect("/note" . $this->user->id . "_" . $note->getVirtualId()); diff --git a/Web/Presenters/OpenVKPresenter.php b/Web/Presenters/OpenVKPresenter.php index c232cd91..51840c3d 100755 --- a/Web/Presenters/OpenVKPresenter.php +++ b/Web/Presenters/OpenVKPresenter.php @@ -210,12 +210,20 @@ abstract class OpenVKPresenter extends SimplePresenter $this->user->id = $this->user->identity->getId(); $this->template->thisUser = $this->user->identity; $this->template->userTainted = $user->isTainted(); + + if($this->user->identity->isDeleted()) { + 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) { header("HTTP/1.1 403 Forbidden"); $this->getTemplatingEngine()->render(__DIR__ . "/templates/@banned.xml", [ "thisUser" => $this->user->identity, "csrfToken" => $GLOBALS["csrfToken"], + "isTimezoned" => Session::i()->get("_timezoneOffset"), ]); exit; } diff --git a/Web/Presenters/SupportPresenter.php b/Web/Presenters/SupportPresenter.php index 8a48a0db..a96ac465 100644 --- a/Web/Presenters/SupportPresenter.php +++ b/Web/Presenters/SupportPresenter.php @@ -226,6 +226,29 @@ final class SupportPresenter extends OpenVKPresenter $this->template->content = $parser->text($content); } + function renderDeleteComment(int $id): void + { + $this->assertUserLoggedIn(); + $this->assertNoCSRF(); + + $comment = $this->comments->get($id); + if(is_null($comment)) + $this->notFound(); + + $ticket = $comment->getTicket(); + + if($ticket->isDeleted()) + $this->notFound(); + + if(!($ticket->getUserId() === $this->user->id && $comment->getUType() === 0)) + $this->assertPermission("openvk\Web\Models\Entities\TicketReply", "write", 0); + + $this->willExecuteWriteAction(); + $comment->delete(); + + $this->flashFail("succ", tr("ticket_changed"), tr("ticket_changed_comment")); + } + function renderRateAnswer(int $id, int $mark): void { $this->willExecuteWriteAction(); diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml index d410bc84..4834aed8 100644 --- a/Web/Presenters/templates/@layout.xml +++ b/Web/Presenters/templates/@layout.xml @@ -190,7 +190,11 @@ {else} - {_menu_support} + {_menu_support} + {if $ticketAnsweredCount > 0} + ({$ticketAnsweredCount}) + {/if} + {_menu_logout} {/if} {else} diff --git a/Web/Presenters/templates/About/AboutInstance.xml b/Web/Presenters/templates/About/AboutInstance.xml index 61bd9d2f..af63d9ee 100644 --- a/Web/Presenters/templates/About/AboutInstance.xml +++ b/Web/Presenters/templates/About/AboutInstance.xml @@ -42,15 +42,17 @@ -