1
Plugin-Protection
Jonathan Miller edited this page 2026-05-24 09:13:56 +00:00

Plugin Protection

MokoWaaS uses multiple layers of protection to prevent accidental or unauthorized disabling and uninstallation. The master user retains full control over the plugin at all times.

Protection Layers

1. Protected Flag (protected=1)

During installation and on every admin session, MokoWaaS sets the protected column to 1 in the #__extensions database table for both mokowaas and pkg_mokowaas entries.

The Joomla framework itself enforces this flag: protected extensions cannot be disabled or uninstalled through the standard admin interface.

The locked column is set to 0 so the extension can still receive updates and configuration changes.

2. Self-Healing

The ensureProtectedFlag() method runs once per admin session (using a static flag to avoid repeated queries). If the protected column has been reset to 0 (e.g., by a database modification), it is automatically restored to 1.

This runs in the protectPlugin() method, which is called from onBeforeRender() on every admin page load.

3. Hidden from Plugin List

For non-master users, MokoWaaS injects JavaScript on the com_plugins and com_installer pages that hides any table row containing "mokowaas" or "MokoWaaS". This prevents non-master users from seeing the plugin in the extension list.

The hidePluginFromList() method adds an inline script that runs on DOMContentLoaded:

document.querySelectorAll('tr').forEach(function(row) {
    var text = row.textContent || '';
    if (text.indexOf('mokowaas') !== -1 || text.indexOf('MokoWaaS') !== -1) {
        row.style.display = 'none';
    }
});

4. onExtensionBeforeSave Interception

The onExtensionBeforeSave event handler intercepts save attempts on the plugin configuration. If a non-master user attempts to save the plugin with enabled = 0, the handler:

  1. Displays an error message: "MokoWaaS cannot be disabled."
  2. Forces enabled back to 1 on the table object
  3. Returns true to allow the save to proceed (with the corrected value)

5. protectPlugin() -- Uninstall and Disable Blocking

The protectPlugin() method runs on every admin page request and checks for active uninstall or disable attempts:

Uninstall blocking: If the current request is to com_installer with task manage.remove, and the extension IDs include any MokoWaaS extension, the request is blocked with an error message and a redirect back to the installer manage view.

Disable blocking: If the current request is to com_plugins with task plugins.publish, and the extension IDs include MokoWaaS, the request is blocked with an error message and a redirect back to the plugins list.

The isOurExtension() helper method checks extension IDs against the database to determine if they belong to MokoWaaS (matching on element name mokowaas or pkg_mokowaas).

Master User Exemption

All protection checks call isMasterUser() first. If the current user is the designated master user (matching the configured master_username), all protections are bypassed. The master user can:

  • See MokoWaaS in the plugin and extension lists
  • Disable the plugin via the configuration page
  • Uninstall the plugin via the Extension Manager
  • Modify all plugin settings

Installation-Time Protection

The package installer script (Pkg_MokowaasInstallerScript) and the plugin installer script both set protected=1 during postflight:

  • enableAndLockPlugin() sets enabled=1, locked=1, protected=1 on the system plugin
  • protectExtensions() sets protected=1, locked=0 on all MokoWaaS extensions (plugin and package)

This ensures protection is active immediately after installation, before the first admin page load triggers the self-healing logic.

Summary of Protection Flow

Installation
  -> postflight sets protected=1, enabled=1

Every admin page load (onBeforeRender)
  -> protectPlugin()
     -> ensureProtectedFlag() (once per session, restores protected=1 if needed)
     -> if not master user:
        -> block uninstall attempts (com_installer manage.remove)
        -> block disable attempts (com_plugins plugins.publish)
     -> hidePluginFromList() for non-master users

Plugin config save (onExtensionBeforeSave)
  -> if not master user and enabled=0:
     -> force enabled=1, show error