Add display_name (unique) and email_confirmed_at columns plus matching getters, DTO fields, repo methods (findByDisplayName, update), and migration. Existing auth tests updated to construct User with the new params.
144 lines
4.1 KiB
PHP
144 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\Auth\Middleware;
|
|
|
|
use App\Auth\CreateSessionDto;
|
|
use App\Http\Middleware\AuthMiddleware;
|
|
use App\Shared\ValueObject\EmailAddress;
|
|
use App\User\User;
|
|
use Closure;
|
|
use DateTimeImmutable;
|
|
use DateTimeZone;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Tests\Fakes\FakeClock;
|
|
use Tests\Fakes\FakeSessionRepository;
|
|
use Tests\TestCase;
|
|
|
|
class AuthMiddlewareTest extends TestCase
|
|
{
|
|
private FakeSessionRepository $sessionRepo;
|
|
|
|
private FakeClock $clock;
|
|
|
|
private DateTimeImmutable $now;
|
|
|
|
private AuthMiddleware $middleware;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->now = new DateTimeImmutable(
|
|
'2026-05-06T12:00:00',
|
|
new DateTimeZone('UTC')
|
|
);
|
|
$this->sessionRepo = new FakeSessionRepository;
|
|
$this->clock = new FakeClock($this->now);
|
|
$this->middleware = new AuthMiddleware(
|
|
$this->sessionRepo,
|
|
$this->clock,
|
|
);
|
|
}
|
|
|
|
private function makeRequest(?string $token): Request
|
|
{
|
|
$request = Request::create('/api/anything', 'POST');
|
|
if ($token !== null) {
|
|
$request->cookies->set('auth_token', $token);
|
|
}
|
|
|
|
return $request;
|
|
}
|
|
|
|
private function nextThatRecords(?Request &$captured): Closure
|
|
{
|
|
return function (Request $request) use (&$captured) {
|
|
$captured = $request;
|
|
|
|
return new JsonResponse(['ok' => true], 200);
|
|
};
|
|
}
|
|
|
|
private function makeUser(int $id): User
|
|
{
|
|
return new User(
|
|
id: $id,
|
|
email: new EmailAddress('user@example.com'),
|
|
displayName: 'user',
|
|
passwordHash: 'hashed:irrelevant',
|
|
isAdmin: false,
|
|
emailConfirmedAt: null,
|
|
);
|
|
}
|
|
|
|
public function test_missing_cookie_returns_unauthorized_json(): void
|
|
{
|
|
$captured = null;
|
|
$response = $this->middleware->handle(
|
|
$this->makeRequest(null),
|
|
$this->nextThatRecords($captured),
|
|
);
|
|
|
|
$this->assertSame(401, $response->getStatusCode());
|
|
$this->assertSame(
|
|
['error' => 'unauthenticated'],
|
|
json_decode($response->getContent(), true),
|
|
);
|
|
$this->assertNull($captured);
|
|
}
|
|
|
|
public function test_unknown_token_returns_unauthorized(): void
|
|
{
|
|
$captured = null;
|
|
$response = $this->middleware->handle(
|
|
$this->makeRequest('does-not-exist'),
|
|
$this->nextThatRecords($captured),
|
|
);
|
|
|
|
$this->assertSame(401, $response->getStatusCode());
|
|
$this->assertNull($captured);
|
|
}
|
|
|
|
public function test_expired_session_returns_unauthorized_and_is_deleted(): void
|
|
{
|
|
$this->sessionRepo->create(new CreateSessionDto(
|
|
token: 'expired-token',
|
|
user: $this->makeUser(7),
|
|
createdAt: $this->now->modify('-8 days'),
|
|
expiresAt: $this->now->modify('-1 day'),
|
|
));
|
|
|
|
$captured = null;
|
|
$response = $this->middleware->handle(
|
|
$this->makeRequest('expired-token'),
|
|
$this->nextThatRecords($captured),
|
|
);
|
|
|
|
$this->assertSame(401, $response->getStatusCode());
|
|
$this->assertNull($captured);
|
|
$this->assertNull(
|
|
$this->sessionRepo->findByToken('expired-token')
|
|
);
|
|
}
|
|
|
|
public function test_valid_session_attaches_user_and_calls_next(): void
|
|
{
|
|
$this->sessionRepo->create(new CreateSessionDto(
|
|
token: 'valid-token',
|
|
user: $this->makeUser(id: 7),
|
|
createdAt: $this->now,
|
|
expiresAt: $this->now->modify('+7 days'),
|
|
));
|
|
|
|
$captured = null;
|
|
$response = $this->middleware->handle(
|
|
$this->makeRequest('valid-token'),
|
|
$this->nextThatRecords($captured),
|
|
);
|
|
|
|
$this->assertSame(200, $response->getStatusCode());
|
|
$this->assertNotNull($captured);
|
|
$attachedUser = $captured->attributes->get('user');
|
|
$this->assertInstanceOf(User::class, $attachedUser);
|
|
$this->assertSame(7, $attachedUser->getId());
|
|
}
|
|
}
|