diff --git a/lib/Controllers/PasswordController.php b/lib/Controllers/PasswordController.php index f63618a..7c5d891 100644 --- a/lib/Controllers/PasswordController.php +++ b/lib/Controllers/PasswordController.php @@ -4,8 +4,8 @@ namespace KTXM\AuthenticationProviderPassword\Controllers; use KTXC\Http\Response\JsonResponse; use KTXC\Service\UserAccountsService; -use KTXC\SessionIdentity; -use KTXC\SessionTenant; +use KTXC\Context\IdentityContextInterface; +use KTXC\Context\TenantContextInterface; use KTXF\Controller\ControllerAbstract; use KTXF\Routing\Attributes\AuthenticatedRoute; use KTXF\Security\Crypto; @@ -15,8 +15,8 @@ use KTXM\AuthenticationProviderPassword\Stores\CredentialStore; class PasswordController extends ControllerAbstract { public function __construct( - private readonly SessionIdentity $sessionIdentity, - private readonly SessionTenant $sessionTenant, + private readonly IdentityContextInterface $identityContext, + private readonly TenantContextInterface $tenantContext, private readonly CredentialStore $credentialStore, private readonly Provider $provider, private readonly Crypto $crypto, @@ -27,8 +27,8 @@ class PasswordController extends ControllerAbstract #[AuthenticatedRoute('/password/update', name: 'password.update', methods: ['POST'])] public function update(string $current_password, string $new_password): JsonResponse { - $tenantId = $this->sessionTenant->identifier(); - $identifier = $this->sessionIdentity->mailAddress(); + $tenantId = $this->tenantContext->identifier(); + $identifier = $this->identityContext->mailAddress(); if ($tenantId === null || $identifier === null) { return new JsonResponse(['error' => 'Invalid session state'], 400); @@ -56,7 +56,7 @@ class PasswordController extends ControllerAbstract #[AuthenticatedRoute('/status', name: 'password.admin.status', methods: ['POST'], permissions: ['authentication_provider_password.admin.view', 'authentication_provider_password.admin.manage'])] public function getStatus(string $uid): JsonResponse { - $tenantId = $this->sessionTenant->identifier(); + $tenantId = $this->tenantContext->identifier(); if ($tenantId === null) { return new JsonResponse(['error' => 'Invalid session state'], 400); @@ -82,7 +82,7 @@ class PasswordController extends ControllerAbstract #[AuthenticatedRoute('/reset', name: 'password.admin.reset', methods: ['POST'], permissions: ['authentication_provider_password.admin.manage'])] public function adminReset(string $uid, string $password): JsonResponse { - $tenantId = $this->sessionTenant->identifier(); + $tenantId = $this->tenantContext->identifier(); if ($tenantId === null) { return new JsonResponse(['error' => 'Invalid session state'], 400); @@ -113,7 +113,7 @@ class PasswordController extends ControllerAbstract #[AuthenticatedRoute('/remove', name: 'password.admin.remove', methods: ['POST'], permissions: ['authentication_provider_password.admin.manage'])] public function adminRemove(string $uid): JsonResponse { - $tenantId = $this->sessionTenant->identifier(); + $tenantId = $this->tenantContext->identifier(); if ($tenantId === null) { return new JsonResponse(['error' => 'Invalid session state'], 400); diff --git a/tests/php/Integration/IntegrationTestCase.php b/tests/php/Integration/IntegrationTestCase.php index 3e00c8a..b060d84 100644 --- a/tests/php/Integration/IntegrationTestCase.php +++ b/tests/php/Integration/IntegrationTestCase.php @@ -6,7 +6,7 @@ namespace KTXT\AuthenticationProviderPassword\Tests\Integration; use KTXC\Http\Request\Request; use KTXC\Http\Response\Response; -use KTXC\Server; +use KTXC\Application; use KTXC\Stores\UserRolesStore; use PHPUnit\Framework\TestCase; @@ -19,11 +19,11 @@ use PHPUnit\Framework\TestCase; * through the real HTTP kernel (routing, tenant resolution, auth middleware, * controller), not by calling controllers directly. * - * A fresh Server (and DI container) is built for every request() call, + * A fresh Application (and DI container) is built for every request() call, * mirroring the one-process-per-request model this app is actually * deployed under. Session identity is a container-lifetime singleton that * AuthenticationMiddleware only ever sets, never clears, so reusing one - * Server across requests would leak an authenticated identity from one + * Application across requests would leak an authenticated identity from one * "request" into the next — a problem that can't occur in production, * where each request gets its own process, but very much can here. * @@ -37,7 +37,7 @@ abstract class IntegrationTestCase extends TestCase public static function setUpBeforeClass(): void { - if (static::buildServer()->environment() === 'prod') { + if (static::buildApplication()->environment() === 'prod') { self::fail('Refusing to run integration tests against a server configured for the "prod" environment.'); } @@ -58,9 +58,9 @@ abstract class IntegrationTestCase extends TestCase } } - protected static function buildServer(): Server + protected static function buildApplication(): Application { - return new Server(SERVER_ROOT); + return Application::create(SERVER_ROOT); } // ========================================================================= @@ -103,17 +103,16 @@ abstract class IntegrationTestCase extends TestCase */ protected static function createRoleWithPermissions(array $permissions, string $label = 'Test Role'): string { - $server = static::buildServer(); + $application = static::buildApplication(); try { - $server->kernel()->boot(); - $store = $server->container()->get(UserRolesStore::class); + $application->kernel()->boot(); + $store = $application->container()->get(UserRolesStore::class); $role = $store->createRole(static::$tenantIdentifier, [ 'label' => $label, 'permissions' => $permissions, ]); } finally { - restore_error_handler(); - restore_exception_handler(); + $application->shutdown(); } return $role['rid']; @@ -174,15 +173,13 @@ abstract class IntegrationTestCase extends TestCase $uri = 'http://' . static::$tenantDomain . $path; $request = Request::create($uri, $method, [], [], [], $server, $content); - // Kernel::boot() registers a global error/exception handler per - // instance and never removes it (fine under one-process-per-request - // in production; here it would otherwise stack a handler per test). - // Pop back to whatever was in place before this request. + // A fresh application mirrors production while shutdown restores its + // process-level error handler after the in-process request. + $application = static::buildApplication(); try { - $response = static::buildServer()->handle($request); + $response = $application->handleHttp($request); } finally { - restore_error_handler(); - restore_exception_handler(); + $application->shutdown(); } $body = $response->getContent();