From aff227ac31ff09c15300630dc2d5fdf07c0f3a66 Mon Sep 17 00:00:00 2001 From: discomrade <83621080+discomrade@users.noreply.github.com> Date: Wed, 21 Feb 2024 11:13:09 +0000 Subject: [PATCH] [core] fix permissions in forum and notes This includes preventing silent failures when permission is denied, preventing unauthorized users from being shown the note edit form, patching typos, and extracting NOTES_REQUEST to its own permission --- core/permissions.php | 1 + core/userclass.php | 1 + ext/forum/main.php | 55 +++++++++++++++---------------------- ext/notes/main.php | 64 ++++++++++++++++++-------------------------- ext/notes/script.js | 11 +++++--- ext/notes/theme.php | 3 ++- 6 files changed, 59 insertions(+), 76 deletions(-) diff --git a/core/permissions.php b/core/permissions.php index 6f507530..a4123099 100644 --- a/core/permissions.php +++ b/core/permissions.php @@ -125,6 +125,7 @@ abstract class Permissions public const NOTES_ADMIN = "notes_admin"; public const NOTES_CREATE = "notes_create"; public const NOTES_EDIT = "notes_edit"; + public const NOTES_REQUEST = "notes_request"; public const POOLS_ADMIN = "pools_admin"; public const POOLS_CREATE = "pools_create"; diff --git a/core/userclass.php b/core/userclass.php index 1f9aec85..cf700d80 100644 --- a/core/userclass.php +++ b/core/userclass.php @@ -119,6 +119,7 @@ new UserClass("user", "base", [ Permissions::FORUM_CREATE => true, Permissions::NOTES_CREATE => true, Permissions::NOTES_EDIT => true, + Permissions::NOTES_REQUEST => true, Permissions::POOLS_CREATE => true, Permissions::POOLS_UPDATE => true, ]); diff --git a/ext/forum/main.php b/ext/forum/main.php index 53d3eb44..6e072f5e 100644 --- a/ext/forum/main.php +++ b/ext/forum/main.php @@ -102,7 +102,7 @@ class Forum extends Extension if ($event->page_matches("forum/index", paged: true)) { $pageNumber = $event->get_iarg('page_num', 1) - 1; $this->show_last_threads($page, $pageNumber, $user->can(Permissions::FORUM_ADMIN)); - if (!$user->can(Permissions::FORUM_CREATE)) { + if ($user->can(Permissions::FORUM_CREATE)) { $this->theme->display_new_thread_composer($page); } } @@ -119,62 +119,51 @@ class Forum extends Extension if ($user->can(Permissions::FORUM_ADMIN)) { $this->theme->add_actions_block($page, $threadID); } - if (!$user->can(Permissions::FORUM_CREATE)) { + if ($user->can(Permissions::FORUM_CREATE)) { $this->theme->display_new_post_composer($page, $threadID); } } - if ($event->page_matches("forum/new")) { + if ($event->page_matches("forum/new", permission: Permissions::FORUM_CREATE)) { $this->theme->display_new_thread_composer($page); } - if ($event->page_matches("forum/create")) { - $redirectTo = "forum/index"; - if (!$user->can(Permissions::FORUM_CREATE)) { - $errors = $this->sanity_check_new_thread(); + if ($event->page_matches("forum/create", permission: Permissions::FORUM_CREATE)) { + $errors = $this->sanity_check_new_thread(); - if (count($errors) > 0) { - throw new InvalidInput(implode("
", $errors)); - } - - $newThreadID = $this->save_new_thread($user); - $this->save_new_post($newThreadID, $user); - $redirectTo = "forum/view/" . $newThreadID . "/1"; + if (count($errors) > 0) { + throw new InvalidInput(implode("
", $errors)); } + $newThreadID = $this->save_new_thread($user); + $this->save_new_post($newThreadID, $user); + $redirectTo = "forum/view/" . $newThreadID . "/1"; + $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link($redirectTo)); } - if ($event->page_matches("forum/delete/{threadID}/{postID}")) { + if ($event->page_matches("forum/delete/{threadID}/{postID}", permission: Permissions::FORUM_ADMIN)) { $threadID = $event->get_iarg('threadID'); $postID = $event->get_iarg('postID'); - - if ($user->can(Permissions::FORUM_ADMIN)) { - $this->delete_post($postID); - } - + $this->delete_post($postID); $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link("forum/view/" . $threadID)); } - if ($event->page_matches("forum/nuke/{threadID}")) { + if ($event->page_matches("forum/nuke/{threadID}", permission: Permissions::FORUM_ADMIN)) { $threadID = $event->get_iarg('threadID'); - - if ($user->can(Permissions::FORUM_ADMIN)) { - $this->delete_thread($threadID); - } - + $this->delete_thread($threadID); $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link("forum/index")); } - if ($event->page_matches("forum/answer")) { + if ($event->page_matches("forum/answer", permission: Permissions::FORUM_CREATE)) { $threadID = int_escape($event->req_POST("threadID")); $total_pages = $this->get_total_pages_for_thread($threadID); - if (!$user->can(Permissions::FORUM_CREATE)) { - $errors = $this->sanity_check_new_post(); - if (count($errors) > 0) { - throw new InvalidInput(implode("
", $errors)); - } - $this->save_new_post($threadID, $user); + $errors = $this->sanity_check_new_post(); + + if (count($errors) > 0) { + throw new InvalidInput(implode("
", $errors)); } + $this->save_new_post($threadID, $user); + $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link("forum/view/" . $threadID . "/" . $total_pages)); } diff --git a/ext/notes/main.php b/ext/notes/main.php index 21b362ef..e19ce22c 100644 --- a/ext/notes/main.php +++ b/ext/notes/main.php @@ -90,61 +90,46 @@ class Notes extends Extension if ($event->page_matches("note/history/{note_id}", paged: true)) { $this->get_history($event->get_iarg('note_id'), $event->get_iarg('page_num', 1) - 1); } - if ($event->page_matches("note/revert/{noteID}/{reviewID}")) { + if ($event->page_matches("note/revert/{noteID}/{reviewID}", permission: Permissions::NOTES_EDIT)) { $noteID = $event->get_iarg('noteID'); $reviewID = $event->get_iarg('reviewID'); - if (!$user->is_anonymous()) { - $this->revert_history($noteID, $reviewID); - } + $this->revert_history($noteID, $reviewID); $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link("note/updated")); } - if ($event->page_matches("note/add_request")) { + if ($event->page_matches("note/add_request", permission: Permissions::NOTES_REQUEST)) { $image_id = int_escape($event->req_POST("image_id")); - if (!$user->is_anonymous()) { - $this->add_note_request($image_id); - } + $this->add_note_request($image_id); $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link("post/view/$image_id")); } - if ($event->page_matches("note/nuke_requests")) { + if ($event->page_matches("note/nuke_requests", permission: Permissions::NOTES_ADMIN)) { $image_id = int_escape($event->req_POST("image_id")); - if ($user->can(Permissions::NOTES_ADMIN)) { - $this->nuke_requests($image_id); - } + $this->nuke_requests($image_id); $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link("post/view/$image_id")); } - if ($event->page_matches("note/create_note")) { + if ($event->page_matches("note/create_note", permission: Permissions::NOTES_CREATE)) { $page->set_mode(PageMode::DATA); - if (!$user->can(Permissions::NOTES_CREATE)) { - $note_id = $this->add_new_note(); - $page->set_data(\Safe\json_encode([ - 'status' => 'success', - 'note_id' => $note_id, - ])); - } + $note_id = $this->add_new_note(); + $page->set_data(\Safe\json_encode([ + 'status' => 'success', + 'note_id' => $note_id, + ])); } - if ($event->page_matches("note/update_note")) { + if ($event->page_matches("note/update_note", permission: Permissions::NOTES_EDIT)) { $page->set_mode(PageMode::DATA); - if (!$user->can(Permissions::NOTES_EDIT)) { - $this->update_note(); - $page->set_data(\Safe\json_encode(['status' => 'success'])); - } + $this->update_note(); + $page->set_data(\Safe\json_encode(['status' => 'success'])); } - if ($event->page_matches("note/delete_note")) { + if ($event->page_matches("note/delete_note", permission: Permissions::NOTES_ADMIN)) { $page->set_mode(PageMode::DATA); - if ($user->can(Permissions::NOTES_ADMIN)) { - $this->delete_note(); - $page->set_data(\Safe\json_encode(['status' => 'success'])); - } + $this->delete_note(); + $page->set_data(\Safe\json_encode(['status' => 'success'])); } - if ($event->page_matches("note/nuke_notes")) { + if ($event->page_matches("note/nuke_notes", permission: Permissions::NOTES_ADMIN)) { $image_id = int_escape($event->req_POST("image_id")); - if ($user->can(Permissions::NOTES_ADMIN)) { - $this->nuke_notes($image_id); - } - + $this->nuke_notes($image_id); $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link("post/view/$image_id")); } @@ -160,7 +145,7 @@ class Notes extends Extension //display form on image event $notes = $this->get_notes($event->image->id); - $this->theme->display_note_system($page, $event->image->id, $notes, $user->can(Permissions::NOTES_ADMIN)); + $this->theme->display_note_system($page, $event->image->id, $notes, $user->can(Permissions::NOTES_ADMIN), $user->can(Permissions::NOTES_EDIT)); } @@ -170,14 +155,17 @@ class Notes extends Extension public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event): void { global $user; - if (!$user->can(Permissions::NOTES_CREATE)) { + if ($user->can(Permissions::NOTES_CREATE)) { $event->add_part($this->theme->note_button($event->image->id)); - $event->add_part($this->theme->request_button($event->image->id)); + if ($user->can(Permissions::NOTES_ADMIN)) { $event->add_part($this->theme->nuke_notes_button($event->image->id)); $event->add_part($this->theme->nuke_requests_button($event->image->id)); } } + if ($user->can(Permissions::NOTES_REQUEST)) { + $event->add_part($this->theme->request_button($event->image->id)); + } } diff --git a/ext/notes/script.js b/ext/notes/script.js index ea2bb87c..81cf56fe 100644 --- a/ext/notes/script.js +++ b/ext/notes/script.js @@ -48,10 +48,13 @@ function renderNotes() { noteDiv.style.height = note.height * scale + 'px'; let text = document.createElement('div'); text.innerText = note.note; - noteDiv.addEventListener('click', (e) => { - noteBeingEdited = note.note_id; - renderNotes(); - }); + // only add listener if user has edit permissions + if (window.notes_edit) { + noteDiv.addEventListener('click', (e) => { + noteBeingEdited = note.note_id; + renderNotes(); + }); + } noteDiv.appendChild(text); notesContainer.appendChild(noteDiv); diff --git a/ext/notes/theme.php b/ext/notes/theme.php index 169c0444..a14996d8 100644 --- a/ext/notes/theme.php +++ b/ext/notes/theme.php @@ -47,7 +47,7 @@ class NotesTheme extends Themelet /** * @param Note[] $recovered_notes */ - public function display_note_system(Page $page, int $image_id, array $recovered_notes, bool $adminOptions): void + public function display_note_system(Page $page, int $image_id, array $recovered_notes, bool $adminOptions, bool $editOptions): void { $to_json = []; foreach ($recovered_notes as $note) { @@ -65,6 +65,7 @@ class NotesTheme extends Themelet window.notes = ".\Safe\json_encode($to_json)."; window.notes_image_id = $image_id; window.notes_admin = ".($adminOptions ? "true" : "false")."; + window.notes_edit = ".($editOptions ? "true" : "false")."; "); }