From 799de10f502d6970244dc7cac6a4a36759cee9d7 Mon Sep 17 00:00:00 2001 From: Floorb <132411956+Neetpone@users.noreply.github.com> Date: Sat, 13 May 2023 21:19:35 -0400 Subject: [PATCH] feat: add moderator role system --- config/site.example.php | 4 +- includes/Helpers/AbilityHelper.php | 44 ++++------ includes/Models/User.php | 3 + includes/common.php | 2 - includes/functions.php | 6 +- public/admin/common.php | 12 ++- public/admin/configuration.php | 35 +------- public/admin/index.php | 2 +- public/admin/menu.php | 31 ++++--- public/admin/pastes.php | 3 + public/admin/users.php | 4 +- theme/bulma/common.php | 3 +- theme/bulma/main.php | 136 ++--------------------------- theme/bulma/view.php | 2 +- 14 files changed, 76 insertions(+), 211 deletions(-) diff --git a/config/site.example.php b/config/site.example.php index b8bb696..3ad1765 100644 --- a/config/site.example.php +++ b/config/site.example.php @@ -5,11 +5,9 @@ return array ( array ( 'title' => 'PonePaste', 'description' => 'PonePaste can store green', - 'baseurl' => 'ponepaste.local/', 'keywords' => '', 'site_name' => 'PonePaste', - 'email' => '', - 'additional_scripts' => '', + 'email' => '' ), 'interface' => array ( diff --git a/includes/Helpers/AbilityHelper.php b/includes/Helpers/AbilityHelper.php index f4df8e2..167c11f 100644 --- a/includes/Helpers/AbilityHelper.php +++ b/includes/Helpers/AbilityHelper.php @@ -14,54 +14,44 @@ class AbilityHelper { } public function can(string $action, mixed $subject) : bool { - if ($this->user && $this->user->admin) { + if ($this->user !== null + && $this->user->role == User::ROLE_ADMIN) { // Admins can do anything return true; } return $this->modelToActions[$subject::class][$action]($this->user, $subject); - -// $is_destructive = in_array($action, self::DESTRUCTIVE_ACTIONS); -// -// if (is_a($subject, 'PonePaste\\Models\\Paste')) { -// if (((int) $subject->visible === Paste::VISIBILITY_PRIVATE) || $is_destructive) { -// return $this->user !== null && $subject->user_id === $this->user->id; -// } -// -// if ($subject->is_hidden) { -// return false; -// } -// -// return true; -// } -// -// if (is_a($subject, 'PonePaste\\Models\\User')) { -// return !$is_destructive || ($this->user !== null && $subject->id === $this->user->id); -// } -// -// return false; } private function setupAllowedActions() : void { $this->modelToActions['PonePaste\\Models\\Paste'] = [ 'view' => function(User | null $user, Paste $paste) { - return ((int) $paste->visible !== Paste::VISIBILITY_PRIVATE && !$paste->is_hidden) || ($user !== null && $user->id === $paste->user_id); + $publicly_visible = ((int) $paste->visible !== Paste::VISIBILITY_PRIVATE) && !$paste->is_hidden; + + return $publicly_visible // Everyone can see public pastes + || ($user !== null && $user->id === $paste->user_id) // Creators of pastes can see their own private pastes + || $user->role >= User::ROLE_MODERATOR; // Moderators and above can see all pastes }, 'edit' => function(User | null $user, Paste $paste) { - return $user !== null && $user->id === $paste->user_id; + return $user !== null + && $user->id === $paste->user_id; // Creators of non-anonymous pastes can edit their own pastes }, 'hide' => function(User | null $user, Paste $paste) { - return $user !== null && $user->admin; + return $user !== null + && $user->role >= User::ROLE_MODERATOR; // Moderators and above can hide pastes }, 'delete' => function(User | null $user, Paste $paste) { - return $user !== null && $user->id === $paste->user_id; + return $user !== null + && ($user->id === $paste->user_id // Creators of pastes can delete their own pastes + || $user->role >= User::ROLE_ADMIN); // Admins can delete all pastes } ]; $this->modelToActions['PonePaste\\Models\\User'] = [ 'view' => function(User | null $user, User $subject) { - return true; + return true; // Everyone can view users }, 'edit' => function(User | null $user, User $subject) { - return $user !== null && $user->id === $subject->id; + return $user !== null + && $user->id === $subject->id; // Users can edit their own profiles }, ]; } diff --git a/includes/Models/User.php b/includes/Models/User.php index 55f0334..c7bf6bd 100644 --- a/includes/Models/User.php +++ b/includes/Models/User.php @@ -4,6 +4,9 @@ namespace PonePaste\Models; use Illuminate\Database\Eloquent\Model; class User extends Model { + public const ROLE_MODERATOR = 1; + public const ROLE_ADMIN = 2; + protected $table = 'users'; protected $fillable = [ 'username', 'password', 'recovery_code_hash' diff --git a/includes/common.php b/includes/common.php index c678b28..a21a399 100644 --- a/includes/common.php +++ b/includes/common.php @@ -249,10 +249,8 @@ $site_info = getSiteInfo(); $global_site_info = $site_info['site_info']; $row = $site_info['site_info']; $title = trim($row['title']); -$baseurl = paste_protocol() . rtrim(trim($row['baseurl']), '/'); $site_name = trim($row['site_name']); $email = trim($row['email']); -$additional_scripts = trim($row['additional_scripts']); // Setup theme $default_theme = 'bulma'; diff --git a/includes/functions.php b/includes/functions.php index e00b8ef..c698bab 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -147,7 +147,7 @@ function truncate(string $input, int $maxWords, int $maxChars) : string { } function embedView($paste_id, $p_title, $content, $title) : bool { - global $baseurl; + $baseurl = pp_site_url(); $stats = false; if ($content) { @@ -238,6 +238,10 @@ function paste_protocol() : string { return !empty($_SERVER['HTTPS']) ? 'https://' : 'http://'; } +function pp_site_url() : string { + return paste_protocol() . $_SERVER['HTTP_HOST']; +} + /* get rid of unintended wildcards in a parameter to LIKE queries; not a security issue, just unexpected behaviour. */ function escapeLikeQuery(string $query) : string { return str_replace(['\\', '_', '%'], ['\\\\', '\\_', '\\%'], $query); diff --git a/public/admin/common.php b/public/admin/common.php index 4ae35b3..94f0dfe 100644 --- a/public/admin/common.php +++ b/public/admin/common.php @@ -18,7 +18,7 @@ function updateAdminHistory(User $admin, int $action) : void { $log->save(); } -if ($current_user === null || !$current_user->admin) { +if ($current_user === null || $current_user->role < User::ROLE_MODERATOR) { header('Location: ..'); die(); } @@ -37,4 +37,14 @@ if (isset($_GET['logout'])) { exit(); } +function checkAdminAccess(int $role) { + global $current_user; + + if ($current_user === null || $current_user->role < $role) { + flashError('You do not have access to this page.'); + header('Location: /admin/'); + die(); + } +} + $flashes = getFlashes(); diff --git a/public/admin/configuration.php b/public/admin/configuration.php index df049c3..5efc976 100644 --- a/public/admin/configuration.php +++ b/public/admin/configuration.php @@ -1,10 +1,13 @@ trim($data['title']), 'description' => trim($data['description']), - 'baseurl' => trim($data['baseurl']), 'keywords' => trim($data['keywords']), 'site_name' => trim($data['site_name']), - 'email' => trim($data['email']), - 'additional_scripts' => trim($data['additional_scripts']) + 'email' => trim($data['email']) ]; $current_config['site_info'] = $new_site_info; @@ -167,22 +168,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { -
- -
- - ; - -
-
- -
-
-
@@ -214,18 +199,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
-
- -
- -
-
-
diff --git a/public/admin/index.php b/public/admin/index.php index 7efe277..6ffa202 100644 --- a/public/admin/index.php +++ b/public/admin/index.php @@ -15,7 +15,7 @@ function updateAdminHistory(User $admin, int $action) : void { $log->save(); } -if ($current_user === null || !$current_user->admin) { +if ($current_user === null || $current_user->role < User::ROLE_MODERATOR) { header('Location: ..'); die(); } diff --git a/public/admin/menu.php b/public/admin/menu.php index 61ea563..d01c9f0 100644 --- a/public/admin/menu.php +++ b/public/admin/menu.php @@ -1,11 +1,14 @@ 'Dashboard', 'icon' => 'fa-home', 'path' => '/admin/dashboard.php'], - ['name' => 'Configuration', 'icon' => 'fa-cogs', 'path' => '/admin/configuration.php'], - ['name' => 'Admin Password', 'icon' => 'fa-user', 'path' => '/admin/admin.php'], - ['name' => 'Reports', 'icon' => 'fa-flag', 'path' => '/admin/reports.php'], - ['name' => 'Pastes', 'icon' => 'fa-clipboard', 'path' => '/admin/pastes.php'], - ['name' => 'Users', 'icon' => 'fa-users', 'path' => '/admin/users.php'] + +use PonePaste\Models\User; + +$menu_options = [ + ['name' => 'Dashboard', 'icon' => 'fa-home', 'path' => '/admin/dashboard.php', 'access' => User::ROLE_MODERATOR], + ['name' => 'Configuration', 'icon' => 'fa-cogs', 'path' => '/admin/configuration.php', 'access' => User::ROLE_ADMIN], + ['name' => 'Admin Password', 'icon' => 'fa-user', 'path' => '/admin/admin.php', 'access' => User::ROLE_MODERATOR], + ['name' => 'Reports', 'icon' => 'fa-flag', 'path' => '/admin/reports.php', 'access' => User::ROLE_MODERATOR], + ['name' => 'Pastes', 'icon' => 'fa-clipboard', 'path' => '/admin/pastes.php', 'access' => User::ROLE_ADMIN], + ['name' => 'Users', 'icon' => 'fa-users', 'path' => '/admin/users.php', 'access' => User::ROLE_ADMIN] ]; $current_path = $_SERVER['PHP_SELF']; ?> @@ -13,12 +16,14 @@
diff --git a/public/admin/pastes.php b/public/admin/pastes.php index fe8e750..f5ba848 100644 --- a/public/admin/pastes.php +++ b/public/admin/pastes.php @@ -3,6 +3,9 @@ define('IN_PONEPASTE', 1); require_once(__DIR__ . '/common.php'); use PonePaste\Models\Paste; +use PonePaste\Models\User; + +checkAdminAccess(User::ROLE_ADMIN); list($per_page, $current_page) = pp_setup_pagination(); diff --git a/public/admin/users.php b/public/admin/users.php index 055fb33..9f2fe91 100644 --- a/public/admin/users.php +++ b/public/admin/users.php @@ -5,14 +5,13 @@ use PonePaste\Models\User; define('IN_PONEPASTE', 1); require_once(__DIR__ . '/common.php'); +checkAdminAccess(User::ROLE_ADMIN); list($per_page, $current_page) = pp_setup_pagination(); $total_users = User::count(); $all_users = User::limit($per_page)->offset($current_page * $per_page)->get(); - ?> - @@ -24,7 +23,6 @@ $all_users = User::limit($per_page)->offset($current_page * $per_page)->get(); -
-
diff --git a/theme/bulma/view.php b/theme/bulma/view.php index c5af083..12c1c7f 100644 --- a/theme/bulma/view.php +++ b/theme/bulma/view.php @@ -127,7 +127,7 @@ $selectedloader = "$bg[$i]"; // set variable equal to which random filename was title="Full Screen">