refactor: rename lib/ to core/ for clearer core-module separation
Rename the top-level lib/ directory to core/ so the project root immediately communicates which code is core platform and which lives in modules/. PHP namespaces (MintyPHP\*) are unchanged — only the Composer PSR-4 path mapping moves from lib/ to core/. Module-internal lib/ directories (modules/*/lib/) are untouched. Updated across the full stack: - composer.json PSR-4 mapping - bootstrap entry points (web/index.php, bin/*, tests/bootstrap.php) - tooling configs (phpstan.neon, phpunit.xml, php-cs-fixer) - 26 architecture contract tests - enforcement-policy, guard-catalog, quality-gates - all documentation (CLAUDE.md, README, 25 docs/, .agents/skills/) - bin/qa-extended.sh search paths - .claude/settings.local.json permission paths Workflow: .agents/runs/CORE-LIB-RENAME-001/ (Analyst → Planner → Executor → Code Review (4 findings fixed) → Security Review → Acceptance Test → Finalizer) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
123
core/Service/Access/AccessPolicyFactory.php
Normal file
123
core/Service/Access/AccessPolicyFactory.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\Access;
|
||||
|
||||
use MintyPHP\App\Module\ModuleRegistry;
|
||||
use MintyPHP\Service\Tenant\TenantScopeService;
|
||||
|
||||
class AccessPolicyFactory
|
||||
{
|
||||
private ?UserAuthorizationPolicy $userAuthorizationPolicy = null;
|
||||
private ?RoleAuthorizationPolicy $roleAuthorizationPolicy = null;
|
||||
private ?PermissionAuthorizationPolicy $permissionAuthorizationPolicy = null;
|
||||
private ?OperationsAuthorizationPolicy $operationsAuthorizationPolicy = null;
|
||||
private ?SettingsAuthorizationPolicy $settingsAuthorizationPolicy = null;
|
||||
private ?TenantAuthorizationPolicy $tenantAuthorizationPolicy = null;
|
||||
private ?DepartmentAuthorizationPolicy $departmentAuthorizationPolicy = null;
|
||||
private ?AuthorizationService $authorizationService = null;
|
||||
private \Closure $moduleClassResolver;
|
||||
|
||||
public function __construct(
|
||||
private readonly PermissionService $permissionService,
|
||||
private readonly TenantScopeService $tenantScopeService,
|
||||
private readonly ?ModuleRegistry $moduleRegistry = null,
|
||||
?callable $moduleClassResolver = null
|
||||
) {
|
||||
$this->moduleClassResolver = $moduleClassResolver !== null
|
||||
? \Closure::fromCallable($moduleClassResolver)
|
||||
: static fn (string $class): ?object => null;
|
||||
}
|
||||
|
||||
public function createUserAuthorizationPolicy(): UserAuthorizationPolicy
|
||||
{
|
||||
return $this->userAuthorizationPolicy ??= new UserAuthorizationPolicy(
|
||||
$this->permissionService,
|
||||
$this->tenantScopeService
|
||||
);
|
||||
}
|
||||
|
||||
public function createRoleAuthorizationPolicy(): RoleAuthorizationPolicy
|
||||
{
|
||||
return $this->roleAuthorizationPolicy ??= new RoleAuthorizationPolicy($this->permissionService);
|
||||
}
|
||||
|
||||
public function createPermissionAuthorizationPolicy(): PermissionAuthorizationPolicy
|
||||
{
|
||||
return $this->permissionAuthorizationPolicy ??= new PermissionAuthorizationPolicy($this->permissionService);
|
||||
}
|
||||
|
||||
public function createOperationsAuthorizationPolicy(): OperationsAuthorizationPolicy
|
||||
{
|
||||
return $this->operationsAuthorizationPolicy ??= new OperationsAuthorizationPolicy($this->permissionService);
|
||||
}
|
||||
|
||||
public function createSettingsAuthorizationPolicy(): SettingsAuthorizationPolicy
|
||||
{
|
||||
return $this->settingsAuthorizationPolicy ??= new SettingsAuthorizationPolicy($this->permissionService);
|
||||
}
|
||||
|
||||
public function createTenantAuthorizationPolicy(): TenantAuthorizationPolicy
|
||||
{
|
||||
return $this->tenantAuthorizationPolicy ??= new TenantAuthorizationPolicy(
|
||||
$this->permissionService,
|
||||
$this->tenantScopeService
|
||||
);
|
||||
}
|
||||
|
||||
public function createDepartmentAuthorizationPolicy(): DepartmentAuthorizationPolicy
|
||||
{
|
||||
return $this->departmentAuthorizationPolicy ??= new DepartmentAuthorizationPolicy(
|
||||
$this->permissionService,
|
||||
$this->tenantScopeService
|
||||
);
|
||||
}
|
||||
|
||||
// Assembles all policies into a single AuthorizationService.
|
||||
// Core policies are registered first; module-contributed policies are appended.
|
||||
// Each ability maps to exactly one policy via supports() — first match wins.
|
||||
public function createAuthorizationService(): AuthorizationService
|
||||
{
|
||||
if ($this->authorizationService !== null) {
|
||||
return $this->authorizationService;
|
||||
}
|
||||
|
||||
$policies = [
|
||||
$this->createUserAuthorizationPolicy(),
|
||||
$this->createRoleAuthorizationPolicy(),
|
||||
$this->createPermissionAuthorizationPolicy(),
|
||||
$this->createOperationsAuthorizationPolicy(),
|
||||
$this->createSettingsAuthorizationPolicy(),
|
||||
$this->createTenantAuthorizationPolicy(),
|
||||
$this->createDepartmentAuthorizationPolicy(),
|
||||
];
|
||||
|
||||
// Append module-contributed authorization policies.
|
||||
if ($this->moduleRegistry !== null) {
|
||||
try {
|
||||
foreach ($this->moduleRegistry->getAuthorizationPolicies() as $policyClass) {
|
||||
if (!is_string($policyClass) || trim($policyClass) === '') {
|
||||
continue;
|
||||
}
|
||||
$policy = $this->instantiateModulePolicy($policyClass);
|
||||
if ($policy instanceof AuthorizationPolicyInterface) {
|
||||
$policies[] = $policy;
|
||||
}
|
||||
}
|
||||
} catch (\Throwable) {
|
||||
// fail-open: no module registry available in this context
|
||||
}
|
||||
}
|
||||
|
||||
return $this->authorizationService = new AuthorizationService($policies);
|
||||
}
|
||||
|
||||
private function instantiateModulePolicy(string $policyClass): ?AuthorizationPolicyInterface
|
||||
{
|
||||
try {
|
||||
$instance = ($this->moduleClassResolver)($policyClass);
|
||||
return $instance instanceof AuthorizationPolicyInterface ? $instance : null;
|
||||
} catch (\Throwable) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user