Upgrade spectre to v4

This commit is contained in:
James Cole
2018-04-28 05:25:29 +02:00
parent 85d655d3e2
commit bc8bcf7a1a
12 changed files with 102 additions and 68 deletions

View File

@@ -160,6 +160,8 @@ class IndexController extends Controller
Preferences::delete('spectre_client_id'); Preferences::delete('spectre_client_id');
Preferences::delete('spectre_app_secret'); Preferences::delete('spectre_app_secret');
Preferences::delete('spectre_service_secret'); Preferences::delete('spectre_service_secret');
Preferences::delete('spectre_app_id');
Preferences::delete('spectre_secret');
Preferences::delete('spectre_private_key'); Preferences::delete('spectre_private_key');
Preferences::delete('spectre_public_key'); Preferences::delete('spectre_public_key');
Preferences::delete('spectre_customer'); Preferences::delete('spectre_customer');

View File

@@ -71,9 +71,8 @@ class SpectrePrerequisites implements PrerequisitesInterface
public function hasPrerequisites(): bool public function hasPrerequisites(): bool
{ {
$values = [ $values = [
Preferences::getForUser($this->user, 'spectre_client_id', false), Preferences::getForUser($this->user, 'spectre_app_id', false),
Preferences::getForUser($this->user, 'spectre_app_secret', false), Preferences::getForUser($this->user, 'spectre_secret', false),
Preferences::getForUser($this->user, 'spectre_service_secret', false),
]; ];
/** @var Preference $value */ /** @var Preference $value */
foreach ($values as $value) { foreach ($values as $value) {
@@ -111,9 +110,8 @@ class SpectrePrerequisites implements PrerequisitesInterface
public function storePrerequisites(Request $request): MessageBag public function storePrerequisites(Request $request): MessageBag
{ {
Log::debug('Storing Spectre API keys..'); Log::debug('Storing Spectre API keys..');
Preferences::setForUser($this->user, 'spectre_client_id', $request->get('client_id')); Preferences::setForUser($this->user, 'spectre_app_id', $request->get('app_id'));
Preferences::setForUser($this->user, 'spectre_app_secret', $request->get('app_secret')); Preferences::setForUser($this->user, 'spectre_secret', $request->get('secret'));
Preferences::setForUser($this->user, 'spectre_service_secret', $request->get('service_secret'));
Log::debug('Done!'); Log::debug('Done!');
return new MessageBag; return new MessageBag;

View File

@@ -0,0 +1,32 @@
<?php
/**
* WrongRequestFormat.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Spectre\Exception;
/**
* Class WrongRequestFormatException
*/
class WrongRequestFormatException extends SpectreException
{
}

View File

@@ -56,7 +56,7 @@ class Account extends SpectreObject
*/ */
public function __construct(array $data) public function __construct(array $data)
{ {
$this->id = $data['id']; $this->id = (int)$data['id'];
$this->loginId = $data['login_id']; $this->loginId = $data['login_id'];
$this->currencyCode = $data['currency_code']; $this->currencyCode = $data['currency_code'];
$this->balance = $data['balance']; $this->balance = $data['balance'];

View File

@@ -58,8 +58,6 @@ class Attempt extends SpectreObject
private $failErrorClass; private $failErrorClass;
/** @var string */ /** @var string */
private $failMessage; private $failMessage;
/** @var string */
private $fetchType;
/** @var bool */ /** @var bool */
private $finished; private $finished;
/** @var bool */ /** @var bool */
@@ -90,6 +88,8 @@ class Attempt extends SpectreObject
private $updatedAt; private $updatedAt;
/** @var string */ /** @var string */
private $userAgent; // undocumented private $userAgent; // undocumented
/** @var array */
private $fetchScopes = [];
/** /**
* Attempt constructor. * Attempt constructor.
@@ -114,7 +114,7 @@ class Attempt extends SpectreObject
$this->failAt = new Carbon($data['fail_at']); $this->failAt = new Carbon($data['fail_at']);
$this->failErrorClass = $data['fail_error_class']; $this->failErrorClass = $data['fail_error_class'];
$this->failMessage = $data['fail_message']; $this->failMessage = $data['fail_message'];
$this->fetchType = $data['fetch_type']; $this->fetchScopes = $data['fetch_scopes'];
$this->finished = $data['finished']; $this->finished = $data['finished'];
$this->finishedRecent = $data['finished_recent']; $this->finishedRecent = $data['finished_recent'];
$this->fromDate = new Carbon($data['from_date']); $this->fromDate = new Carbon($data['from_date']);
@@ -185,7 +185,7 @@ class Attempt extends SpectreObject
'fail_at' => $this->failAt->toIso8601String(), 'fail_at' => $this->failAt->toIso8601String(),
'fail_error_class' => $this->failErrorClass, 'fail_error_class' => $this->failErrorClass,
'fail_message' => $this->failMessage, 'fail_message' => $this->failMessage,
'fetch_type' => $this->fetchType, 'fetch_scopes' => $this->fetchScopes,
'finished' => $this->finished, 'finished' => $this->finished,
'finished_recent' => $this->finishedRecent, 'finished_recent' => $this->finishedRecent,
'from_date' => $this->fromDate->toIso8601String(), 'from_date' => $this->fromDate->toIso8601String(),

View File

@@ -83,7 +83,7 @@ class Login extends SpectreObject
$this->customerId = $data['customer_id']; $this->customerId = $data['customer_id'];
$this->dailyRefresh = $data['daily_refresh']; $this->dailyRefresh = $data['daily_refresh'];
$this->holderInfo = new Holder($data['holder_info']); $this->holderInfo = new Holder($data['holder_info']);
$this->id = $data['id']; $this->id = (int)$data['id'];
$this->lastAttempt = new Attempt($data['last_attempt']); $this->lastAttempt = new Attempt($data['last_attempt']);
$this->lastSuccessAt = new Carbon($data['last_success_at']); $this->lastSuccessAt = new Carbon($data['last_success_at']);
$this->nextRefreshPossibleAt = new Carbon($data['next_refresh_possible_at']); $this->nextRefreshPossibleAt = new Carbon($data['next_refresh_possible_at']);

View File

@@ -64,7 +64,7 @@ class Transaction extends SpectreObject
*/ */
public function __construct(array $data) public function __construct(array $data)
{ {
$this->id = $data['id']; $this->id = (int)$data['id'];
$this->mode = $data['mode']; $this->mode = $data['mode'];
$this->status = $data['status']; $this->status = $data['status'];
$this->madeOn = new Carbon($data['made_on']); $this->madeOn = new Carbon($data['made_on']);

View File

@@ -52,7 +52,7 @@ class CreateTokenRequest extends SpectreRequest
$data = [ $data = [
'data' => [ 'data' => [
'customer_id' => $this->customer->getId(), 'customer_id' => $this->customer->getId(),
'fetch_type' => 'recent', 'fetch_scopes' => ['accounts', 'transactions'],
'daily_refresh' => true, 'daily_refresh' => true,
'include_fake_providers' => true, 'include_fake_providers' => true,
'show_consent_confirmation' => true, 'show_consent_confirmation' => true,

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Services\Spectre\Request; namespace FireflyIII\Services\Spectre\Request;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Services\Spectre\Object\Customer; use FireflyIII\Services\Spectre\Object\Customer;
use FireflyIII\Services\Spectre\Object\Login; use FireflyIII\Services\Spectre\Object\Login;
use Log; use Log;
@@ -39,9 +40,7 @@ class ListLoginsRequest extends SpectreRequest
private $logins = []; private $logins = [];
/** /**
* * @throws FireflyException
* @throws \FireflyIII\Services\Spectre\Exception\SpectreException
* @throws \FireflyIII\Exceptions\FireflyException
*/ */
public function call(): void public function call(): void
{ {
@@ -54,7 +53,7 @@ class ListLoginsRequest extends SpectreRequest
$response = $this->sendSignedSpectreGet($uri, []); $response = $this->sendSignedSpectreGet($uri, []);
// count entries: // count entries:
Log::debug(sprintf('Found %d entries in data-array', count($response['data']))); Log::debug(sprintf('Found %d entries in data-array', \count($response['data'])));
// extract next ID // extract next ID
$hasNextPage = false; $hasNextPage = false;

View File

@@ -34,17 +34,15 @@ use Requests_Response;
*/ */
abstract class SpectreRequest abstract class SpectreRequest
{ {
/** @var string */ /** @var int */
protected $clientId = '';
/**
* @var int
*/
protected $expiresAt = 0; protected $expiresAt = 0;
/** @var string */ /** @var string */
protected $serviceSecret = ''; private $appId;
/** @var string */ /** @var string */
private $privateKey; private $privateKey;
/** @var string */ /** @var string */
private $secret;
/** @var string */
private $server; private $server;
/** @var User */ /** @var User */
private $user; private $user;
@@ -67,12 +65,12 @@ abstract class SpectreRequest
$this->privateKey = $privateKey->data; $this->privateKey = $privateKey->data;
// set client ID // set client ID
$clientId = app('preferences')->get('spectre_client_id', null); $appId = app('preferences')->get('spectre_app_id', null);
$this->clientId = $clientId->data; $this->appId = $appId->data;
// set service secret // set service secret
$serviceSecret = app('preferences')->get('spectre_service_secret', null); $secret = app('preferences')->get('spectre_secret', null);
$this->serviceSecret = $serviceSecret->data; $this->secret = $secret->data;
} }
/** /**
@@ -83,17 +81,33 @@ abstract class SpectreRequest
/** /**
* @return string * @return string
*/ */
public function getClientId(): string public function getAppId(): string
{ {
return $this->clientId; return $this->appId;
} }
/** /**
* @param string $clientId * @param string $appId
*/ */
public function setClientId(string $clientId): void public function setAppId(string $appId): void
{ {
$this->clientId = $clientId; $this->appId = $appId;
}
/**
* @return string
*/
public function getSecret(): string
{
return $this->secret;
}
/**
* @param string $secret
*/
public function setSecret(string $secret): void
{
$this->secret = $secret;
} }
/** /**
@@ -104,26 +118,10 @@ abstract class SpectreRequest
return $this->server; return $this->server;
} }
/**
* @return string
*/
public function getServiceSecret(): string
{
return $this->serviceSecret;
}
/**
* @param string $serviceSecret
*/
public function setServiceSecret(string $serviceSecret): void
{
$this->serviceSecret = $serviceSecret;
}
/** /**
* @param string $privateKey * @param string $privateKey
*/ */
public function setPrivateKey(string $privateKey) public function setPrivateKey(string $privateKey): void
{ {
$this->privateKey = $privateKey; $this->privateKey = $privateKey;
} }
@@ -139,10 +137,11 @@ abstract class SpectreRequest
*/ */
protected function generateSignature(string $method, string $uri, string $data): string protected function generateSignature(string $method, string $uri, string $data): string
{ {
if (0 === strlen($this->privateKey)) { if ('' === $this->privateKey) {
throw new FireflyException('No private key present.'); throw new FireflyException('No private key present.');
} }
if ('get' === strtolower($method) || 'delete' === strtolower($method)) { $method = strtolower($method);
if ('get' === $method || 'delete' === $method) {
$data = ''; $data = '';
} }
$toSign = $this->expiresAt . '|' . strtoupper($method) . '|' . $uri . '|' . $data . ''; // no file so no content there. $toSign = $this->expiresAt . '|' . strtoupper($method) . '|' . $uri . '|' . $data . ''; // no file so no content there.
@@ -150,7 +149,7 @@ abstract class SpectreRequest
$signature = ''; $signature = '';
// Sign the data // Sign the data
openssl_sign($toSign, $signature, $this->privateKey, OPENSSL_ALGO_SHA1); openssl_sign($toSign, $signature, $this->privateKey, OPENSSL_ALGO_SHA256);
$signature = base64_encode($signature); $signature = base64_encode($signature);
return $signature; return $signature;
@@ -164,13 +163,13 @@ abstract class SpectreRequest
$userAgent = sprintf('FireflyIII v%s', config('firefly.version')); $userAgent = sprintf('FireflyIII v%s', config('firefly.version'));
return [ return [
'Client-Id' => $this->getClientId(), 'App-id' => $this->getAppId(),
'Service-Secret' => $this->getServiceSecret(), 'Secret' => $this->getSecret(),
'Accept' => 'application/json', 'Accept' => 'application/json',
'Content-type' => 'application/json', 'Content-type' => 'application/json',
'Cache-Control' => 'no-cache', 'Cache-Control' => 'no-cache',
'User-Agent' => $userAgent, 'User-Agent' => $userAgent,
'Expires-at' => $this->expiresAt, 'Expires-at' => $this->expiresAt,
]; ];
} }
@@ -184,7 +183,7 @@ abstract class SpectreRequest
*/ */
protected function sendSignedSpectreGet(string $uri, array $data): array protected function sendSignedSpectreGet(string $uri, array $data): array
{ {
if (0 === strlen($this->server)) { if ('' === $this->server) {
throw new FireflyException('No Spectre server defined'); throw new FireflyException('No Spectre server defined');
} }
@@ -227,7 +226,7 @@ abstract class SpectreRequest
*/ */
protected function sendSignedSpectrePost(string $uri, array $data): array protected function sendSignedSpectrePost(string $uri, array $data): array
{ {
if (0 === strlen($this->server)) { if ('' === $this->server) {
throw new FireflyException('No Spectre server defined'); throw new FireflyException('No Spectre server defined');
} }
@@ -277,7 +276,5 @@ abstract class SpectreRequest
if (200 !== $statusCode) { if (200 !== $statusCode) {
throw new FireflyException(sprintf('Status code %d: %s', $statusCode, $response->body)); throw new FireflyException(sprintf('Status code %d: %s', $statusCode, $response->body));
} }
return;
} }
} }

View File

@@ -47,20 +47,27 @@
{% endfor %} {% endfor %}
</td> </td>
<td> <td>
{% if account.options|length > 0 %}
<select class="form-control" name="import[{{ account.id }}]"> <select class="form-control" name="import[{{ account.id }}]">
{% for id,name in account.options %} {% for id,name in account.options %}
<option value="{{ id }}" label="{{ name }}">{{ name }}</option> <option value="{{ id }}" label="{{ name }}">{{ name }}</option>
{% endfor %} {% endfor %}
</select> </select>
{% else %}
<em>
{{ trans('import.spectre_no_supported_accounts') }}
</em>
{% endif %}
</td> </td>
<td> <td>
{% if account.options|length > 0 %}
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" value="1" name="do_import[{{ account.id }}]" checked> <input type="checkbox" value="1" name="do_import[{{ account.id }}]" checked>
{{ trans('import.spectre_do_import') }} {{ trans('import.spectre_do_import') }}
</label> </label>
</div> </div>
{% endif %}
</td> </td>
</tr> </tr>

View File

@@ -23,9 +23,8 @@
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
{{ ExpandedForm.text('client_id') }} {{ ExpandedForm.text('app_id') }}
{{ ExpandedForm.text('service_secret') }} {{ ExpandedForm.text('secret') }}
{{ ExpandedForm.text('app_secret') }}
</div> </div>
</div> </div>
<div class="row"> <div class="row">