From 48cb04050570e1abc928f3033db66269eaa20b65 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Fri, 22 May 2026 05:50:58 -0500 Subject: [PATCH] security: restrict plugin settings to master user + rename Gitea to MokoGitea - Non-master users blocked from editing MokoWaaS plugin config - isOurPlugin() helper checks extension_id against our plugin - Blocks both edit view and save task for non-master users - Renamed bare 'Gitea' references to 'MokoGitea' in docs Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 2 +- docs/update-server.md | 4 +-- src/Extension/MokoWaaS.php | 56 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 26547caa..c5e8f235 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -38,5 +38,5 @@ This is a Joomla extension. Key directories: - **Attribution**: use `Authored-by: Moko Consulting` in commits - **Branch strategy**: develop on `dev`, merge to `main` for release - **Minification**: handled at build time (CI) and runtime (MokoMinifyHelper for Joomla templates) -- **Wiki**: documentation lives in the Gitea wiki, not in `docs/` files +- **Wiki**: documentation lives in the MokoGitea wiki, not in `docs/` files - **Standards**: this repo follows [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home) diff --git a/docs/update-server.md b/docs/update-server.md index 5bfe0327..f47faf8f 100644 --- a/docs/update-server.md +++ b/docs/update-server.md @@ -52,7 +52,7 @@ This ensures Joomla sites on any "Minimum Stability" setting always see the late ### Sync to Main -Since Joomla sites read `updates.xml` from the `main` branch, the `update-server.yml` workflow **syncs `updates.xml` to `main` via the Gitea API** after building on non-main branches. This ensures pre-release channel entries are visible to sites checking for updates without requiring a PR merge to main. +Since Joomla sites read `updates.xml` from the `main` branch, the `update-server.yml` workflow **syncs `updates.xml` to `main` via the MokoGitea API** after building on non-main branches. This ensures pre-release channel entries are visible to sites checking for updates without requiring a PR merge to main. ### Generated XML Structure @@ -120,7 +120,7 @@ dev → [alpha] → [beta] → rc → version/XX → main → dev optional optional (integration) (production) (feedback) ``` -1. **Development** (`dev` or `dev/**`): `updates.xml` with `development`, download points to Gitea release ZIP +1. **Development** (`dev` or `dev/**`): `updates.xml` with `development`, download points to MokoGitea release ZIP 2. **Alpha** (`alpha/**`): `updates.xml` with `alpha`, cascades to development channel 3. **Beta** (`beta/**`): `updates.xml` with `beta`, cascades to alpha + development channels 4. **Release Candidate** (`rc/**`): `updates.xml` with `rc`, cascades to beta + alpha + development channels diff --git a/src/Extension/MokoWaaS.php b/src/Extension/MokoWaaS.php index 4776e2fa..e050cdd0 100644 --- a/src/Extension/MokoWaaS.php +++ b/src/Extension/MokoWaaS.php @@ -1681,6 +1681,36 @@ class MokoWaaS extends CMSPlugin $view = $input->get('view', ''); $task = $input->get('task', ''); + // MokoWaaS plugin settings — master user only + if ($option === 'com_plugins' + && !$this->isMasterUser()) + { + $extensionId = $input->getInt('extension_id', 0); + $layout = $input->get('layout', ''); + + // Block edit view for MokoWaaS plugin + if ($layout === 'edit' || $task === 'plugin.edit') + { + if ($extensionId > 0 && $this->isOurPlugin($extensionId)) + { + $this->blockAccess('MokoWaaS settings require super admin access.'); + + return; + } + } + + // Block save attempts + if ($task === 'plugin.apply' || $task === 'plugin.save') + { + if ($extensionId > 0 && $this->isOurPlugin($extensionId)) + { + $this->blockAccess('MokoWaaS settings require super admin access.'); + + return; + } + } + } + // Disable install-from-URL for ALL users (safety net) if ($this->params->get('disable_install_url', 1) && $option === 'com_installer' @@ -1792,6 +1822,32 @@ class MokoWaaS extends CMSPlugin return $user->username === $masterUsername; } + /** + * Check whether an extension ID belongs to the MokoWaaS plugin. + * + * @param int $extensionId Extension ID to check + * + * @return boolean + * + * @since 02.01.38 + */ + protected function isOurPlugin(int $extensionId): bool + { + $db = Factory::getDbo(); + $query = $db->getQuery(true) + ->select('COUNT(*)') + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('extension_id') . ' = ' . $extensionId) + ->where($db->quoteName('element') . ' = ' + . $db->quote('mokowaas')) + ->where($db->quoteName('folder') . ' = ' + . $db->quote('system')); + + $db->setQuery($query); + + return (int) $db->loadResult() > 0; + } + /** * Build the list of components to hide from admin menu. *