Skip to content

Commit

Permalink
LogoutCode (enum-like class)
Browse files Browse the repository at this point in the history
  • Loading branch information
mabar committed Jan 13, 2022
1 parent 00177e9 commit faedb2c
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 39 deletions.
13 changes: 5 additions & 8 deletions src/Authentication/BaseFirewall.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public function login(Identity $identity): void
{
$logins = $this->getLogins();

$this->unauthenticate($logins, Firewall::LOGOUT_MANUAL, null);
$this->unauthenticate($logins, LogoutCode::Manual(), null);
$logins->setCurrentLogin(new CurrentLogin($identity, $this->clock->getTime()));

foreach ($this->onLogin as $cb) {
Expand Down Expand Up @@ -104,18 +104,15 @@ public function logout(): void
return;
}

$this->unauthenticate($this->getLogins(), self::LOGOUT_MANUAL, null);
$this->unauthenticate($this->getLogins(), LogoutCode::Manual(), null);
}

public function addLogoutCallback(Closure $callback): void
{
$this->onLogout[] = $callback;
}

/**
* @phpstan-param self::LOGOUT_* $logoutCode
*/
private function unauthenticate(Logins $logins, int $logoutCode, ?DecisionReason $logoutReason): void
private function unauthenticate(Logins $logins, LogoutCode $logoutCode, ?DecisionReason $logoutReason): void
{
$login = $logins->getCurrentLogin();

Expand Down Expand Up @@ -272,7 +269,7 @@ private function checkInactivity(Logins $logins): void
$now = $this->clock->getTime();

if ($expiration->getTime()->isBefore($now)) {
$this->unauthenticate($logins, self::LOGOUT_INACTIVITY, null);
$this->unauthenticate($logins, LogoutCode::Inactivity(), null);
} else {
$expiration->setTime($now->plusSeconds($expiration->getDelta()->toSeconds()));
}
Expand All @@ -289,7 +286,7 @@ private function checkIdentity(Logins $logins): void
try {
$identity = $this->refresher->refresh($login->getIdentity());
} catch (IdentityExpired $exception) {
$this->unauthenticate($logins, self::LOGOUT_INVALID_IDENTITY, $exception->getLogoutReason());
$this->unauthenticate($logins, LogoutCode::InvalidIdentity(), $exception->getLogoutReason());

return;
}
Expand Down
19 changes: 6 additions & 13 deletions src/Authentication/Data/ExpiredLogin.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,21 @@
namespace Orisai\Auth\Authentication\Data;

use Orisai\Auth\Authentication\DecisionReason;
use Orisai\Auth\Authentication\Firewall;
use Orisai\Auth\Authentication\LogoutCode;
use function is_string;

final class ExpiredLogin extends BaseLogin
{

private ?Expiration $expiration = null;

/** @phpstan-var Firewall::LOGOUT_* */
private int $logoutCode;
private LogoutCode $logoutCode;

private ?DecisionReason $logoutReason;

/**
* @phpstan-param Firewall::LOGOUT_* $logoutCode
*/
public function __construct(
CurrentLogin $currentLogin,
int $logoutCode,
LogoutCode $logoutCode,
?DecisionReason $logoutReason = null
)
{
Expand All @@ -41,10 +37,7 @@ public function getExpiration(): ?Expiration
return $this->expiration;
}

/**
* @phpstan-return Firewall::LOGOUT_*
*/
public function getLogoutCode(): int
public function getLogoutCode(): LogoutCode
{
return $this->logoutCode;
}
Expand All @@ -60,7 +53,7 @@ public function getLogoutReason(): ?DecisionReason
public function __serialize(): array
{
$data = parent::__serialize();
$data['logoutReason'] = $this->logoutCode;
$data['logoutReason'] = $this->logoutCode->value;
$data['logoutReasonDescription'] = $this->logoutReason;
$data['expiration'] = $this->expiration;

Expand All @@ -73,7 +66,7 @@ public function __serialize(): array
public function __unserialize(array $data): void
{
parent::__unserialize($data);
$this->logoutCode = $data['logoutReason'];
$this->logoutCode = LogoutCode::from($data['logoutReason']);
$description = $data['logoutReasonDescription'] ?? null;
$this->logoutReason = !is_string($description) ? $description : DecisionReason::create($description);
$this->expiration = $data['expiration'];
Expand Down
6 changes: 0 additions & 6 deletions src/Authentication/Firewall.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@
interface Firewall
{

public const LOGOUT_MANUAL = 1;

public const LOGOUT_INACTIVITY = 2;

public const LOGOUT_INVALID_IDENTITY = 3;

public function isLoggedIn(): bool;

/**
Expand Down
84 changes: 84 additions & 0 deletions src/Authentication/LogoutCode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php declare(strict_types = 1);

namespace Orisai\Auth\Authentication;

use Exception;
use function array_key_exists;

/**
* phpcs:disable Generic.NamingConventions.CamelCapsFunctionName.ScopeNotCamelCaps
*/
final class LogoutCode
{

private const MANUAL = 1,
INACTIVITY = 2,
INVALID_IDENTITY = 3;

private const VALUES_AND_NAMES = [
self::MANUAL => 'Manual',
self::INACTIVITY => 'Inactivity',
self::INVALID_IDENTITY => 'InvalidIdentity',
];

/** @readonly */
public string $name;

/** @readonly */
public int $value;

private function __construct(string $name, int $value)
{
$this->name = $name;
$this->value = $value;
}

public static function Manual(): self
{
return self::from(self::MANUAL);
}

public static function Inactivity(): self
{
return self::from(self::INACTIVITY);
}

public static function InvalidIdentity(): self
{
return self::from(self::INVALID_IDENTITY);
}

public static function tryFrom(int $value): ?self
{
if (!array_key_exists($value, self::VALUES_AND_NAMES)) {
return null;
}

return new self(self::VALUES_AND_NAMES[$value], $value);
}

public static function from(int $value): self
{
$self = self::tryFrom($value);

if ($self === null) {
throw new Exception();
}

return $self;
}

/**
* @return array<self>
*/
public static function cases(): array
{
$cases = [];
foreach (self::VALUES_AND_NAMES as $value => $name) {
$cases[] = self::from($value);
}

return $cases;
}

}
7 changes: 4 additions & 3 deletions tests/Unit/Authentication/BaseFirewallTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Orisai\Auth\Authentication\DecisionReason;
use Orisai\Auth\Authentication\Exception\NotLoggedIn;
use Orisai\Auth\Authentication\IntIdentity;
use Orisai\Auth\Authentication\LogoutCode;
use Orisai\Auth\Authentication\StringIdentity;
use Orisai\Auth\Authorization\AuthorizationDataBuilder;
use Orisai\Auth\Authorization\PolicyManager;
Expand Down Expand Up @@ -77,7 +78,7 @@ public function testBase(): void

$expired = $firewall->getExpiredLogins()[123];
self::assertSame($identity, $expired->getIdentity());
self::assertSame($firewall::LOGOUT_MANUAL, $expired->getLogoutCode());
self::assertEquals(LogoutCode::Manual(), $expired->getLogoutCode());
self::assertNull($expired->getLogoutReason());

$this->expectException(NotLoggedIn::class);
Expand Down Expand Up @@ -333,7 +334,7 @@ public function testRefresherRemovedIdentity(?DecisionReason $reasonDescription)

$expired = $firewall->getExpiredLogins()[123];
self::assertSame($identity, $expired->getIdentity());
self::assertSame($firewall::LOGOUT_INVALID_IDENTITY, $expired->getLogoutCode());
self::assertEquals(LogoutCode::InvalidIdentity(), $expired->getLogoutCode());
self::assertSame($reasonDescription, $expired->getLogoutReason());
}

Expand Down Expand Up @@ -401,7 +402,7 @@ public function testTimeExpiredIdentity(): void
self::assertFalse($firewall->isLoggedIn());
$expired = $firewall->getExpiredLogins()[123];
self::assertSame($identity, $expired->getIdentity());
self::assertSame($firewall::LOGOUT_INACTIVITY, $expired->getLogoutCode());
self::assertEquals(LogoutCode::Inactivity(), $expired->getLogoutCode());
self::assertNull($expired->getLogoutReason());

$firewall->login($identity);
Expand Down
12 changes: 6 additions & 6 deletions tests/Unit/Authentication/Data/ExpiredLoginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
use Orisai\Auth\Authentication\Data\Expiration;
use Orisai\Auth\Authentication\Data\ExpiredLogin;
use Orisai\Auth\Authentication\DecisionReason;
use Orisai\Auth\Authentication\Firewall;
use Orisai\Auth\Authentication\IntIdentity;
use Orisai\Auth\Authentication\LogoutCode;
use PHPUnit\Framework\TestCase;
use function assert;
use function serialize;
Expand All @@ -24,18 +24,18 @@ public function testBase(): void
$identity = new IntIdentity(1, []);
$authTime = Instant::of(2);
$currentLogin = new CurrentLogin($identity, $authTime);
$login = new ExpiredLogin($currentLogin, Firewall::LOGOUT_MANUAL);
$login = new ExpiredLogin($currentLogin, LogoutCode::Manual());

self::assertSame($identity, $login->getIdentity());
self::assertSame($authTime, $login->getAuthenticationTime());
self::assertNull($login->getExpiration());
self::assertSame(Firewall::LOGOUT_MANUAL, $login->getLogoutCode());
self::assertEquals(LogoutCode::Manual(), $login->getLogoutCode());
self::assertNull($login->getLogoutReason());

self::assertEquals($login, unserialize(serialize($login)));

$reason = DecisionReason::create('description');
$login = new ExpiredLogin($currentLogin, Firewall::LOGOUT_MANUAL, $reason);
$login = new ExpiredLogin($currentLogin, LogoutCode::Manual(), $reason);
self::assertSame($reason, $login->getLogoutReason());
self::assertEquals($login, unserialize(serialize($login)));
}
Expand All @@ -47,7 +47,7 @@ public function testExpiration(): void
$time = Instant::of(123);
$delta = Duration::ofSeconds(456);
$currentLogin->setExpiration(new CurrentExpiration($time, $delta));
$login = new ExpiredLogin($currentLogin, Firewall::LOGOUT_MANUAL);
$login = new ExpiredLogin($currentLogin, LogoutCode::Manual());

$expiration = $login->getExpiration();
self::assertInstanceOf(Expiration::class, $expiration);
Expand Down Expand Up @@ -78,7 +78,7 @@ public function testSerializationBC(): void
self::assertSame(2, $login->getAuthenticationTime()->getEpochSecond());
self::assertInstanceOf(IntIdentity::class, $login->getIdentity());
self::assertNull($login->getExpiration());
self::assertSame(Firewall::LOGOUT_MANUAL, $login->getLogoutCode());
self::assertEquals(LogoutCode::Manual(), $login->getLogoutCode());
self::assertNull($login->getLogoutReason());

// phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
Expand Down
9 changes: 6 additions & 3 deletions tests/Unit/Authentication/Data/LoginsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
use Orisai\Auth\Authentication\Data\CurrentLogin;
use Orisai\Auth\Authentication\Data\ExpiredLogin;
use Orisai\Auth\Authentication\Data\Logins;
use Orisai\Auth\Authentication\Firewall;
use Orisai\Auth\Authentication\Identity;
use Orisai\Auth\Authentication\IntIdentity;
use Orisai\Auth\Authentication\LogoutCode;
use Orisai\Auth\Authentication\StringIdentity;
use PHPUnit\Framework\TestCase;
use function assert;
Expand All @@ -31,7 +31,7 @@ public function test(): void
$logins->removeCurrentLogin();
self::assertNull($logins->getCurrentLogin());

$e1 = new ExpiredLogin($currentLogin, Firewall::LOGOUT_MANUAL);
$e1 = new ExpiredLogin($currentLogin, LogoutCode::Manual());
$logins->addExpiredLogin($e1);
self::assertSame(['test' => $e1], $logins->getExpiredLogins());
self::assertSame($e1, $logins->getLastExpiredLogin());
Expand Down Expand Up @@ -116,7 +116,10 @@ public function test(): void

private function expiredLogin(Identity $identity): ExpiredLogin
{
return new ExpiredLogin(new CurrentLogin($identity, Instant::of(1)), Firewall::LOGOUT_MANUAL);
return new ExpiredLogin(
new CurrentLogin($identity, Instant::of(1)),
LogoutCode::Manual(),
);
}

public function testIncompleteIdentityClasses(): void
Expand Down
38 changes: 38 additions & 0 deletions tests/Unit/Authentication/LogoutCodeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php declare(strict_types = 1);

namespace Tests\Orisai\Auth\Unit\Authentication;

use Orisai\Auth\Authentication\LogoutCode;
use PHPUnit\Framework\TestCase;
use Throwable;

final class LogoutCodeTest extends TestCase
{

public function test(): void
{
self::assertSame(1, LogoutCode::Manual()->value);
self::assertSame('Manual', LogoutCode::Manual()->name);
self::assertSame(2, LogoutCode::Inactivity()->value);
self::assertSame('Inactivity', LogoutCode::Inactivity()->name);
self::assertSame(3, LogoutCode::InvalidIdentity()->value);
self::assertSame('InvalidIdentity', LogoutCode::InvalidIdentity()->name);

self::assertEquals(
[
LogoutCode::Manual(),
LogoutCode::Inactivity(),
LogoutCode::InvalidIdentity(),
],
LogoutCode::cases(),
);

self::assertEquals(LogoutCode::Manual(), LogoutCode::from(1));
self::assertEquals(LogoutCode::Manual(), LogoutCode::tryFrom(1));

self::assertNull(LogoutCode::tryFrom(4));
$this->expectException(Throwable::class);
LogoutCode::from(4);
}

}

0 comments on commit faedb2c

Please sign in to comment.