SiteWeaver_CMS/tests/unit/Core/AuthServiceTest.php

128 lines
4.3 KiB
PHP
Raw Normal View History

<?php
/**
* File: tests/unit/Core/AuthServiceTest.php
*
* Author: Funky Waddle
* Date: 2026-09-12
*
* Purpose:
* Unit tests for AuthService, SessionService and TOTPService.
*/
declare(strict_types=1);
namespace Tests\unit\Core;
use SiteWeaver\Core\Config;
use SiteWeaver\Core\Repositories\UserRepository;
use SiteWeaver\Core\Services\AuthService;
use SiteWeaver\Core\Services\SessionService;
use SiteWeaver\Core\Services\TOTPService;
use SiteWeaver\Core\Models\User;
use PHPUnit\Framework\TestCase;
// Dummy TOTP service for testing
class DummyTOTPService extends TOTPService {
public function verify(string $secret, string $otp): bool { return true; }
}
final class AuthServiceTest extends TestCase
{
private Config $config;
private SessionService $session;
private AuthService $auth;
protected function setUp(): void
{
$this->session = new SessionService();
$this->session->start();
$this->config = new Config();
$this->user_repo = $this->createMock(UserRepository::class);
$this->auth = new AuthService($this->config, $this->session, $this->user_repo);
}
protected function tearDown(): void
{
$this->session->destroy();
}
public function testRegisterAndLoginWithPassword(): void
{
$user = $this->auth->register('alice', 'alice@example.com', 'secret123');
$this->assertInstanceOf(User::class, $user);
$mockUser = new \SiteWeaver\Core\Models\User(1, 'alice', 'alice@example.com', 'secret123');
$mockUser->setHashedPassword(password_hash('secret123', PASSWORD_DEFAULT));
$this->user_repo->method('findByUsername')->willReturn($mockUser);
$this->user_repo->method('findById')->willReturn($mockUser);
// login should succeed with correct password
$result = $this->auth->login('alice', 'secret123');
$this->assertTrue($result);
}
public function testLoginWithTOTP(): void
{
// register user and enable TOTP
$user = new \SiteWeaver\Core\Models\User(1, 'bob', 'bob@example.com', 'password');
$user->setHashedPassword(password_hash('password', PASSWORD_DEFAULT));
$user->setTotpSecret('dummysecret');
$this->user_repo->method('findByUsername')->willReturn($user);
$this->user_repo->method('findById')->willReturn($user);
// set dummy TOTP service that always verifies
$totp = new DummyTOTPService();
$this->auth->setTOTPService($totp);
// login without OTP should fail
$this->assertFalse($this->auth->login('bob', 'password'));
// login with OTP should succeed
$this->assertTrue($this->auth->login('bob', 'password', '123456'));
}
public function testAuthMiddlewareAccessControl(): void
{
// register and log in a user
$user = new \SiteWeaver\Core\Models\User(1, 'carol', 'carol@example.com', 'pass');
$user->setHashedPassword(password_hash('pass', PASSWORD_DEFAULT));
$this->user_repo->method('findByUsername')->willReturn($user);
$this->user_repo->method('findById')->willReturn($user);
$this->auth->login('carol', 'pass');
// instantiate middleware
$middleware = new \SiteWeaver\Core\Middleware\AuthMiddleware($this->auth);
// should not throw exception for authenticated user
$this->expectNotToPerformAssertions();
$middleware->handle();
// logout user by removing session key
$this->session->remove('user_id');
// handle should now throw RuntimeException
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Unauthorized');
$middleware->handle();
}
public function testLogout(): void
{
// ensure user is logged in
$user = new \SiteWeaver\Core\Models\User(1, 'alice', 'alice@example.com', 'secret123');
$user->setHashedPassword(password_hash('secret123', PASSWORD_DEFAULT));
$this->user_repo->method('findByUsername')->willReturn($user);
$this->user_repo->method('findById')->willReturn($user);
$this->auth->login('alice', 'secret123');
$this->assertTrue($this->auth->isAuthenticated());
// logout should clear session
$this->auth->logout();
$this->assertFalse($this->auth->isAuthenticated());
}
}