aboutsummaryrefslogtreecommitdiff
path: root/handler/AdminHandler.php
diff options
context:
space:
mode:
authorEvgeny Zinoviev <me@ch1p.io>2024-01-31 06:11:00 +0300
committerEvgeny Zinoviev <me@ch1p.io>2024-01-31 20:45:40 +0300
commitc0dc531ebefd8912819f3b6c8bda1fed3c7e750c (patch)
tree2c75aa9df182260aef09faf4befd81a4c2b9c5e2 /handler/AdminHandler.php
parent48d688cdf7f9eae1bf11b8a6f0e5b98687c604cb (diff)
make it simple, but not simpler
Diffstat (limited to 'handler/AdminHandler.php')
-rw-r--r--handler/AdminHandler.php470
1 files changed, 470 insertions, 0 deletions
diff --git a/handler/AdminHandler.php b/handler/AdminHandler.php
new file mode 100644
index 0000000..f90fc42
--- /dev/null
+++ b/handler/AdminHandler.php
@@ -0,0 +1,470 @@
+<?php
+
+class AdminHandler extends request_handler {
+
+ function __construct() {
+ parent::__construct();
+ add_static('css/admin.css', 'js/admin.js');
+ }
+
+ function before_dispatch(string $http_method, string $action) {
+ if ($action != 'login' && !is_admin())
+ forbidden();
+ }
+
+ function GET_index() {
+ set_title('$admin_title');
+ render('admin/index');
+ }
+
+ function GET_login() {
+ if (is_admin())
+ redirect('/admin/');
+ set_title('$admin_title');
+ render('admin/login');
+ }
+
+ function POST_login() {
+ csrf_check('adminlogin');
+ $password = $_POST['password'] ?? '';
+ $valid = admin_check_password($password);
+ if ($valid) {
+ admin_log_auth();
+ admin_set_cookie();
+ redirect('/admin/');
+ }
+ forbidden();
+ }
+
+ function GET_logout() {
+ csrf_check('logout');
+ admin_unset_cookie();
+ redirect('/admin/login/', HTTPCode::Found);
+ }
+
+ function GET_uploads() {
+ list($error) = input('error');
+ $uploads = uploads::getAllUploads();
+
+ set_title('$blog_upload');
+ render('admin/uploads',
+ error: $error,
+ uploads: $uploads);
+ }
+
+ function POST_uploads() {
+ csrf_check('addupl');
+
+ list($custom_name, $note) = input('name, note');
+
+ if (!isset($_FILES['files']))
+ redirect('/uploads/?error='.urlencode('no file'));
+
+ $files = [];
+ for ($i = 0; $i < count($_FILES['files']['name']); $i++) {
+ $files[] = [
+ 'name' => $_FILES['files']['name'][$i],
+ 'type' => $_FILES['files']['type'][$i],
+ 'tmp_name' => $_FILES['files']['tmp_name'][$i],
+ 'error' => $_FILES['files']['error'][$i],
+ 'size' => $_FILES['files']['size'][$i],
+ ];
+ }
+
+ if (count($files) > 1) {
+ $note = '';
+ $custom_name = '';
+ }
+
+ foreach ($files as $f) {
+ if ($f['error'])
+ redirect('/uploads/?error='.urlencode('error code '.$f['error']));
+
+ if (!$f['size'])
+ redirect('/uploads/?error='.urlencode('received empty file'));
+
+ $ext = extension($f['name']);
+ if (!uploads::isExtensionAllowed($ext))
+ redirect('/uploads/?error='.urlencode('extension not allowed'));
+
+ $upload_id = uploads::add(
+ $f['tmp_name'],
+ $custom_name ?: $f['name'],
+ $note);
+
+ if (!$upload_id)
+ redirect('/uploads/?error='.urlencode('failed to create upload'));
+ }
+
+ redirect('/uploads/');
+ }
+
+ function GET_upload_delete() {
+ list($id) = input('i:id');
+ $upload = uploads::get($id);
+ if (!$upload)
+ redirect('/uploads/?error='.urlencode('upload not found'));
+ csrf_check('delupl'.$id);
+ uploads::delete($id);
+ redirect('/uploads/');
+ }
+
+ function POST_upload_edit_note() {
+ list($id, $note) = input('i:id, note');
+
+ $upload = uploads::get($id);
+ if (!$upload)
+ redirect('/uploads/?error='.urlencode('upload not found'));
+
+ csrf_check('editupl'.$id);
+
+ $upload->setNote($note);
+ redirect('/uploads/');
+ }
+
+ function POST_ajax_md_preview() {
+ list($md, $title, $use_image_previews) = input('md, title, b:use_image_previews');
+ $html = markup::markdownToHtml($md, $use_image_previews);
+ $ctx = new SkinContext('\\skin\\admin');
+ $html = $ctx->markdownPreview(
+ unsafe_html: $html,
+ title: $title
+ );
+ ajax_ok(['html' => $html]);
+ }
+
+ function GET_page_add() {
+ list($name) = input('short_name');
+ $page = pages::getByName($name);
+ if ($page)
+ not_found();
+ return $this->_get_pageAdd($name);
+ }
+
+ function POST_page_add() {
+ csrf_check('addpage');
+
+ list($name, $text, $title) = input('short_name, text, title');
+ $page = pages::getByName($name);
+ if ($page)
+ not_found();
+
+ $error_code = null;
+
+ if (!$title) {
+ $error_code = 'no_title';
+ } else if (!$text) {
+ $error_code = 'no_text';
+ }
+
+ if ($error_code) {
+ return $this->_get_pageAdd(
+ name: $name,
+ title: $title,
+ text: $text,
+ error_code: $error_code
+ );
+ }
+
+ if (!pages::add([
+ 'short_name' => $name,
+ 'title' => $title,
+ 'md' => $text
+ ])) {
+ return $this->_get_pageAdd(
+ name: $name,
+ title: $title,
+ text: $text,
+ error_code: 'db_err'
+ );
+ }
+
+ $page = pages::getByName($name);
+ redirect($page->getUrl());
+ }
+
+ function GET_post_add() {
+ return $this->_get_postAdd();
+ }
+
+ function POST_post_add() {
+ csrf_check('addpost');
+
+ list($text, $title, $tags, $visible, $short_name)
+ = input('text, title, tags, b:visible, short_name');
+ $tags = tags::splitString($tags);
+
+ $error_code = null;
+ if (!$title) {
+ $error_code = 'no_title';
+ } else if (!$text) {
+ $error_code = 'no_text';
+ } else if (empty($tags)) {
+ $error_code = 'no_tags';
+ } else if (empty($short_name)) {
+ $error_code = 'no_short_name';
+ }
+
+ if ($error_code)
+ return $this->_get_postAdd(
+ title: $title,
+ text: $text,
+ tags: $tags,
+ short_name: $short_name,
+ error_code: $error_code
+ );
+
+ $id = posts::add([
+ 'title' => $title,
+ 'md' => $text,
+ 'visible' => (int)$visible,
+ 'short_name' => $short_name,
+ ]);
+
+ if (!$id)
+ $this->_get_postAdd(
+ title: $title,
+ text: $text,
+ tags: $tags,
+ short_name: $short_name,
+ error_code: 'db_err'
+ );
+
+ // set tags
+ $post = posts::get($id);
+ $tag_ids = array_values(tags::getTags($tags));
+ $post->setTagIds($tag_ids);
+
+ redirect($post->getUrl());
+ }
+
+ function GET_auto_delete() {
+ list($name) = input('short_name');
+
+ $post = posts::getByName($name);
+ if ($post) {
+ csrf_check('delpost'.$post->id);
+ posts::delete($post);
+ redirect('/');
+ }
+
+ $page = pages::getByName($name);
+ if ($page) {
+ csrf_check('delpage'.$page->shortName);
+ pages::delete($page);
+ redirect('/');
+ }
+
+ not_found();
+ }
+
+ function GET_auto_edit() {
+ list($short_name, $saved) = input('short_name, b:saved');
+
+ $post = posts::getByName($short_name);
+ if ($post) {
+ $tags = $post->getTags();
+ return $this->_get_postEdit($post,
+ title: $post->title,
+ text: $post->md,
+ tags: $post->getTags(),
+ visible: $post->visible,
+ toc: $post->toc,
+ short_name: $post->shortName,
+ saved: $saved,
+ );
+ }
+
+ $page = pages::getByName($short_name);
+ if ($page) {
+ return $this->_get_pageEdit($page,
+ title: $page->title,
+ text: $page->md,
+ saved: $saved,
+ visible: $page->visible,
+ );
+ }
+
+ not_found();
+ }
+
+ function POST_auto_edit() {
+ list($short_name) = input('short_name');
+
+ $post = posts::getByName($short_name);
+ if ($post) {
+ csrf_check('editpost'.$post->id);
+
+ list($text, $title, $tags, $visible, $toc, $short_name)
+ = input('text, title, tags, b:visible, b:toc, new_short_name');
+
+ $tags = tags::splitString($tags);
+ $error_code = null;
+
+ if (!$title) {
+ $error_code = 'no_title';
+ } else if (!$text) {
+ $error_code = 'no_text';
+ } else if (empty($tags)) {
+ $error_code = 'no_tags';
+ } else if (empty($short_name)) {
+ $error_code = 'no_short_name';
+ }
+
+ if ($error_code)
+ $this->_get_postEdit($post,
+ title: $title,
+ text: $text,
+ tags: $tags,
+ visible: $visible,
+ toc: $toc,
+ short_name: $short_name,
+ error_code: $error_code
+ );
+
+ $post->edit([
+ 'title' => $title,
+ 'md' => $text,
+ 'visible' => (int)$visible,
+ 'toc' => (int)$toc,
+ 'short_name' => $short_name
+ ]);
+ $tag_ids = array_values(tags::getTags($tags));
+ $post->setTagIds($tag_ids);
+
+ redirect($post->getUrl().'edit/?saved=1');
+ }
+
+ $page = pages::getByName($short_name);
+ if ($page) {
+ csrf_check('editpage'.$page->shortName);
+
+ list($text, $title, $visible, $short_name)
+ = input('text, title, b:visible, new_short_name');
+
+ $text = trim($text);
+ $title = trim($title);
+ $error_code = null;
+
+ if (!$title) {
+ $error_code = 'no_title';
+ } else if (!$text) {
+ $error_code = 'no_text';
+ } else if (!$short_name) {
+ $error_code = 'no_short_name';
+ }
+
+ if ($error_code) {
+ return $this->_get_pageEdit($page,
+ title: $title,
+ text: $text,
+ visible: $visible,
+ error_code: $error_code
+ );
+ }
+
+ $page->edit([
+ 'title' => $title,
+ 'md' => $text,
+ 'visible' => (int)$visible,
+ 'short_name' => $short_name,
+ ]);
+
+ redirect($page->getUrl().'edit/?saved=1');
+ }
+
+ not_found();
+ }
+
+ protected static function setWidePage() {
+ set_skin_opts([
+ 'full_width' => true,
+ 'no_footer' => true
+ ]);
+ }
+
+ protected function _get_pageAdd(
+ string $name,
+ string $title = '',
+ string $text = '',
+ ?string $error_code = null
+ ) {
+ add_skin_strings_re('/^(err_)?pages_/');
+ set_title(lang('pages_create_title', $name));
+ static::setWidePage();
+ render('admin/pageForm',
+ short_name: $name,
+ title: $title,
+ text: $text,
+ error_code: $error_code);
+ }
+
+ protected function _get_pageEdit(
+ Page $page,
+ string $title = '',
+ string $text = '',
+ bool $saved = false,
+ bool $visible = false,
+ ?string $error_code = null
+ ) {
+ add_skin_strings_re('/^(err_)?pages_/');
+ set_title(lang('pages_page_edit_title', $page->shortName.'.html'));
+ static::setWidePage();
+ render('admin/pageForm',
+ is_edit: true,
+ short_name: $page->shortName,
+ title: $title,
+ text: $text,
+ visible: $visible,
+ saved: $saved,
+ error_code: $error_code);
+ }
+
+ protected function _get_postEdit(
+ Post $post,
+ string $title = '',
+ string $text = '',
+ ?array $tags = null,
+ bool $visible = false,
+ bool $toc = false,
+ string $short_name = '',
+ ?string $error_code = null,
+ bool $saved = false,
+ ) {
+ add_skin_strings_re('/^(err_)?blog_/');
+ set_title(lang('blog_post_edit_title', $post->title));
+ static::setWidePage();
+ render('admin/postForm',
+ is_edit: true,
+ post_id: $post->id,
+ post_url: $post->getUrl(),
+ title: $title,
+ text: $text,
+ tags: $tags ? implode(', ', $tags) : '',
+ visible: $visible,
+ toc: $toc,
+ saved: $saved,
+ short_name: $short_name,
+ error_code: $error_code
+ );
+ }
+
+ protected function _get_postAdd(
+ string $title = '',
+ string $text = '',
+ ?array $tags = null,
+ string $short_name = '',
+ ?string $error_code = null
+ ) {
+ add_skin_strings_re('/^(err_)?blog_/');
+ set_title('$blog_write');
+ static::setWidePage();
+ render('admin/postForm',
+ title: $title,
+ text: $text,
+ tags: $tags ? implode(', ', $tags) : '',
+ short_name: $short_name,
+ error_code: $error_code);
+ }
+
+} \ No newline at end of file