Add login test
This commit is contained in:
parent
829dd01358
commit
b78b0a5b21
|
@ -3,3 +3,5 @@
|
|||
*.swo
|
||||
*.swm
|
||||
tags
|
||||
.cookies
|
||||
/.phpunit.result.cache
|
||||
|
|
90
src/Api.php
90
src/Api.php
|
@ -5,30 +5,31 @@ namespace Zoomyboy\LaravelNami;
|
|||
use App\Conf;
|
||||
use App\Nami\Exceptions\TooManyLoginAttemptsException;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Client\PendingRequest;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
use Illuminate\Support\Str;
|
||||
use Log;
|
||||
use Zoomyboy\LaravelNami\Authentication\Cookie;
|
||||
use Zoomyboy\LaravelNami\Backend\Backend;
|
||||
use Zoomyboy\LaravelNami\Concerns\IsNamiMember;
|
||||
use Zoomyboy\LaravelNami\Cookies\Cookie;
|
||||
use Zoomyboy\LaravelNami\Exceptions\RightException;
|
||||
use Zoomyboy\LaravelNami\NamiException;
|
||||
|
||||
class Api {
|
||||
|
||||
private $cookie;
|
||||
public $loggedIn = null;
|
||||
public static $url = 'https://nami.dpsg.de';
|
||||
public string $url = 'https://nami.dpsg.de';
|
||||
private Cookie $cookie;
|
||||
|
||||
public function __construct($cookieStore) {
|
||||
$this->cookie = $cookieStore;
|
||||
public function __construct(Cookie $cookie)
|
||||
{
|
||||
$this->cookie = $cookie;
|
||||
}
|
||||
|
||||
public function http() {
|
||||
return Backend::init($this->cookie);
|
||||
public function http(): PendingRequest {
|
||||
return Http::withOptions(['cookies' => $this->cookie->load()]);
|
||||
}
|
||||
|
||||
public function findNr(int $nr): Member
|
||||
|
@ -54,7 +55,7 @@ class Api {
|
|||
$page = 1;
|
||||
while (!isset ($totalEntries) || ($page-1) * 100 + 1 <= $totalEntries) {
|
||||
$start = ($page-1) * 100;
|
||||
$url = self::$url.'/ica/rest/nami/search-multi/result-list?searchedValues='.rawurlencode(json_encode((object) $payload) ?: '{}').'&page='.$page.'&start='.$start.'&limit=100';
|
||||
$url = $this->url.'/ica/rest/nami/search-multi/result-list?searchedValues='.rawurlencode(json_encode((object) $payload) ?: '{}').'&page='.$page.'&start='.$start.'&limit=100';
|
||||
$response = $this->http()->get($url);
|
||||
$totalEntries = $response->json()['totalEntries'];
|
||||
if ($response->json()['success'] !== true) {
|
||||
|
@ -70,12 +71,8 @@ class Api {
|
|||
});
|
||||
}
|
||||
|
||||
protected function loggedInAlready(): bool {
|
||||
return $this->loggedIn !== null;
|
||||
}
|
||||
|
||||
public function deleteMember($id) {
|
||||
$url = self::$url.'/ica/rest/nami/mitglied/filtered-for-navigation/mglschaft-beenden';
|
||||
$url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/mglschaft-beenden';
|
||||
$payload = [
|
||||
'id' => $id,
|
||||
'isConfirmed' => 'true',
|
||||
|
@ -88,19 +85,18 @@ class Api {
|
|||
}
|
||||
}
|
||||
|
||||
public function login($mglnr = null, $password = null, $groupid = null): self {
|
||||
$resolved = $this->cookie->resolve($mglnr);
|
||||
|
||||
if ($resolved && !$this->cookie->isExpired()) {
|
||||
public function login($mglnr = null, $password = null): self {
|
||||
if ($this->cookie->isLoggedIn()) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->cookie->beforeLogin();
|
||||
|
||||
$mglnr = $mglnr ?: config('nami.auth.mglnr');
|
||||
$password = $password ?: config('nami.auth.password');
|
||||
$groupid = $groupid ?: config('nami.auth.groupid');
|
||||
|
||||
$this->http()->get(self::$url.'/ica/pages/login.jsp');
|
||||
$response = $this->http()->asForm()->post(self::$url.'/ica/rest/nami/auth/manual/sessionStartup', [
|
||||
$this->http()->get($this->url.'/ica/pages/login.jsp');
|
||||
$response = $this->http()->asForm()->post($this->url.'/ica/rest/nami/auth/manual/sessionStartup', [
|
||||
'Login' => 'API',
|
||||
'redirectTo' => './app.jsp',
|
||||
'username' => $mglnr,
|
||||
|
@ -113,14 +109,14 @@ class Api {
|
|||
throw $e;
|
||||
}
|
||||
|
||||
$this->cookie->store($mglnr);
|
||||
$this->loggedIn = $mglnr;
|
||||
$this->cookie->afterLogin();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function membersOf($groupId): Collection {
|
||||
return collect($this->http()->get(self::$url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/flist')->json()['data']);
|
||||
return collect($this->http()->get($this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/flist')->json()['data']);
|
||||
}
|
||||
|
||||
public function putMember(array $attributes) {
|
||||
|
@ -130,14 +126,14 @@ class Api {
|
|||
$payload = array_merge($existing, $member->toNami());
|
||||
$payload['kontoverbindung'] = json_encode(data_get($payload, 'kontoverbindung', []));
|
||||
$response = $this->http()->put(
|
||||
self::$url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$member->group_id.'/'.$member->id,
|
||||
$this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$member->group_id.'/'.$member->id,
|
||||
$payload
|
||||
);
|
||||
if (data_get($response->json(), 'success') !== true) {
|
||||
$this->exception('Update failed', $member->toNami(), $response->json());
|
||||
}
|
||||
} else {
|
||||
$response = $this->http()->post(self::$url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$member->group_id, $member->toNami());
|
||||
$response = $this->http()->post($this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$member->group_id, $member->toNami());
|
||||
if (data_get($response->json(), 'success') !== true) {
|
||||
$this->exception('Update failed', $member->toNami(), $response->json());
|
||||
}
|
||||
|
@ -151,10 +147,10 @@ class Api {
|
|||
public function putMembership(int $memberId, array $data): int
|
||||
{
|
||||
if (data_get($data, 'id')) {
|
||||
$url = self::$url."/ica/rest/nami/zugeordnete-taetigkeiten/filtered-for-navigation/gruppierung-mitglied/mitglied/{$memberId}/{$data['id']}";
|
||||
$url = $this->url."/ica/rest/nami/zugeordnete-taetigkeiten/filtered-for-navigation/gruppierung-mitglied/mitglied/{$memberId}/{$data['id']}";
|
||||
$response = $this->http()->put($url, $data);
|
||||
} else {
|
||||
$url = self::$url."/ica/rest/nami/zugeordnete-taetigkeiten/filtered-for-navigation/gruppierung-mitglied/mitglied/{$memberId}";
|
||||
$url = $this->url."/ica/rest/nami/zugeordnete-taetigkeiten/filtered-for-navigation/gruppierung-mitglied/mitglied/{$memberId}";
|
||||
$response = $this->http()->post($url, $data);
|
||||
}
|
||||
if (data_get($response->json(), 'success') !== true) {
|
||||
|
@ -169,7 +165,7 @@ class Api {
|
|||
}
|
||||
|
||||
public function membershipsOf($memberId): Collection {
|
||||
$url = self::$url.'/ica/rest/nami/zugeordnete-taetigkeiten/filtered-for-navigation/gruppierung-mitglied/mitglied/'.$memberId.'/flist';
|
||||
$url = $this->url.'/ica/rest/nami/zugeordnete-taetigkeiten/filtered-for-navigation/gruppierung-mitglied/mitglied/'.$memberId.'/flist';
|
||||
|
||||
$r = $this->http()->get($url);
|
||||
|
||||
|
@ -183,13 +179,13 @@ class Api {
|
|||
}
|
||||
|
||||
public function subactivitiesOf($activityId) {
|
||||
return collect($this->http()->get(self::$url.'/ica/rest/nami/untergliederungauftaetigkeit/filtered/untergliederung/taetigkeit/'.$activityId)->json()['data'])->map(function($subactivity) {
|
||||
return collect($this->http()->get($this->url.'/ica/rest/nami/untergliederungauftaetigkeit/filtered/untergliederung/taetigkeit/'.$activityId)->json()['data'])->map(function($subactivity) {
|
||||
return Subactivity::fromNami($subactivity);
|
||||
});;
|
||||
}
|
||||
|
||||
public function membership($memberId, $membershipId) {
|
||||
$url = self::$url.'/ica/rest/nami/zugeordnete-taetigkeiten/filtered-for-navigation/gruppierung-mitglied/mitglied/'.$memberId.'/'.$membershipId;
|
||||
$url = $this->url.'/ica/rest/nami/zugeordnete-taetigkeiten/filtered-for-navigation/gruppierung-mitglied/mitglied/'.$memberId.'/'.$membershipId;
|
||||
$response = $this->http()->get($url);
|
||||
|
||||
Logger::http($url, $response, 'Single Membership '.$membershipId.' from '.$memberId, ['memberId' => $memberId]);
|
||||
|
@ -203,7 +199,7 @@ class Api {
|
|||
|
||||
public function courses(): Collection
|
||||
{
|
||||
$url = self::$url.'/ica/rest/module/baustein';
|
||||
$url = $this->url.'/ica/rest/module/baustein';
|
||||
$response = $this->http()->get($url);
|
||||
|
||||
return collect($response->json()['data'])->map(function($course) {
|
||||
|
@ -213,7 +209,7 @@ class Api {
|
|||
|
||||
public function coursesFor(int $memberId): Collection
|
||||
{
|
||||
$url = self::$url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/flist";
|
||||
$url = $this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/flist";
|
||||
$response = $this->http()->get($url);
|
||||
|
||||
if (!$response->ok() || $response->json()['success'] === false) {
|
||||
|
@ -221,7 +217,7 @@ class Api {
|
|||
}
|
||||
|
||||
return collect($response->json()['data'])->map(function($course) use ($memberId) {
|
||||
$single = $this->http()->get(self::$url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$course['id']}")['data'];
|
||||
$single = $this->http()->get($this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$course['id']}")['data'];
|
||||
|
||||
return (object) [
|
||||
'id' => $single['id'],
|
||||
|
@ -240,7 +236,7 @@ class Api {
|
|||
*/
|
||||
public function createCourse(int $memberId, array $payload): int
|
||||
{
|
||||
$response = $this->http()->post(self::$url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}", [
|
||||
$response = $this->http()->post($this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}", [
|
||||
'bausteinId' => $payload['course_id'],
|
||||
'vstgName' => $payload['event_name'],
|
||||
'vstgTag' => Carbon::parse($payload['completed_at'])->format('Y-m-d').'T00:00:00',
|
||||
|
@ -262,7 +258,7 @@ class Api {
|
|||
*/
|
||||
public function updateCourse(int $memberId, int $courseId, array $payload): void
|
||||
{
|
||||
$response = $this->http()->put(self::$url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$courseId}", [
|
||||
$response = $this->http()->put($this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$courseId}", [
|
||||
'bausteinId' => $payload['course_id'],
|
||||
'vstgName' => $payload['event_name'],
|
||||
'vstgTag' => Carbon::parse($payload['completed_at'])->format('Y-m-d').'T00:00:00',
|
||||
|
@ -276,7 +272,7 @@ class Api {
|
|||
|
||||
public function deleteCourse(int $memberId, int $courseId): void
|
||||
{
|
||||
$response = $this->http()->delete(self::$url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$courseId}");
|
||||
$response = $this->http()->delete($this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$courseId}");
|
||||
|
||||
if ($response->json() !== null && data_get($response->json(), 'success') !== true) {
|
||||
$this->exception('Course deletion failed', [], $response->json());
|
||||
|
@ -284,7 +280,7 @@ class Api {
|
|||
}
|
||||
|
||||
public function member($groupId, $memberId) {
|
||||
$url = self::$url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/'.$memberId;
|
||||
$url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/'.$memberId;
|
||||
$response = $this->http()->get($url);
|
||||
|
||||
Logger::http($url, $response, 'Show member '.$memberId, ['memberId' => $memberId]);
|
||||
|
@ -316,7 +312,7 @@ class Api {
|
|||
}
|
||||
|
||||
public function groups($parentGroupId = null): Collection {
|
||||
return collect($this->http()->get(self::$url.'/ica/rest/nami/gruppierungen/filtered-for-navigation/gruppierung/node/'.($parentGroupId ?: 'root'))->json()['data'])->map(function($group) use ($parentGroupId) {
|
||||
return collect($this->http()->get($this->url.'/ica/rest/nami/gruppierungen/filtered-for-navigation/gruppierung/node/'.($parentGroupId ?: 'root'))->json()['data'])->map(function($group) use ($parentGroupId) {
|
||||
return Group::fromResponse($group, $parentGroupId);
|
||||
});
|
||||
}
|
||||
|
@ -332,51 +328,51 @@ class Api {
|
|||
}
|
||||
|
||||
public function genders(): Collection {
|
||||
return collect($this->http()->get(self::$url."/ica/rest/baseadmin/geschlecht")['data'])->map(function($gender) {
|
||||
return collect($this->http()->get($this->url."/ica/rest/baseadmin/geschlecht")['data'])->map(function($gender) {
|
||||
return Gender::fromNami($gender);
|
||||
})->filter(fn($gender) => !$gender->isNull);
|
||||
}
|
||||
|
||||
public function nationalities(): Collection {
|
||||
return collect($this->http()->get(self::$url."/ica/rest/baseadmin/staatsangehoerigkeit")['data'])->map(function($gender) {
|
||||
return collect($this->http()->get($this->url."/ica/rest/baseadmin/staatsangehoerigkeit")['data'])->map(function($gender) {
|
||||
return Nationality::fromNami($gender);
|
||||
});
|
||||
}
|
||||
|
||||
public function countries() {
|
||||
return collect($this->http()->get(self::$url."/ica/rest/baseadmin/land")['data'])->map(function($country) {
|
||||
return collect($this->http()->get($this->url."/ica/rest/baseadmin/land")['data'])->map(function($country) {
|
||||
return Country::fromNami($country);
|
||||
});
|
||||
}
|
||||
|
||||
public function regions() {
|
||||
return collect($this->http()->get(self::$url."/ica/rest/baseadmin/region")['data'])->map(function($region) {
|
||||
return collect($this->http()->get($this->url."/ica/rest/baseadmin/region")['data'])->map(function($region) {
|
||||
return Region::fromNami($region);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public function feesOf($groupid) {
|
||||
return collect($this->http()->get(self::$url."/ica/rest/namiBeitrag/beitragsartmgl/gruppierung/{$groupid}")['data'])->map(function($fee) {
|
||||
return collect($this->http()->get($this->url."/ica/rest/namiBeitrag/beitragsartmgl/gruppierung/{$groupid}")['data'])->map(function($fee) {
|
||||
return Fee::fromNami($fee);
|
||||
});
|
||||
}
|
||||
|
||||
public function confessions(): Collection {
|
||||
return collect($this->http()->get(self::$url."/ica/rest/baseadmin/konfession")['data'])->map(function($gender) {
|
||||
return collect($this->http()->get($this->url."/ica/rest/baseadmin/konfession")['data'])->map(function($gender) {
|
||||
return Confession::fromNami($gender);
|
||||
});
|
||||
}
|
||||
|
||||
public function activities($groupId) {
|
||||
return collect($this->http()->get(self::$url."/ica/rest/nami/taetigkeitaufgruppierung/filtered/gruppierung/gruppierung/".$groupId)['data'])->map(function($activity) {
|
||||
return collect($this->http()->get($this->url."/ica/rest/nami/taetigkeitaufgruppierung/filtered/gruppierung/gruppierung/".$groupId)['data'])->map(function($activity) {
|
||||
return Activity::fromNami($activity);
|
||||
});
|
||||
}
|
||||
|
||||
public function memberOverviewOf(int $groupId): Collection
|
||||
{
|
||||
$url = self::$url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/flist';
|
||||
$url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/flist';
|
||||
$response = $this->http()->get($url);
|
||||
|
||||
return collect($response['data'])->map(function($member) use ($groupId) {
|
||||
|
@ -390,7 +386,7 @@ class Api {
|
|||
}
|
||||
|
||||
private function singleMemberFallback($groupId, $memberId) {
|
||||
$url = self::$url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/flist';
|
||||
$url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/flist';
|
||||
$response = $this->http()->get($url);
|
||||
|
||||
$member = collect($response['data'])->first(function($member) use ($memberId) {
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\LaravelNami\Authentication;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use GuzzleHttp\Cookie\FileCookieJar;
|
||||
|
||||
class Cookie {
|
||||
|
||||
public string $path = __DIR__.'/../../.cookies';
|
||||
private FileCookieJar $cookie;
|
||||
|
||||
/**
|
||||
* Loads the cookie for a new request
|
||||
*
|
||||
* @return FileCookieJar
|
||||
*/
|
||||
public function load(): FileCookieJar
|
||||
{
|
||||
$cookieFile = $this->file() ?: $this->newFileName();
|
||||
|
||||
return $this->cookie = new FileCookieJar($cookieFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all cookies before logging in
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function beforeLogin(): void
|
||||
{
|
||||
while ($file = $this->file()) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set last login to now after login
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function afterLogin(): void
|
||||
{
|
||||
$this->cookie->save($this->newFileName());
|
||||
}
|
||||
|
||||
public function isLoggedIn(): bool
|
||||
{
|
||||
if ($this->file() === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! $this->isExpired();
|
||||
}
|
||||
|
||||
private function newFileName(): string
|
||||
{
|
||||
return $this->path.'/'.time().'.txt';
|
||||
}
|
||||
|
||||
private function isExpired(): bool
|
||||
{
|
||||
$lastLoginTime = Carbon::createFromTimestamp(pathinfo($this->file(), PATHINFO_FILENAME));
|
||||
|
||||
return $lastLoginTime->addMinutes(50)->isPast();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cookie file if it exists
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
private function file(): ?string
|
||||
{
|
||||
$files = glob($this->path.'/*');
|
||||
|
||||
if (!count($files)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $files[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\LaravelNami\Backend;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
class Backend extends Facade {
|
||||
protected static function getFacadeAccessor() { return 'nami.backend'; }
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\LaravelNami\Backend;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Zoomyboy\LaravelNami\Cookies\Cookie;
|
||||
|
||||
class LiveBackend {
|
||||
|
||||
public static function init($cookie) {
|
||||
return Http::withOptions(['cookies' => $cookie->forBackend()]);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\LaravelNami\Cookies;
|
||||
|
||||
use GuzzleHttp\Cookie\SetCookie;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class CacheCookie {
|
||||
|
||||
private $store;
|
||||
private $createdAt;
|
||||
|
||||
public function __construct() {
|
||||
$this->store = new \GuzzleHttp\Cookie\CookieJar();
|
||||
}
|
||||
|
||||
public function forBackend() {
|
||||
return $this->store;
|
||||
return \GuzzleHttp\Cookie\CookieJar::fromArray(['JSESSIONID' => Cache::get("namicookie-{$mglnr}")], 'nami.dpsg.de');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the current cookie in the cache
|
||||
*/
|
||||
public function store($mglnr) {
|
||||
Cache::forever("namicookie-{$mglnr}", [
|
||||
'cookie' => $this->store->getCookieByName('JSESSIONID')->getValue(),
|
||||
'created_at' => now(),
|
||||
]);
|
||||
$this->createdAt = now();
|
||||
}
|
||||
|
||||
public function isExpired() {
|
||||
return $this->createdAt->addHour(1)->isPast();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cookie by string
|
||||
*/
|
||||
public function set($mglnr, $cookie) {
|
||||
$this->store->setCookie(tap(SetCookie::fromString('JSESSIONID='.$cookie.'; path=/ica'), function($cookie) {
|
||||
$cookie->setDomain('nami.dpsg.de');
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stored cookie from the cache
|
||||
*/
|
||||
public function resolve($mglnr) {
|
||||
$cookie = Cache::get("namicookie-{$mglnr}");
|
||||
if ($cookie === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->set($mglnr, $cookie['cookie']);
|
||||
$this->createdAt = $cookie['created_at'];
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
namespace Zoomyboy\LaravelNami\Providers;
|
||||
|
||||
use GuzzleHttp\Client as GuzzleClient;
|
||||
use GuzzleHttp\Cookie\CookieJarInterface;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Zoomyboy\LaravelNami\Api;
|
||||
|
@ -21,14 +22,8 @@ class NamiServiceProvider extends ServiceProvider
|
|||
}
|
||||
|
||||
public function register() {
|
||||
$this->app->singleton('nami.api', function() {
|
||||
return new Api($this->app['nami.cookie']);
|
||||
});
|
||||
$this->app->bind('nami.backend', function() {
|
||||
return new LiveBackend();
|
||||
});
|
||||
$this->app->singleton('nami.cookie', function() {
|
||||
return new CacheCookie();
|
||||
$this->app->bind('nami.api', function() {
|
||||
return app(Api::class);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ class TestCase extends \Orchestra\Testbench\TestCase
|
|||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
Cookie::swap(new FakeCookie());
|
||||
$this->clearCookies();
|
||||
}
|
||||
|
||||
protected function getPackageProviders($app)
|
||||
|
@ -30,19 +30,6 @@ class TestCase extends \Orchestra\Testbench\TestCase
|
|||
return [];
|
||||
}
|
||||
|
||||
protected function setCredentials() {
|
||||
Config::set('nami.auth.mglnr', '11223');
|
||||
Config::set('nami.auth.password', 'secret');
|
||||
Config::set('nami.auth.groupid', '55555');
|
||||
}
|
||||
|
||||
public function login() {
|
||||
return [
|
||||
'https://nami.dpsg.de/ica/pages/login.jsp' => Http::response('<html></html>', 200),
|
||||
'https://nami.dpsg.de/ica/rest/nami/auth/manual/sessionStartup' => Http::response($this->successJson, 200)
|
||||
];
|
||||
}
|
||||
|
||||
public function fakeJson(string $file, array $data = []): string {
|
||||
ob_start();
|
||||
include(__DIR__.'/json/'.$file);
|
||||
|
@ -55,4 +42,11 @@ class TestCase extends \Orchestra\Testbench\TestCase
|
|||
];
|
||||
}
|
||||
|
||||
private function clearCookies(): void
|
||||
{
|
||||
foreach (glob(__DIR__.'/../.cookies/*') as $file) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,80 +10,106 @@ use Zoomyboy\LaravelNami\Tests\TestCase;
|
|||
class LoginTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* A basic unit test example.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_first_successful_login()
|
||||
public function test_first_successful_login(): void
|
||||
{
|
||||
Http::fake($this->login());
|
||||
$this->setCredentials();
|
||||
Nami::login();
|
||||
Http::fake($this->fakeSuccessfulLogin());
|
||||
|
||||
Nami::login(12345, 'secret');
|
||||
|
||||
Http::assertSent(function($request) {
|
||||
return $request->url() == 'https://nami.dpsg.de/ica/pages/login.jsp';
|
||||
});
|
||||
Http::assertSent(function($request) {
|
||||
return $request->url() == 'https://nami.dpsg.de/ica/rest/nami/auth/manual/sessionStartup'
|
||||
&& $request['username'] == '11223' && $request['password'] == 'secret' && $request['redirectTo'] == './app.jsp' && $request['Login'] == 'API';
|
||||
});
|
||||
Http::assertSentCount(2);
|
||||
Http::assertSent(fn ($request) => $request->url() == 'https://nami.dpsg.de/ica/pages/login.jsp');
|
||||
Http::assertSent(fn ($request) => $request->url() == 'https://nami.dpsg.de/ica/rest/nami/auth/manual/sessionStartup'
|
||||
&& $request['username'] == '12345' && $request['password'] == 'secret'
|
||||
&& $request['redirectTo'] == './app.jsp' && $request['Login'] == 'API'
|
||||
);
|
||||
}
|
||||
|
||||
public function test_first_login_fails_because_of_bruteforce_protection()
|
||||
public function test_it_throws_exception_when_login_failed(): void
|
||||
{
|
||||
Http::fake([
|
||||
'https://nami.dpsg.de/ica/pages/login.jsp' => Http::response('<html></html>', 200),
|
||||
'https://nami.dpsg.de/ica/rest/nami/auth/manual/sessionStartup' => Http::response($this->bruteJson, 200)
|
||||
]);
|
||||
|
||||
$this->setCredentials();
|
||||
Http::fake($this->fakeFailedLogin());
|
||||
|
||||
try {
|
||||
Nami::login();
|
||||
Nami::login(12345, 'wrongpassword');
|
||||
} catch (LoginException $e) {
|
||||
$this->assertEquals(LoginException::WRONG_CREDENTIALS, $e->reason);
|
||||
}
|
||||
}
|
||||
|
||||
public function test_first_login_fails_because_of_bruteforce_protection(): void
|
||||
{
|
||||
Http::fake($this->fakeBruteforceFailure());
|
||||
|
||||
try {
|
||||
Nami::login(12345, 'secret');
|
||||
} catch (LoginException $e) {
|
||||
$this->assertEquals(LoginException::TOO_MANY_FAILED_LOGINS, $e->reason);
|
||||
}
|
||||
}
|
||||
|
||||
public function test_login_once_on_second_login()
|
||||
public function test_store_cookie_after_login(): void
|
||||
{
|
||||
Http::fake([
|
||||
'https://nami.dpsg.de/ica/pages/login.jsp' => Http::response('<html></html>', 200),
|
||||
'https://nami.dpsg.de/ica/rest/nami/auth/manual/sessionStartup' => Http::response($this->successJson, 200)
|
||||
]);
|
||||
Http::fake($this->fakeSuccessfulLogin());
|
||||
|
||||
$this->setCredentials();
|
||||
Nami::login(12345, 'secret');
|
||||
|
||||
Nami::login();
|
||||
Nami::login();
|
||||
$this->assertFileExists(__DIR__.'/../../.cookies/'.time().'.txt');
|
||||
}
|
||||
|
||||
public function test_dont_login_if_cookie_exists(): void
|
||||
{
|
||||
touch(__DIR__.'/../../.cookies/'.time().'.txt');
|
||||
|
||||
Nami::login(12345, 'secret');
|
||||
|
||||
Http::assertSentCount(0);
|
||||
}
|
||||
|
||||
public function test_delete_expired_cookie_before_login(): void
|
||||
{
|
||||
$lastLogin = now()->subHour(2)->timestamp;
|
||||
touch(__DIR__."/../../.cookies/{$lastLogin}.txt");
|
||||
Http::fake($this->fakeSuccessfulLogin());
|
||||
|
||||
Nami::login(12345, 'secret');
|
||||
|
||||
Http::assertSentCount(2);
|
||||
$this->assertFileDoesNotExist(__DIR__."/../../.cookies/{$lastLogin}.txt");
|
||||
}
|
||||
|
||||
public function test_login_once_if_cookie_is_expired(): void
|
||||
{
|
||||
$lastLogin = now()->subHour()->subMinutes(10)->timestamp;
|
||||
touch(__DIR__."/../../.cookies/{$lastLogin}.txt");
|
||||
Http::fake($this->fakeSuccessfulLogin());
|
||||
|
||||
Nami::login(12345, 'secret');
|
||||
Nami::login(12345, 'secret');
|
||||
|
||||
Http::assertSent(function($request) {
|
||||
return $request->url() == 'https://nami.dpsg.de/ica/pages/login.jsp';
|
||||
});
|
||||
Http::assertSent(function($request) {
|
||||
return $request->url() == 'https://nami.dpsg.de/ica/rest/nami/auth/manual/sessionStartup'
|
||||
&& $request['username'] == '11223' && $request['password'] == 'secret' && $request['redirectTo'] == './app.jsp' && $request['Login'] == 'API';
|
||||
});
|
||||
Http::assertSentCount(2);
|
||||
}
|
||||
|
||||
public function test_login_check()
|
||||
private function fakeSuccessfulLogin(): array
|
||||
{
|
||||
Http::fake([
|
||||
'https://nami.dpsg.de/ica/pages/login.jsp' => Http::response('<html></html>', 200),
|
||||
return [
|
||||
'https://nami.dpsg.de/ica/pages/login.jsp' => Http::sequence()->push('<html></html>', 200),
|
||||
'https://nami.dpsg.de/ica/rest/nami/auth/manual/sessionStartup' => Http::sequence()->push($this->successJson, 200),
|
||||
];
|
||||
}
|
||||
|
||||
private function fakeFailedLogin(): array
|
||||
{
|
||||
return [
|
||||
'https://nami.dpsg.de/ica/pages/login.jsp' => Http::sequence()->push('<html></html>', 200),
|
||||
'https://nami.dpsg.de/ica/rest/nami/auth/manual/sessionStartup' => Http::sequence()->push($this->wrongCredentialsJson, 200)
|
||||
]);
|
||||
|
||||
$this->setCredentials();
|
||||
|
||||
try {
|
||||
Nami::login();
|
||||
} catch(LoginException $e) {
|
||||
$this->assertEquals(LoginException::WRONG_CREDENTIALS, $e->reason);
|
||||
];
|
||||
}
|
||||
|
||||
Http::assertSentCount(2);
|
||||
private function fakeBruteforceFailure(): array
|
||||
{
|
||||
return [
|
||||
'https://nami.dpsg.de/ica/pages/login.jsp' => Http::sequence()->push('<html></html>', 200),
|
||||
'https://nami.dpsg.de/ica/rest/nami/auth/manual/sessionStartup' => Http::sequence()->push($this->bruteJson, 200)
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue