From 1f7def05c15f77fe5556415a9f30ede41e0221c4 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 23 Jun 2026 14:04:12 -0500 Subject: [PATCH 1/2] feat: complete config.xml and access.xml (#137) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit config.xml: - Defaults fieldset: archive format, MokoRestore mode, sanitization defaults (passwords, emails, sessions), log retention days - Global ntfy fieldset: server, topic, token (fallback for profiles) access.xml: - mokosuitebackup.backup.purge — bulk delete old backups - mokosuitebackup.backup.compare — compare two backups - mokosuitebackup.backup.browse — browse archive file listings 30+ new language strings for all fields and ACL actions. Partial #137 (ACL enforcement audit in separate commit) --- .../packages/com_mokosuitebackup/access.xml | 3 + .../packages/com_mokosuitebackup/config.xml | 93 +++++++++++++++++++ .../language/en-GB/com_mokosuitebackup.ini | 32 +++++++ 3 files changed, 128 insertions(+) diff --git a/source/packages/com_mokosuitebackup/access.xml b/source/packages/com_mokosuitebackup/access.xml index 53fcc84..37c2f9d 100644 --- a/source/packages/com_mokosuitebackup/access.xml +++ b/source/packages/com_mokosuitebackup/access.xml @@ -12,5 +12,8 @@ + + + diff --git a/source/packages/com_mokosuitebackup/config.xml b/source/packages/com_mokosuitebackup/config.xml index 6fdd1ad..ff63899 100644 --- a/source/packages/com_mokosuitebackup/config.xml +++ b/source/packages/com_mokosuitebackup/config.xml @@ -39,6 +39,73 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+
Date: Tue, 23 Jun 2026 14:16:54 -0500 Subject: [PATCH 2/2] fix: enforce correct ACL permissions across all controllers (#137) 13 ACL fixes across 5 files: - BackupsController: purge() uses backup.purge (was core.delete) - SnapshotsController: delete() uses snapshot.manage (was core.delete) - AjaxController: restoreInit/Step use backup.restore (was backup.run), browseArchive uses backup.browse (was core.manage), countPurge uses backup.purge (was core.delete), compareBackups uses backup.compare (was core.manage) - API SnapshotsController: displayList/download use snapshot.manage (was core.manage) - HtmlView: verify gated by core.manage, compare by backup.compare, purge separated from delete with backup.purge Closes #137 --- .../api/src/Controller/SnapshotsController.php | 4 ++-- .../src/Controller/AjaxController.php | 10 +++++----- .../src/Controller/BackupsController.php | 2 +- .../src/Controller/SnapshotsController.php | 2 +- .../com_mokosuitebackup/src/View/Backups/HtmlView.php | 9 +++++++-- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/source/packages/com_mokosuitebackup/api/src/Controller/SnapshotsController.php b/source/packages/com_mokosuitebackup/api/src/Controller/SnapshotsController.php index 92c3eb5..0d77d96 100644 --- a/source/packages/com_mokosuitebackup/api/src/Controller/SnapshotsController.php +++ b/source/packages/com_mokosuitebackup/api/src/Controller/SnapshotsController.php @@ -36,7 +36,7 @@ class SnapshotsController extends ApiController */ public function displayList(): static { - if (!$this->app->getIdentity()->authorise('core.manage', 'com_mokosuitebackup')) { + if (!$this->app->getIdentity()->authorise('mokosuitebackup.snapshot.manage', 'com_mokosuitebackup')) { $this->app->setHeader('status', 403); echo json_encode(['errors' => [['title' => 'Access denied']]]); $this->app->close(); @@ -250,7 +250,7 @@ class SnapshotsController extends ApiController */ public function download(): static { - if (!$this->app->getIdentity()->authorise('core.manage', 'com_mokosuitebackup')) { + if (!$this->app->getIdentity()->authorise('mokosuitebackup.snapshot.manage', 'com_mokosuitebackup')) { $this->app->setHeader('status', 403); echo json_encode(['errors' => [['title' => 'Access denied']]]); $this->app->close(); diff --git a/source/packages/com_mokosuitebackup/src/Controller/AjaxController.php b/source/packages/com_mokosuitebackup/src/Controller/AjaxController.php index fb38651..191dc50 100644 --- a/source/packages/com_mokosuitebackup/src/Controller/AjaxController.php +++ b/source/packages/com_mokosuitebackup/src/Controller/AjaxController.php @@ -348,7 +348,7 @@ class AjaxController extends BaseController return; } - if (!$this->app->getIdentity()->authorise('mokosuitebackup.backup.run', 'com_mokosuitebackup')) { + if (!$this->app->getIdentity()->authorise('mokosuitebackup.backup.restore', 'com_mokosuitebackup')) { $this->sendJson(['error' => true, 'message' => 'Access denied'], 403); return; @@ -384,7 +384,7 @@ class AjaxController extends BaseController return; } - if (!$this->app->getIdentity()->authorise('mokosuitebackup.backup.run', 'com_mokosuitebackup')) { + if (!$this->app->getIdentity()->authorise('mokosuitebackup.backup.restore', 'com_mokosuitebackup')) { $this->sendJson(['error' => true, 'message' => 'Access denied'], 403); return; @@ -416,7 +416,7 @@ class AjaxController extends BaseController return; } - if (!$this->app->getIdentity()->authorise('core.manage', 'com_mokosuitebackup')) { + if (!$this->app->getIdentity()->authorise('mokosuitebackup.backup.browse', 'com_mokosuitebackup')) { $this->sendJson(['error' => true, 'message' => 'Access denied'], 403); return; @@ -725,7 +725,7 @@ class AjaxController extends BaseController return; } - if (!$this->app->getIdentity()->authorise('core.delete', 'com_mokosuitebackup')) { + if (!$this->app->getIdentity()->authorise('mokosuitebackup.backup.purge', 'com_mokosuitebackup')) { $this->sendJson(['error' => true, 'message' => 'Access denied'], 403); return; @@ -776,7 +776,7 @@ class AjaxController extends BaseController return; } - if (!$this->app->getIdentity()->authorise('core.manage', 'com_mokosuitebackup')) { + if (!$this->app->getIdentity()->authorise('mokosuitebackup.backup.compare', 'com_mokosuitebackup')) { $this->sendJson(['error' => true, 'message' => 'Access denied'], 403); return; diff --git a/source/packages/com_mokosuitebackup/src/Controller/BackupsController.php b/source/packages/com_mokosuitebackup/src/Controller/BackupsController.php index 205dcd3..1f09d49 100644 --- a/source/packages/com_mokosuitebackup/src/Controller/BackupsController.php +++ b/source/packages/com_mokosuitebackup/src/Controller/BackupsController.php @@ -176,7 +176,7 @@ class BackupsController extends AdminController { $this->checkToken(); - if (!$this->app->getIdentity()->authorise('core.delete', 'com_mokosuitebackup')) { + if (!$this->app->getIdentity()->authorise('mokosuitebackup.backup.purge', 'com_mokosuitebackup')) { $this->setMessage(Text::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 'error'); $this->setRedirect(Route::_('index.php?option=com_mokosuitebackup&view=backups', false)); diff --git a/source/packages/com_mokosuitebackup/src/Controller/SnapshotsController.php b/source/packages/com_mokosuitebackup/src/Controller/SnapshotsController.php index 057b30e..f72ff53 100644 --- a/source/packages/com_mokosuitebackup/src/Controller/SnapshotsController.php +++ b/source/packages/com_mokosuitebackup/src/Controller/SnapshotsController.php @@ -259,7 +259,7 @@ class SnapshotsController extends AdminController { $this->checkToken(); - if (!$this->app->getIdentity()->authorise('core.delete', 'com_mokosuitebackup')) { + if (!$this->app->getIdentity()->authorise('mokosuitebackup.snapshot.manage', 'com_mokosuitebackup')) { $this->setMessage(Text::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 'error'); $this->setRedirect(Route::_('index.php?option=com_mokosuitebackup&view=snapshots', false)); diff --git a/source/packages/com_mokosuitebackup/src/View/Backups/HtmlView.php b/source/packages/com_mokosuitebackup/src/View/Backups/HtmlView.php index 1e69cb7..2ac116a 100644 --- a/source/packages/com_mokosuitebackup/src/View/Backups/HtmlView.php +++ b/source/packages/com_mokosuitebackup/src/View/Backups/HtmlView.php @@ -120,14 +120,19 @@ class HtmlView extends BaseHtmlView ToolbarHelper::custom('backups.restore', 'upload', '', 'COM_MOKOJOOMBACKUP_TOOLBAR_RESTORE', true); } - ToolbarHelper::custom('backups.verify', 'shield', '', 'COM_MOKOJOOMBACKUP_TOOLBAR_VERIFY', true); - if ($user->authorise('core.manage', 'com_mokosuitebackup')) { + ToolbarHelper::custom('backups.verify', 'shield', '', 'COM_MOKOJOOMBACKUP_TOOLBAR_VERIFY', true); + } + + if ($user->authorise('mokosuitebackup.backup.compare', 'com_mokosuitebackup')) { ToolbarHelper::custom('backups.compare', 'copy', '', 'COM_MOKOJOOMBACKUP_TOOLBAR_COMPARE', true); } if ($user->authorise('core.delete', 'com_mokosuitebackup')) { ToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'backups.delete'); + } + + if ($user->authorise('mokosuitebackup.backup.purge', 'com_mokosuitebackup')) { ToolbarHelper::custom('backups.purgeModal', 'trash', '', 'COM_MOKOJOOMBACKUP_TOOLBAR_PURGE', false); } -- 2.52.0