diff --git a/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php b/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php index 86ec2a2..62e935b 100644 --- a/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php +++ b/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php @@ -985,6 +985,15 @@ class MokoWaaS extends CMSPlugin */ protected function protectPlugin() { + // Ensure protected flag is set (self-healing — runs once per session) + static $flagChecked = false; + + if (!$flagChecked) + { + $flagChecked = true; + $this->ensureProtectedFlag(); + } + if ($this->isMasterUser()) { return; @@ -993,7 +1002,7 @@ class MokoWaaS extends CMSPlugin $option = $this->app->input->get('option', ''); $task = $this->app->input->get('task', ''); - // Block non-master from disabling or uninstalling MokoWaaS + // Block non-master from uninstalling MokoWaaS if ($option === 'com_installer' && strpos($task, 'manage.remove') !== false) { $cid = $this->app->input->get('cid', [], 'array'); @@ -1004,6 +1013,49 @@ class MokoWaaS extends CMSPlugin $this->app->redirect('index.php?option=com_installer&view=manage'); } } + + // Block non-master from disabling via list toggle + if ($option === 'com_plugins' && strpos($task, 'plugins.publish') !== false) + { + $cid = $this->app->input->get('cid', [], 'array'); + + if ($this->isOurExtension($cid)) + { + $this->app->enqueueMessage('MokoWaaS cannot be disabled.', 'error'); + $this->app->redirect('index.php?option=com_plugins'); + } + } + } + + /** + * Ensure the protected flag is set on MokoWaaS extensions in the DB. + * + * Sets protected=1, locked=0 so the extension can't be disabled or + * uninstalled but can still receive updates and config changes. + * + * @return void + * + * @since 02.03.10 + */ + protected function ensureProtectedFlag() + { + try + { + $db = Factory::getDbo(); + $query = $db->getQuery(true) + ->update($db->quoteName('#__extensions')) + ->set($db->quoteName('protected') . ' = 1') + ->set($db->quoteName('locked') . ' = 0') + ->where('(' . $db->quoteName('element') . ' = ' . $db->quote('mokowaas') + . ' OR ' . $db->quoteName('element') . ' = ' . $db->quote('pkg_mokowaas') . ')') + ->where($db->quoteName('protected') . ' = 0'); + $db->setQuery($query); + $db->execute(); + } + catch (\Throwable $e) + { + // Non-critical + } } /** diff --git a/src/script.php b/src/script.php index e7ea151..cc58abf 100644 --- a/src/script.php +++ b/src/script.php @@ -37,6 +37,9 @@ class Pkg_MokowaasInstallerScript $this->enablePlugin('system', 'mokowaas'); $this->enablePlugin('webservices', 'mokowaas'); + // Mark MokoWaaS extensions as protected (prevents disable/uninstall at framework level) + $this->protectExtensions(); + // Trigger heartbeat registration $this->sendHeartbeat(); } @@ -71,6 +74,36 @@ class Pkg_MokowaasInstallerScript } } + /** + * Set the protected flag on all MokoWaaS extensions. + * + * Joomla's protected flag prevents disabling and uninstalling at the + * framework level — no plugin-side interception needed. + * + * @return void + * + * @since 02.03.10 + */ + private function protectExtensions(): void + { + try + { + $db = Factory::getDbo(); + $query = $db->getQuery(true) + ->update($db->quoteName('#__extensions')) + ->set($db->quoteName('protected') . ' = 1') + ->set($db->quoteName('locked') . ' = 0') + ->where('(' . $db->quoteName('element') . ' = ' . $db->quote('mokowaas') + . ' OR ' . $db->quoteName('element') . ' = ' . $db->quote('pkg_mokowaas') . ')'); + $db->setQuery($query); + $db->execute(); + } + catch (\Throwable $e) + { + Log::add('Error protecting MokoWaaS extensions: ' . $e->getMessage(), Log::WARNING, 'jerror'); + } + } + /** * Send heartbeat to the MokoWaaS monitoring receiver. *