feat: integrate MokoGitea license system for update checks

Update server now points to MokoGitea's dynamic endpoint which
validates license keys (dlid) and generates update XML from git
releases. Users enter the download key via Joomla's native
System → Update Sites interface. Legacy static URLs are auto-migrated
on install/update.

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jonathan Miller
2026-05-31 10:36:53 -05:00
parent 7ba7337054
commit 1b6747d9f9
8 changed files with 82 additions and 59 deletions
+5
View File
@@ -93,6 +93,11 @@ sftp-settings.json
.replit
replit.md
# ============================================================
# Update server (generated dynamically by MokoGitea)
# ============================================================
updates.xml
# ============================================================
# Archives / release artifacts
# ============================================================
+25 -13
View File
@@ -154,7 +154,7 @@ The version in `README.md` **must always match** the `<version>` tag in `manifes
```
MokoWaaS/
├── manifest.xml # Joomla installer manifest (root — required)
├── updates.xml # Update server manifest (root — required, see below)
├── (no updates.xml) # Update XML is generated dynamically by MokoGitea
├── site/ # Frontend (site) code
│ ├── controller.php
│ ├── controllers/
@@ -183,24 +183,35 @@ MokoWaaS/
---
## updates.xml — Required in Repo Root
## Update Server — MokoGitea Dynamic Endpoint
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
`updates.xml` is **NOT** stored in the repo. MokoGitea generates the update XML dynamically from git releases at:
The `manifest.xml` must reference it via:
```
https://git.mokoconsulting.tech/{Owner}/{Repo}/updates.xml
```
The package manifest (`pkg_mokowaas.xml`) references it via:
```xml
<updateservers>
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
https://github.com/mokoconsulting-tech/MokoWaaS/raw/main/updates.xml
<server type="extension" priority="1" name="MokoWaaS Update Server">
https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/updates.xml
</server>
</updateservers>
```
**License Key (Download Key):**
- MokoGitea's endpoint validates license keys passed as `?dlid=MOKO-XXXX-XXXX-XXXX-XXXX`
- The generated XML includes `<downloadkey prefix="dlid=" suffix="" />` to tell Joomla a key is required
- Users enter the download key via Joomla's native **System → Update Sites** interface
- Joomla stores the key in `#__update_sites.extra_query` and appends it to all update/download requests
- Invalid/expired keys receive an empty `<updates></updates>` response
**Rules:**
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
- Do NOT create or commit a static `updates.xml` — MokoGitea generates it from releases
- The `<version>` in release tags must match `<version>` in the manifest and `README.md`
- Release assets (ZIPs) must be attached to git releases — MokoGitea uses them for `<downloadurl>`
- `<targetplatform name="joomla" version="(5|6)\..*">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression
---
@@ -286,8 +297,8 @@ Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `d
| Change type | Documentation to update |
|-------------|------------------------|
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
| New or changed manifest.xml | Bump README.md version |
| New release | Create git release with ZIP asset; update CHANGELOG.md; bump README.md version |
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
| **Every PR** | **Bump the patch version** — increment `XX.YY.ZZ` in `README.md`; `sync-version-on-merge` propagates it |
@@ -301,4 +312,5 @@ Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `d
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
- Never hardcode version numbers in body text — update `README.md` and let automation propagate
- Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows — always use `secrets.GH_TOKEN`
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
- Never let `manifest.xml` version and `README.md` version go out of sync
- Never commit a static `updates.xml` — the update feed is generated dynamically by MokoGitea
+24 -13
View File
@@ -154,7 +154,7 @@ The version in `README.md` **must always match** the `<version>` tag in `manifes
```
MokoWaaS/
├── manifest.xml # Joomla installer manifest (root — required)
├── updates.xml # Update server manifest (root — required, see below)
├── (no updates.xml) # Update XML is generated dynamically by MokoGitea
├── site/ # Frontend (site) code
│ ├── controller.php
│ ├── controllers/
@@ -183,24 +183,34 @@ MokoWaaS/
---
## updates.xml — Required in Repo Root
## Update Server — MokoGitea Dynamic Endpoint
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
`updates.xml` is **NOT** stored in the repo. MokoGitea generates the update XML dynamically from git releases at:
The `manifest.xml` must reference it via:
```
https://git.mokoconsulting.tech/{Owner}/{Repo}/updates.xml
```
The package manifest (`pkg_mokowaas.xml`) references it via:
```xml
<updateservers>
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
https://github.com/mokoconsulting-tech/MokoWaaS/raw/main/updates.xml
<server type="extension" priority="1" name="MokoWaaS Update Server">
https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/updates.xml
</server>
</updateservers>
```
**License Key (Download Key):**
- MokoGitea's endpoint validates license keys passed as `?dlid=MOKO-XXXX-XXXX-XXXX-XXXX`
- The generated XML includes `<downloadkey prefix="dlid=" suffix="" />` to tell Joomla a key is required
- Users enter the download key via Joomla's native **System → Update Sites** interface
- Joomla stores the key in `#__update_sites.extra_query` and appends it to all update/download requests
- Invalid/expired keys receive an empty `<updates></updates>` response
**Rules:**
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
- Do NOT create or commit a static `updates.xml` — MokoGitea generates it from releases
- The `<version>` in release tags must match `<version>` in the manifest and `README.md`
- Release assets (ZIPs) must be attached to git releases — MokoGitea uses them for `<downloadurl>`
---
@@ -286,8 +296,8 @@ Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `d
| Change type | Documentation to update |
|-------------|------------------------|
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
| New or changed manifest.xml | Bump README.md version |
| New release | Create git release with ZIP asset; update CHANGELOG.md; bump README.md version |
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
| **Every PR** | **Bump the patch version** — increment `XX.YY.ZZ` in `README.md`; `sync-version-on-merge` propagates it |
@@ -301,4 +311,5 @@ Approved prefixes: `dev/` · `rc/` · `version/` · `patch/` · `copilot/` · `d
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
- Never hardcode version numbers in body text — update `README.md` and let automation propagate
- Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows — always use `secrets.GH_TOKEN`
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
- Never let `manifest.xml` version and `README.md` version go out of sync
- Never commit a static `updates.xml` — the update feed is generated dynamically by MokoGitea
+9
View File
@@ -19,6 +19,15 @@
-->
# Changelog
## [02.30.00] - 2026-05-31
### Added
- License key support via Joomla's native Update Sites download key system (dlid)
- Update server URL migrated from static XML to MokoGitea's dynamic update feed endpoint
- Legacy static update site URLs auto-migrated to dynamic endpoint on install/update
### Removed
- Static `updates.xml` — update feed is now generated dynamically by MokoGitea from git releases
## [02.29.04] - 2026-05-31
### Fixed
- Remove secondary master username from enforcement — only primary master user is created/enforced
@@ -938,6 +938,7 @@ class MokoWaaS extends CMSPlugin implements BootableExtensionInterface
);
$db->execute();
}
}
/**
+1 -1
View File
@@ -23,6 +23,6 @@
</files>
<updateservers>
<server type="extension" priority="1" name="MokoWaaS Update Server">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/raw/branch/main/updates.xml</server>
<server type="extension" priority="1" name="MokoWaaS Update Server">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/updates.xml</server>
</updateservers>
</extension>
+17 -5
View File
@@ -219,11 +219,12 @@ class Pkg_MokowaasInstallerScript
}
/**
* Ensure the MokoWaaS update server entry stays enabled.
* Ensure the MokoWaaS update server entry stays enabled and points
* to the correct dynamic endpoint with the license key attached.
*
* Joomla stores update server records in #__update_sites. If a tenant
* or automation disables it, the site stops receiving updates. This
* re-enables it on every install/update.
* Migrates legacy static URLs (raw/branch/main/updates.xml) to the
* dynamic MokoGitea update feed, and syncs the license key from
* plugin params into extra_query so Joomla sends it as dlid.
*
* @return void
*
@@ -235,7 +236,18 @@ class Pkg_MokowaasInstallerScript
{
$db = Factory::getDbo();
// Find update site by name or URL pattern
// Migrate legacy static URL to dynamic MokoGitea endpoint
$db->setQuery(
$db->getQuery(true)
->update($db->quoteName('#__update_sites'))
->set($db->quoteName('location') . ' = '
. $db->quote('https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/updates.xml'))
->where($db->quoteName('location') . ' LIKE '
. $db->quote('%MokoWaaS/raw/branch/%updates.xml%'))
);
$db->execute();
// Enable all MokoWaaS update sites
$query = $db->getQuery(true)
->update($db->quoteName('#__update_sites'))
->set($db->quoteName('enabled') . ' = 1')
-27
View File
@@ -1,27 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
SPDX-License-Identifier: GPL-3.0-or-later
VERSION: 02.29.04
-->
<updates>
<update>
<name>Package - MokoWaaS</name>
<description>Package - MokoWaaS stable build.</description>
<element>pkg_mokowaas</element>
<type>package</type>
<client>site</client>
<version>02.29.04</version>
<creationDate>2026-05-31</creationDate>
<infourl title='Package - MokoWaaS'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/stable</infourl>
<downloads>
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.29.04.zip</downloadurl>
</downloads>
<sha256>b39d1e0d269f54a362acd5a6edafefb7e5813cdadc289617e0ab6dfdc5c97d16</sha256>
<tags><tag>stable</tag></tags>
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/raw/branch/main/CHANGELOG.md</changelogurl>
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
<targetplatform name="joomla" version="(5|6)\..*" />
</update>
</updates>