[wiki] cleanups and security

This commit is contained in:
Shish 2024-02-10 16:40:38 +00:00
parent 7895978d93
commit 20a87576b9
4 changed files with 80 additions and 92 deletions

View file

@ -97,7 +97,7 @@ class ImageIO extends Extension
send_event(new ImageDeletionEvent($image)); send_event(new ImageDeletionEvent($image));
if ($config->get_string(ImageConfig::ON_DELETE) === ImageConfig::ON_DELETE_NEXT) { if ($config->get_string(ImageConfig::ON_DELETE) === ImageConfig::ON_DELETE_NEXT) {
redirect_to_next_image($image, @$event->get_GET('search')); redirect_to_next_image($image, $event->get_GET('search'));
} else { } else {
$page->set_mode(PageMode::REDIRECT); $page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link(), ['post/view'])); $page->set_redirect(referer_or(make_link(), ['post/view']));

View file

@ -182,65 +182,67 @@ class Wiki extends Extension
} else { } else {
$title = $event->get_arg(0); $title = $event->get_arg(0);
} }
$action = $event->count_args() > 1 ? $event->get_arg(1) : "view";
$revision = -1;
if ($event->get_GET('revision')) {
$revision = int_escape($event->get_GET('revision'));
}
$content = $this->get_page($title, $revision); if($action == "view") {
$this->theme->display_page($page, $content, $this->get_page("wiki:sidebar")); $revision = int_escape($event->get_GET('revision') ?? "-1");
} elseif ($event->page_matches("wiki_admin/edit")) { $content = $this->get_page($title, $revision);
$content = $this->get_page($event->req_POST('title')); $this->theme->display_page($page, $content, $this->get_page("wiki:sidebar"));
$this->theme->display_page_editor($page, $content); } elseif($action == "history") {
} elseif ($event->page_matches("wiki_admin/save")) { $history = $this->get_history($title);
$title = $event->req_POST('title'); $this->theme->display_page_history($page, $title, $history);
$rev = int_escape($event->req_POST('revision')); } elseif($action == "edit") {
$body = $event->req_POST('body'); $content = $this->get_page($title);
$lock = $user->can(Permissions::WIKI_ADMIN) && ($event->get_POST('lock') == "on"); if ($this->can_edit($user, $content)) {
$this->theme->display_page_editor($page, $content);
} else {
$this->theme->display_permission_denied();
}
} elseif($action == "save" && $user->check_auth_token()) {
$rev = int_escape($event->req_POST('revision'));
$body = $event->req_POST('body');
$lock = $user->can(Permissions::WIKI_ADMIN) && ($event->get_POST('lock') == "on");
if ($this->can_edit($user, $this->get_page($title))) { if ($this->can_edit($user, $this->get_page($title))) {
$wikipage = $this->get_page($title); $wikipage = $this->get_page($title);
$wikipage->revision = $rev; $wikipage->revision = $rev;
$wikipage->body = $body; $wikipage->body = $body;
$wikipage->locked = $lock; $wikipage->locked = $lock;
send_event(new WikiUpdateEvent($user, $wikipage)); send_event(new WikiUpdateEvent($user, $wikipage));
$u_title = url_escape($title); $u_title = url_escape($title);
$page->set_mode(PageMode::REDIRECT); $page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("wiki/$u_title")); $page->set_redirect(make_link("wiki/$u_title"));
} else { } else {
$this->theme->display_permission_denied(); $this->theme->display_permission_denied();
} }
} elseif ($event->page_matches("wiki_admin/history")) { } elseif($action == "delete_revision" && $user->check_auth_token()) {
$history = $this->get_history($event->get_GET('title')); $content = $this->get_page($title);
$this->theme->display_page_history($page, $event->get_GET('title'), $history); if ($user->can(Permissions::WIKI_ADMIN)) {
} elseif ($event->page_matches("wiki_admin/delete_revision")) { $revision = int_escape($event->req_POST('revision'));
if ($user->can(Permissions::WIKI_ADMIN)) { send_event(new WikiDeleteRevisionEvent($title, $revision));
$title = $event->req_POST('title'); $u_title = url_escape($title);
$revision = int_escape($event->req_POST('revision')); $page->set_mode(PageMode::REDIRECT);
send_event(new WikiDeleteRevisionEvent($title, $revision)); $page->set_redirect(make_link("wiki/$u_title"));
$u_title = url_escape($title); } else {
$page->set_mode(PageMode::REDIRECT); $this->theme->display_permission_denied();
$page->set_redirect(make_link("wiki/$u_title")); }
} } elseif($action == "delete_all" && $user->check_auth_token()) {
} elseif ($event->page_matches("wiki_admin/delete_all")) { if ($user->can(Permissions::WIKI_ADMIN)) {
if ($user->can(Permissions::WIKI_ADMIN)) { send_event(new WikiDeletePageEvent($title));
$title = $event->req_POST('title'); $u_title = url_escape($title);
send_event(new WikiDeletePageEvent($title)); $page->set_mode(PageMode::REDIRECT);
$u_title = url_escape($title); $page->set_redirect(make_link("wiki/$u_title"));
$page->set_mode(PageMode::REDIRECT); }
$page->set_redirect(make_link("wiki/$u_title"));
} }
} }
} }
public function onPageNavBuilding(PageNavBuildingEvent $event): void public function onPageNavBuilding(PageNavBuildingEvent $event): void
{ {
$event->add_nav_link("wiki", new Link('wiki'), "Wiki"); $event->add_nav_link("wiki", new Link('wiki'), "Wiki");
} }
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event): void public function onPageSubNavBuilding(PageSubNavBuildingEvent $event): void
{ {
if ($event->parent == "wiki") { if ($event->parent == "wiki") {

View file

@ -13,44 +13,30 @@ class WikiTest extends ShimmiePHPUnitTestCase
$this->assert_text("This is a default page"); $this->assert_text("This is a default page");
} }
public function testAccess(): void // By default users are read-only
public function testAccessUser(): void
{ {
global $config; $this->log_in_as_user();
foreach (["anon", "user", "admin"] as $user) {
foreach ([false, true] as $allowed) {
// admin has no settings to set
if ($user != "admin") {
$config->set_bool("wiki_edit_$user", $allowed);
}
if ($user == "user") { $this->get_page("wiki/test");
$this->log_in_as_user(); $this->assert_title("test");
} $this->assert_text("This is a default page");
if ($user == "admin") {
$this->log_in_as_admin();
}
$this->get_page("wiki/test"); $this->get_page("wiki/test/edit");
$this->assert_title("test"); $this->assert_no_text("Editor");
$this->assert_text("This is a default page"); }
if ($allowed || $user == "admin") { // Admins can edit
$this->post_page("wiki_admin/edit", ["title" => "test"]); public function testAccessAdmin(): void
$this->assert_text("Editor"); {
} $this->log_in_as_admin();
/*
// Everyone can see the editor
else {
$this->post_page("wiki_admin/edit", ["title"=>"test"]);
$this->assert_no_text("Editor");
}
*/
if ($user == "user" || $user == "admin") { $this->get_page("wiki/test");
$this->log_out(); $this->assert_title("test");
} $this->assert_text("This is a default page");
}
} $this->get_page("wiki/test/edit");
$this->assert_text("Editor");
} }
public function testDefault(): void public function testDefault(): void
@ -107,6 +93,10 @@ class WikiTest extends ShimmiePHPUnitTestCase
$this->assert_text("Mooooo 2"); $this->assert_text("Mooooo 2");
$this->assert_text("Revision 2"); $this->assert_text("Revision 2");
$this->get_page("wiki/test/history");
$this->assert_title("test");
$this->assert_text("2");
send_event(new WikiDeleteRevisionEvent("test", 2)); send_event(new WikiDeleteRevisionEvent("test", 2));
$this->get_page("wiki/test"); $this->get_page("wiki/test");
$this->assert_text("Mooooo 1"); $this->assert_text("Mooooo 1");

View file

@ -75,7 +75,7 @@ class WikiTheme extends Themelet
protected function create_edit_html(WikiPage $page): string protected function create_edit_html(WikiPage $page): string
{ {
$h_title = html_escape($page->title); $u_title = url_escape($page->title);
$i_revision = $page->revision + 1; $i_revision = $page->revision + 1;
global $user; global $user;
@ -85,9 +85,7 @@ class WikiTheme extends Themelet
} else { } else {
$lock = ""; $lock = "";
} }
return " return make_form(make_link("wiki/$u_title/save"))."
".make_form(make_link("wiki_admin/save"))."
<input type='hidden' name='title' value='$h_title'>
<input type='hidden' name='revision' value='$i_revision'> <input type='hidden' name='revision' value='$i_revision'>
<textarea name='body' style='width: 100%' rows='20'>".html_escape($page->body)."</textarea> <textarea name='body' style='width: 100%' rows='20'>".html_escape($page->body)."</textarea>
$lock $lock
@ -100,6 +98,7 @@ class WikiTheme extends Themelet
{ {
global $user; global $user;
$u_title = url_escape($page->title);
$owner = $page->get_owner(); $owner = $page->get_owner();
$formatted_body = Wiki::format_tag_wiki_page($page); $formatted_body = Wiki::format_tag_wiki_page($page);
@ -107,8 +106,7 @@ class WikiTheme extends Themelet
$edit = "<table><tr>"; $edit = "<table><tr>";
$edit .= Wiki::can_edit($user, $page) ? $edit .= Wiki::can_edit($user, $page) ?
" "
<td>".make_form(make_link("wiki_admin/edit"))." <td>".make_form(make_link("wiki/$u_title/edit"))."
<input type='hidden' name='title' value='".html_escape($page->title)."'>
<input type='hidden' name='revision' value='".$page->revision."'> <input type='hidden' name='revision' value='".$page->revision."'>
<input type='submit' value='Edit'> <input type='submit' value='Edit'>
</form></td> </form></td>
@ -116,13 +114,11 @@ class WikiTheme extends Themelet
""; "";
if ($user->can(Permissions::WIKI_ADMIN)) { if ($user->can(Permissions::WIKI_ADMIN)) {
$edit .= " $edit .= "
<td>".make_form(make_link("wiki_admin/delete_revision"))." <td>".make_form(make_link("wiki/$u_title/delete_revision"))."
<input type='hidden' name='title' value='".html_escape($page->title)."'>
<input type='hidden' name='revision' value='".$page->revision."'> <input type='hidden' name='revision' value='".$page->revision."'>
<input type='submit' value='Delete This Version'> <input type='submit' value='Delete This Version'>
</form></td> </form></td>
<td>".make_form(make_link("wiki_admin/delete_all"))." <td>".make_form(make_link("wiki/$u_title/delete_all"))."
<input type='hidden' name='title' value='".html_escape($page->title)."'>
<input type='submit' value='Delete All'> <input type='submit' value='Delete All'>
</form></td> </form></td>
"; ";
@ -134,7 +130,7 @@ class WikiTheme extends Themelet
$formatted_body $formatted_body
<hr> <hr>
<p class='wiki-footer'> <p class='wiki-footer'>
<a href='".make_link("wiki_admin/history", "title={$page->title}")."'>Revision {$page->revision}</a> <a href='".make_link("wiki/$u_title/history")."'>Revision {$page->revision}</a>
by <a href='".make_link("user/{$owner->name}")."'>{$owner->name}</a> by <a href='".make_link("user/{$owner->name}")."'>{$owner->name}</a>
at {$page->date} at {$page->date}
$edit $edit