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) <noreply@anthropic.com>
This commit is contained in:
Jonathan Miller
2026-05-22 05:50:58 -05:00
parent aec849c9ae
commit 48cb040505
3 changed files with 59 additions and 3 deletions
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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 `<tag>development</tag>`, download points to Gitea release ZIP
1. **Development** (`dev` or `dev/**`): `updates.xml` with `<tag>development</tag>`, download points to MokoGitea release ZIP
2. **Alpha** (`alpha/**`): `updates.xml` with `<tag>alpha</tag>`, cascades to development channel
3. **Beta** (`beta/**`): `updates.xml` with `<tag>beta</tag>`, cascades to alpha + development channels
4. **Release Candidate** (`rc/**`): `updates.xml` with `<tag>rc</tag>`, cascades to beta + alpha + development channels
+56
View File
@@ -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.
*