From 798f7222e985c0591c148f0558ed8a01f1537513 Mon Sep 17 00:00:00 2001 From: philipp lang Date: Sat, 19 Feb 2022 13:37:53 +0100 Subject: [PATCH] Add check for authentication --- src/Api.php | 14 +++++ src/Authentication/Authenticator.php | 1 + src/Authentication/FakeCookie.php | 11 +++- src/Authentication/MainCookie.php | 12 ++-- src/Backend/FakeBackend.php | 31 ++-------- src/Exceptions/NotAuthenticatedException.php | 9 +++ src/Fakes/CourseFake.php | 22 +++++++ src/Nami.php | 6 +- tests/Unit/CourseTest.php | 62 ++++++++++++++++++++ tests/Unit/LoginTest.php | 11 ++++ 10 files changed, 139 insertions(+), 40 deletions(-) create mode 100644 src/Exceptions/NotAuthenticatedException.php create mode 100644 tests/Unit/CourseTest.php diff --git a/src/Api.php b/src/Api.php index 711b070..a5c1334 100644 --- a/src/Api.php +++ b/src/Api.php @@ -15,6 +15,7 @@ use Log; use Zoomyboy\LaravelNami\Authentication\Authenticator; use Zoomyboy\LaravelNami\Backend\Backend; use Zoomyboy\LaravelNami\Concerns\IsNamiMember; +use Zoomyboy\LaravelNami\Exceptions\NotAuthenticatedException; use Zoomyboy\LaravelNami\Exceptions\RightException; use Zoomyboy\LaravelNami\NamiException; @@ -92,6 +93,11 @@ class Api { return $this; } + public function isLoggedIn(): bool + { + return $this->authenticator->isLoggedIn(); + } + public function membersOf($groupId): Collection { return collect($this->http()->get($this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/flist')->json()['data']); } @@ -186,6 +192,7 @@ class Api { public function coursesFor(int $memberId): Collection { + $this->assertLoggedIn(); $url = $this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/flist"; $response = $this->http()->get($url); @@ -382,5 +389,12 @@ class Api { throw (new NamiException($message))->response($response)->request($request); } + private function assertLoggedIn(): void + { + if (!$this->isLoggedIn()) { + throw new NotAuthenticatedException('You need to login first'); + } + } + } diff --git a/src/Authentication/Authenticator.php b/src/Authentication/Authenticator.php index 4d35191..d9b367f 100644 --- a/src/Authentication/Authenticator.php +++ b/src/Authentication/Authenticator.php @@ -8,5 +8,6 @@ abstract class Authenticator { abstract public function login(int $mglnr, string $password): self; abstract public function http(): PendingRequest; + abstract public function isLoggedIn(): bool; } diff --git a/src/Authentication/FakeCookie.php b/src/Authentication/FakeCookie.php index c036b39..f695ade 100644 --- a/src/Authentication/FakeCookie.php +++ b/src/Authentication/FakeCookie.php @@ -33,6 +33,11 @@ class FakeCookie extends Authenticator { return $this; } + public function isLoggedIn(): bool + { + return $this->authenticated !== null; + } + public function http(): PendingRequest { return Http::withOptions([]); @@ -82,15 +87,15 @@ class FakeCookie extends Authenticator { public function assertNotLoggedIn(): void { - Assert::assertNull( - $this->authenticated, + Assert::assertFalse( + $this->isLoggedIn(), 'Failed asserting that noone is logged in. Found login with '.data_get($this->authenticated, 'mglnr') ); } public function assertLoggedIn(): void { - + Assert::assertTrue($this->isLoggedIn()); } } diff --git a/src/Authentication/MainCookie.php b/src/Authentication/MainCookie.php index fca6136..9dc15d2 100644 --- a/src/Authentication/MainCookie.php +++ b/src/Authentication/MainCookie.php @@ -43,12 +43,7 @@ class MainCookie extends Authenticator { return $this; } - public function http(): PendingRequest - { - return Http::withOptions(['cookies' => $this->load()]); - } - - private function isLoggedIn(): bool + public function isLoggedIn(): bool { if ($this->file() === null) { return false; @@ -57,6 +52,11 @@ class MainCookie extends Authenticator { return ! $this->isExpired(); } + public function http(): PendingRequest + { + return Http::withOptions(['cookies' => $this->load()]); + } + private function newFileName(): string { return $this->path.'/'.time().'.txt'; diff --git a/src/Backend/FakeBackend.php b/src/Backend/FakeBackend.php index 607777e..470a271 100644 --- a/src/Backend/FakeBackend.php +++ b/src/Backend/FakeBackend.php @@ -8,19 +8,13 @@ use Illuminate\Http\Client\Response; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Http; use Illuminate\Support\Str; +use Zoomyboy\LaravelNami\Fakes\CourseFake; use Zoomyboy\LaravelNami\Fakes\Fake; use Zoomyboy\LaravelNami\Fakes\FakeInstance; use Zoomyboy\LaravelNami\Fakes\LoginFake; class FakeBackend { - public function fakeLogin(string $mglnr): self - { - app(LoginFake::class)->succeeds($mglnr); - - return $this; - } - /** * @param int $mitgliedsNr * @param array $data @@ -116,27 +110,12 @@ class FakeBackend { ]) ?: '{}', 200); } } - - foreach ($data as $member) { - if ($request->url() === "https://nami.dpsg.de/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$member['id']}/flist") { - return Http::response(json_encode([ - 'success' => true, - 'totalEntries' => collect($member['courses'] ?? [])->count(), - 'data' => collect($member['courses'] ?? [])->map(fn ($course) => ['id' => $course['id']]), - ]) ?: '{}', 200); - } - - foreach ($member['courses'] ?? [] as $course) { - if ($request->url() === "https://nami.dpsg.de/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$member['id']}/{$course['id']}") { - return Http::response(json_encode([ - 'success' => true, - 'data' => $course, - ]) ?: '{}', 200); - } - } - } }); + foreach ($data as $member) { + app(CourseFake::class)->forMember($member['id'], $member['courses'] ?? []); + } + return $this; } diff --git a/src/Exceptions/NotAuthenticatedException.php b/src/Exceptions/NotAuthenticatedException.php new file mode 100644 index 0000000..591ff5f --- /dev/null +++ b/src/Exceptions/NotAuthenticatedException.php @@ -0,0 +1,9 @@ +url() === "https://nami.dpsg.de/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/flist") { + return Http::response(json_encode([ + 'success' => true, + 'totalEntries' => collect($data)->count(), + 'data' => collect($data)->map(fn ($course) => ['id' => $course['id']]), + ]) ?: '{}', 200); + } + + foreach ($data as $course) { + if ($request->url() === "https://nami.dpsg.de/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$course['id']}") { + return Http::response(json_encode([ + 'success' => true, + 'data' => $course, + ]) ?: '{}', 200); + } + } + }); + } + public function createsSuccessful(int $memberId, int $courseId): void { Http::fake(function($request) use ($memberId, $courseId) { diff --git a/src/Nami.php b/src/Nami.php index 60ee4fb..a4d7740 100644 --- a/src/Nami.php +++ b/src/Nami.php @@ -6,15 +6,11 @@ use Illuminate\Support\Facades\Facade; /** * @method static \Zoomyboy\LaravelNami\Api login(int $mglnr, string $password) + * @method static bool isLoggedIn() * @method static \Zoomyboy\LaravelNami\Api fake() */ class Nami extends Facade { protected static function getFacadeAccessor() { return 'nami.api'; } - protected static function fake(): void - { - static::swap(ApiFake::class); - } - } diff --git a/tests/Unit/CourseTest.php b/tests/Unit/CourseTest.php new file mode 100644 index 0000000..36879b4 --- /dev/null +++ b/tests/Unit/CourseTest.php @@ -0,0 +1,62 @@ +forMember(11111, [ + ['bausteinId' => 506, 'id' => 788, 'veranstalter' => 'KJA', 'vstgName' => 'eventname', 'vstgTag' => '2021-11-12 00:00:00'] + ]); + + $courses = Nami::login(12345, 'secret')->coursesFor(11111); + + $this->assertEquals(788, $courses->first()->id); + $this->assertEquals('KJA', $courses->first()->organizer); + $this->assertEquals(506, $courses->first()->course_id); + $this->assertEquals('eventname', $courses->first()->event_name); + $this->assertEquals('2021-11-12 00:00:00', $courses->first()->completed_at); + + Http::assertSent(function($request) { + return $request->url() == 'https://nami.dpsg.de/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/11111/flist'; + }); + Http::assertSent(function($request) { + return $request->url() == 'https://nami.dpsg.de/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/11111/788'; + }); + Http::assertSentCount(2); + } + + public function test_needs_login(): void + { + $this->expectException(NotAuthenticatedException::class); + + $courses = Nami::coursesFor(11111); + } + + public function test_parses_failed_login(): void + { + Auth::failed(12345, 'secret'); + $this->expectException(LoginException::class); + + Nami::login(12345, 'secret')->coursesFor(11111); + } + +} diff --git a/tests/Unit/LoginTest.php b/tests/Unit/LoginTest.php index 9c55bb9..d0a1281 100644 --- a/tests/Unit/LoginTest.php +++ b/tests/Unit/LoginTest.php @@ -119,6 +119,17 @@ class LoginTest extends TestCase Auth::assertNotLoggedIn(); } + public function test_it_fakes_login_state(): void + { + Auth::fake(); + Auth::success(12345, 'secret'); + $this->assertFalse(Nami::isLoggedIn()); + + Nami::login(12345, 'secret'); + + $this->assertTrue(Nami::isLoggedIn()); + } + private function fakeSuccessfulLogin(): array { return [