[core] merge method-check and permission-check into page_matches()

This commit is contained in:
Shish 2024-02-10 23:03:14 +00:00
parent 5735320a95
commit cc9de6b4b2
61 changed files with 1472 additions and 1799 deletions

View file

@ -37,15 +37,6 @@ class BaseThemelet
$page->add_block(new Block("Error", $message));
}
/**
* A specific, common error message
*/
public function display_permission_denied(): void
{
$this->display_error(403, "Permission Denied", "You do not have permission to access this page");
}
/**
* Generic thumbnail code; returns HTML rather than adding
* a block since thumbs tend to go inside blocks...

View file

@ -59,6 +59,7 @@ class PageRequestEvent extends Event
public array $args;
public int $arg_count;
public int $part_count;
public bool $is_authed;
/**
* @param string $method The HTTP method used to make the request
@ -68,6 +69,7 @@ class PageRequestEvent extends Event
*/
public function __construct(string $method, string $path, array $get, array $post)
{
global $user;
parent::__construct();
global $config;
@ -81,6 +83,7 @@ class PageRequestEvent extends Event
$this->path = $path;
$this->GET = $get;
$this->POST = $post;
$this->is_authed = $user->check_auth_token();
// break the path into parts
$args = explode('/', $path);
@ -163,28 +166,40 @@ class PageRequestEvent extends Event
*
* If it matches, store the remaining path elements in $args
*/
public function page_matches(string $name): bool
public function page_matches(string $name, ?string $method = null, ?bool $authed = null, ?string $permission = null): bool
{
$parts = explode("/", $name);
$this->part_count = count($parts);
global $user;
if ($this->part_count > $this->arg_count) {
assert($method === null || in_array($method, ["GET", "POST", "OPTIONS"]));
$authed = $authed ?? $method == "POST";
// method check is fast so do that first
if($method !== null && $this->method !== $method) {
return false;
}
// check if the path matches
$parts = explode("/", $name);
$this->part_count = count($parts);
if ($this->part_count > $this->arg_count) {
return false;
}
for ($i = 0; $i < $this->part_count; $i++) {
if ($parts[$i] != $this->args[$i]) {
return false;
}
}
return true;
// if we matched the method and the path, but the page requires
// authentication and the user is not authenticated, then complain
if($authed && $this->is_authed === false) {
throw new PermissionDeniedException("Permission Denied");
}
if($permission !== null && !$user->can($permission)) {
throw new PermissionDeniedException("Permission Denied");
}
public function authed_page_matches(string $name): bool
{
global $user;
return $this->page_matches($name) && $user->check_auth_token();
return true;
}
/**

View file

@ -88,7 +88,7 @@ abstract class Permissions
public const BULK_EDIT_VOTE = "bulk_edit_vote";
public const EDIT_OTHER_VOTE = "edit_other_vote";
public const VIEW_SYSINTO = "view_sysinfo";
public const VIEW_SYSINFO = "view_sysinfo";
public const HELLBANNED = "hellbanned";
public const VIEW_HELLBANNED = "view_hellbanned";

View file

@ -188,7 +188,7 @@ new UserClass("admin", "base", [
Permissions::BULK_EDIT_VOTE => true,
Permissions::EDIT_OTHER_VOTE => true,
Permissions::CREATE_VOTE => true,
Permissions::VIEW_SYSINTO => true,
Permissions::VIEW_SYSINFO => true,
Permissions::HELLBANNED => false,
Permissions::VIEW_HELLBANNED => true,

View file

@ -49,24 +49,18 @@ class AdminPage extends Extension
{
global $database, $page, $user;
if ($event->page_matches("admin")) {
if (!$user->can(Permissions::MANAGE_ADMINTOOLS)) {
$this->theme->display_permission_denied();
} else {
if ($event->page_matches("admin", permission: Permissions::MANAGE_ADMINTOOLS)) {
if ($event->count_args() == 0) {
send_event(new AdminBuildingEvent($page));
} else {
$action = $event->get_arg(0);
$aae = new AdminActionEvent($action, $event->POST);
if ($user->check_auth_token()) {
$user->ensure_authed();
log_info("admin", "Util: $action");
shm_set_timeout(null);
$database->set_timeout(null);
send_event($aae);
} else {
throw new SCoreException("Invalid CSRF token");
}
if ($aae->redirect) {
$page->set_mode(PageMode::REDIRECT);
@ -75,7 +69,6 @@ class AdminPage extends Extension
}
}
}
}
public function onCliGen(CliGenEvent $event): void
{

View file

@ -9,14 +9,14 @@ class AdminPageTest extends ShimmiePHPUnitTestCase
public function testAuth(): void
{
send_event(new UserLoginEvent(User::by_name(self::$anon_name)));
$page = $this->get_page('admin');
$this->assertEquals(403, $page->code);
$this->assertEquals("Permission Denied", $page->title);
$this->assertException(PermissionDeniedException::class, function () {
$this->get_page('admin');
});
send_event(new UserLoginEvent(User::by_name(self::$user_name)));
$page = $this->get_page('admin');
$this->assertEquals(403, $page->code);
$this->assertEquals("Permission Denied", $page->title);
$this->assertException(PermissionDeniedException::class, function () {
$this->get_page('admin');
});
send_event(new UserLoginEvent(User::by_name(self::$admin_name)));
$page = $this->get_page('admin');

View file

@ -66,9 +66,7 @@ class AliasEditor extends Extension
global $config, $database, $page, $user;
if ($event->page_matches("alias")) {
if ($event->get_arg(0) == "add") {
if ($user->can(Permissions::MANAGE_ALIAS_LIST)) {
$user->ensure_authed();
if ($event->page_matches("alias/add", method: "POST", permission: Permissions::MANAGE_ALIAS_LIST)) {
$input = validate_input(["c_oldtag" => "string", "c_newtag" => "string"]);
try {
send_event(new AddAliasEvent($input['c_oldtag'], $input['c_newtag']));
@ -78,15 +76,13 @@ class AliasEditor extends Extension
$this->theme->display_error(500, "Error adding alias", $ex->getMessage());
}
}
} elseif ($event->get_arg(0) == "remove") {
if ($user->can(Permissions::MANAGE_ALIAS_LIST)) {
$user->ensure_authed();
if ($event->page_matches("alias/remove", method: "POST", permission: Permissions::MANAGE_ALIAS_LIST)) {
$input = validate_input(["d_oldtag" => "string"]);
send_event(new DeleteAliasEvent($input['d_oldtag']));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("alias/list"));
}
} elseif ($event->get_arg(0) == "list") {
if ($event->page_matches("alias/list")) {
$t = new AliasTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
@ -96,13 +92,14 @@ class AliasEditor extends Extension
$t->delete_url = make_link("alias/remove");
}
$this->theme->display_aliases($t->table($t->query()), $t->paginator());
} elseif ($event->get_arg(0) == "export") {
}
if ($event->page_matches("alias/export")) {
$page->set_mode(PageMode::DATA);
$page->set_mime(MimeType::CSV);
$page->set_filename("aliases.csv");
$page->set_data($this->get_alias_csv($database));
} elseif ($event->get_arg(0) == "import") {
if ($user->can(Permissions::MANAGE_ALIAS_LIST)) {
}
if ($event->page_matches("alias/import", method: "POST", permission: Permissions::MANAGE_ALIAS_LIST)) {
if (count($_FILES) > 0) {
$tmp = $_FILES['alias_file']['tmp_name'];
$contents = file_get_contents_ex($tmp);
@ -113,9 +110,6 @@ class AliasEditor extends Extension
} else {
$this->theme->display_error(400, "No File Specified", "You have to upload a file");
}
} else {
$this->theme->display_error(401, "Admins Only", "Only admins can edit the alias list");
}
}
}
}

View file

@ -40,16 +40,14 @@ class Approval extends Extension
{
global $page, $user;
if ($event->page_matches("approve_image") && $user->can(Permissions::APPROVE_IMAGE)) {
// Try to get the image ID
if ($event->page_matches("approve_image", method: "POST", permission: Permissions::APPROVE_IMAGE)) {
$image_id = int_escape(null_throws($event->get_arg(0)));
self::approve_image($image_id);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/" . $image_id));
}
if ($event->page_matches("disapprove_image") && $user->can(Permissions::APPROVE_IMAGE)) {
// Try to get the image ID
if ($event->page_matches("disapprove_image", method: "POST", permission: Permissions::APPROVE_IMAGE)) {
$image_id = int_escape(null_throws($event->get_arg(0)));
self::disapprove_image($image_id);
$page->set_mode(PageMode::REDIRECT);

View file

@ -169,32 +169,22 @@ class Artists extends Extension
{
global $page, $user;
if ($event->page_matches("artist")) {
switch ($event->get_arg(0)) {
//*************ARTIST SECTION**************
case "list":
{
$this->get_listing($event);
if ($event->page_matches("artist/list")) {
$this->get_listing(clamp(int_escape($event->get_arg(0)), 1, null) - 1);
$this->theme->sidebar_options("neutral");
break;
}
case "new":
{
if ($event->page_matches("artist/new")) {
if (!$user->is_anonymous()) {
$this->theme->new_artist_composer();
} else {
$this->theme->display_error(401, "Error", "You must be registered and logged in to create a new artist.");
}
break;
}
case "new_artist":
{
if ($event->page_matches("artist/new_artist")) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/new"));
break;
}
case "create":
{
if ($event->page_matches("artist/create")) {
if (!$user->is_anonymous()) {
$newArtistID = $this->add_artist();
if ($newArtistID == -1) {
@ -206,12 +196,9 @@ class Artists extends Extension
} else {
$this->theme->display_error(401, "Error", "You must be registered and logged in to create a new artist.");
}
break;
}
case "view":
{
$artistID = int_escape($event->get_arg(1));
if ($event->page_matches("artist/view")) {
$artistID = int_escape($event->get_arg(0));
$artist = $this->get_artist($artistID);
$aliases = $this->get_alias($artist['id']);
$members = $this->get_members($artist['id']);
@ -232,13 +219,9 @@ class Artists extends Extension
*/
$this->theme->sidebar_options("editor", $artistID, $userIsAdmin);
break;
}
case "edit":
{
$artistID = int_escape($event->get_arg(1));
if ($event->page_matches("artist/edit")) {
$artistID = int_escape($event->get_arg(0));
$artist = $this->get_artist($artistID);
$aliases = $this->get_alias($artistID);
$members = $this->get_members($artistID);
@ -252,178 +235,115 @@ class Artists extends Extension
} else {
$this->theme->display_error(401, "Error", "You must be registered and logged in to edit an artist.");
}
break;
}
case "edit_artist":
{
if ($event->page_matches("artist/edit_artist")) {
$artistID = int_escape($event->req_POST('artist_id'));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/edit/" . $artistID));
break;
}
case "edited":
{
if ($event->page_matches("artist/edited")) {
$artistID = int_escape($event->get_POST('id'));
$this->update_artist();
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
break;
}
case "nuke_artist":
{
if ($event->page_matches("artist/nuke_artist")) {
$artistID = int_escape($event->req_POST('artist_id'));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/nuke/" . $artistID));
break;
}
case "nuke":
{
$artistID = int_escape($event->get_arg(1));
if ($event->page_matches("artist/nuke")) {
$artistID = int_escape($event->get_arg(0));
$this->delete_artist($artistID); // this will delete the artist, its alias, its urls and its members
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/list"));
break;
}
case "add_alias":
{
if ($event->page_matches("artist/add_alias")) {
$artistID = int_escape($event->req_POST('artist_id'));
$this->theme->show_new_alias_composer($artistID);
break;
}
case "add_member":
{
if ($event->page_matches("artist/add_member")) {
$artistID = int_escape($event->req_POST('artist_id'));
$this->theme->show_new_member_composer($artistID);
break;
}
case "add_url":
{
if ($event->page_matches("artist/add_url")) {
$artistID = int_escape($event->req_POST('artist_id'));
$this->theme->show_new_url_composer($artistID);
break;
}
//***********ALIAS SECTION ***********************
case "alias":
{
switch ($event->get_arg(1)) {
case "add":
{
if ($event->page_matches("artist/alias/add")) {
$artistID = int_escape($event->req_POST('artist_id'));
$this->add_alias();
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
break;
}
case "delete":
{
$aliasID = int_escape($event->get_arg(2));
if ($event->page_matches("artist/alias/delete")) {
$aliasID = int_escape($event->get_arg(0));
$artistID = $this->get_artistID_by_aliasID($aliasID);
$this->delete_alias($aliasID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
break;
}
case "edit":
{
$aliasID = int_escape($event->get_arg(2));
if ($event->page_matches("artist/alias/edit")) {
$aliasID = int_escape($event->get_arg(0));
$alias = $this->get_alias_by_id($aliasID);
$this->theme->show_alias_editor($alias);
break;
}
case "edited":
{
if ($event->page_matches("artist/alias/edited")) {
$this->update_alias();
$aliasID = int_escape($event->req_POST('aliasID'));
$artistID = $this->get_artistID_by_aliasID($aliasID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
break;
}
}
break; // case: alias
}
//**************** URLS SECTION **********************
case "url":
{
switch ($event->get_arg(1)) {
case "add":
{
if ($event->page_matches("artist/url/add")) {
$artistID = int_escape($event->req_POST('artist_id'));
$this->add_urls();
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
break;
}
case "delete":
{
$urlID = int_escape($event->get_arg(2));
if ($event->page_matches("artist/url/delete")) {
$urlID = int_escape($event->get_arg(0));
$artistID = $this->get_artistID_by_urlID($urlID);
$this->delete_url($urlID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
break;
}
case "edit":
{
$urlID = int_escape($event->get_arg(2));
if ($event->page_matches("artist/url/edit")) {
$urlID = int_escape($event->get_arg(0));
$url = $this->get_url_by_id($urlID);
$this->theme->show_url_editor($url);
break;
}
case "edited":
{
if ($event->page_matches("artist/url/edited")) {
$this->update_url();
$urlID = int_escape($event->req_POST('urlID'));
$artistID = $this->get_artistID_by_urlID($urlID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
break;
}
}
break; // case: urls
}
//******************* MEMBERS SECTION *********************
case "member":
{
switch ($event->get_arg(1)) {
case "add":
{
if ($event->page_matches("artist/member/add")) {
$artistID = int_escape($event->req_POST('artist_id'));
$this->add_members();
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
break;
}
case "delete":
{
$memberID = int_escape($event->get_arg(2));
if ($event->page_matches("artist/member/delete")) {
$memberID = int_escape($event->get_arg(0));
$artistID = $this->get_artistID_by_memberID($memberID);
$this->delete_member($memberID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
break;
}
case "edit":
{
$memberID = int_escape($event->get_arg(2));
if ($event->page_matches("artist/member/edit")) {
$memberID = int_escape($event->get_arg(0));
$member = $this->get_member_by_id($memberID);
$this->theme->show_member_editor($member);
break;
}
case "edited":
{
if ($event->page_matches("artist/member/edited")) {
$this->update_member();
$memberID = int_escape($event->req_POST('memberID'));
$artistID = $this->get_artistID_by_memberID($memberID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/" . $artistID));
break;
}
}
break; //case: members
}
}
}
}
@ -875,11 +795,10 @@ class Artists extends Extension
/*
* HERE WE GET THE LIST OF ALL ARTIST WITH PAGINATION
*/
private function get_listing(PageRequestEvent $event): void
private function get_listing(int $pageNumber): void
{
global $config, $database;
$pageNumber = clamp(int_escape($event->get_arg(1)), 1, null) - 1;
$artistsPerPage = $config->get_int("artistsPerPage");
$listing = $database->get_all(

View file

@ -72,9 +72,7 @@ class AutoTagger extends Extension
global $config, $database, $page, $user;
if ($event->page_matches("auto_tag")) {
if ($event->get_arg(0) == "add") {
if ($user->can(Permissions::MANAGE_AUTO_TAG)) {
$user->ensure_authed();
if ($event->page_matches("auto_tag/add", method: "POST", permission: Permissions::MANAGE_AUTO_TAG)) {
$input = validate_input(["c_tag" => "string", "c_additional_tags" => "string"]);
try {
send_event(new AddAutoTagEvent($input['c_tag'], $input['c_additional_tags']));
@ -84,15 +82,13 @@ class AutoTagger extends Extension
$this->theme->display_error(500, "Error adding auto-tag", $ex->getMessage());
}
}
} elseif ($event->get_arg(0) == "remove") {
if ($user->can(Permissions::MANAGE_AUTO_TAG)) {
$user->ensure_authed();
if ($event->page_matches("auto_tag/remove", method: "POST", permission: Permissions::MANAGE_AUTO_TAG)) {
$input = validate_input(["d_tag" => "string"]);
send_event(new DeleteAutoTagEvent($input['d_tag']));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("auto_tag/list"));
}
} elseif ($event->get_arg(0) == "list") {
if ($event->page_matches("auto_tag/list")) {
$t = new AutoTaggerTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
@ -102,13 +98,14 @@ class AutoTagger extends Extension
$t->delete_url = make_link("auto_tag/remove");
}
$this->theme->display_auto_tagtable($t->table($t->query()), $t->paginator());
} elseif ($event->get_arg(0) == "export") {
}
if ($event->page_matches("auto_tag/export")) {
$page->set_mode(PageMode::DATA);
$page->set_mime(MimeType::CSV);
$page->set_filename("auto_tag.csv");
$page->set_data($this->get_auto_tag_csv($database));
} elseif ($event->get_arg(0) == "import") {
if ($user->can(Permissions::MANAGE_AUTO_TAG)) {
}
if ($event->page_matches("auto_tag/import", method: "POST", permission: Permissions::MANAGE_AUTO_TAG)) {
if (count($_FILES) > 0) {
$tmp = $_FILES['auto_tag_file']['tmp_name'];
$contents = file_get_contents_ex($tmp);
@ -119,9 +116,6 @@ class AutoTagger extends Extension
} else {
$this->theme->display_error(400, "No File Specified", "You have to upload a file");
}
} else {
$this->theme->display_error(401, "Admins Only", "Only admins can edit the auto-tag list");
}
}
}
}

View file

@ -26,8 +26,7 @@ class Biography extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $page, $user, $user_config;
if ($event->page_matches("biography")) {
if ($user->check_auth_token()) {
if ($event->page_matches("biography", method: "POST")) {
$user_config->set_string("biography", $event->get_POST('biography'));
$page->flash("Bio Updated");
$page->set_mode(PageMode::REDIRECT);
@ -35,4 +34,3 @@ class Biography extends Extension
}
}
}
}

View file

@ -68,9 +68,8 @@ class Blocks extends Extension
}
}
if ($event->page_matches("blocks") && $user->can(Permissions::MANAGE_BLOCKS)) {
if ($event->get_arg(0) == "add") {
if ($user->check_auth_token()) {
if ($event->page_matches("blocks", permission: Permissions::MANAGE_BLOCKS)) {
if ($event->page_matches("blocks/add", method: "POST")) {
$database->execute("
INSERT INTO blocks (pages, title, area, priority, content, userclass)
VALUES (:pages, :title, :area, :priority, :content, :userclass)
@ -80,9 +79,7 @@ class Blocks extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("blocks/list"));
}
}
if ($event->get_arg(0) == "update") {
if ($user->check_auth_token()) {
if ($event->page_matches("blocks/update", method: "POST")) {
if (!empty($event->req_POST('delete'))) {
$database->execute("
DELETE FROM blocks
@ -100,7 +97,7 @@ class Blocks extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("blocks/list"));
}
} elseif ($event->get_arg(0) == "list") {
if ($event->page_matches("blocks/list")) {
$this->theme->display_blocks($database->get_all("SELECT * FROM blocks ORDER BY area, priority"));
}
}

View file

@ -72,26 +72,11 @@ class Blotter extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $page, $database, $user;
if ($event->page_matches("blotter") && $event->count_args() > 0) {
switch ($event->get_arg(0)) {
case "editor":
/**
* Displays the blotter editor.
*/
if (!$user->can(Permissions::BLOTTER_ADMIN)) {
$this->theme->display_permission_denied();
} else {
if ($event->page_matches("blotter/editor", method: "GET", permission: Permissions::BLOTTER_ADMIN)) {
$entries = $database->get_all("SELECT * FROM blotter ORDER BY id DESC");
$this->theme->display_editor($entries);
}
break;
case "add":
/**
* Adds an entry
*/
if (!$user->can(Permissions::BLOTTER_ADMIN) || !$user->check_auth_token()) {
$this->theme->display_permission_denied();
} else {
if ($event->page_matches("blotter/add", method: "POST", permission: Permissions::BLOTTER_ADMIN)) {
$entry_text = $event->req_POST('entry_text');
$important = !is_null($event->get_POST('important'));
// Now insert into db:
@ -103,29 +88,16 @@ class Blotter extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("blotter/editor"));
}
break;
case "remove":
/**
* Removes an entry
*/
if (!$user->can(Permissions::BLOTTER_ADMIN) || !$user->check_auth_token()) {
$this->theme->display_permission_denied();
} else {
if ($event->page_matches("blotter/remove", method: "POST", permission: Permissions::BLOTTER_ADMIN)) {
$id = int_escape($event->req_POST('id'));
$database->execute("DELETE FROM blotter WHERE id=:id", ["id" => $id]);
log_info("blotter", "Removed Entry #$id");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("blotter/editor"));
}
break;
case "list":
/**
* Displays all blotter entries
*/
if ($event->page_matches("blotter/list", method: "GET")) {
$entries = $database->get_all("SELECT * FROM blotter ORDER BY id DESC");
$this->theme->display_blotter_page($entries);
break;
}
}
/**
* Finally, display the blotter on whatever page we're viewing.

View file

@ -8,12 +8,15 @@ class BlotterTest extends ShimmiePHPUnitTestCase
{
public function testDenial(): void
{
$this->assertException(PermissionDeniedException::class, function () {
$this->get_page("blotter/editor");
$this->assert_response(403);
$this->get_page("blotter/add");
$this->assert_response(403);
$this->get_page("blotter/remove");
$this->assert_response(403);
});
$this->assertException(PermissionDeniedException::class, function () {
$this->post_page("blotter/add");
});
$this->assertException(PermissionDeniedException::class, function () {
$this->post_page("blotter/remove");
});
}
public function testAddViewRemove(): void

View file

@ -169,7 +169,7 @@ class BulkActions extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $page, $user;
if ($event->page_matches("bulk_action") && $user->can(Permissions::PERFORM_BULK_ACTIONS)) {
if ($event->page_matches("bulk_action", method: "POST", permission: Permissions::PERFORM_BULK_ACTIONS)) {
$action = $event->req_POST('bulk_action');
try {

View file

@ -30,15 +30,13 @@ class BulkAdd extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $page, $user;
if ($event->page_matches("bulk_add")) {
$dir = $event->get_POST('dir');
if ($user->can(Permissions::BULK_ADD) && $user->check_auth_token() && $dir) {
if ($event->page_matches("bulk_add", method: "POST", permission: Permissions::BULK_ADD)) {
$dir = $event->req_POST('dir');
shm_set_timeout(null);
$bae = send_event(new BulkAddEvent($dir));
$this->theme->display_upload_results($page, $bae->results);
}
}
}
public function onCliGen(CliGenEvent $event): void
{

View file

@ -16,15 +16,13 @@ class BulkAddCSV extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $page, $user;
if ($event->page_matches("bulk_add_csv")) {
$csv = $event->get_POST('csv');
if ($user->can(Permissions::BULK_ADD) && $user->check_auth_token() && $csv) {
if ($event->page_matches("bulk_add_csv", method: "POST", permission: Permissions::BULK_ADD)) {
$csv = $event->req_POST('csv');
shm_set_timeout(null);
$this->add_csv($csv);
$this->theme->display_upload_results($page);
}
}
}
public function onCliGen(CliGenEvent $event): void
{

View file

@ -201,37 +201,8 @@ class CommentList extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
if ($event->page_matches("comment")) {
switch ($event->get_arg(0)) {
case "add":
$this->onPageRequest_add($event);
break;
case "delete":
$this->onPageRequest_delete($event);
break;
case "bulk_delete":
$this->onPageRequest_bulk_delete($event);
break;
case "list":
$this->onPageRequest_list($event);
break;
case "beta-search":
$this->onPageRequest_beta_search($event);
break;
}
}
}
public function onRobotsBuilding(RobotsBuildingEvent $event): void
{
// comment lists change all the time, crawlers should
// index individual image's comments
$event->add_disallow("comment");
}
private function onPageRequest_add(PageRequestEvent $event): void
{
global $user, $page;
global $cache, $config, $database, $user, $page;
if ($event->page_matches("comment/add", method: "POST", permission: Permissions::CREATE_COMMENT)) {
try {
$i_iid = int_escape($event->req_POST('image_id'));
send_event(new CommentPostingEvent($i_iid, $user, $event->req_POST('comment')));
@ -241,27 +212,14 @@ class CommentList extends Extension
$this->theme->display_error(403, "Comment Blocked", $ex->getMessage());
}
}
private function onPageRequest_delete(PageRequestEvent $event): void
{
global $user, $page;
if ($user->can(Permissions::DELETE_COMMENT)) {
if ($event->page_matches("comment/delete", permission: Permissions::DELETE_COMMENT)) {
// FIXME: post, not args
if ($event->count_args() === 3) {
send_event(new CommentDeletionEvent(int_escape($event->get_arg(1))));
send_event(new CommentDeletionEvent(int_escape($event->get_arg(0))));
$page->flash("Deleted comment");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link("post/view/" . $event->get_arg(2))));
$page->set_redirect(referer_or(make_link("post/view/" . $event->get_arg(1))));
}
} else {
$this->theme->display_permission_denied();
}
}
private function onPageRequest_bulk_delete(PageRequestEvent $event): void
{
global $user, $database, $page;
if ($user->can(Permissions::DELETE_COMMENT)) {
if ($event->page_matches("comment/bulk_delete", method: "POST", permission: Permissions::DELETE_COMMENT)) {
$ip = $event->req_POST('ip');
$comment_ids = $database->get_col("
@ -278,15 +236,8 @@ class CommentList extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("admin"));
} else {
$this->theme->display_permission_denied();
}
}
private function onPageRequest_list(PageRequestEvent $event): void
{
global $cache, $config, $database, $user;
if ($event->page_matches("comment/list")) {
$threads_per_page = 10;
$where = SPEED_HAX ? "WHERE posted > now() - interval '24 hours'" : "";
@ -335,11 +286,9 @@ class CommentList extends Extension
$this->theme->display_comment_list($images, $current_page + 1, $total_pages, $user->can(Permissions::CREATE_COMMENT));
}
private function onPageRequest_beta_search(PageRequestEvent $event): void
{
$search = $event->get_arg(1);
$page_num = $event->try_page_num(2);
if ($event->page_matches("comment/beta-search")) {
$search = $event->get_arg(0);
$page_num = $event->try_page_num(1);
$duser = User::by_name($search);
$i_comment_count = Comment::count_comments_by_user($duser);
$com_per_page = 50;
@ -347,6 +296,14 @@ class CommentList extends Extension
$comments = $this->get_user_comments($duser->id, $com_per_page, $page_num * $com_per_page);
$this->theme->display_all_user_comments($comments, $page_num + 1, $total_pages, $duser);
}
}
public function onRobotsBuilding(RobotsBuildingEvent $event): void
{
// comment lists change all the time, crawlers should
// index individual image's comments
$event->add_disallow("comment");
}
public function onAdminBuilding(AdminBuildingEvent $event): void
{

View file

@ -16,18 +16,16 @@ class ET extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $user;
if ($event->page_matches("system_info")) {
if ($user->can(Permissions::VIEW_SYSINTO)) {
if ($event->page_matches("system_info", permission: Permissions::VIEW_SYSINFO)) {
$this->theme->display_info_page($this->to_yaml($this->get_info()));
}
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event): void
{
global $user;
if ($event->parent === "system") {
if ($user->can(Permissions::VIEW_SYSINTO)) {
if ($user->can(Permissions::VIEW_SYSINFO)) {
$event->add_nav_link("system_info", new Link('system_info'), "System Info", null, 10);
}
}
@ -36,7 +34,7 @@ class ET extends Extension
public function onUserBlockBuilding(UserBlockBuildingEvent $event): void
{
global $user;
if ($user->can(Permissions::VIEW_SYSINTO)) {
if ($user->can(Permissions::VIEW_SYSINFO)) {
$event->add_link("System Info", make_link("system_info"), 99);
}
}

View file

@ -67,13 +67,13 @@ class Favorites extends Extension
return;
} // FIXME: proper permissions
if ($event->authed_page_matches("favourite/add")) {
if ($event->page_matches("favourite/add", method: "POST")) {
$image_id = int_escape($event->get_arg(0));
send_event(new FavoriteSetEvent($image_id, $user, true));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
}
if ($event->authed_page_matches("favourite/remove")) {
if ($event->page_matches("favourite/remove", method: "POST")) {
$image_id = int_escape($event->get_arg(0));
send_event(new FavoriteSetEvent($image_id, $user, false));
$page->set_mode(PageMode::REDIRECT);

View file

@ -19,16 +19,14 @@ class Featured extends Extension
{
global $config, $page, $user;
if ($event->page_matches("featured_image")) {
if ($event->get_arg(0) == "set" && $user->check_auth_token()) {
$id = int_escape($event->get_POST('image_id'));
if ($user->can(Permissions::EDIT_FEATURE) && $id > 0) {
if ($event->page_matches("featured_image/set", method: "POST", permission: Permissions::EDIT_FEATURE)) {
$id = int_escape($event->req_POST('image_id'));
$config->set_int("featured_id", $id);
log_info("featured", "Featured post set to >>$id", "Featured post set");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$id"));
}
}
if ($event->get_arg(0) == "download") {
if ($event->page_matches("featured_image/download")) {
$image = Image::by_id($config->get_int("featured_id"));
if (!is_null($image)) {
$page->set_mode(PageMode::DATA);
@ -36,7 +34,7 @@ class Featured extends Extension
$page->set_data(file_get_contents_ex($image->get_image_filename()));
}
}
if ($event->get_arg(0) == "view") {
if ($event->page_matches("featured_image/view")) {
$image = Image::by_id($config->get_int("featured_id"));
if (!is_null($image)) {
send_event(new DisplayingImageEvent($image));

View file

@ -99,45 +99,51 @@ class Forum extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $page, $user;
if ($event->page_matches("forum")) {
switch ($event->get_arg(0)) {
case "index":
$this->show_last_threads($page, $event, $user->can(Permissions::FORUM_ADMIN));
if ($event->page_matches("forum/index")) {
if ($event->count_args() >= 2) {
$pageNumber = page_number($event->get_arg(1));
} else {
$pageNumber = 0;
}
$this->show_last_threads($page, $pageNumber, $user->can(Permissions::FORUM_ADMIN));
if (!$user->is_anonymous()) {
$this->theme->display_new_thread_composer($page);
}
break;
case "view":
}
if ($event->page_matches("forum/view")) {
$threadID = int_escape($event->get_arg(1));
// $pageNumber = int_escape($event->get_arg(2));
$errors = $this->sanity_check_viewed_thread($threadID);
if (count($errors) > 0) {
$this->theme->display_error(500, "Error", implode("<br>", $errors));
break;
throw new UserErrorException(implode("<br>", $errors));
}
$this->show_posts($event, $user->can(Permissions::FORUM_ADMIN));
$threadID = int_escape($event->get_arg(1));
if ($event->count_args() >= 3) {
$pageNumber = page_number($event->get_arg(2));
} else {
$pageNumber = 0;
}
$this->show_posts($threadID, $pageNumber, $user->can(Permissions::FORUM_ADMIN));
if ($user->can(Permissions::FORUM_ADMIN)) {
$this->theme->add_actions_block($page, $threadID);
}
if (!$user->is_anonymous()) {
$this->theme->display_new_post_composer($page, $threadID);
}
break;
case "new":
global $page;
}
if ($event->page_matches("forum/new")) {
$this->theme->display_new_thread_composer($page);
break;
case "create":
}
if ($event->page_matches("forum/create")) {
$redirectTo = "forum/index";
if (!$user->is_anonymous()) {
$errors = $this->sanity_check_new_thread();
if (count($errors) > 0) {
$this->theme->display_error(500, "Error", implode("<br>", $errors));
break;
throw new UserErrorException(implode("<br>", $errors));
}
$newThreadID = $this->save_new_thread($user);
@ -147,9 +153,8 @@ class Forum extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link($redirectTo));
break;
case "delete":
}
if ($event->page_matches("forum/delete")) {
$threadID = int_escape($event->get_arg(1));
$postID = int_escape($event->get_arg(2));
@ -159,8 +164,8 @@ class Forum extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/view/" . $threadID));
break;
case "nuke":
}
if ($event->page_matches("forum/nuke")) {
$threadID = int_escape($event->get_arg(1));
if ($user->can(Permissions::FORUM_ADMIN)) {
@ -169,29 +174,22 @@ class Forum extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/index"));
break;
case "answer":
}
if ($event->page_matches("forum/answer")) {
$threadID = int_escape($event->req_POST("threadID"));
$total_pages = $this->get_total_pages_for_thread($threadID);
if (!$user->is_anonymous()) {
$errors = $this->sanity_check_new_post();
if (count($errors) > 0) {
$this->theme->display_error(500, "Error", implode("<br>", $errors));
break;
throw new UserErrorException(implode("<br>", $errors));
}
$this->save_new_post($threadID, $user);
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/view/" . $threadID . "/" . $total_pages));
break;
default:
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/index"));
//$this->theme->display_error(400, "Invalid action", "You should check forum/index.");
break;
}
}
}
private function get_total_pages_for_thread(int $threadID): int
@ -268,18 +266,12 @@ class Forum extends Extension
return $database->get_one("SELECT t.title FROM forum_threads AS t WHERE t.id = :id ", ['id' => $threadID]);
}
private function show_last_threads(Page $page, PageRequestEvent $event, bool $showAdminOptions = false): void
private function show_last_threads(Page $page, int $pageNumber, bool $showAdminOptions = false): void
{
global $config, $database;
$threadsPerPage = $config->get_int('forumThreadsPerPage', 15);
$totalPages = (int) ceil($database->get_one("SELECT COUNT(*) FROM forum_threads") / $threadsPerPage);
if ($event->count_args() >= 2) {
$pageNumber = page_number($event->get_arg(1), $totalPages);
} else {
$pageNumber = 0;
}
$threads = $database->get_all(
"SELECT f.id, f.sticky, f.title, f.date, f.uptodate, u.name AS user_name, u.email AS user_email, u.class AS user_class, sum(1) - 1 AS response_count " .
"FROM forum_threads AS f " .
@ -295,20 +287,13 @@ class Forum extends Extension
$this->theme->display_thread_list($page, $threads, $showAdminOptions, $pageNumber + 1, $totalPages);
}
private function show_posts(PageRequestEvent $event, bool $showAdminOptions = false): void
private function show_posts(int $threadID, int $pageNumber, bool $showAdminOptions = false): void
{
global $config, $database;
$threadID = int_escape($event->get_arg(1));
$postsPerPage = $config->get_int('forumPostsPerPage', 15);
$totalPages = (int) ceil($database->get_one("SELECT COUNT(*) FROM forum_posts WHERE thread_id = :id", ['id' => $threadID]) / $postsPerPage);
$threadTitle = $this->get_thread_title($threadID);
if ($event->count_args() >= 3) {
$pageNumber = page_number($event->get_arg(2), $totalPages);
} else {
$pageNumber = 0;
}
$posts = $database->get_all(
"SELECT p.id, p.date, p.message, u.name as user_name, u.email AS user_email, u.class AS user_class " .
"FROM forum_posts AS p " .

View file

@ -88,10 +88,9 @@ class ImageIO extends Extension
$thumb_height = $config->get_int(ImageConfig::THUMB_HEIGHT, 192);
$page->add_html_header("<style>:root {--thumb-width: {$thumb_width}px; --thumb-height: {$thumb_height}px;}</style>");
if ($event->page_matches("image/delete")) {
if ($event->page_matches("image/delete", method: "POST", permission: Permissions::DELETE_IMAGE)) {
global $page, $user;
if ($user->can(Permissions::DELETE_IMAGE) && $event->get_POST('image_id') && $user->check_auth_token()) {
$image = Image::by_id(int_escape($event->get_POST('image_id')));
$image = Image::by_id(int_escape($event->req_POST('image_id')));
if ($image) {
send_event(new ImageDeletionEvent($image));
@ -102,7 +101,6 @@ class ImageIO extends Extension
$page->set_redirect(referer_or(make_link(), ['post/view']));
}
}
}
} elseif ($event->page_matches("image")) {
$num = int_escape($event->get_arg(0));
$this->send_file($num, "image", $event->GET);

View file

@ -89,10 +89,8 @@ class ImageBan extends Extension
{
global $database, $page, $user;
if ($event->page_matches("image_hash_ban")) {
if ($user->can(Permissions::BAN_IMAGE)) {
if ($event->get_arg(0) == "add") {
$user->ensure_authed();
if ($event->page_matches("image_hash_ban", permission: Permissions::BAN_IMAGE)) {
if ($event->page_matches("image_hash_ban/add", method: "POST")) {
$input = validate_input(["c_hash" => "optional,string", "c_reason" => "string", "c_image_id" => "optional,int"]);
$image = isset($input['c_image_id']) ? Image::by_id($input['c_image_id']) : null;
$hash = isset($input["c_hash"]) ? $input["c_hash"] : $image->hash;
@ -110,14 +108,15 @@ class ImageBan extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link()));
}
} elseif ($event->get_arg(0) == "remove") {
$user->ensure_authed();
}
if ($event->page_matches("image_hash_ban/remove", method: "POST")) {
$input = validate_input(["d_hash" => "string"]);
send_event(new RemoveImageHashBanEvent($input['d_hash']));
$page->flash("Post ban removed");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link()));
} elseif ($event->get_arg(0) == "list") {
}
if ($event->page_matches("image_hash_ban/list")) {
$t = new HashBanTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
@ -125,7 +124,6 @@ class ImageBan extends Extension
}
}
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event): void
{

View file

@ -180,24 +180,25 @@ class IPBan extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
if ($event->page_matches("ip_ban")) {
if ($event->page_matches("ip_ban", permission: Permissions::BAN_IP)) {
global $database, $page, $user;
if ($user->can(Permissions::BAN_IP)) {
if ($event->get_arg(0) == "create") {
if ($event->page_matches("ip_ban/create", method: "POST")) {
$user->ensure_authed();
$input = validate_input(["c_ip" => "string", "c_mode" => "string", "c_reason" => "string", "c_expires" => "optional,date"]);
send_event(new AddIPBanEvent($input['c_ip'], $input['c_mode'], $input['c_reason'], $input['c_expires']));
$page->flash("Ban for {$input['c_ip']} added");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ip_ban/list"));
} elseif ($event->get_arg(0) == "delete") {
}
if ($event->page_matches("ip_ban/delete", method: "POST")) {
$user->ensure_authed();
$input = validate_input(["d_id" => "int"]);
send_event(new RemoveIPBanEvent($input['d_id']));
$page->flash("Ban removed");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ip_ban/list"));
} elseif ($event->get_arg(0) == "list") {
}
if ($event->page_matches("ip_ban/list")) {
$event->GET['c_banner'] = $user->name;
$event->GET['c_added'] = date('Y-m-d');
$t = new IPBanTable($database->raw_db());
@ -205,9 +206,6 @@ class IPBan extends Extension
$t->inputs = $event->GET;
$this->theme->display_bans($page, $t->table($t->query()), $t->paginator());
}
} else {
$this->theme->display_permission_denied();
}
}
}

View file

@ -10,9 +10,9 @@ class IPBanTest extends ShimmiePHPUnitTestCase
public function testAccess(): void
{
$page = $this->get_page('ip_ban/list');
$this->assertEquals(403, $page->code);
$this->assertEquals("Permission Denied", $page->title);
$this->assertException(PermissionDeniedException::class, function () {
$this->get_page('ip_ban/list');
});
}
public function testIPBan(): void

View file

@ -278,14 +278,12 @@ class LogDatabase extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $database, $user;
if ($event->page_matches("log/view")) {
if ($user->can(Permissions::VIEW_EVENTLOG)) {
if ($event->page_matches("log/view", permission: Permissions::VIEW_EVENTLOG)) {
$t = new LogTable($database->raw_db());
$t->inputs = $event->GET;
$this->theme->display_crud("Event Log", $t->table($t->query()), $t->paginator());
}
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event): void
{

View file

@ -75,7 +75,7 @@ class Media extends Extension
global $page, $user;
if (
$event->authed_page_matches("media_rescan") &&
$event->page_matches("media_rescan", method: "POST") &&
$user->can(Permissions::RESCAN_MEDIA)
) {
$image = Image::by_id(int_escape($event->get_arg(0)));

View file

@ -126,10 +126,8 @@ class NotATag extends Extension
{
global $database, $page, $user;
if ($event->page_matches("untag")) {
if ($user->can(Permissions::BAN_IMAGE)) {
if ($event->get_arg(0) == "add") {
$user->ensure_authed();
if ($event->page_matches("untag", permission: Permissions::BAN_IMAGE)) {
if ($event->page_matches("untag/add", method: "POST")) {
$input = validate_input(["c_tag" => "string", "c_redirect" => "string"]);
$database->execute(
"INSERT INTO untags(tag, redirect) VALUES (:tag, :redirect)",
@ -137,8 +135,8 @@ class NotATag extends Extension
);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link()));
} elseif ($event->get_arg(0) == "remove") {
$user->ensure_authed();
}
if ($event->page_matches("untag/remove", method: "POST")) {
$input = validate_input(["d_tag" => "string"]);
$database->execute(
"DELETE FROM untags WHERE LOWER(tag) = LOWER(:tag)",
@ -147,7 +145,8 @@ class NotATag extends Extension
$page->flash("Post ban removed");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link()));
} elseif ($event->get_arg(0) == "list") {
}
if ($event->page_matches("untag/list")) {
$t = new NotATagTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
@ -156,4 +155,3 @@ class NotATag extends Extension
}
}
}
}

View file

@ -78,53 +78,49 @@ class Notes extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $page, $user;
if ($event->page_matches("note")) {
switch ($event->get_arg(0)) {
case "list": //index
$this->get_notes_list($event); // This should show images like post/list but i don't know how do that.
break;
case "requests": // The same as post/list but only for note_request table.
$this->get_notes_requests($event); // This should show images like post/list but i don't know how do that.
break;
case "search":
if ($event->page_matches("note/lost")) {
$this->get_notes_list($event->try_page_num(0)); // This should show images like post/list but i don't know how do that.
}
if ($event->page_matches("note/requests")) {
$this->get_notes_requests($event->try_page_num(0)); // This should show images like post/list but i don't know how do that.
}
if ($event->page_matches("note/search")) {
if (!$user->is_anonymous()) {
$this->theme->search_notes_page($page);
}
break;
case "updated": //Thinking how to build this function.
$this->get_histories($event);
break;
case "history": //Thinking how to build this function.
$this->get_history($event);
break;
case "revert":
$noteID = int_escape($event->get_arg(1));
$reviewID = int_escape($event->get_arg(2));
}
if ($event->page_matches("note/updated")) {
$this->get_histories($event->try_page_num(0));
}
if ($event->page_matches("note/history")) {
$this->get_history(int_escape($event->get_arg(0)), $event->try_page_num(1));
}
if ($event->page_matches("note/revert")) {
$noteID = int_escape($event->get_arg(0));
$reviewID = int_escape($event->get_arg(1));
if (!$user->is_anonymous()) {
$this->revert_history($noteID, $reviewID);
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("note/updated"));
break;
case "add_request":
}
if ($event->page_matches("note/add_request")) {
$image_id = int_escape($event->req_POST("image_id"));
if (!$user->is_anonymous()) {
$this->add_note_request($image_id);
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
break;
case "nuke_requests":
}
if ($event->page_matches("note/nuke_requests")) {
$image_id = int_escape($event->req_POST("image_id"));
if ($user->can(Permissions::NOTES_ADMIN)) {
$this->nuke_requests($image_id);
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
break;
case "create_note":
}
if ($event->page_matches("note/create_note")) {
$page->set_mode(PageMode::DATA);
if (!$user->is_anonymous()) {
$note_id = $this->add_new_note();
@ -133,22 +129,22 @@ class Notes extends Extension
'note_id' => $note_id,
]));
}
break;
case "update_note":
}
if ($event->page_matches("note/update_note")) {
$page->set_mode(PageMode::DATA);
if (!$user->is_anonymous()) {
$this->update_note();
$page->set_data(json_encode_ex(['status' => 'success']));
}
break;
case "delete_note":
}
if ($event->page_matches("note/delete_note")) {
$page->set_mode(PageMode::DATA);
if ($user->can(Permissions::NOTES_ADMIN)) {
$this->delete_note();
$page->set_data(json_encode_ex(['status' => 'success']));
}
break;
case "nuke_notes":
}
if ($event->page_matches("note/nuke_notes")) {
$image_id = int_escape($event->req_POST("image_id"));
if ($user->can(Permissions::NOTES_ADMIN)) {
$this->nuke_notes($image_id);
@ -156,13 +152,6 @@ class Notes extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
break;
default:
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("note/list"));
break;
}
}
}
@ -364,11 +353,10 @@ class Notes extends Extension
log_info("notes", "Requests deleted from {$image_id} by {$user->name}");
}
private function get_notes_list(PageRequestEvent $event): void
private function get_notes_list(int $pageNumber): void
{
global $database, $config;
$pageNumber = $event->try_page_num(1);
$notesPerPage = $config->get_int('notesNotesPerPage');
$totalPages = (int) ceil($database->get_one("SELECT COUNT(DISTINCT image_id) FROM notes") / $notesPerPage);
@ -390,12 +378,10 @@ class Notes extends Extension
$this->theme->display_note_list($images, $pageNumber + 1, $totalPages);
}
private function get_notes_requests(PageRequestEvent $event): void
private function get_notes_requests(int $pageNumber): void
{
global $config, $database;
$pageNumber = $event->try_page_num(1);
$requestsPerPage = $config->get_int('notesRequestsPerPage');
//$result = $database->get_all("SELECT * FROM pool_images WHERE pool_id=:pool_id", ['pool_id'=>$poolID]);
@ -430,17 +416,26 @@ class Notes extends Extension
INSERT INTO note_histories (note_enable, note_id, review_id, image_id, user_id, user_ip, date, x1, y1, height, width, note)
VALUES (:note_enable, :note_id, :review_id, :image_id, :user_id, :user_ip, now(), :x1, :y1, :height, :width, :note)
",
['note_enable' => $noteEnable, 'note_id' => $noteID, 'review_id' => $reviewID, 'image_id' => $imageID, 'user_id' => $user->id, 'user_ip' => get_real_ip(),
'x1' => $noteX1, 'y1' => $noteY1, 'height' => $noteHeight, 'width' => $noteWidth, 'note' => $noteText]
[
'note_enable' => $noteEnable,
'note_id' => $noteID,
'review_id' => $reviewID,
'image_id' => $imageID,
'user_id' => $user->id,
'user_ip' => get_real_ip(),
'x1' => $noteX1,
'y1' => $noteY1,
'height' => $noteHeight,
'width' => $noteWidth,
'note' => $noteText
]
);
}
private function get_histories(PageRequestEvent $event): void
private function get_histories(int $pageNumber): void
{
global $config, $database;
$pageNumber = $event->try_page_num(1);
$historiesPerPage = $config->get_int('notesHistoriesPerPage');
//ORDER BY IMAGE & DATE
@ -458,13 +453,10 @@ class Notes extends Extension
$this->theme->display_histories($histories, $pageNumber + 1, $totalPages);
}
private function get_history(PageRequestEvent $event): void
private function get_history(int $noteID, int $pageNumber): void
{
global $config, $database;
$noteID = $event->get_arg(1);
$pageNumber = $event->try_page_num(2);
$historiesPerPage = $config->get_int('notesHistoriesPerPage');
$histories = $database->get_all(

View file

@ -156,8 +156,7 @@ class NumericScore extends Extension
$html .= "</td></tr>";
}
die($html);
} elseif ($event->page_matches("numeric_score_vote") && $user->check_auth_token()) {
if ($user->can(Permissions::CREATE_VOTE)) {
} elseif ($event->page_matches("numeric_score_vote", method: "POST", permission: Permissions::CREATE_VOTE)) {
$image_id = int_escape($event->req_POST("image_id"));
$score = int_escape($event->req_POST("vote"));
if (($score == -1 || $score == 0 || $score == 1) && $image_id > 0) {
@ -165,9 +164,7 @@ class NumericScore extends Extension
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
}
} elseif ($event->page_matches("numeric_score/remove_votes_on") && $user->check_auth_token()) {
if ($user->can(Permissions::EDIT_OTHER_VOTE)) {
} elseif ($event->page_matches("numeric_score/remove_votes_on", method: "POST", permission: Permissions::EDIT_OTHER_VOTE)) {
$image_id = int_escape($event->req_POST("image_id"));
$database->execute(
"DELETE FROM numeric_score_votes WHERE image_id=:image_id",
@ -179,13 +176,10 @@ class NumericScore extends Extension
);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
}
} elseif ($event->page_matches("numeric_score/remove_votes_by") && $user->check_auth_token()) {
if ($user->can(Permissions::EDIT_OTHER_VOTE)) {
} elseif ($event->page_matches("numeric_score/remove_votes_by", method: "POST", permission: Permissions::EDIT_OTHER_VOTE)) {
$this->delete_votes_by(int_escape($event->req_POST('user_id')));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
}
} elseif ($event->page_matches("popular_by_day") || $event->page_matches("popular_by_month") || $event->page_matches("popular_by_year")) {
//FIXME: popular_by isn't linked from anywhere
list($day, $month, $year) = [date("d"), date("m"), date("Y")];

View file

@ -227,10 +227,7 @@ class PrivMsg extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $cache, $database, $page, $user;
if ($event->page_matches("pm")) {
switch ($event->get_arg(0)) {
case "read":
if ($user->can(Permissions::READ_PM)) {
if ($event->page_matches("pm/read", permission: Permissions::READ_PM)) {
$pm_id = int_escape($event->get_arg(1));
$pm = $database->get_row("SELECT * FROM private_message WHERE id = :id", ["id" => $pm_id]);
if (is_null($pm)) {
@ -247,14 +244,11 @@ class PrivMsg extends Extension
$this->theme->display_composer($page, $user, $from_user, "Re: ".$pmo->subject);
}
} else {
$this->theme->display_permission_denied();
throw new PermissionDeniedException("You do not have permission to view this PM");
}
}
break;
case "delete":
if ($user->can(Permissions::READ_PM)) {
if ($user->check_auth_token()) {
$pm_id = int_escape($event->get_POST("pm_id"));
if ($event->page_matches("pm/delete", method: "POST", permission: Permissions::READ_PM)) {
$pm_id = int_escape($event->req_POST("pm_id"));
$pm = $database->get_row("SELECT * FROM private_message WHERE id = :id", ["id" => $pm_id]);
if (is_null($pm)) {
$this->theme->display_error(404, "No such PM", "There is no PM #$pm_id");
@ -266,12 +260,8 @@ class PrivMsg extends Extension
$page->set_redirect(referer_or(make_link()));
}
}
}
break;
case "send":
if ($user->can(Permissions::SEND_PM)) {
if ($user->check_auth_token()) {
$to_id = int_escape($event->get_POST("to_id"));
if ($event->page_matches("pm/send", method: "POST", permission: Permissions::SEND_PM)) {
$to_id = int_escape($event->req_POST("to_id"));
$from_id = $user->id;
$subject = $event->req_POST("subject");
$message = $event->req_POST("message");
@ -281,13 +271,6 @@ class PrivMsg extends Extension
$page->set_redirect(referer_or(make_link()));
}
}
break;
default:
$this->theme->display_error(400, "Invalid action", "That's not something you can do with a PM");
break;
}
}
}
public function onSendPM(SendPMEvent $event): void
{

View file

@ -251,52 +251,47 @@ class Pools extends Extension
$page_num = $event->try_page_num(0);
}
$this->list_pools($page, $page_num, $search);
} elseif ($event->page_matches("pool")) {
// What action are we trying to perform?
switch ($event->get_arg(0)) {
case "new": // Show form for new pools
}
if ($event->page_matches("pool/new", method: "GET")) {
if (!$user->is_anonymous()) {
$this->theme->new_pool_composer($page);
} else {
$errMessage = "You must be registered and logged in to create a new pool.";
$this->theme->display_error(401, "Error", $errMessage);
}
break;
case "create": // ADD _POST
}
if ($event->page_matches("pool/create", method: "POST")) {
try {
$event = send_event(new PoolCreationEvent(
$pce = send_event(
new PoolCreationEvent(
$event->req_POST("title"),
$user,
bool_escape($event->req_POST("public")),
$event->req_POST("description")
));
)
);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/view/" . $event->new_id));
$page->set_redirect(make_link("pool/view/" . $pce->new_id));
} catch (PoolCreationException $e) {
$this->theme->display_error(400, "Error", $e->error);
}
break;
case "view":
$poolID = int_escape($event->get_arg(1));
$this->get_posts($event, $poolID);
break;
case "updated":
$this->get_history($event->try_page_num(1));
break;
case "revert":
}
if ($event->page_matches("pool/view", method: "GET")) {
$poolID = int_escape($event->get_arg(0));
$this->get_posts($event->try_page_num(1), $poolID);
}
if ($event->page_matches("pool/updated")) {
$this->get_history($event->try_page_num(0));
}
if ($event->page_matches("pool/revert")) {
if (!$user->is_anonymous()) {
$historyID = int_escape($event->get_arg(1));
$historyID = int_escape($event->get_arg(0));
$this->revert_history($historyID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/updated"));
}
break;
case "edit": // Edit the pool (remove images)
}
if ($event->page_matches("pool/edit")) {
$pool_id = int_escape($event->req_POST("pool_id"));
$pool = $this->get_single_pool($pool_id);
@ -311,9 +306,8 @@ class Pools extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/view/" . $pool_id));
}
break;
case "order": // Order the pool (view and change the order of images within the pool)
}
if ($event->page_matches("pool/order")) {
$pool_id = int_escape($event->req_POST("pool_id"));
$pool = $this->get_single_pool($pool_id);
@ -361,8 +355,8 @@ class Pools extends Extension
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
}
}
break;
case "reverse":
}
if ($event->page_matches("pool/reverse")) {
$pool_id = int_escape($event->req_POST("pool_id"));
$pool = $this->get_single_pool($pool_id);
@ -390,8 +384,8 @@ class Pools extends Extension
} else {
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
}
break;
case "import":
}
if ($event->page_matches("pool/import")) {
$pool_id = int_escape($event->req_POST("pool_id"));
$pool = $this->get_single_pool($pool_id);
@ -404,9 +398,8 @@ class Pools extends Extension
} else {
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
}
break;
case "add_posts":
}
if ($event->page_matches("pool/add_posts")) {
$pool_id = int_escape($event->req_POST("pool_id"));
$pool = $this->get_single_pool($pool_id);
@ -418,9 +411,8 @@ class Pools extends Extension
} else {
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
}
break;
case "remove_posts":
}
if ($event->page_matches("pool/remove_posts")) {
$pool_id = int_escape($event->req_POST("pool_id"));
$pool = $this->get_single_pool($pool_id);
@ -443,10 +435,8 @@ class Pools extends Extension
} else {
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
}
break;
case "edit_description":
}
if ($event->page_matches("pool/edit_description")) {
$pool_id = int_escape($event->req_POST("pool_id"));
$pool = $this->get_single_pool($pool_id);
@ -460,10 +450,8 @@ class Pools extends Extension
} else {
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
}
break;
case "nuke":
}
if ($event->page_matches("pool/nuke")) {
// Completely remove the given pool.
// -> Only admins and owners may do this
$pool_id = int_escape($event->req_POST("pool_id"));
@ -476,8 +464,6 @@ class Pools extends Extension
} else {
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
}
break;
}
}
}
@ -839,11 +825,10 @@ class Pools extends Extension
/**
* Retrieve all the images in a pool, given a pool ID.
*/
private function get_posts(PageRequestEvent $event, int $poolID): void
private function get_posts(int $pageNumber, int $poolID): void
{
global $config, $user, $database;
$pageNumber = $event->try_page_num(2);
$pool = $this->get_single_pool($poolID);
$imagesPerPage = $config->get_int(PoolsConfig::IMAGES_PER_PAGE);

View file

@ -43,7 +43,7 @@ class PrivateImage extends Extension
{
global $page, $user, $user_config;
if ($event->page_matches("privatize_image") && $user->can(Permissions::SET_PRIVATE_IMAGE)) {
if ($event->page_matches("privatize_image", method: "POST", permission: Permissions::SET_PRIVATE_IMAGE)) {
// Try to get the image ID
$image_id = int_escape(null_throws($event->get_arg(0)));
$image = Image::by_id($image_id);
@ -59,7 +59,7 @@ class PrivateImage extends Extension
$page->set_redirect(make_link("post/view/" . $image_id));
}
if ($event->page_matches("publicize_image")) {
if ($event->page_matches("publicize_image", method: "POST")) {
// Try to get the image ID
$image_id = int_escape(null_throws($event->get_arg(0)));
$image = Image::by_id($image_id);
@ -75,12 +75,7 @@ class PrivateImage extends Extension
$page->set_redirect(make_link("post/view/".$image_id));
}
if ($event->page_matches("user_admin")) {
if (!$user->check_auth_token()) {
return;
}
switch ($event->get_arg(0)) {
case "private_image":
if ($event->page_matches("user_admin/private_image", method: "POST")) {
$id = int_escape($event->req_POST('id'));
if ($id != $user->id) {
throw new SCoreException("Cannot change another user's settings");
@ -93,11 +88,9 @@ class PrivateImage extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("user"));
}
}
break;
}
}
}
public function onDisplayingImage(DisplayingImageEvent $event): void
{
global $user, $page;
@ -108,7 +101,6 @@ class PrivateImage extends Extension
}
}
public const SEARCH_REGEXP = "/^private:(yes|no|any)/";
public function onSearchTermParse(SearchTermParseEvent $event): void
{

View file

@ -374,10 +374,7 @@ class Ratings extends Extension
{
global $user, $page;
if ($event->page_matches("admin/bulk_rate")) {
if (!$user->can(Permissions::BULK_EDIT_IMAGE_RATING)) {
throw new PermissionDeniedException("Permission denied");
} else {
if ($event->page_matches("admin/bulk_rate", method: "POST", permission: Permissions::BULK_EDIT_IMAGE_RATING)) {
$n = 0;
while (true) {
$images = Search::find_images($n, 100, Tag::explode($event->req_POST("query")));
@ -396,7 +393,6 @@ class Ratings extends Extension
$page->set_redirect(make_link());
}
}
}
/**
* @return ImageRating[]

View file

@ -21,8 +21,8 @@ class RegenThumb extends Extension
{
global $page, $user;
if ($event->page_matches("regen_thumb") && $user->can(Permissions::DELETE_IMAGE)) {
if ($event->authed_page_matches("regen_thumb/one")) {
if ($event->page_matches("regen_thumb", method: "POST", permission: Permissions::DELETE_IMAGE)) {
if ($event->page_matches("regen_thumb/one")) {
$image = Image::by_id(int_escape($event->get_arg(0)));
$this->regenerate_thumbnail($image);

View file

@ -13,12 +13,7 @@ class ReplaceFile extends Extension
{
global $cache, $page, $user;
if ($event->page_matches("replace")) {
if (!$user->can(Permissions::REPLACE_IMAGE)) {
$this->theme->display_error(403, "Error", "{$user->name} doesn't have permission to replace images");
return;
}
if ($event->page_matches("replace", permission: Permissions::REPLACE_IMAGE)) {
$image_id = int_escape($event->get_arg(0));
$image = Image::by_id($image_id);
if (is_null($image)) {
@ -28,6 +23,7 @@ class ReplaceFile extends Extension
if($event->method == "GET") {
$this->theme->display_replace_page($page, $image_id);
} elseif($event->method == "POST") {
$user->ensure_authed();
if (!empty($event->get_POST("url"))) {
$tmp_filename = shm_tempnam("transload");
fetch_url($event->req_POST("url"), $tmp_filename);

View file

@ -52,30 +52,27 @@ class ReportImage extends Extension
{
global $page, $user;
if ($event->page_matches("image_report")) {
if ($event->get_arg(0) == "add") {
if ($event->page_matches("image_report/add")) {
$image_id = int_escape($event->req_POST('image_id'));
send_event(new AddReportedImageEvent(new ImageReport($image_id, $user->id, $event->req_POST('reason'))));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
} elseif ($event->get_arg(0) == "remove") {
if ($user->can(Permissions::VIEW_IMAGE_REPORT)) {
}
if ($event->page_matches("image_report/remove", method: "POST", permission: Permissions::VIEW_IMAGE_REPORT)) {
send_event(new RemoveReportedImageEvent(int_escape($event->req_POST('id'))));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("image_report/list"));
}
} elseif ($event->get_arg(0) == "remove_reports_by" && $user->check_auth_token()) {
if ($user->can(Permissions::VIEW_IMAGE_REPORT)) {
if ($event->page_matches("image_report/remove_reports_by", method: "POST", permission: Permissions::VIEW_IMAGE_REPORT)) {
$this->delete_reports_by(int_escape($event->req_POST('user_id')));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
}
} elseif ($event->get_arg(0) == "list") {
if ($user->can(Permissions::VIEW_IMAGE_REPORT)) {
if ($event->page_matches("image_report/list", permission: Permissions::VIEW_IMAGE_REPORT)) {
$this->theme->display_reported_images($page, $this->get_reported_images());
}
}
}
}
public function onAddReportedImage(AddReportedImageEvent $event): void
{

View file

@ -141,7 +141,7 @@ class ResizeImage extends Extension
{
global $page, $user;
if ($event->authed_page_matches("resize") && $user->can(Permissions::EDIT_FILES)) {
if ($event->page_matches("resize", method: "POST", permission: Permissions::EDIT_FILES)) {
// Try to get the image ID
$image_id = int_escape(null_throws($event->get_arg(0)));
$image = Image::by_id($image_id);

View file

@ -59,7 +59,7 @@ class RotateImage extends Extension
{
global $page, $user;
if ($event->authed_page_matches("rotate") && $user->can(Permissions::EDIT_FILES)) {
if ($event->page_matches("rotate", method: "POST", permission: Permissions::EDIT_FILES)) {
// Try to get the image ID
$image_id = int_escape(null_throws($event->get_arg(0)));
$image = Image::by_id($image_id);

View file

@ -129,10 +129,7 @@ class S3 extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $config, $page, $user;
if (
$event->authed_page_matches("s3/sync") &&
$user->can(Permissions::DELETE_IMAGE)
) {
if ($event->page_matches("s3/sync", method: "POST", permission: Permissions::DELETE_IMAGE)) {
$id = int_escape($event->get_arg(0));
$this->sync_post(Image::by_id($id));
log_info("s3", "Manual resync for >>$id", "File re-sync'ed");

View file

@ -336,10 +336,7 @@ class Setup extends Extension
$page->set_data("ok");
}
if ($event->page_matches("setup")) {
if (!$user->can(Permissions::CHANGE_SETTING)) {
$this->theme->display_permission_denied();
} else {
if ($event->page_matches("setup", permission: Permissions::CHANGE_SETTING)) {
if ($event->count_args() == 0) {
$panel = new SetupPanel($config);
send_event(new SetupBuildingEvent($panel));
@ -355,7 +352,6 @@ class Setup extends Extension
}
}
}
}
public function onSetupBuilding(SetupBuildingEvent $event): void
{

View file

@ -18,17 +18,17 @@ class SetupTest extends ShimmiePHPUnitTestCase
public function testAuthAnon(): void
{
$this->assertException(PermissionDeniedException::class, function () {
$this->get_page('setup');
$this->assert_response(403);
$this->assert_title("Permission Denied");
});
}
public function testAuthUser(): void
{
$this->log_in_as_user();
$this->assertException(PermissionDeniedException::class, function () {
$this->get_page('setup');
$this->assert_response(403);
$this->assert_title("Permission Denied");
});
}
public function testAuthAdmin(): void

View file

@ -32,15 +32,11 @@ class SourceHistory extends Extension
{
global $page, $user;
if ($event->page_matches("source_history/revert")) {
if ($event->page_matches("source_history/revert", method: "POST", permission: Permissions::EDIT_IMAGE_TAG)) {
// this is a request to revert to a previous version of the source
if ($user->can(Permissions::EDIT_IMAGE_TAG)) {
$this->process_revert_request((int)$event->req_POST('revert'));
}
} elseif ($event->page_matches("source_history/bulk_revert")) {
if ($user->can(Permissions::BULK_EDIT_IMAGE_TAG) && $user->check_auth_token()) {
} elseif ($event->page_matches("source_history/bulk_revert", method: "POST", permission: Permissions::BULK_EDIT_IMAGE_TAG)) {
$this->process_bulk_revert_request();
}
} elseif ($event->page_matches("source_history/all")) {
$page_id = int_escape($event->get_arg(0));
$this->theme->display_global_page($page, $this->get_global_source_history($page_id), $page_id);

View file

@ -69,11 +69,11 @@ class TagCategories extends Extension
{
global $database, $page, $user;
if ($event->page_matches("tags/categories")) {
if ($user->can(Permissions::EDIT_TAG_CATEGORIES)) {
$this->page_update();
if ($event->page_matches("tags/categories", method: "GET")) {
$this->theme->show_tag_categories($page, $database->get_all('SELECT * FROM image_tag_categories'));
}
if ($event->page_matches("tags/categories", method: "POST", permission: Permissions::EDIT_TAG_CATEGORIES)) {
$this->page_update();
}
}

View file

@ -146,25 +146,21 @@ class TagEdit extends Extension
public function onPageRequest(PageRequestEvent $event): void
{
global $user, $page;
if ($event->page_matches("tag_edit")) {
if ($event->page_matches("tag_edit", method: "POST", permission: Permissions::MASS_TAG_EDIT)) {
if ($event->get_arg(0) == "replace") {
if ($user->can(Permissions::MASS_TAG_EDIT)) {
$search = $event->req_POST('search');
$replace = $event->req_POST('replace');
$this->mass_tag_edit($search, $replace, true);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("admin"));
}
}
if ($event->get_arg(0) == "mass_source_set") {
if ($user->can(Permissions::MASS_TAG_EDIT)) {
$this->mass_source_edit($event->req_POST('tags'), $event->req_POST('source'));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(search_link());
}
}
}
}
public function onCliGen(CliGenEvent $event): void
{

View file

@ -26,15 +26,11 @@ class TagHistory extends Extension
{
global $page, $user;
if ($event->page_matches("tag_history/revert")) {
if ($event->page_matches("tag_history/revert", method: "POST", permission: Permissions::EDIT_IMAGE_TAG)) {
// this is a request to revert to a previous version of the tags
if ($user->can(Permissions::EDIT_IMAGE_TAG)) {
$this->process_revert_request((int)$event->req_POST('revert'));
}
} elseif ($event->page_matches("tag_history/bulk_revert")) {
if ($user->can(Permissions::BULK_EDIT_IMAGE_TAG) && $user->check_auth_token()) {
} elseif ($event->page_matches("tag_history/bulk_revert", method: "POST", permission: Permissions::BULK_EDIT_IMAGE_TAG)) {
$this->process_bulk_revert_request();
}
} elseif ($event->page_matches("tag_history/all")) {
$page_id = int_escape($event->get_arg(0));
$this->theme->display_global_page($page, $this->get_global_tag_history($page_id), $page_id);

View file

@ -67,14 +67,11 @@ class Tips extends Extension
$this->getTip();
if ($event->page_matches("tips") && $user->can(Permissions::TIPS_ADMIN)) {
switch ($event->get_arg(0)) {
case "list":
if ($event->page_matches("tips/list", permission: Permissions::TIPS_ADMIN)) {
$this->manageTips();
$this->getAll();
break;
case "save":
if ($user->check_auth_token()) {
}
if ($event->page_matches("tips/save", method: "POST", permission: Permissions::TIPS_ADMIN)) {
send_event(new CreateTipEvent(
$event->get_POST("enable") == "on",
$event->req_POST("image"),
@ -83,22 +80,19 @@ class Tips extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("tips/list"));
}
break;
case "status":
if ($event->page_matches("tips/status", permission: Permissions::TIPS_ADMIN)) {
// FIXME: HTTP GET CSRF
$tipID = int_escape($event->get_arg(1));
$this->setStatus($tipID);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("tips/list"));
break;
case "delete":
}
if ($event->page_matches("tips/delete", permission: Permissions::TIPS_ADMIN)) {
// FIXME: HTTP GET CSRF
$tipID = int_escape($event->get_arg(1));
send_event(new DeleteTipEvent($tipID));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("tips/list"));
break;
}
}
}

View file

@ -207,7 +207,7 @@ class TranscodeImage extends Extension
{
global $page, $user;
if ($event->page_matches("transcode") && $user->can(Permissions::EDIT_FILES)) {
if ($event->page_matches("transcode", method: "POST", permission: Permissions::EDIT_FILES)) {
$image_id = int_escape($event->get_arg(0));
$image_obj = Image::by_id($image_id);
if (is_null($image_obj)) {

View file

@ -101,7 +101,7 @@ class TranscodeVideo extends Extension
{
global $page, $user;
if ($event->page_matches("transcode_video") && $user->can(Permissions::EDIT_FILES)) {
if ($event->page_matches("transcode_video", method: "POST", permission: Permissions::EDIT_FILES)) {
$image_id = int_escape($event->get_arg(0));
$image_obj = Image::by_id($image_id);
if (is_null($image_obj)) {

View file

@ -29,7 +29,7 @@ class Trash extends Extension
{
global $page, $user;
if ($event->page_matches("trash_restore") && $user->can(Permissions::VIEW_TRASH)) {
if ($event->page_matches("trash_restore", method: "POST", permission: Permissions::VIEW_TRASH)) {
$image_id = int_escape(null_throws($event->get_arg(0)));
self::set_trash($image_id, false);
$page->set_mode(PageMode::REDIRECT);

View file

@ -36,8 +36,9 @@ class Update extends Extension
global $user, $page;
$sha = $event->get_GET('sha');
if ($user->can(Permissions::EDIT_FILES) && $sha) {
if ($event->page_matches("update/download")) {
// FIXME: use POST
if ($event->page_matches("update/download", permission: Permissions::EDIT_FILES)) {
assert(!is_null($sha));
$ok = $this->download_shimmie($sha);
$page->set_mode(PageMode::REDIRECT);
@ -46,7 +47,9 @@ class Update extends Extension
} else {
$page->set_redirect(make_link("admin"));
} //TODO: Show error?
} elseif ($event->page_matches("update/update")) {
}
if ($event->page_matches("update/update", permission: Permissions::EDIT_FILES)) {
assert(!is_null($sha));
$ok = $this->update_shimmie($sha);
$page->set_mode(PageMode::REDIRECT);
@ -58,7 +61,6 @@ class Update extends Extension
} //TODO: Show error?
}
}
}
private function download_shimmie(string $commitSHA): bool
{

View file

@ -216,11 +216,7 @@ class Upload extends Extension
}
}
if ($event->page_matches("upload")) {
if (!$user->can(Permissions::CREATE_IMAGE)) {
$this->theme->display_error(403, "Error", "{$user->name} doesn't have permission to upload images");
return;
}
if ($event->page_matches("upload", permission: Permissions::CREATE_IMAGE)) {
if ($this->is_full) {
$this->theme->display_error(507, "Error", "Can't upload images: disk nearly full");
return;

View file

@ -169,29 +169,61 @@ class UserPage extends Extension
$page->add_html_header("<style>.hb {display: none !important;}</style>");
}
if ($event->page_matches("user_admin")) {
if ($event->get_arg(0) == "login") {
if ($event->method == "POST") {
$this->page_login($event->req_POST('user'), $event->req_POST('pass'));
} else {
if ($event->page_matches("user_admin/login", method: "GET")) {
$this->theme->display_login_page($page);
}
} elseif ($event->get_arg(0) == "recover") {
if ($event->page_matches("user_admin/login", method: "POST", authed: false)) {
$this->page_login($event->req_POST('user'), $event->req_POST('pass'));
}
if ($event->page_matches("user_admin/recover", method: "POST")) {
$this->page_recover($event->req_POST('username'));
} elseif ($event->get_arg(0) == "create") {
$this->page_create($event);
} elseif ($event->get_arg(0) == "create_other") {
send_event(new UserCreationEvent(
}
if ($event->page_matches("user_admin/create", method: "GET", permission: Permissions::CREATE_USER)) {
global $config, $page, $user;
if (!$config->get_bool("login_signup_enabled")) {
$this->theme->display_signups_disabled($page);
return;
}
$this->theme->display_signup_page($page);
}
if ($event->page_matches("user_admin/create", method: "POST", authed: false, permission: Permissions::CREATE_USER)) {
global $config, $page, $user;
if (!$config->get_bool("login_signup_enabled")) {
$this->theme->display_signups_disabled($page);
return;
}
try {
$uce = send_event(
new UserCreationEvent(
$event->req_POST('name'),
$event->req_POST('pass1'),
$event->req_POST('pass2'),
$event->req_POST('email'),
true
)
);
$this->set_login_cookie($uce->username);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("user"));
} catch (UserCreationException $ex) {
$this->theme->display_error(400, "User Creation Error", $ex->getMessage());
}
}
if ($event->page_matches("user_admin/create_other", method: "POST", permission: Permissions::CREATE_OTHER_USER)) {
send_event(
new UserCreationEvent(
$event->req_POST("name"),
$event->req_POST("pass1"),
$event->req_POST("pass1"),
$event->req_POST("email"),
false
));
)
);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("admin"));
$page->flash("Created new user");
} elseif ($event->get_arg(0) == "list") {
}
if ($event->page_matches("user_admin/list", method: "GET")) {
$t = new UserTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
@ -201,48 +233,79 @@ class UserPage extends Extension
array_splice($t->columns, 2, 0, [$col]);
}
$this->theme->display_crud("Users", $t->table($t->query()), $t->paginator());
} elseif ($event->get_arg(0) == "classes") {
}
if ($event->page_matches("user_admin/classes", method: "GET")) {
$this->theme->display_user_classes(
$page,
UserClass::$known_classes,
(new \ReflectionClass(Permissions::class))->getReflectionConstants()
);
} elseif ($event->get_arg(0) == "logout") {
}
if ($event->page_matches("user_admin/logout", method: "GET")) {
// FIXME: security
$this->page_logout();
}
if (!$user->check_auth_token()) {
return;
} elseif ($event->get_arg(0) == "change_name") {
if ($event->page_matches("user_admin/change_name", method: "POST", permission: Permissions::EDIT_USER_NAME)) {
$input = validate_input([
'id' => 'user_id,exists',
'name' => 'user_name',
]);
$duser = User::by_id($input['id']);
$this->change_name_wrapper($duser, $input['name']);
} elseif ($event->get_arg(0) == "change_pass") {
if ($this->user_can_edit_user($user, $duser)) {
$duser->set_name($input['name']);
$page->flash("Username changed");
// TODO: set login cookie if user changed themselves
$this->redirect_to_user($duser);
}
}
if ($event->page_matches("user_admin/change_pass", method: "POST")) {
$input = validate_input([
'id' => 'user_id,exists',
'pass1' => 'password',
'pass2' => 'password',
]);
$duser = User::by_id($input['id']);
$this->change_password_wrapper($duser, $input['pass1'], $input['pass2']);
} elseif ($event->get_arg(0) == "change_email") {
if ($this->user_can_edit_user($user, $duser)) {
if ($input['pass1'] != $input['pass2']) {
throw new UserErrorException("Passwords don't match");
} else {
// FIXME: send_event()
$duser->set_password($input['pass1']);
if ($duser->id == $user->id) {
$this->set_login_cookie($duser->name);
}
$page->flash("Password changed");
$this->redirect_to_user($duser);
}
}
}
if ($event->page_matches("user_admin/change_email", method: "POST")) {
$input = validate_input([
'id' => 'user_id,exists',
'address' => 'email',
]);
$duser = User::by_id($input['id']);
$this->change_email_wrapper($duser, $input['address']);
} elseif ($event->get_arg(0) == "change_class") {
if ($this->user_can_edit_user($user, $duser)) {
$duser->set_email($input['address']);
$page->flash("Email changed");
$this->redirect_to_user($duser);
}
}
if ($event->page_matches("user_admin/change_class", method: "POST")) {
$input = validate_input([
'id' => 'user_id,exists',
'class' => 'user_class',
]);
$duser = User::by_id($input['id']);
$this->change_class_wrapper($duser, $input['class']);
} elseif ($event->get_arg(0) == "delete_user") {
// hard-coded that only admins can change people's classes
if ($user->class->name == "admin") {
$duser->set_class($input['class']);
$page->flash("Class changed");
$this->redirect_to_user($duser);
}
}
if ($event->page_matches("user_admin/delete_user", method: "POST", permission: Permissions::DELETE_USER)) {
$this->delete_user(
$page,
int_escape($event->req_POST('id')),
@ -250,7 +313,6 @@ class UserPage extends Extension
$event->get_POST("with_comments") == "on"
);
}
}
if ($event->page_matches("user")) {
$display_user = ($event->count_args() == 0) ? $user : User::by_name($event->get_arg(0));
@ -294,7 +356,8 @@ class UserPage extends Extension
$av = $event->display_user->get_avatar_html();
if ($av) {
$event->add_stats($av, 0);
} elseif ((
} elseif (
(
$config->get_string("avatar_host") == "gravatar"
) &&
($user->id == $event->display_user->id)
@ -496,8 +559,10 @@ class UserPage extends Extension
public static function has_user_query(array $context): bool
{
foreach ($context as $term) {
if (preg_match(self::USER_SEARCH_REGEX, $term) ||
preg_match(self::USER_ID_SEARCH_REGEX, $term)) {
if (
preg_match(self::USER_SEARCH_REGEX, $term) ||
preg_match(self::USER_ID_SEARCH_REGEX, $term)
) {
return true;
}
}
@ -606,38 +671,6 @@ class UserPage extends Extension
}
}
private function page_create(PageRequestEvent $event): void
{
global $config, $page, $user;
if (!$user->can(Permissions::CREATE_USER)) {
$this->theme->display_error(403, "Account creation blocked", "Account creation is currently disabled");
return;
}
if (!$config->get_bool("login_signup_enabled")) {
$this->theme->display_signups_disabled($page);
return;
}
if ($event->method == "GET") {
$this->theme->display_signup_page($page);
} else {
try {
$uce = send_event(new UserCreationEvent(
$event->req_POST('name'),
$event->req_POST('pass1'),
$event->req_POST('pass2'),
$event->req_POST('email'),
true
));
$this->set_login_cookie($uce->username);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("user"));
} catch (UserCreationException $ex) {
$this->theme->display_error(400, "User Creation Error", $ex->getMessage());
}
}
}
private function create_user(UserCreationEvent $event): User
{
global $database;
@ -720,64 +753,6 @@ class UserPage extends Extension
}
}
private function change_name_wrapper(User $duser, string $name): void
{
global $page, $user;
if ($user->can(Permissions::EDIT_USER_NAME) && $this->user_can_edit_user($user, $duser)) {
$duser->set_name($name);
$page->flash("Username changed");
// TODO: set login cookie if user changed themselves
$this->redirect_to_user($duser);
} else {
$this->theme->display_error(400, "Error", "Permission denied");
}
}
private function change_password_wrapper(User $duser, string $pass1, string $pass2): void
{
global $page, $user;
if ($this->user_can_edit_user($user, $duser)) {
if ($pass1 != $pass2) {
$this->theme->display_error(400, "Error", "Passwords don't match");
} else {
// FIXME: send_event()
$duser->set_password($pass1);
if ($duser->id == $user->id) {
$this->set_login_cookie($duser->name);
}
$page->flash("Password changed");
$this->redirect_to_user($duser);
}
}
}
private function change_email_wrapper(User $duser, string $address): void
{
global $page, $user;
if ($this->user_can_edit_user($user, $duser)) {
$duser->set_email($address);
$page->flash("Email changed");
$this->redirect_to_user($duser);
}
}
private function change_class_wrapper(User $duser, string $class): void
{
global $page, $user;
if ($user->class->name == "admin") {
$duser->set_class($class);
$page->flash("Class changed");
$this->redirect_to_user($duser);
}
}
/**
* @return array<string, int>
*/
@ -837,9 +812,6 @@ class UserPage extends Extension
$page->set_heading("Error");
$page->add_block(new NavBlock());
if (!$user->can(Permissions::DELETE_USER)) {
$page->add_block(new Block("Not Admin", "Only admins can delete accounts"));
} else {
$duser = User::by_id($uid);
log_warning("user", "Deleting user #{$uid} (@{$duser->name})");
@ -880,4 +852,3 @@ class UserPage extends Extension
$page->set_redirect(make_link());
}
}
}

View file

@ -58,7 +58,7 @@ class UserPageTest extends ShimmiePHPUnitTestCase
{
global $page;
$this->assertException(UserCreationException::class, function () {
$this->assertException(PermissionDeniedException::class, function () {
$this->log_out();
$this->post_page('user_admin/create_other', [
'name' => 'testnew',

View file

@ -125,26 +125,15 @@ class UserConfig extends Extension
}
}
if ($event->page_matches("user_admin")) {
if (!$user->check_auth_token()) {
return;
}
switch ($event->get_arg(0)) {
case "reset_api_key":
if ($event->page_matches("user_admin/reset_api_key", method: "POST")) {
$user_config->set_string(self::API_KEY, "");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("user"));
break;
}
}
}
if ($event->page_matches("user_config")) {
if (!$user->can(Permissions::CHANGE_USER_SETTING)) {
$this->theme->display_permission_denied();
} else {
if ($event->page_matches("user_config", permission: Permissions::CHANGE_USER_SETTING)) {
if ($event->count_args() == 0) {
$uobe = send_event(new UserOptionsBuildingEvent($user, new SetupPanel($user_config)));
$this->theme->display_user_config_page($page, $uobe->user, $uobe->panel);
@ -155,8 +144,7 @@ class UserConfig extends Extension
$duser = User::by_id($input['id']);
if ($user->id != $duser->id && !$user->can(Permissions::CHANGE_OTHER_USER_SETTING)) {
$this->theme->display_permission_denied();
return;
throw new PermissionDeniedException("You do not have permission to change other user's settings");
}
$target_config = UserConfig::get_for_user($duser->id);
@ -168,7 +156,6 @@ class UserConfig extends Extension
}
}
}
}
public function onUserOperationsBuilding(UserOperationsBuildingEvent $event): void
{

View file

@ -10,9 +10,9 @@ class UserConfigTest extends ShimmiePHPUnitTestCase
public function testUserConfigPage(): void
{
$this->assertException(PermissionDeniedException::class, function () {
$this->get_page('user_config');
$this->assert_title("Permission Denied");
$this->assert_no_text(self::OPTIONS_BLOCK_TITLE);
});
$this->log_in_as_user();
$this->get_page('user_config');

View file

@ -72,7 +72,7 @@ class ViewPost extends Extension
} else {
$this->theme->display_error(404, "Post not found", "No post in the database has the ID #$image_id");
}
} elseif ($event->page_matches("post/set")) {
} elseif ($event->page_matches("post/set", method: "POST")) {
$image_id = int_escape($event->req_POST('image_id'));
$image = Image::by_id($image_id);
if (!$image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK)) {

View file

@ -197,7 +197,7 @@ class Wiki extends Extension
if ($this->can_edit($user, $content)) {
$this->theme->display_page_editor($page, $content);
} else {
$this->theme->display_permission_denied();
throw new PermissionDeniedException("You are not allowed to edit this page");
}
} elseif($action == "save" && $user->check_auth_token()) {
$rev = int_escape($event->req_POST('revision'));
@ -214,7 +214,7 @@ class Wiki extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("wiki/$u_title"));
} else {
$this->theme->display_permission_denied();
throw new PermissionDeniedException("You are not allowed to edit this page");
}
} elseif($action == "delete_revision" && $user->check_auth_token()) {
$content = $this->get_page($title);
@ -225,7 +225,7 @@ class Wiki extends Extension
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("wiki/$u_title"));
} else {
$this->theme->display_permission_denied();
throw new PermissionDeniedException("You are not allowed to edit this page");
}
} elseif($action == "delete_all" && $user->check_auth_token()) {
if ($user->can(Permissions::WIKI_ADMIN)) {

View file

@ -22,8 +22,9 @@ class WikiTest extends ShimmiePHPUnitTestCase
$this->assert_title("test");
$this->assert_text("This is a default page");
$this->assertException(PermissionDeniedException::class, function () {
$this->get_page("wiki/test/edit");
$this->assert_no_text("Editor");
});
}
// Admins can edit

View file

@ -105,7 +105,15 @@ try {
if ($database->is_transaction_open()) {
$database->rollback();
}
if(is_a($e, \Shimmie2\UserErrorException::class)) {
$page->set_mode(PageMode::PAGE);
$page->set_code($e->http_code);
$page->set_title("Error");
$page->add_block(new Block(null, \MicroHTML\SPAN($e->getMessage())));
$page->display();
} else {
_fatal_error($e);
}
$exit_code = 1;
} finally {
$_tracer->end();