diff --git a/src/Commands/Seat/Buckets/Update.php b/src/Commands/Seat/Buckets/Update.php index fdca5738..8ff9db19 100644 --- a/src/Commands/Seat/Buckets/Update.php +++ b/src/Commands/Seat/Buckets/Update.php @@ -26,7 +26,7 @@ use Illuminate\Support\Facades\Cache; use Seat\Eveapi\Bus\Character; use Seat\Eveapi\Bus\Corporation; -use Seat\Eveapi\Jobs\Character\Roles; +use Seat\Eveapi\Jobs\Token\RefreshAccessToken; use Seat\Eveapi\Models\Bucket; use Seat\Eveapi\Models\RefreshToken; use Seat\Eveapi\Models\RefreshTokenSchedule; @@ -140,8 +140,7 @@ private function dispatchCharacterEsiUpdate(RefreshToken $token): void */ private function dispatchCharacterTokenKeepAlive(RefreshToken $token): void { - // TODO: add a job that only requests a new access token instead of a random esi job. This will require some eseye rework - Roles::dispatch($token)->onQueue('characters'); + RefreshAccessToken::dispatch($token)->onQueue('characters'); } /** diff --git a/src/InteractsWithToken.php b/src/InteractsWithToken.php new file mode 100644 index 00000000..f41f75ae --- /dev/null +++ b/src/InteractsWithToken.php @@ -0,0 +1,72 @@ +getToken(); + if($token !== null) { + $this->getClient()->setAuthentication($token); + } + } + + /** + * Update the access_token last used in the job, + * along with the expiry time. + * + * @return void + */ + public function updateRefreshToken(): void + { + $client = $this->getClient(); + $token = $this->getToken(); + + // If it is an unauthenticated call, there is nothing to update + if (is_null($token)) + return; + + if (! $client->isAuthenticated()) + return; + + $last_auth = $client->getAuthentication(); + + // update the token + if (! empty($last_auth->getRefreshToken())) + $token->refresh_token = $last_auth->getRefreshToken(); + $token->token = $last_auth->getAccessToken() ?? '-'; + $token->expires_on = $last_auth->getExpiresOn(); + $token->save(); + } +} diff --git a/src/Jobs/EsiBase.php b/src/Jobs/EsiBase.php index 69cdb83f..bf856528 100644 --- a/src/Jobs/EsiBase.php +++ b/src/Jobs/EsiBase.php @@ -29,6 +29,7 @@ use Seat\Eveapi\Exception\PermanentInvalidTokenException; use Seat\Eveapi\Exception\TemporaryEsiOutageException; use Seat\Eveapi\Exception\UnavailableEveServersException; +use Seat\Eveapi\InteractsWithToken; use Seat\Eveapi\Jobs\Middleware\CheckEsiRateLimit; use Seat\Eveapi\Jobs\Middleware\CheckEsiRouteStatus; use Seat\Eveapi\Jobs\Middleware\CheckServerStatus; @@ -46,6 +47,8 @@ */ abstract class EsiBase extends AbstractJob { + use InteractsWithToken; + /** * ANTI_RACE_DELAY prevents rapid job recycling with low queue depths. */ @@ -212,6 +215,11 @@ public function getToken(): ?RefreshToken return $this->token; } + protected function getClient(): EsiClient + { + return $this->esi; + } + /** * @return string */ @@ -299,17 +307,13 @@ public function retrieve(array $path_values = []): EsiResponse if (! is_null($this->page)) $this->esi->page($this->page); + $this->configureTokenForEsiClient(); + // Generally, we want to bubble up exceptions all the way to the // callee. However, in the case of this worker class, we need to // try and be vigilant with tokens that may have expired. So for // those cases we wrap in a try/catch. try { - if ($this->token) { - $this->token = $this->token->fresh(); - - $this->esi->setAuthentication($this->token); - } - $result = $this->esi->invoke($this->method, $this->endpoint, $path_values); // Update the refresh token we have stored in the database. @@ -398,35 +402,6 @@ public function warning(EsiResponse $response): void } } - /** - * Update the access_token last used in the job, - * along with the expiry time. - */ - public function updateRefreshToken(): void - { - - tap($this->token, function ($token) { - - // If no API call was made, the client would have never - // been instantiated and auth information never updated. - if (is_null($token)) - return; - - if (! $this->esi->isAuthenticated()) - return; - - $last_auth = $this->esi->getAuthentication(); - - if (! empty($last_auth->getRefreshToken())) - $token->refresh_token = $last_auth->getRefreshToken(); - - $token->token = $last_auth->getAccessToken() ?? '-'; - $token->expires_on = $last_auth->getExpiresOn(); - - $token->save(); - }); - } - /** * Check if there are any pages left in a response * based on the number of pages available and the diff --git a/src/Jobs/Token/RefreshAccessToken.php b/src/Jobs/Token/RefreshAccessToken.php new file mode 100644 index 00000000..9765ec12 --- /dev/null +++ b/src/Jobs/Token/RefreshAccessToken.php @@ -0,0 +1,88 @@ +token = $token; + $this->esi = app()->make(EsiClient::class); + } + + /** + * @return void + * + * @throws InvalidContainerDataException + */ + public function handle(): void + { + // pass this token to the esi client + $this->configureTokenForEsiClient(); + + // ensure we have a valid access token + $this->esi->getValidAccessToken(); + + // make sure the new token is stored + $this->updateRefreshToken(); + } + + public function getClient(): EsiClient + { + return $this->esi; + } + + public function getToken(): ?RefreshToken + { + return $this->token; + } +} diff --git a/src/Services/EseyeClient.php b/src/Services/EseyeClient.php index 7233303c..70df1377 100644 --- a/src/Services/EseyeClient.php +++ b/src/Services/EseyeClient.php @@ -34,6 +34,8 @@ use Seat\Eseye\Configuration; use Seat\Eseye\Containers\EsiAuthentication; use Seat\Eseye\Eseye; +use Seat\Eseye\Exceptions\InvalidAuthenticationException; +use Seat\Eseye\Exceptions\InvalidContainerDataException; use Seat\Services\Contracts\EsiClient; use Seat\Services\Contracts\EsiResponse; use Seat\Services\Contracts\EsiToken; @@ -227,4 +229,13 @@ public function getCache(): CacheInterface { return $this->instance->getConfiguration()->getCache(); } + + /** + * @throws InvalidAuthenticationException + * @throws InvalidContainerDataException + */ + public function getValidAccessToken(): string + { + return $this->instance->getValidAccessToken()->access_token; + } }