2026-03-19 18:25:19 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace MintyPHP\Tests\Architecture;
|
|
|
|
|
|
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
|
|
|
|
|
|
class AuthzUiTemplateContractTest extends TestCase
|
|
|
|
|
{
|
|
|
|
|
use ProjectFileAssertionSupport;
|
|
|
|
|
|
|
|
|
|
public function testAdminTenantTemplatesUseServerCapabilities(): void
|
|
|
|
|
{
|
|
|
|
|
$indexTemplate = $this->readProjectFile('pages/admin/tenants/index(default).phtml');
|
|
|
|
|
$this->assertStringNotContainsString("can('tenants.create')", $indexTemplate);
|
|
|
|
|
$this->assertStringContainsString('$canCreateTenants', $indexTemplate);
|
|
|
|
|
|
|
|
|
|
$createTemplate = $this->readProjectFile('pages/admin/tenants/create(default).phtml');
|
|
|
|
|
$this->assertStringNotContainsString("can('custom_fields.manage')", $createTemplate);
|
|
|
|
|
$this->assertStringNotContainsString("can('tenants.sso_manage')", $createTemplate);
|
|
|
|
|
$this->assertStringContainsString('$canManageCustomFields', $createTemplate);
|
|
|
|
|
$this->assertStringContainsString('$canManageSso', $createTemplate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testAdminDepartmentsListTemplateUsesServerCapabilities(): void
|
|
|
|
|
{
|
|
|
|
|
$content = $this->readProjectFile('pages/admin/departments/index(default).phtml');
|
|
|
|
|
$this->assertStringNotContainsString("can('departments.create')", $content);
|
|
|
|
|
$this->assertStringContainsString('$canCreateDepartments', $content);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testAdminRoleTemplatesUseServerCapabilities(): void
|
|
|
|
|
{
|
|
|
|
|
$indexTemplate = $this->readProjectFile('pages/admin/roles/index(default).phtml');
|
|
|
|
|
$this->assertStringNotContainsString("can('roles.create')", $indexTemplate);
|
|
|
|
|
$this->assertStringContainsString('$canCreateRoles', $indexTemplate);
|
|
|
|
|
|
|
|
|
|
$editTemplate = $this->readProjectFile('pages/admin/roles/edit(default).phtml');
|
|
|
|
|
$this->assertStringNotContainsString("can('roles.update')", $editTemplate);
|
|
|
|
|
$this->assertStringNotContainsString("can('roles.delete')", $editTemplate);
|
|
|
|
|
$this->assertStringContainsString('$canUpdateRole', $editTemplate);
|
|
|
|
|
$this->assertStringContainsString('$canDeleteRole', $editTemplate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testAdminPermissionTemplatesUseServerCapabilities(): void
|
|
|
|
|
{
|
|
|
|
|
$indexTemplate = $this->readProjectFile('pages/admin/permissions/index(default).phtml');
|
|
|
|
|
$this->assertStringNotContainsString("can('permissions.create')", $indexTemplate);
|
|
|
|
|
$this->assertStringContainsString('$canCreatePermissions', $indexTemplate);
|
|
|
|
|
|
|
|
|
|
$editTemplate = $this->readProjectFile('pages/admin/permissions/edit(default).phtml');
|
|
|
|
|
$this->assertStringNotContainsString("can('permissions.update')", $editTemplate);
|
|
|
|
|
$this->assertStringNotContainsString("can('permissions.delete')", $editTemplate);
|
|
|
|
|
$this->assertStringContainsString('$canUpdatePermission', $editTemplate);
|
|
|
|
|
$this->assertStringContainsString('$canDeletePermission', $editTemplate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testAdminSettingsTemplateUsesServerCapabilities(): void
|
|
|
|
|
{
|
refactor(settings): split admin/settings into hub + per-section subpages
Splits the 755-line monolithic settings page into a tile-based landing hub
and six focused subpages (general, security, email, api, sso, branding),
each with its own form, CSRF scope and POST handler. Each subpage offers
Save / Save & close buttons plus a Cancel/back link to the hub.
Backend (AdminSettingsService, gateways, policies, DB schema) unchanged.
A new settingsSectionMergePost() helper overlays section POSTs onto the
current DB values so partial saves don't wipe unrelated fields (the
service defaults missing keys to 0/empty).
Sub-action files (logo/favicon/tokens/lifecycle) redirect to the matching
subpage, and architecture contracts now check the subpage files instead
of the removed monolithic index.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 22:43:12 +02:00
|
|
|
// Settings was split into a landing hub + per-section subpages.
|
|
|
|
|
// The form-carrying subpages must use the server-side $canUpdateSettings
|
|
|
|
|
// capability instead of the legacy can() helper.
|
2026-04-25 08:50:05 +02:00
|
|
|
foreach (['general', 'account-access', 'user-lifecycle', 'audit', 'telemetry', 'email', 'api', 'sso', 'branding'] as $section) {
|
refactor(settings): split admin/settings into hub + per-section subpages
Splits the 755-line monolithic settings page into a tile-based landing hub
and six focused subpages (general, security, email, api, sso, branding),
each with its own form, CSRF scope and POST handler. Each subpage offers
Save / Save & close buttons plus a Cancel/back link to the hub.
Backend (AdminSettingsService, gateways, policies, DB schema) unchanged.
A new settingsSectionMergePost() helper overlays section POSTs onto the
current DB values so partial saves don't wipe unrelated fields (the
service defaults missing keys to 0/empty).
Sub-action files (logo/favicon/tokens/lifecycle) redirect to the matching
subpage, and architecture contracts now check the subpage files instead
of the removed monolithic index.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 22:43:12 +02:00
|
|
|
$templateContent = $this->readProjectFile("pages/admin/settings/{$section}(default).phtml");
|
|
|
|
|
$this->assertStringNotContainsString("can('settings.update')", $templateContent, $section);
|
|
|
|
|
$this->assertStringContainsString('$canUpdateSettings', $templateContent, $section);
|
|
|
|
|
}
|
2026-03-19 18:25:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testAdminUserEditTemplateUsesServerCapabilities(): void
|
|
|
|
|
{
|
|
|
|
|
$content = $this->readProjectFile('pages/admin/users/edit(default).phtml');
|
|
|
|
|
$this->assertStringNotContainsString("can('users.", $content);
|
|
|
|
|
$this->assertStringNotContainsString("can('permissions.view')", $content);
|
|
|
|
|
$this->assertStringContainsString('$canViewSecurityArtifacts', $content);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testHardCutTemplatesDoNotUseLegacyCanHelper(): void
|
|
|
|
|
{
|
|
|
|
|
$templates = [
|
|
|
|
|
'templates/partials/app-main-aside.phtml',
|
|
|
|
|
'templates/partials/app-main-aside-icon-bar.phtml',
|
2026-03-26 08:13:37 +01:00
|
|
|
'modules/audit/pages/audit/api-audit/index(default).phtml',
|
|
|
|
|
'modules/audit/pages/audit/system-audit/index(default).phtml',
|
|
|
|
|
'modules/audit/pages/audit/import-audit/index(default).phtml',
|
2026-03-19 18:25:19 +01:00
|
|
|
'pages/admin/scheduled-jobs/index(default).phtml',
|
|
|
|
|
'pages/admin/stats/index(default).phtml',
|
2026-03-26 08:13:37 +01:00
|
|
|
'modules/audit/pages/audit/user-lifecycle-audit/index(default).phtml',
|
|
|
|
|
'modules/audit/pages/audit/user-lifecycle-audit/view(default).phtml',
|
2026-03-19 18:25:19 +01:00
|
|
|
'pages/admin/users/index(default).phtml',
|
|
|
|
|
'pages/admin/users/create(default).phtml',
|
|
|
|
|
'pages/admin/tenants/edit(default).phtml',
|
|
|
|
|
'pages/admin/departments/edit(default).phtml',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
foreach ($templates as $template) {
|
|
|
|
|
$content = $this->readProjectFile($template);
|
|
|
|
|
$this->assertStringNotContainsString("can('", $content, $template);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testStatsTemplateDefinesAuditTabAndPanel(): void
|
|
|
|
|
{
|
|
|
|
|
$content = $this->readProjectFile('pages/admin/stats/index(default).phtml');
|
|
|
|
|
$this->assertStringContainsString('data-tab="audit"', $content);
|
|
|
|
|
$this->assertStringContainsString('data-tab-panel="audit"', $content);
|
|
|
|
|
}
|
|
|
|
|
}
|