diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml index 75a6963..a9a4025 100644 --- a/.mokogitea/workflows/issue-branch.yml +++ b/.mokogitea/workflows/issue-branch.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: Gitea.Workflow # INGROUP: mokocli.Automation -# VERSION: 01.00.00 +# VERSION: 01.39.01 # BRIEF: Auto-create feature branch when an issue is opened name: "Universal: Issue Branch" diff --git a/CHANGELOG.md b/CHANGELOG.md index 36e165e..9775608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ - MokoRestore: auto-detect sanitized passwords and prompt for reset - Data sanitization: passwords, emails, sessions in backup profile settings (#129) +### Fixed +- MokoRestore: data-only mode now uses REPLACE INTO to handle existing rows +- MokoRestore: temporary password is now randomly generated (not hardcoded "changeme") + ## [01.38.05] --- 2026-06-23 ## [01.38.05] --- 2026-06-23 diff --git a/README.md b/README.md index 2b3a610..edf4659 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,80 @@ # MokoSuiteBackup - - Full-site backup and restore for Joomla — database, files, and configuration. -## Overview - -MokoSuiteBackup is a comprehensive backup solution for Joomla 4/5/6 sites. It creates complete site backups including the database, files, and configuration, packaged into downloadable ZIP archives. Supports multiple backup profiles, scheduled backups via CLI/cron, and a REST API for remote management. +| Field | Value | +|---|---| +| **Package** | `pkg_mokosuitebackup` | +| **Type** | Joomla Package (8 sub-extensions) | +| **Joomla** | 6.x+ | +| **PHP** | 8.1+ | +| **License** | GPL-3.0-or-later | ## Features -- Full site backup (database + files + configuration) -- Database-only backup mode -- Files-only backup mode -- Multiple backup profiles with independent configurations -- File and directory exclusion filters -- Table exclusion filters for database backups -- Step-based backup engine (avoids PHP timeout on large sites) -- CLI script for cron/scheduled backups -- REST API (Joomla Web Services) for remote management -- Backup record management (list, download, delete) -- Automatic old backup cleanup (configurable retention) -- Admin dashboard with backup history and storage usage +### Backup +- Full site, database-only, files-only, and differential backup modes +- Pre-flight validation — checks directory, disk space, extensions, credentials before starting +- Auto-verify archive integrity after creation +- Stepped AJAX engine prevents timeout on shared hosting +- AES-256 ZIP encryption with configurable password +- Configurable archive naming with placeholders ([HOST], [DATE], [SITE_NAME], etc.) +- Data sanitization — optionally clear user passwords, emails, and sessions in backup + +### Content Snapshots +- Lightweight JSON snapshots of articles, categories, and modules +- Includes tags, custom fields, workflow associations +- Restore modes: Replace (clean slate) or Merge (upsert) +- Selective article restore — browse and pick individual items +- Automatic retention (max count + max age) +- Scheduled snapshot task via com_scheduler + +### Remote Storage +- SFTP with SSH key file authentication (key stored base64-encoded in database) +- Amazon S3 and S3-compatible (DigitalOcean Spaces, Wasabi, MinIO) +- Google Drive with OAuth2 and resumable uploads +- Graceful degradation — local backup preserved if upload fails + +### MokoRestore Standalone Wizard +- 9-step restore wizard that works without Joomla installed +- Per-table conflict resolution: Replace / Skip / Merge / Data Only +- Post-restore actions: reset passwords, hits, versions, sessions, cache +- Auto-detect sanitized passwords and prompt for reset +- Standalone mode: restore.php scans directory for ZIP files +- Wrapped mode: restore.php bundled inside backup ZIP +- Security gate with filesystem verification + +### Notifications +- Email on success/failure per profile +- ntfy push notifications +- Notifications for restore and snapshot operations + +### Admin Dashboard +- Last backup status, next scheduled, total count, storage used +- Snapshot widget with latest info and type badges +- 30-day backup trend chart +- Per-profile storage breakdown +- System health checks + +### CLI +- `mokosuitebackup:run --profile=1` — run backup +- `mokosuitebackup:restore 1 --files-only --db-only --password=xxx` +- `mokosuitebackup:snapshot create|restore|list|delete` + +### REST API +- Backup: start, list, download, delete, profiles +- Snapshots: create, list, restore, delete, download +- Profile credentials masked in API responses ## Installation -1. Download `pkg_mokobackup-*.zip` from [Releases](https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteBackup/releases) +1. Download from [Releases](https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteBackup/releases) 2. Joomla Administrator > Extensions > Install -3. System plugin enabled automatically on install +3. Components > MokoSuiteBackup > Dashboard -## Configuration +## Documentation -- **Component**: Administrator > Components > MokoSuiteBackup -- **Profiles**: Create backup profiles with different file/database filters -- **System Plugin**: Configure scheduled backup triggers and notifications -- **CLI**: `php cli/mokobackup.php --profile=1` for cron-based backups - -## REST API - -The webservices plugin exposes endpoints compatible with the MokoBackup MCP server: - -- `POST /api/index.php/v1/mokobackup/backup` — Start a backup -- `GET /api/index.php/v1/mokobackup/backups` — List backup records -- `GET /api/index.php/v1/mokobackup/backup/:id/download` — Download archive -- `DELETE /api/index.php/v1/mokobackup/backup/:id` — Delete backup record -- `GET /api/index.php/v1/mokobackup/profiles` — List backup profiles +See the [Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteBackup/wiki) for guides and reference. ## License diff --git a/source/packages/com_mokosuitebackup/mokosuitebackup.xml b/source/packages/com_mokosuitebackup/mokosuitebackup.xml index ecca7bc..662b13f 100644 --- a/source/packages/com_mokosuitebackup/mokosuitebackup.xml +++ b/source/packages/com_mokosuitebackup/mokosuitebackup.xml @@ -7,7 +7,7 @@ --> MokoSuiteBackup - 01.39.00 + 01.39.01 2026-06-02 Moko Consulting hello@mokoconsulting.tech diff --git a/source/packages/com_mokosuitebackup/src/Engine/MokoRestore.php b/source/packages/com_mokosuitebackup/src/Engine/MokoRestore.php index c01354b..f72f513 100644 --- a/source/packages/com_mokosuitebackup/src/Engine/MokoRestore.php +++ b/source/packages/com_mokosuitebackup/src/Engine/MokoRestore.php @@ -724,11 +724,14 @@ function actionDatabase(array $data): array $part = preg_replace('/^INSERT\s+INTO/i', 'INSERT IGNORE INTO', $part); } } elseif ($mode === 'dataonly') { - // Skip DROP and CREATE; execute INSERT as-is + /* Skip DROP and CREATE; use REPLACE INTO for data (overwrites on duplicate key) */ if ($isDrop || $isCreate) { $skipped++; continue; } + if ($isInsert) { + $part = preg_replace('/^INSERT\s+INTO/i', 'REPLACE INTO', $part); + } } // mode === 'replace' => execute everything as-is (default) @@ -1123,15 +1126,16 @@ function actionPostRestore(array $data): array try { switch ($task) { case 'reset_passwords': - // Set all user passwords to a known temporary hash ("changeme"), + /* Set all user passwords to a random temporary hash, block non-admin users */ + $tempPassword = bin2hex(random_bytes(8)); /* 16-char random hex */ // clear activation tokens, and force password reset on next login. - $tempHash = password_hash('changeme', PASSWORD_DEFAULT); + $tempHash = password_hash($tempPassword, PASSWORD_DEFAULT); $stmt = $pdo->prepare( "UPDATE {$prefix}users SET password = ?, activation = '', requireReset = 1" ); $stmt->execute([$tempHash]); $affected = $stmt->rowCount(); - $results[] = "All {$affected} user password(s) reset to temporary password (changeme) with forced reset"; + $results[] = "All {$affected} user password(s) reset to temporary password ({$tempPassword}) with forced reset"; break; case 'reset_hits': @@ -1670,7 +1674,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica N Sanitized passwords detected! This backup contains placeholder password hashes that will prevent all users from logging in. The "Reset all user passwords" option below is strongly recommended.