diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d451d2..dcc09a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ All notable changes to **Tiger Core** (`webtigers/tiger-core`). Format follows ## [Unreleased] +## [1.33.0] — 2026-10-21 + +### Changed +- **TIGER-335 migration (batch 2)** — `_isAdmin()` → `_isAllowed('')` in five more + blanket-granted modules: **analytics** (TIGER-354), **code** (TIGER-345, incl. the datatable + `can_edit`/`can_delete` privilege flags), **translations** (TIGER-346), **profile** (TIGER-340, the + admin `Org*` services), **access** (TIGER-339, incl. the User/Org datatable flags). Behavior-preserving; + no `acl.ini` changes (each service is a wildcard-privilege grant to its role). + ## [1.32.0] — 2026-10-21 ### Changed diff --git a/library/Tiger/Version.php b/library/Tiger/Version.php index 0f826a7..31b37c3 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.32.0'; + const VERSION = '1.33.0'; } diff --git a/modules/access/services/Org.php b/modules/access/services/Org.php index 512d104..d25f90e 100644 --- a/modules/access/services/Org.php +++ b/modules/access/services/Org.php @@ -28,7 +28,7 @@ class Access_Service_Org extends Tiger_Service_Service */ public function datatable(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('datatable')) { $this->_error('core.api.error.not_allowed'); return; } $dt = $this->_dtParams($params); @@ -41,8 +41,8 @@ public function datatable(array $params): void 'limit' => $dt['length'], ]); - $canEdit = $this->_isAdmin(static::class, 'save'); - $canDelete = $this->_isAdmin(static::class, 'delete'); + $canEdit = $this->_isAllowed('save'); + $canDelete = $this->_isAllowed('delete'); $rows = []; foreach ($data['rows'] as $r) { @@ -72,7 +72,7 @@ public function datatable(array $params): void */ public function save(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('save')) { $this->_error('core.api.error.not_allowed'); return; } $form = new Access_Form_Org(); if (!$form->isValid($params)) { $this->_formErrors($form); return; } @@ -114,7 +114,7 @@ public function save(array $params): void */ public function delete(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('delete')) { $this->_error('core.api.error.not_allowed'); return; } $id = !empty($params['org_id']) ? (string) $params['org_id'] : ''; if ($id === '') { $this->_error('core.api.error.general'); return; } if ($id === $this->_org_id) { $this->_error('access.org.no_self_delete'); return; } diff --git a/modules/access/services/User.php b/modules/access/services/User.php index 7f3a380..58e028a 100644 --- a/modules/access/services/User.php +++ b/modules/access/services/User.php @@ -24,7 +24,7 @@ class Access_Service_User extends Tiger_Service_Service */ public function datatable(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('datatable')) { $this->_error('core.api.error.not_allowed'); return; } $dt = $this->_dtParams($params); @@ -37,8 +37,8 @@ public function datatable(array $params): void 'limit' => $dt['length'], ]); - $canEdit = $this->_isAdmin(static::class, 'save'); - $canDelete = $this->_isAdmin(static::class, 'delete'); + $canEdit = $this->_isAllowed('save'); + $canDelete = $this->_isAllowed('delete'); $rows = []; foreach ($data['rows'] as $r) { @@ -69,7 +69,7 @@ public function datatable(array $params): void */ public function save(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('save')) { $this->_error('core.api.error.not_allowed'); return; } $form = new Access_Form_User(); if (!$form->isValid($params)) { $this->_formErrors($form); return; } @@ -127,7 +127,7 @@ public function save(array $params): void */ public function delete(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('delete')) { $this->_error('core.api.error.not_allowed'); return; } $id = !empty($params['user_id']) ? (string) $params['user_id'] : ''; if ($id === '') { $this->_error('core.api.error.general'); return; } if ($id === $this->_user_id) { $this->_error('access.user.no_self_delete'); return; } diff --git a/modules/analytics/services/Analytics.php b/modules/analytics/services/Analytics.php index 4f194f0..2e036fd 100644 --- a/modules/analytics/services/Analytics.php +++ b/modules/analytics/services/Analytics.php @@ -19,7 +19,7 @@ class Analytics_Service_Analytics 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/analytics/services/Reports.php b/modules/analytics/services/Reports.php index 29192ce..f1fb0a5 100644 --- a/modules/analytics/services/Reports.php +++ b/modules/analytics/services/Reports.php @@ -18,7 +18,7 @@ class Analytics_Service_Reports extends Tiger_Service_Service */ public function summary(array $params): void { - if (!$this->_isAdmin()) { + if (!$this->_isAllowed('summary')) { $this->_error('core.api.error.not_allowed'); return; } @@ -53,7 +53,7 @@ public function summary(array $params): void */ public function test(array $params): void { - if (!$this->_isAdmin()) { + if (!$this->_isAllowed('test')) { $this->_error('core.api.error.not_allowed'); return; } diff --git a/modules/code/services/Code.php b/modules/code/services/Code.php index d3f50ae..b405b90 100644 --- a/modules/code/services/Code.php +++ b/modules/code/services/Code.php @@ -40,14 +40,14 @@ private function _tr(string $key, string $fallback): string */ public function datatable(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('datatable')) { $this->_error('core.api.error.not_allowed'); return; } $dt = $this->_dtParams($params); $search = strtolower(trim((string) $dt['search'])); $langf = (string) ($params['language'] ?? ''); - $canEdit = $this->_isAdmin(static::class, 'save'); - $canDelete = $this->_isAdmin(static::class, 'delete'); + $canEdit = $this->_isAllowed('save'); + $canDelete = $this->_isAllowed('delete'); // LOCAL snippets (the `code` table). Pull the whole matching set — the table is small // (dozens) — so it can be merged with module snippets and paginated together below. @@ -132,7 +132,7 @@ public function datatable(array $params): void */ public function moduleSource(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('moduleSource')) { $this->_error('core.api.error.not_allowed'); return; } $id = (string) ($params['code_id'] ?? ''); $key = (strncmp($id, 'module:', 7) === 0) ? substr($id, 7) : ''; $s = $key !== '' ? Tiger_Code_Modules::get($key) : null; @@ -158,7 +158,7 @@ public function moduleSource(array $params): void */ public function save(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('save')) { $this->_error('core.api.error.not_allowed'); return; } $form = new Code_Form_Code(); if (!$form->isValid($params)) { $this->_formErrors($form); return; } @@ -244,7 +244,7 @@ public function deactivate(array $params): void { $this->_toggle($params, false) protected function _toggle(array $params, $on): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('_toggle')) { $this->_error('core.api.error.not_allowed'); return; } $id = !empty($params['code_id']) ? (string) $params['code_id'] : ''; if ($id === '') { $this->_error('core.api.error.general'); return; } @@ -317,7 +317,7 @@ protected function _toggleModule($key, $on): void */ public function delete(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('delete')) { $this->_error('core.api.error.not_allowed'); return; } $id = !empty($params['code_id']) ? (string) $params['code_id'] : ''; if ($id === '') { $this->_error('core.api.error.general'); return; } try { @@ -337,7 +337,7 @@ public function delete(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; } $id = !empty($params['code_id']) ? (string) $params['code_id'] : ''; $version = isset($params['version']) ? (int) $params['version'] : 0; if ($id === '' || $version < 1) { $this->_error('core.api.error.general'); return; } diff --git a/modules/profile/services/Org.php b/modules/profile/services/Org.php index a71a5a1..fafcab8 100644 --- a/modules/profile/services/Org.php +++ b/modules/profile/services/Org.php @@ -21,7 +21,7 @@ class Profile_Service_Org extends Tiger_Service_Service */ public function save(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('save')) { $this->_error('core.api.error.not_allowed'); return; } $orgId = (string) $this->_org_id; if ($orgId === '') { $this->_error('core.api.error.not_allowed'); return; } diff --git a/modules/profile/services/OrgAddress.php b/modules/profile/services/OrgAddress.php index bb5814f..9ed8026 100644 --- a/modules/profile/services/OrgAddress.php +++ b/modules/profile/services/OrgAddress.php @@ -21,7 +21,7 @@ class Profile_Service_OrgAddress extends Profile_Service_Base */ public function save(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('save')) { $this->_error('core.api.error.not_allowed'); return; } $orgId = (string) $this->_org_id; if ($orgId === '') { $this->_error('core.api.error.not_allowed'); return; } @@ -81,7 +81,7 @@ public function save(array $params): void */ public function delete(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('delete')) { $this->_error('core.api.error.not_allowed'); return; } $orgId = (string) $this->_org_id; if ($orgId === '') { $this->_error('core.api.error.not_allowed'); return; } if (!$this->_validCsrf(Profile_Form_Address::class, $params)) { $this->_error('core.api.error.csrf'); return; } diff --git a/modules/profile/services/OrgContact.php b/modules/profile/services/OrgContact.php index 5406429..13021e5 100644 --- a/modules/profile/services/OrgContact.php +++ b/modules/profile/services/OrgContact.php @@ -21,7 +21,7 @@ class Profile_Service_OrgContact extends Profile_Service_Base */ public function save(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('save')) { $this->_error('core.api.error.not_allowed'); return; } $orgId = (string) $this->_org_id; if ($orgId === '') { $this->_error('core.api.error.not_allowed'); return; } @@ -79,7 +79,7 @@ public function save(array $params): void */ public function delete(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('delete')) { $this->_error('core.api.error.not_allowed'); return; } $orgId = (string) $this->_org_id; if ($orgId === '') { $this->_error('core.api.error.not_allowed'); return; } if (!$this->_validCsrf(Profile_Form_Contact::class, $params)) { $this->_error('core.api.error.csrf'); return; } diff --git a/modules/profile/services/OrgLogo.php b/modules/profile/services/OrgLogo.php index 4cfa2be..09f9a2d 100644 --- a/modules/profile/services/OrgLogo.php +++ b/modules/profile/services/OrgLogo.php @@ -34,7 +34,7 @@ class Profile_Service_OrgLogo extends Tiger_Service_Service */ public function upload(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('upload')) { $this->_error('core.api.error.not_allowed'); return; } $orgId = (string) $this->_org_id; if ($orgId === '') { $this->_error('core.api.error.not_allowed'); return; } @@ -105,7 +105,7 @@ public function upload(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; } $orgId = (string) $this->_org_id; if ($orgId === '') { $this->_error('core.api.error.not_allowed'); return; } (new Tiger_Model_Option())->forget(Tiger_Model_Option::SCOPE_ORG, $orgId, self::OPTION_KEY); diff --git a/modules/translations/services/Translation.php b/modules/translations/services/Translation.php index 6c1e467..81e8abe 100644 --- a/modules/translations/services/Translation.php +++ b/modules/translations/services/Translation.php @@ -46,7 +46,7 @@ class Translations_Service_Translation extends Tiger_Service_Service */ public function datatable(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('datatable')) { $this->_error('core.api.error.not_allowed'); return; } $dt = $this->_dtParams($params); $default = $this->_default(); @@ -95,7 +95,7 @@ public function datatable(array $params): void }); $page = array_slice($rows, $dt['start'], $dt['length']); - $canEdit = $this->_isAdmin(static::class, 'save'); + $canEdit = $this->_isAllowed('save'); $data = []; foreach ($page as $r) { @@ -118,7 +118,7 @@ public function datatable(array $params): void */ public function entry(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('entry')) { $this->_error('core.api.error.not_allowed'); return; } $key = trim((string) ($params['key'] ?? '')); if ($key === '') { $this->_error('translations.error.no_key'); return; } @@ -162,7 +162,7 @@ public function entry(array $params): void */ public function save(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('save')) { $this->_error('core.api.error.not_allowed'); return; } $key = trim((string) ($params['key'] ?? '')); $values = (array) ($params['values'] ?? []); @@ -200,7 +200,7 @@ public function save(array $params): void */ public function revert(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('revert')) { $this->_error('core.api.error.not_allowed'); return; } $key = trim((string) ($params['key'] ?? '')); if ($key === '') { $this->_error('translations.error.no_key'); return; } @@ -233,7 +233,7 @@ public function revert(array $params): void */ public function translate(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('translate')) { $this->_error('core.api.error.not_allowed'); return; } if (!Tiger_Agent::isConnected()) { $this->_error('translations.error.no_ai'); return; } $source = (string) ($params['source'] ?? ''); @@ -264,7 +264,7 @@ public function translate(array $params): void */ public function context(array $params): void { - if (!$this->_isAdmin()) { $this->_error('core.api.error.not_allowed'); return; } + if (!$this->_isAllowed('context')) { $this->_error('core.api.error.not_allowed'); return; } $key = trim((string) ($params['key'] ?? '')); if ($key === '') { $this->_error('translations.error.no_key'); return; }