From d280d48699dda94317900c300f7c9e89eedee6e0 Mon Sep 17 00:00:00 2001 From: "Beau Beauchamp, WebTigers" Date: Wed, 21 Oct 2026 09:42:00 -0400 Subject: [PATCH] =?UTF-8?q?TIGER-335=20batch=201:=20=5FisAdmin()=20?= =?UTF-8?q?=E2=86=92=20=5FisAllowed()=20in=20identity/matomo/schedule/back?= =?UTF-8?q?up/ally=20(v1.32.0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the deprecated resource-level _isAdmin() guards with privilege-scoped _isAllowed('') in five admin-only modules. Each service is granted to `admin` at the resource (wildcard privilege), so the conversion is behavior-preserving; the in-method guard remains as defense-in-depth for any in-process caller, now without a role comparer. No acl.ini changes needed (blanket admin covers all method privileges). Tests green: 117 across the five modules. Closes TIGER-349, TIGER-350, TIGER-351, TIGER-355, TIGER-356. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ --- CHANGELOG.md | 11 +++++++++++ library/Tiger/Version.php | 2 +- modules/ally/services/Scan.php | 8 ++++---- modules/backup/services/Backup.php | 8 ++++---- modules/identity/services/Identity.php | 2 +- modules/matomo/services/Matomo.php | 2 +- modules/schedule/services/Schedule.php | 6 +++--- 7 files changed, 25 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65151ed..1d451d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,17 @@ All notable changes to **Tiger Core** (`webtigers/tiger-core`). Format follows ## [Unreleased] +## [1.32.0] — 2026-10-21 + +### Changed +- **TIGER-335 migration (batch 1 of the per-module sweep)** — replaced the deprecated resource-level + `_isAdmin()` guards with privilege-scoped `_isAllowed('')` in five admin-only modules: + **identity** (TIGER-356), **matomo** (TIGER-355), **schedule** (TIGER-351), **backup** (TIGER-349), + **ally** (TIGER-350). Behavior-preserving (each service is granted to `admin` at the resource, so the + wildcard grant covers every method privilege); the in-method guard stays as defense-in-depth for any + in-process caller, now expressed without a role comparer. The deprecated comparers are removed in a + later release once every module is migrated (TIGER-358). + ## [1.31.0] — 2026-10-21 ### Added diff --git a/library/Tiger/Version.php b/library/Tiger/Version.php index db8fcd9..0f826a7 100644 --- a/library/Tiger/Version.php +++ b/library/Tiger/Version.php @@ -9,5 +9,5 @@ class Tiger_Version { /** Current Tiger Core version. Keep in lockstep with the git tag cut for a release. */ - const VERSION = '1.31.0'; + const VERSION = '1.32.0'; } diff --git a/modules/ally/services/Scan.php b/modules/ally/services/Scan.php index 18f2df0..76e5f55 100644 --- a/modules/ally/services/Scan.php +++ b/modules/ally/services/Scan.php @@ -22,7 +22,7 @@ class Ally_Service_Scan extends Tiger_Service_Service */ public function scan(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('scan')) { $this->_error('core.api.error.not_allowed'); return; } $html = (string) ($params['html'] ?? ''); $pageId = trim((string) ($params['page_id'] ?? '')); @@ -63,7 +63,7 @@ public function scan(array $params): void */ public function scanModule(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('scanModule')) { $this->_error('core.api.error.not_allowed'); return; } $mod = preg_replace('/[^a-zA-Z0-9_-]/', '', (string) ($params['module'] ?? '')); if ($mod === '' || !defined('MODULES_PATH')) { $this->_error('ally.scan.module_not_found'); return; } @@ -106,7 +106,7 @@ public function scanModule(array $params): void */ public function pages(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('pages')) { $this->_error('core.api.error.not_allowed'); return; } $this->_success(['pages' => $this->_pageList()], 'core.api.success'); } @@ -118,7 +118,7 @@ public function pages(array $params): void */ public function scanAll(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('scanAll')) { $this->_error('core.api.error.not_allowed'); return; } $renderer = new Tiger_Cms_Renderer(); $results = []; diff --git a/modules/backup/services/Backup.php b/modules/backup/services/Backup.php index 13d1c9e..b5c0c85 100644 --- a/modules/backup/services/Backup.php +++ b/modules/backup/services/Backup.php @@ -21,7 +21,7 @@ class Backup_Service_Backup extends Tiger_Service_Service */ public function run(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('run')) { $this->_error('core.api.error.not_allowed'); return; } $components = $this->_components($params); if (!$components) { $this->_error('backup.bad_component', ['field' => 'components']); return; } @@ -53,7 +53,7 @@ public function run(array $params): void */ public function remove(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('remove')) { $this->_error('core.api.error.not_allowed'); return; } $id = (string) ($params['backup_id'] ?? ''); if ($id === '' || !(new Tiger_Model_Backup())->findById($id)) { $this->_error('backup.not_found'); return; } Tiger_Backup::delete($id); @@ -68,7 +68,7 @@ public function remove(array $params): void */ public function restore(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('restore')) { $this->_error('core.api.error.not_allowed'); return; } if ((string) ($params['confirm'] ?? '') !== 'RESTORE') { $this->_error('backup.restore.confirm', ['field' => 'confirm']); return; } $model = new Tiger_Model_Backup(); @@ -103,7 +103,7 @@ public function restore(array $params): void */ public function saveSettings(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('saveSettings')) { $this->_error('core.api.error.not_allowed'); return; } $components = $this->_components($params); $disk = $this->_disk($params['disk'] ?? 'local'); diff --git a/modules/identity/services/Identity.php b/modules/identity/services/Identity.php index 253afc2..ab57f2b 100644 --- a/modules/identity/services/Identity.php +++ b/modules/identity/services/Identity.php @@ -43,7 +43,7 @@ class Identity_Service_Identity extends Tiger_Service_Service */ public function save(array $params): void { - if (!$this->_isAdmin()) { + if (!$this->_isAllowed('save')) { $this->_error('core.api.error.not_allowed'); return; } diff --git a/modules/matomo/services/Matomo.php b/modules/matomo/services/Matomo.php index 9b71b67..2823990 100644 --- a/modules/matomo/services/Matomo.php +++ b/modules/matomo/services/Matomo.php @@ -20,7 +20,7 @@ class Matomo_Service_Matomo extends Tiger_Service_Service */ public function save(array $params): void { - if (!$this->_isAdmin()) { + if (!$this->_isAllowed('save')) { $this->_error('core.api.error.not_allowed'); return; } diff --git a/modules/schedule/services/Schedule.php b/modules/schedule/services/Schedule.php index 3bdfd5f..7870588 100644 --- a/modules/schedule/services/Schedule.php +++ b/modules/schedule/services/Schedule.php @@ -21,7 +21,7 @@ class Schedule_Service_Schedule extends Tiger_Service_Service */ public function jobs(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('jobs')) { $this->_error('core.api.error.not_allowed'); return; } $latest = (new Tiger_Model_ScheduleRun())->latestPerJob(); $now = time(); @@ -65,7 +65,7 @@ public function jobs(array $params): void */ public function setSchedule(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('setSchedule')) { $this->_error('core.api.error.not_allowed'); return; } $key = preg_replace('/[^a-zA-Z0-9._-]/', '', (string) ($params['key'] ?? '')); if ($key === '' || !Tiger_Schedule::get($key)) { $this->_error('schedule.unknown_job'); return; } @@ -96,7 +96,7 @@ public function setSchedule(array $params): void */ public function runNow(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('runNow')) { $this->_error('core.api.error.not_allowed'); return; } $key = preg_replace('/[^a-zA-Z0-9._-]/', '', (string) ($params['key'] ?? '')); if ($key === '' || !Tiger_Schedule::get($key)) { $this->_error('schedule.unknown_job'); return; } $r = Tiger_Schedule::runNow($key);