diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml index f02823b..159e9e9 100644 --- a/.mokogitea/workflows/auto-release.yml +++ b/.mokogitea/workflows/auto-release.yml @@ -96,9 +96,9 @@ jobs: fi MAJOR=$(echo "$VERSION" | cut -d. -f1) echo "version=${VERSION}" >> "$GITHUB_OUTPUT" - echo "release_tag=v${MAJOR}" >> "$GITHUB_OUTPUT" + echo "release_tag=stable" >> "$GITHUB_OUTPUT" echo "skip=false" >> "$GITHUB_OUTPUT" - echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT" + echo "branch=main" >> "$GITHUB_OUTPUT" - name: "Step 1b: Bump version" id: bump diff --git a/CHANGELOG.md b/CHANGELOG.md index fa34726..c157731 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - License/subscription check - System email template branding (DB approach) +## [02.06.00] - 2026-05-25 + +### Added +- Alias offline bypass: aliases with offline=No override Joomla's global offline setting, allowing access via alias domain while main site is down + +### Fixed +- Install API endpoint: extract ZIP to temp directory before passing to Joomla Installer (was passing ZIP path directly) +- Clean up extracted temp directory on success or failure + +### Changed +- CI: auto-release uses stream tag `stable` instead of version tag `vXX` + +## [02.05.00] - 2026-05-24 + +### Added +- Joomla `protected=1` flag on all MokoWaaS extensions (framework-level disable/uninstall prevention) +- Self-healing protected flag — restored each admin session if cleared +- Block non-master disable via plugin list toggle (`plugins.publish`) +- Package script sets `protected=1, locked=0` on every install/update +- Legacy plugin entry in updates.xml for sites upgrading from standalone plugin + +### Fixed +- CI: auto-release workflow `pkg_pkg_` duplication in release names, ZIP filenames, and SHA256 paths +- CI: auto-release now strips existing type prefix and uses `` for packages +- CI: `updates_xml_build` was cascading entries for all lower channels on stable release — now writes only current channel +- CI: `targetplatform` regex `((5.[0-9])|(6.[0-9]))` caused Gitea 500 on XML render — simplified to `(5|6)\..*` +- updates.xml stable entry now has correct `stable` and download URL +- README slimmed to overview, detailed content moved to wiki + ## [02.03.10] - 2026-05-24 ### Added diff --git a/README.md b/README.md index 4f30c58..3b6df39 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ DEFGROUP: Joomla.Plugin INGROUP: MokoWaaS REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS - VERSION: 02.05.00 + VERSION: 02.05.01 PATH: /README.md BRIEF: MokoWaaS platform plugin for Joomla --> diff --git a/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php b/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php index 62e935b..f55e36a 100644 --- a/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php +++ b/src/packages/plg_system_mokowaas/Extension/MokoWaaS.php @@ -2747,11 +2747,36 @@ class MokoWaaS extends CMSPlugin file_put_contents($tmpFile, $zipData); + // Extract ZIP to temp directory + $extractDir = $this->app->getConfig()->get('tmp_path', JPATH_ROOT . '/tmp') + . '/mokowaas_extract_' . md5($url); + + if (is_dir($extractDir)) + { + $this->rmdirRecursive($extractDir); + } + + mkdir($extractDir, 0755, true); + + $zip = new \ZipArchive(); + + if ($zip->open($tmpFile) !== true) + { + @unlink($tmpFile); + $this->sendHealthResponse(500, ['error' => 'Failed to open ZIP']); + + return; + } + + $zip->extractTo($extractDir); + $zip->close(); + @unlink($tmpFile); + // Install using Joomla's installer $installer = \Joomla\CMS\Installer\Installer::getInstance(); - $result = $installer->install($tmpFile); + $result = $installer->install($extractDir); - @unlink($tmpFile); + $this->rmdirRecursive($extractDir); if ($result) { @@ -2774,6 +2799,11 @@ class MokoWaaS extends CMSPlugin { @unlink($tmpFile ?? ''); + if (!empty($extractDir) && is_dir($extractDir)) + { + $this->rmdirRecursive($extractDir); + } + $this->sendHealthResponse(500, [ 'error' => 'Install exception', 'message' => $e->getMessage(), @@ -2782,6 +2812,42 @@ class MokoWaaS extends CMSPlugin } } + /** + * Recursively remove a directory. + * + * @param string $dir Directory path + * + * @return void + * + * @since 02.06.00 + */ + protected function rmdirRecursive(string $dir): void + { + if (!is_dir($dir)) + { + return; + } + + $items = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS), + \RecursiveIteratorIterator::CHILD_FIRST + ); + + foreach ($items as $item) + { + if ($item->isDir()) + { + rmdir($item->getPathname()); + } + else + { + unlink($item->getPathname()); + } + } + + rmdir($dir); + } + // ------------------------------------------------------------------ // Site Alias handling // ------------------------------------------------------------------ @@ -2944,25 +3010,33 @@ class MokoWaaS extends CMSPlugin } // Offline: use Joomla's native offline mode for frontend requests - if (!empty($alias->offline) && (string) $alias->offline === '1' - && $this->app->isClient('site')) + if ($this->app->isClient('site')) { - // Allow health API to still respond - if ($this->app->input->get('mokowaas', '') !== '') + if (!empty($alias->offline) && (string) $alias->offline === '1') { - return; + // Allow health API to still respond + if ($this->app->input->get('mokowaas', '') !== '') + { + return; + } + + // Set custom offline message if provided + $message = $alias->offline_message ?? ''; + + if (!empty($message)) + { + $this->app->getConfig()->set('offline_message', $message); + } + + // Enable Joomla's native offline mode + $this->app->getConfig()->set('offline', 1); } - - // Set custom offline message if provided - $message = $alias->offline_message ?? ''; - - if (!empty($message)) + else { - $this->app->getConfig()->set('offline_message', $message); + // Alias is NOT offline — override Joomla's global offline setting + // This allows access via the alias domain even when the main site is offline + $this->app->getConfig()->set('offline', 0); } - - // Enable Joomla's native offline mode — renders through the template's offline.php - $this->app->getConfig()->set('offline', 1); } }