diff --git a/src/Api.php b/src/Api.php index d4756f6..3733e90 100644 --- a/src/Api.php +++ b/src/Api.php @@ -438,6 +438,8 @@ class Api { private function assertLoggedIn(): void { + $this->authenticator->refresh(); + if (!$this->isLoggedIn()) { throw new NotAuthenticatedException('You need to login first'); } diff --git a/src/Authentication/Authenticator.php b/src/Authentication/Authenticator.php index c7671ac..d3e3ba1 100644 --- a/src/Authentication/Authenticator.php +++ b/src/Authentication/Authenticator.php @@ -9,7 +9,9 @@ abstract class Authenticator { abstract public function login(int $mglnr, string $password): self; abstract public function http(): PendingRequest; abstract public function isLoggedIn(): bool; - protected static $path = __DIR__.'/../../.cookies'; + abstract public function refresh(): void; + + protected static string $path = __DIR__.'/../../.cookies'; public static function setPath(string $path): void { diff --git a/src/Authentication/FakeCookie.php b/src/Authentication/FakeCookie.php index f695ade..829bd65 100644 --- a/src/Authentication/FakeCookie.php +++ b/src/Authentication/FakeCookie.php @@ -85,6 +85,11 @@ class FakeCookie extends Authenticator { ); } + public function refresh(): void + { + // + } + public function assertNotLoggedIn(): void { Assert::assertFalse( diff --git a/src/Authentication/MainCookie.php b/src/Authentication/MainCookie.php index 795ffd7..3ab71bf 100644 --- a/src/Authentication/MainCookie.php +++ b/src/Authentication/MainCookie.php @@ -12,6 +12,8 @@ class MainCookie extends Authenticator { private FileCookieJar $cookie; private string $url = 'https://nami.dpsg.de'; + private ?int $mglnr = null; + private ?string $password = null; public function login(int $mglnr, string $password): self { @@ -19,6 +21,9 @@ class MainCookie extends Authenticator { return $this; } + $this->mglnr = $mglnr; + $this->password = $password; + while ($file = $this->file()) { unlink($file); } @@ -52,6 +57,13 @@ class MainCookie extends Authenticator { return ! $this->isExpired(); } + public function refresh(): void + { + if ($this->mglnr && $this->password) { + $this->login($this->mglnr, $this->password); + } + } + public function http(): PendingRequest { return Http::withOptions(['cookies' => $this->load()]); diff --git a/tests/TestCase.php b/tests/TestCase.php index 4dca63e..59da08c 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -44,13 +44,17 @@ class TestCase extends \Orchestra\Testbench\TestCase return Nami::login(123, 'secret'); } - private function setupCookies(): void + protected function clearCookies(): void { - Authenticator::setPath(__DIR__.'/../.cookies_test'); - foreach (glob(__DIR__.'/../.cookies_test/*') as $file) { unlink($file); } } + private function setupCookies(): void + { + Authenticator::setPath(__DIR__.'/../.cookies_test'); + $this->clearCookies(); + } + } diff --git a/tests/Unit/CourseTest.php b/tests/Unit/CourseTest.php index e21634c..57ba7d6 100644 --- a/tests/Unit/CourseTest.php +++ b/tests/Unit/CourseTest.php @@ -91,7 +91,7 @@ class CourseTest extends TestCase { $this->expectException(NotAuthenticatedException::class); - $courses = Nami::coursesFor(11111); + Nami::coursesFor(11111); } public function test_parses_failed_login(): void diff --git a/tests/Unit/LoginTest.php b/tests/Unit/LoginTest.php index 6a8a090..ae39b52 100644 --- a/tests/Unit/LoginTest.php +++ b/tests/Unit/LoginTest.php @@ -4,6 +4,7 @@ namespace Zoomyboy\LaravelNami\Tests\Unit; use Illuminate\Support\Facades\Http; use Zoomyboy\LaravelNami\Authentication\Auth; +use Zoomyboy\LaravelNami\Fakes\CourseFake; use Zoomyboy\LaravelNami\LoginException; use Zoomyboy\LaravelNami\Nami; use Zoomyboy\LaravelNami\Tests\TestCase; @@ -93,6 +94,19 @@ class LoginTest extends TestCase Http::assertSentCount(2); } + public function test_it_refreshes_login_when_a_cookie_of_an_existing_api_is_expired(): void + { + app(CourseFake::class)->forMember(11111, []); + Http::fake($this->fakeSuccessfulLoginForever()); + $api = Nami::login(12345, 'secret'); + $this->clearCookies(); + $lastLogin = now()->subHours(2)->timestamp; + touch(__DIR__."/../../.cookies_test/{$lastLogin}.txt"); + + $courses = $api->coursesFor(11111); + $this->assertCount(0, $courses); + } + public function test_it_fakes_login(): void { Auth::fake(); @@ -138,6 +152,14 @@ class LoginTest extends TestCase ]; } + private function fakeSuccessfulLoginForever(): array + { + return [ + 'https://nami.dpsg.de/ica/pages/login.jsp' => Http::response('', 200), + 'https://nami.dpsg.de/ica/rest/nami/auth/manual/sessionStartup' => Http::response($this->successJson, 200), + ]; + } + private function fakeFailedLogin(): array { return [