From a10672a6839ee2e79c6cd609bc464df797a988bd Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 28 Dec 2017 18:38:59 +0100 Subject: [PATCH] Progress for Spectre import. --- app/Import/Routine/SpectreRoutine.php | 160 +++----- app/Jobs/GetSpectreProviders.php | 109 ------ app/Models/ImportJob.php | 3 + app/Models/SpectreProvider.php | 52 --- app/Services/Spectre/Object/Customer.php | 12 + app/Services/Spectre/Object/Login.php | 32 -- app/Services/Spectre/Object/Token.php | 76 ++++ .../Spectre/Request/CreateLoginRequest.php | 109 ------ .../Spectre/Request/CreateTokenRequest.php | 94 +++++ .../Spectre/Request/ListLoginsRequest.php | 101 ----- .../Spectre/Request/ListProvidersRequest.php | 81 ---- .../Spectre/Request/NewCustomerRequest.php | 12 +- .../Configuration/Spectre/InputMandatory.php | 121 ------ .../Configuration/Spectre/SelectCountry.php | 348 ------------------ .../Configuration/Spectre/SelectProvider.php | 93 ----- .../Import/Information/SpectreInformation.php | 217 ----------- public/js/ff/import/status.js | 15 + resources/views/import/spectre/redirect.twig | 15 + resources/views/import/status.twig | 1 + 19 files changed, 272 insertions(+), 1379 deletions(-) delete mode 100644 app/Jobs/GetSpectreProviders.php delete mode 100644 app/Models/SpectreProvider.php delete mode 100644 app/Services/Spectre/Object/Login.php create mode 100644 app/Services/Spectre/Object/Token.php delete mode 100644 app/Services/Spectre/Request/CreateLoginRequest.php create mode 100644 app/Services/Spectre/Request/CreateTokenRequest.php delete mode 100644 app/Services/Spectre/Request/ListLoginsRequest.php delete mode 100644 app/Services/Spectre/Request/ListProvidersRequest.php delete mode 100644 app/Support/Import/Configuration/Spectre/InputMandatory.php delete mode 100644 app/Support/Import/Configuration/Spectre/SelectCountry.php delete mode 100644 app/Support/Import/Configuration/Spectre/SelectProvider.php delete mode 100644 app/Support/Import/Information/SpectreInformation.php create mode 100644 resources/views/import/spectre/redirect.twig diff --git a/app/Import/Routine/SpectreRoutine.php b/app/Import/Routine/SpectreRoutine.php index fd9f0c6e03..fbd12ae9c7 100644 --- a/app/Import/Routine/SpectreRoutine.php +++ b/app/Import/Routine/SpectreRoutine.php @@ -22,11 +22,11 @@ declare(strict_types=1); namespace FireflyIII\Import\Routine; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\ImportJob; -use FireflyIII\Models\SpectreProvider; use FireflyIII\Services\Spectre\Object\Customer; -use FireflyIII\Services\Spectre\Request\CreateLoginRequest; -use FireflyIII\Services\Spectre\Request\ListLoginsRequest; +use FireflyIII\Services\Spectre\Object\Token; +use FireflyIII\Services\Spectre\Request\CreateTokenRequest; use FireflyIII\Services\Spectre\Request\NewCustomerRequest; use Illuminate\Support\Collection; use Log; @@ -90,31 +90,48 @@ class SpectreRoutine implements RoutineInterface return false; } - set_time_limit(0); Log::info(sprintf('Start with import job %s using Spectre.', $this->job->key)); - // create customer if user does not have one: - $customer = $this->getCustomer(); + set_time_limit(0); - // list all logins present at Spectre - $logins = $this->listLogins($customer); + // check if job has token first! + $config = $this->job->configuration; + $hasToken = $config['has-token'] ?? false; + if ($hasToken === false) { + Log::debug('Job has no token'); + // create customer if user does not have one: + $customer = $this->getCustomer(); + Log::debug(sprintf('Customer ID is %s', $customer->getId())); + // use customer to request a token: + $uri = route('import.status', [$this->job->key]); + $token = $this->getToken($customer, $uri); + Log::debug(sprintf('Token is %s', $token->getToken())); - // use latest (depending on status, and if login exists for selected country + provider) - $country = $this->job->configuration['country']; - $providerId = $this->job->configuration['provider']; - $login = $this->filterLogins($logins, $country, $providerId); + // update job, give it the token: + $config = $this->job->configuration; + $config['has-token'] = true; + $config['token'] = $token->getToken(); + $config['token-expires'] = $token->getExpiresAt()->format('U'); + $config['token-url'] = $token->getConnectUrl(); + $this->job->configuration = $config; - // create new login if list is empty or no login exists. - if (is_null($login)) { - $login = $this->createLogin($customer); - var_dump($login); - exit; + Log::debug('Job config is now', $config); + + // update job, set status to "configuring". + $this->job->status = 'configuring'; + $this->job->save(); + Log::debug(sprintf('Job status is now %s', $this->job->status)); + + return true; + } + $isRedirected = $config['is-redirected'] ?? false; + if ($isRedirected === true) { + // assume user has "used" the token. + // ... + // now what? + throw new FireflyException('Application cannot handle this.'); } - echo '
';
-        print_r($logins);
-        exit;
-
-        return true;
+        throw new FireflyException('Application cannot handle this.');
     }
 
     /**
@@ -135,49 +152,12 @@ class SpectreRoutine implements RoutineInterface
         $newCustomerRequest->call();
         $customer = $newCustomerRequest->getCustomer();
 
-        // store customer. Not sure where. User preference? TODO
+        Preferences::setForUser($this->job->user, 'spectre_customer', $customer->toArray());
+
         return $customer;
 
     }
 
-    /**
-     * @param Customer $customer
-     */
-    protected function createLogin(Customer $customer)
-    {
-
-        $providerId = intval($this->job->configuration['provider']);
-        $provider   = $this->findProvider($providerId);
-
-
-        $createLoginRequest = new CreateLoginRequest($this->job->user);
-        $createLoginRequest->setCustomer($customer);
-        $createLoginRequest->setProvider($provider);
-        $createLoginRequest->setMandatoryFields($this->decrypt($this->job->configuration['mandatory-fields']));
-        $createLoginRequest->call();
-        echo '123';
-        // country code, provider code (find by spectre ID)
-        // credentials
-        // daily_refresh=true
-        // fetch_type=recent
-        // include_fake_providers=true
-        // store_credentials=true
-
-
-        var_dump($this->job->configuration);
-        exit;
-    }
-
-    /**
-     * @param int $providerId
-     *
-     * @return SpectreProvider|null
-     */
-    protected function findProvider(int $providerId): ?SpectreProvider
-    {
-        return SpectreProvider::where('spectre_id', $providerId)->first();
-    }
-
     /**
      * @return Customer
      * @throws \FireflyIII\Exceptions\FireflyException
@@ -188,61 +168,27 @@ class SpectreRoutine implements RoutineInterface
         if (is_null($preference)) {
             return $this->createCustomer();
         }
-        var_dump($preference->data);
-        exit;
+        $customer = new Customer($preference->data);
+
+        return $customer;
     }
 
     /**
      * @param Customer $customer
+     * @param string   $returnUri
      *
-     * @return array
+     * @return Token
      * @throws \FireflyIII\Exceptions\FireflyException
      */
-    protected function listLogins(Customer $customer): array
+    protected function getToken(Customer $customer, string $returnUri): Token
     {
-        $listLoginRequest = new ListLoginsRequest($this->job->user);
-        $listLoginRequest->setCustomer($customer);
-        $listLoginRequest->call();
+        $request = new CreateTokenRequest($this->job->user);
+        $request->setUri($returnUri);
+        $request->setCustomer($customer);
+        $request->call();
+        Log::debug('Call to get token is finished');
 
-        $logins = $listLoginRequest->getLogins();
+        return $request->getToken();
 
-        return $logins;
-    }
-
-    /**
-     * @param array $configuration
-     *
-     * @return array
-     */
-    private function decrypt(array $configuration): array
-    {
-        $new = [];
-        foreach ($configuration as $key => $value) {
-            $new[$key] = app('steam')->tryDecrypt($value);
-        }
-
-        return $new;
-    }
-
-    /**
-     * Return login belonging to country and provider
-     * TODO must return Login object, not array
-     *
-     * @param array  $logins
-     * @param string $country
-     * @param int    $providerId
-     *
-     * @return array|null
-     */
-    private function filterLogins(array $logins, string $country, int $providerId): ?array
-    {
-        if (count($logins) === 0) {
-            return null;
-        }
-        foreach ($logins as $login) {
-            die('do some filter');
-        }
-
-        return null;
     }
 }
diff --git a/app/Jobs/GetSpectreProviders.php b/app/Jobs/GetSpectreProviders.php
deleted file mode 100644
index d29da378fd..0000000000
--- a/app/Jobs/GetSpectreProviders.php
+++ /dev/null
@@ -1,109 +0,0 @@
-.
- */
-
-namespace FireflyIII\Jobs;
-
-use FireflyIII\Models\Configuration;
-use FireflyIII\Models\SpectreProvider;
-use FireflyIII\Services\Spectre\Request\ListProvidersRequest;
-use FireflyIII\User;
-use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Queue\SerializesModels;
-use Log;
-
-/**
- * Class GetSpectreProviders
- */
-class GetSpectreProviders implements ShouldQueue
-{
-    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
-
-    /**
-     * @var User
-     */
-    protected $user;
-
-    /**
-     * Create a new job instance.
-     *
-     * @param User $user
-     */
-    public function __construct(User $user)
-    {
-        $this->user = $user;
-        Log::debug('Constructed job GetSpectreProviders');
-    }
-
-    /**
-     * Execute the job.
-     *
-     * @throws \Illuminate\Container\EntryNotFoundException
-     * @throws \Exception
-     */
-    public function handle()
-    {
-        /** @var Configuration $configValue */
-        $configValue = app('fireflyconfig')->get('spectre_provider_download', 0);
-        $now         = time();
-        if ($now - intval($configValue->data) < 86400) {
-            Log::debug(sprintf('Difference is %d, so will NOT execute job.', ($now - intval($configValue->data))));
-
-            return;
-        }
-        Log::debug(sprintf('Difference is %d, so will execute job.', ($now - intval($configValue->data))));
-
-        // get user
-
-        // fire away!
-        $request = new ListProvidersRequest($this->user);
-        $request->call();
-
-        // store all providers:
-        $providers = $request->getProviders();
-        foreach ($providers as $provider) {
-            // find provider?
-            $dbProvider = SpectreProvider::where('spectre_id', $provider['id'])->first();
-            if (is_null($dbProvider)) {
-                $dbProvider = new SpectreProvider;
-            }
-            // update fields:
-            $dbProvider->spectre_id      = $provider['id'];
-            $dbProvider->code            = $provider['code'];
-            $dbProvider->mode            = $provider['mode'];
-            $dbProvider->status          = $provider['status'];
-            $dbProvider->interactive     = 1 === $provider['interactive'];
-            $dbProvider->automatic_fetch = 1 === $provider['automatic_fetch'];
-            $dbProvider->country_code    = $provider['country_code'];
-            $dbProvider->data            = $provider;
-            $dbProvider->save();
-            Log::debug(sprintf('Stored provider #%d under ID #%d', $provider['id'], $dbProvider->id));
-        }
-
-        app('fireflyconfig')->set('spectre_provider_download', time());
-
-        return;
-    }
-}
diff --git a/app/Models/ImportJob.php b/app/Models/ImportJob.php
index b9256ea25a..57015f946b 100644
--- a/app/Models/ImportJob.php
+++ b/app/Models/ImportJob.php
@@ -127,6 +127,7 @@ class ImportJob extends Model
     public function change(string $status): void
     {
         if (in_array($status, $this->validStatus)) {
+            Log::debug(sprintf('Job status set (in model) to "%s"', $status));
             $this->status = $status;
             $this->save();
 
@@ -169,6 +170,7 @@ class ImportJob extends Model
 
     /**
      * @codeCoverageIgnore
+     *
      * @param $value
      */
     public function setConfigurationAttribute($value)
@@ -178,6 +180,7 @@ class ImportJob extends Model
 
     /**
      * @codeCoverageIgnore
+     *
      * @param $value
      */
     public function setExtendedStatusAttribute($value)
diff --git a/app/Models/SpectreProvider.php b/app/Models/SpectreProvider.php
deleted file mode 100644
index a1d056f93c..0000000000
--- a/app/Models/SpectreProvider.php
+++ /dev/null
@@ -1,52 +0,0 @@
-.
- */
-declare(strict_types=1);
-
-namespace FireflyIII\Models;
-
-use Illuminate\Database\Eloquent\Model;
-
-/**
- * Class SpectreProvider
- */
-class SpectreProvider extends Model
-{
-    /**
-     * The attributes that should be casted to native types.
-     *
-     * @var array
-     */
-    protected $casts
-        = [
-            'spectre_id'      => 'int',
-            'created_at'      => 'datetime',
-            'updated_at'      => 'datetime',
-            'deleted_at'      => 'datetime',
-            'interactive'     => 'boolean',
-            'automatic_fetch' => 'boolean',
-            'data'            => 'array',
-        ];
-
-    /**
-     * @var array
-     */
-    protected $fillable = ['spectre_id', 'code', 'mode', 'name', 'status', 'interactive', 'automatic_fetch', 'country_code', 'data'];
-}
diff --git a/app/Services/Spectre/Object/Customer.php b/app/Services/Spectre/Object/Customer.php
index 53d046a6d9..755dcfc38d 100644
--- a/app/Services/Spectre/Object/Customer.php
+++ b/app/Services/Spectre/Object/Customer.php
@@ -93,4 +93,16 @@ class Customer extends SpectreObject
     {
         $this->secret = $secret;
     }
+
+    /**
+     * @return array
+     */
+    public function toArray(): array
+    {
+        return [
+            'id'         => $this->id,
+            'identifier' => $this->identifier,
+            'secret'     => $this->secret,
+        ];
+    }
 }
diff --git a/app/Services/Spectre/Object/Login.php b/app/Services/Spectre/Object/Login.php
deleted file mode 100644
index 6de8bed874..0000000000
--- a/app/Services/Spectre/Object/Login.php
+++ /dev/null
@@ -1,32 +0,0 @@
-.
- */
-
-declare(strict_types=1);
-
-namespace FireflyIII\Services\Spectre\Object;
-
-/**
- * Class Login
- */
-class Login extends SpectreObject
-{
-
-}
\ No newline at end of file
diff --git a/app/Services/Spectre/Object/Token.php b/app/Services/Spectre/Object/Token.php
new file mode 100644
index 0000000000..d2e51d3c18
--- /dev/null
+++ b/app/Services/Spectre/Object/Token.php
@@ -0,0 +1,76 @@
+.
+ */
+
+declare(strict_types=1);
+
+namespace FireflyIII\Services\Spectre\Object;
+
+use Carbon\Carbon;
+
+/**
+ * Class Token
+ */
+class Token extends SpectreObject
+{
+    /** @var string */
+    private $connectUrl;
+    /** @var Carbon */
+    private $expiresAt;
+    /** @var string */
+    private $token;
+
+    /**
+     * Token constructor.
+     *
+     * @param array $data
+     */
+    public function __construct(array $data)
+    {
+        $this->token      = $data['token'];
+        $this->expiresAt  = new Carbon($data['expires_at']);
+        $this->connectUrl = $data['connect_url'];
+    }
+
+    /**
+     * @return string
+     */
+    public function getConnectUrl(): string
+    {
+        return $this->connectUrl;
+    }
+
+    /**
+     * @return Carbon
+     */
+    public function getExpiresAt(): Carbon
+    {
+        return $this->expiresAt;
+    }
+
+    /**
+     * @return string
+     */
+    public function getToken(): string
+    {
+        return $this->token;
+    }
+
+}
\ No newline at end of file
diff --git a/app/Services/Spectre/Request/CreateLoginRequest.php b/app/Services/Spectre/Request/CreateLoginRequest.php
deleted file mode 100644
index 1b0e3e6b79..0000000000
--- a/app/Services/Spectre/Request/CreateLoginRequest.php
+++ /dev/null
@@ -1,109 +0,0 @@
-.
- */
-
-declare(strict_types=1);
-
-namespace FireflyIII\Services\Spectre\Request;
-
-use FireflyIII\Exceptions\FireflyException;
-use FireflyIII\Models\SpectreProvider;
-use FireflyIII\Services\Spectre\Object\Customer;
-
-/**
- * Class CreateLoginRequest
- */
-class CreateLoginRequest extends SpectreRequest
-{
-    /** @var Customer */
-    private $customer;
-    /** @var array */
-    private $mandatoryFields = [];
-    /** @var SpectreProvider */
-    private $provider;
-
-    /**
-     *
-     * @throws FireflyException
-     */
-    public function call(): void
-    {
-        // add mandatory fields to login object
-        $data = [
-            'customer_id'            => $this->customer->getId(),
-            'country_code'           => $this->provider->country_code,
-            'provider_code'          => $this->provider->code,
-            'credentials'            => $this->buildCredentials(),
-            'daily_refresh'          => true,
-            'fetch_type'             => 'recent',
-            'include_fake_providers' => true,
-        ];
-        $uri  = '/api/v3/logins';
-        $response = $this->sendSignedSpectrePost($uri, $data);
-        echo '
';
-        print_r($response);
-        exit;
-    }
-
-    /**
-     * @param Customer $customer
-     */
-    public function setCustomer(Customer $customer): void
-    {
-        $this->customer = $customer;
-    }
-
-    /**
-     * @param array $mandatoryFields
-     */
-    public function setMandatoryFields(array $mandatoryFields): void
-    {
-        $this->mandatoryFields = $mandatoryFields;
-    }
-
-    /**
-     * @param SpectreProvider $provider
-     */
-    public function setProvider(SpectreProvider $provider): void
-    {
-        $this->provider = $provider;
-    }
-
-    /**
-     * @return array
-     * @throws FireflyException
-     */
-    private function buildCredentials(): array
-    {
-        $return = [];
-        /** @var array $requiredField */
-        foreach ($this->provider->data['required_fields'] as $requiredField) {
-            $fieldName = $requiredField['name'];
-            if (!isset($this->mandatoryFields[$fieldName])) {
-                throw new FireflyException(sprintf('Mandatory field "%s" is missing from job.', $fieldName));
-            }
-            $return[$fieldName] = $this->mandatoryFields[$fieldName];
-        }
-
-        return $return;
-    }
-
-
-}
\ No newline at end of file
diff --git a/app/Services/Spectre/Request/CreateTokenRequest.php b/app/Services/Spectre/Request/CreateTokenRequest.php
new file mode 100644
index 0000000000..adacab4ae8
--- /dev/null
+++ b/app/Services/Spectre/Request/CreateTokenRequest.php
@@ -0,0 +1,94 @@
+.
+ */
+
+declare(strict_types=1);
+
+namespace FireflyIII\Services\Spectre\Request;
+
+use FireflyIII\Services\Spectre\Object\Customer;
+use FireflyIII\Services\Spectre\Object\Token;
+
+
+/**
+ * Class CreateTokenRequest
+ */
+class CreateTokenRequest extends SpectreRequest
+{
+    /** @var Customer */
+    private $customer;
+
+    /** @var Token */
+    private $token;
+
+    /** @var string */
+    private $uri;
+
+    /**
+     *
+     * @throws \FireflyIII\Exceptions\FireflyException
+     */
+    public function call(): void
+    {
+        // add mandatory fields to login object
+        $data        = [
+            'data' => [
+                'customer_id'               => $this->customer->getId(),
+                'fetch_type'                => 'recent',
+                'daily_refresh'             => true,
+                'include_fake_providers'    => true,
+                'show_consent_confirmation' => true,
+                'credentials_strategy'      => 'ask',
+                'return_to'                 => $this->uri,
+            ],
+        ];
+        $uri         = '/api/v3/tokens/create';
+        $response    = $this->sendSignedSpectrePost($uri, $data);
+        $this->token = new Token($response['data']);
+
+        return;
+    }
+
+    /**
+     * @return Token
+     */
+    public function getToken(): Token
+    {
+        return $this->token;
+    }
+
+    /**
+     * @param Customer $customer
+     */
+    public function setCustomer(Customer $customer): void
+    {
+        $this->customer = $customer;
+    }
+
+    /**
+     * @param string $uri
+     */
+    public function setUri(string $uri): void
+    {
+        $this->uri = $uri;
+    }
+
+
+}
\ No newline at end of file
diff --git a/app/Services/Spectre/Request/ListLoginsRequest.php b/app/Services/Spectre/Request/ListLoginsRequest.php
deleted file mode 100644
index d69af2a026..0000000000
--- a/app/Services/Spectre/Request/ListLoginsRequest.php
+++ /dev/null
@@ -1,101 +0,0 @@
-.
- */
-declare(strict_types=1);
-
-namespace FireflyIII\Services\Spectre\Request;
-
-use FireflyIII\Services\Spectre\Object\Customer;
-use Log;
-
-/**
- * Class ListLoginsRequest
- */
-class ListLoginsRequest extends SpectreRequest
-{
-    /** @var Customer */
-    protected $customer;
-
-    /** @var array */
-    protected $logins = [];
-
-    /**
-     *
-     * @throws \FireflyIII\Exceptions\FireflyException
-     */
-    public function call(): void
-    {
-        $hasNextPage = true;
-        $nextId      = 0;
-        while ($hasNextPage) {
-            Log::debug(sprintf('Now calling list-logins for next_id %d', $nextId));
-            $parameters = ['customer_id' => $this->customer->getId(), 'from_id' => $nextId];
-            $uri        = '/api/v3/logins?' . http_build_query($parameters);
-            $response   = $this->sendSignedSpectreGet($uri, []);
-
-            // count entries:
-            Log::debug(sprintf('Found %d entries in data-array', count($response['data'])));
-
-            // extract next ID
-            $hasNextPage = false;
-            if (isset($response['meta']['next_id']) && intval($response['meta']['next_id']) > $nextId) {
-                $hasNextPage = true;
-                $nextId      = $response['meta']['next_id'];
-                Log::debug(sprintf('Next ID is now %d.', $nextId));
-            } else {
-                Log::debug('No next page.');
-            }
-
-            // store providers:
-            foreach ($response['data'] as $loginArray) {
-                var_dump($loginArray);
-                exit;
-            }
-        }
-
-        return;
-    }
-
-    /**
-     * @return Customer
-     */
-    public function getCustomer(): Customer
-    {
-        return $this->customer;
-    }
-
-    /**
-     * @param Customer $customer
-     */
-    public function setCustomer(Customer $customer): void
-    {
-        $this->customer = $customer;
-    }
-
-    /**
-     * @return array
-     */
-    public function getLogins(): array
-    {
-        return $this->logins;
-    }
-
-
-}
diff --git a/app/Services/Spectre/Request/ListProvidersRequest.php b/app/Services/Spectre/Request/ListProvidersRequest.php
deleted file mode 100644
index 966023904c..0000000000
--- a/app/Services/Spectre/Request/ListProvidersRequest.php
+++ /dev/null
@@ -1,81 +0,0 @@
-.
- */
-declare(strict_types=1);
-
-namespace FireflyIII\Services\Spectre\Request;
-
-use Log;
-
-/**
- * Class ListProvidersRequest
- */
-class ListProvidersRequest extends SpectreRequest
-{
-    /**
-     * @var array
-     */
-    protected $providers = [];
-
-    /**
-     * @throws \Exception
-     */
-    public function call(): void
-    {
-        $hasNextPage = true;
-        $nextId      = 0;
-        while ($hasNextPage) {
-            Log::debug(sprintf('Now calling for next_id %d', $nextId));
-            $parameters = ['include_fake_providers' => 'true', 'include_provider_fields' => 'true', 'from_id' => $nextId];
-            $uri        = '/api/v3/providers?' . http_build_query($parameters);
-            $response   = $this->sendSignedSpectreGet($uri, []);
-
-            // count entries:
-            Log::debug(sprintf('Found %d entries in data-array', count($response['data'])));
-
-            // extract next ID
-            $hasNextPage = false;
-            if (isset($response['meta']['next_id']) && intval($response['meta']['next_id']) > $nextId) {
-                $hasNextPage = true;
-                $nextId      = $response['meta']['next_id'];
-                Log::debug(sprintf('Next ID is now %d.', $nextId));
-            } else {
-                Log::debug('No next page.');
-            }
-
-            // store providers:
-            foreach ($response['data'] as $providerArray) {
-                $providerId                   = $providerArray['id'];
-                $this->providers[$providerId] = $providerArray;
-                Log::debug(sprintf('Stored provider #%d', $providerId));
-            }
-        }
-
-        return;
-    }
-
-    /**
-     * @return array
-     */
-    public function getProviders(): array
-    {
-        return $this->providers;
-    }
-}
diff --git a/app/Services/Spectre/Request/NewCustomerRequest.php b/app/Services/Spectre/Request/NewCustomerRequest.php
index ff36919d70..0c6960be90 100644
--- a/app/Services/Spectre/Request/NewCustomerRequest.php
+++ b/app/Services/Spectre/Request/NewCustomerRequest.php
@@ -37,19 +37,13 @@ class NewCustomerRequest extends SpectreRequest
      */
     public function call(): void
     {
-        $data = [
+        $data     = [
             'data' => [
                 'identifier' => 'default_ff3_customer',
             ],
         ];
-        $uri  = '/api/v3/customers/';
-        //$response = $this->sendSignedSpectrePost($uri, $data);
-        $response = ['data' => [
-            'id'         => 527858,
-            'identifier' => 'default_ff3_customer',
-            'secret'     => 'qpZjRPJRTb6mMcQgwDkssZ3fQVVDPIH04zBlkKC6MvI',
-        ],
-        ];
+        $uri      = '/api/v3/customers/';
+        $response = $this->sendSignedSpectrePost($uri, $data);
         // create customer:
         $this->customer = new Customer($response['data']);
 
diff --git a/app/Support/Import/Configuration/Spectre/InputMandatory.php b/app/Support/Import/Configuration/Spectre/InputMandatory.php
deleted file mode 100644
index c6182ff53a..0000000000
--- a/app/Support/Import/Configuration/Spectre/InputMandatory.php
+++ /dev/null
@@ -1,121 +0,0 @@
-.
- */
-declare(strict_types=1);
-
-namespace FireflyIII\Support\Import\Configuration\Spectre;
-
-use Crypt;
-use FireflyIII\Exceptions\FireflyException;
-use FireflyIII\Models\ImportJob;
-use FireflyIII\Models\SpectreProvider;
-use FireflyIII\Support\Import\Configuration\ConfigurationInterface;
-
-/**
- * Class InputMandatory
- */
-class InputMandatory implements ConfigurationInterface
-{
-    /** @var ImportJob */
-    private $job;
-
-    /**
-     * Get the data necessary to show the configuration screen.
-     *
-     * @return array
-     *
-     * @throws FireflyException
-     */
-    public function getData(): array
-    {
-        $config     = $this->job->configuration;
-        $providerId = $config['provider'];
-        $provider   = SpectreProvider::where('spectre_id', $providerId)->first();
-        if (is_null($provider)) {
-            throw new FireflyException(sprintf('Cannot find Spectre provider with ID #%d', $providerId));
-        }
-        $fields    = $provider->data['required_fields'] ?? [];
-        $positions = [];
-        // Obtain a list of columns
-        foreach ($fields as $key => $row) {
-            $positions[$key] = $row['position'];
-        }
-        array_multisort($positions, SORT_ASC, $fields);
-        $country = SelectCountry::$allCountries[$config['country']] ?? $config['country'];
-
-        return compact('provider', 'country', 'fields');
-    }
-
-    /**
-     * Return possible warning to user.
-     *
-     * @return string
-     */
-    public function getWarningMessage(): string
-    {
-        return '';
-    }
-
-    /**
-     * @param ImportJob $job
-     */
-    public function setJob(ImportJob $job)
-    {
-        $this->job = $job;
-    }
-
-    /**
-     * Store the result.
-     *
-     * @param array $data
-     *
-     * @return bool
-     *
-     * @throws FireflyException
-     */
-    public function storeConfiguration(array $data): bool
-    {
-        $config     = $this->job->configuration;
-        $providerId = $config['provider'];
-        $provider   = SpectreProvider::where('spectre_id', $providerId)->first();
-        if (is_null($provider)) {
-            throw new FireflyException(sprintf('Cannot find Spectre provider with ID #%d', $providerId));
-        }
-        $mandatory = [];
-        $fields    = $provider->data['required_fields'] ?? [];
-        foreach ($fields as $field) {
-            $name             = $field['name'];
-            $mandatory[$name] = Crypt::encrypt($data[$name]) ?? null;
-        }
-
-        // store in config of job:
-        $config['mandatory-fields']    = $mandatory;
-        $config['has-input-mandatory'] = true;
-        $this->job->configuration      = $config;
-        $this->job->save();
-
-        // try to grab login for this job. See what happens?
-        // fire job that creates login object. user is redirected to "wait here" page (status page). Page should
-        // refresh and go back to interactive when user is supposed to enter SMS code or something.
-        // otherwise start downloading stuff
-
-        return true;
-    }
-}
diff --git a/app/Support/Import/Configuration/Spectre/SelectCountry.php b/app/Support/Import/Configuration/Spectre/SelectCountry.php
deleted file mode 100644
index eec76e8e54..0000000000
--- a/app/Support/Import/Configuration/Spectre/SelectCountry.php
+++ /dev/null
@@ -1,348 +0,0 @@
-.
- */
-declare(strict_types=1);
-
-namespace FireflyIII\Support\Import\Configuration\Spectre;
-
-use FireflyIII\Models\ImportJob;
-use FireflyIII\Models\SpectreProvider;
-use FireflyIII\Support\Import\Configuration\ConfigurationInterface;
-
-/**
- * Class SelectCountry
- */
-class SelectCountry implements ConfigurationInterface
-{
-    /**
-     * @var array
-     */
-    public static $allCountries
-        = [
-            'AF' => 'Afghanistan',
-            'AX' => 'Aland Islands',
-            'AL' => 'Albania',
-            'DZ' => 'Algeria',
-            'AS' => 'American Samoa',
-            'AD' => 'Andorra',
-            'AO' => 'Angola',
-            'AI' => 'Anguilla',
-            'AQ' => 'Antarctica',
-            'AG' => 'Antigua and Barbuda',
-            'AR' => 'Argentina',
-            'AM' => 'Armenia',
-            'AW' => 'Aruba',
-            'AU' => 'Australia',
-            'AT' => 'Austria',
-            'AZ' => 'Azerbaijan',
-            'BS' => 'Bahamas',
-            'BH' => 'Bahrain',
-            'BD' => 'Bangladesh',
-            'BB' => 'Barbados',
-            'BY' => 'Belarus',
-            'BE' => 'Belgium',
-            'BZ' => 'Belize',
-            'BJ' => 'Benin',
-            'BM' => 'Bermuda',
-            'BT' => 'Bhutan',
-            'BO' => 'Bolivia',
-            'BQ' => 'Bonaire, Saint Eustatius and Saba',
-            'BA' => 'Bosnia and Herzegovina',
-            'BW' => 'Botswana',
-            'BV' => 'Bouvet Island',
-            'BR' => 'Brazil',
-            'IO' => 'British Indian Ocean Territory',
-            'VG' => 'British Virgin Islands',
-            'BN' => 'Brunei',
-            'BG' => 'Bulgaria',
-            'BF' => 'Burkina Faso',
-            'BI' => 'Burundi',
-            'KH' => 'Cambodia',
-            'CM' => 'Cameroon',
-            'CA' => 'Canada',
-            'CV' => 'Cape Verde',
-            'KY' => 'Cayman Islands',
-            'CF' => 'Central African Republic',
-            'TD' => 'Chad',
-            'CL' => 'Chile',
-            'CN' => 'China',
-            'CX' => 'Christmas Island',
-            'CC' => 'Cocos Islands',
-            'CO' => 'Colombia',
-            'KM' => 'Comoros',
-            'CK' => 'Cook Islands',
-            'CR' => 'Costa Rica',
-            'HR' => 'Croatia',
-            'CU' => 'Cuba',
-            'CW' => 'Curacao',
-            'CY' => 'Cyprus',
-            'CZ' => 'Czech Republic',
-            'CD' => 'Democratic Republic of the Congo',
-            'DK' => 'Denmark',
-            'DJ' => 'Djibouti',
-            'DM' => 'Dominica',
-            'DO' => 'Dominican Republic',
-            'TL' => 'East Timor',
-            'EC' => 'Ecuador',
-            'EG' => 'Egypt',
-            'SV' => 'El Salvador',
-            'GQ' => 'Equatorial Guinea',
-            'ER' => 'Eritrea',
-            'EE' => 'Estonia',
-            'ET' => 'Ethiopia',
-            'FK' => 'Falkland Islands',
-            'FO' => 'Faroe Islands',
-            'FJ' => 'Fiji',
-            'FI' => 'Finland',
-            'FR' => 'France',
-            'GF' => 'French Guiana',
-            'PF' => 'French Polynesia',
-            'TF' => 'French Southern Territories',
-            'GA' => 'Gabon',
-            'GM' => 'Gambia',
-            'GE' => 'Georgia',
-            'DE' => 'Germany',
-            'GH' => 'Ghana',
-            'GI' => 'Gibraltar',
-            'GR' => 'Greece',
-            'GL' => 'Greenland',
-            'GD' => 'Grenada',
-            'GP' => 'Guadeloupe',
-            'GU' => 'Guam',
-            'GT' => 'Guatemala',
-            'GG' => 'Guernsey',
-            'GN' => 'Guinea',
-            'GW' => 'Guinea-Bissau',
-            'GY' => 'Guyana',
-            'HT' => 'Haiti',
-            'HM' => 'Heard Island and McDonald Islands',
-            'HN' => 'Honduras',
-            'HK' => 'Hong Kong',
-            'HU' => 'Hungary',
-            'IS' => 'Iceland',
-            'IN' => 'India',
-            'ID' => 'Indonesia',
-            'IR' => 'Iran',
-            'IQ' => 'Iraq',
-            'IE' => 'Ireland',
-            'IM' => 'Isle of Man',
-            'IL' => 'Israel',
-            'IT' => 'Italy',
-            'CI' => 'Ivory Coast',
-            'JM' => 'Jamaica',
-            'JP' => 'Japan',
-            'JE' => 'Jersey',
-            'JO' => 'Jordan',
-            'KZ' => 'Kazakhstan',
-            'KE' => 'Kenya',
-            'KI' => 'Kiribati',
-            'XK' => 'Kosovo',
-            'KW' => 'Kuwait',
-            'KG' => 'Kyrgyzstan',
-            'LA' => 'Laos',
-            'LV' => 'Latvia',
-            'LB' => 'Lebanon',
-            'LS' => 'Lesotho',
-            'LR' => 'Liberia',
-            'LY' => 'Libya',
-            'LI' => 'Liechtenstein',
-            'LT' => 'Lithuania',
-            'LU' => 'Luxembourg',
-            'MO' => 'Macao',
-            'MK' => 'Macedonia',
-            'MG' => 'Madagascar',
-            'MW' => 'Malawi',
-            'MY' => 'Malaysia',
-            'MV' => 'Maldives',
-            'ML' => 'Mali',
-            'MT' => 'Malta',
-            'MH' => 'Marshall Islands',
-            'MQ' => 'Martinique',
-            'MR' => 'Mauritania',
-            'MU' => 'Mauritius',
-            'YT' => 'Mayotte',
-            'MX' => 'Mexico',
-            'FM' => 'Micronesia',
-            'MD' => 'Moldova',
-            'MC' => 'Monaco',
-            'MN' => 'Mongolia',
-            'ME' => 'Montenegro',
-            'MS' => 'Montserrat',
-            'MA' => 'Morocco',
-            'MZ' => 'Mozambique',
-            'MM' => 'Myanmar',
-            'NA' => 'Namibia',
-            'NR' => 'Nauru',
-            'NP' => 'Nepal',
-            'NL' => 'Netherlands',
-            'NC' => 'New Caledonia',
-            'NZ' => 'New Zealand',
-            'NI' => 'Nicaragua',
-            'NE' => 'Niger',
-            'NG' => 'Nigeria',
-            'NU' => 'Niue',
-            'NF' => 'Norfolk Island',
-            'KP' => 'North Korea',
-            'MP' => 'Northern Mariana Islands',
-            'NO' => 'Norway',
-            'OM' => 'Oman',
-            'PK' => 'Pakistan',
-            'PW' => 'Palau',
-            'PS' => 'Palestinian Territory',
-            'PA' => 'Panama',
-            'PG' => 'Papua New Guinea',
-            'PY' => 'Paraguay',
-            'PE' => 'Peru',
-            'PH' => 'Philippines',
-            'PN' => 'Pitcairn',
-            'PL' => 'Poland',
-            'PT' => 'Portugal',
-            'PR' => 'Puerto Rico',
-            'QA' => 'Qatar',
-            'CG' => 'Republic of the Congo',
-            'RE' => 'Reunion',
-            'RO' => 'Romania',
-            'RU' => 'Russia',
-            'RW' => 'Rwanda',
-            'BL' => 'Saint Barthelemy',
-            'SH' => 'Saint Helena',
-            'KN' => 'Saint Kitts and Nevis',
-            'LC' => 'Saint Lucia',
-            'MF' => 'Saint Martin',
-            'PM' => 'Saint Pierre and Miquelon',
-            'VC' => 'Saint Vincent and the Grenadines',
-            'WS' => 'Samoa',
-            'SM' => 'San Marino',
-            'ST' => 'Sao Tome and Principe',
-            'SA' => 'Saudi Arabia',
-            'SN' => 'Senegal',
-            'RS' => 'Serbia',
-            'SC' => 'Seychelles',
-            'SL' => 'Sierra Leone',
-            'SG' => 'Singapore',
-            'SX' => 'Sint Maarten',
-            'SK' => 'Slovakia',
-            'SI' => 'Slovenia',
-            'SB' => 'Solomon Islands',
-            'SO' => 'Somalia',
-            'ZA' => 'South Africa',
-            'GS' => 'South Georgia and the South Sandwich Islands',
-            'KR' => 'South Korea',
-            'SS' => 'South Sudan',
-            'ES' => 'Spain',
-            'LK' => 'Sri Lanka',
-            'SD' => 'Sudan',
-            'SR' => 'Suriname',
-            'SJ' => 'Svalbard and Jan Mayen',
-            'SZ' => 'Swaziland',
-            'SE' => 'Sweden',
-            'CH' => 'Switzerland',
-            'SY' => 'Syria',
-            'TW' => 'Taiwan',
-            'TJ' => 'Tajikistan',
-            'TZ' => 'Tanzania',
-            'TH' => 'Thailand',
-            'TG' => 'Togo',
-            'TK' => 'Tokelau',
-            'TO' => 'Tonga',
-            'TT' => 'Trinidad and Tobago',
-            'TN' => 'Tunisia',
-            'TR' => 'Turkey',
-            'TM' => 'Turkmenistan',
-            'TC' => 'Turks and Caicos Islands',
-            'TV' => 'Tuvalu',
-            'VI' => 'U.S. Virgin Islands',
-            'UG' => 'Uganda',
-            'UA' => 'Ukraine',
-            'AE' => 'United Arab Emirates',
-            'GB' => 'United Kingdom',
-            'US' => 'United States',
-            'UM' => 'United States Minor Outlying Islands',
-            'UY' => 'Uruguay',
-            'UZ' => 'Uzbekistan',
-            'VU' => 'Vanuatu',
-            'VA' => 'Vatican',
-            'VE' => 'Venezuela',
-            'VN' => 'Vietnam',
-            'WF' => 'Wallis and Futuna',
-            'EH' => 'Western Sahara',
-            'YE' => 'Yemen',
-            'ZM' => 'Zambia',
-            'ZW' => 'Zimbabwe',
-            'XF' => 'Fake Country (for testing)',
-            'XO' => 'Other financial applications',
-        ];
-    /** @var ImportJob */
-    private $job;
-
-    /**
-     * Get the data necessary to show the configuration screen.
-     *
-     * @return array
-     */
-    public function getData(): array
-    {
-        $providers = SpectreProvider::get();
-        $countries = [];
-        /** @var SpectreProvider $provider */
-        foreach ($providers as $provider) {
-            $countries[$provider->country_code] = self::$allCountries[$provider->country_code] ?? $provider->country_code;
-        }
-        asort($countries);
-
-        return compact('countries');
-    }
-
-    /**
-     * Return possible warning to user.
-     *
-     * @return string
-     */
-    public function getWarningMessage(): string
-    {
-        return '';
-    }
-
-    /**
-     * @param ImportJob $job
-     */
-    public function setJob(ImportJob $job)
-    {
-        $this->job = $job;
-    }
-
-    /**
-     * Store the result.
-     *
-     * @param array $data
-     *
-     * @return bool
-     */
-    public function storeConfiguration(array $data): bool
-    {
-        $config                     = $this->job->configuration;
-        $config['country']          = $data['country_code'] ?? 'XF'; // default to fake country.
-        $config['selected-country'] = true;
-        $this->job->configuration   = $config;
-        $this->job->save();
-
-        return true;
-    }
-}
diff --git a/app/Support/Import/Configuration/Spectre/SelectProvider.php b/app/Support/Import/Configuration/Spectre/SelectProvider.php
deleted file mode 100644
index 843a722c04..0000000000
--- a/app/Support/Import/Configuration/Spectre/SelectProvider.php
+++ /dev/null
@@ -1,93 +0,0 @@
-.
- */
-declare(strict_types=1);
-
-namespace FireflyIII\Support\Import\Configuration\Spectre;
-
-use FireflyIII\Models\ImportJob;
-use FireflyIII\Models\SpectreProvider;
-use FireflyIII\Support\Import\Configuration\ConfigurationInterface;
-
-/**
- * Class SelectProvider
- */
-class SelectProvider implements ConfigurationInterface
-{
-    /** @var ImportJob */
-    private $job;
-
-    /**
-     * Get the data necessary to show the configuration screen.
-     *
-     * @return array
-     */
-    public function getData(): array
-    {
-        $config    = $this->job->configuration;
-        $selection = SpectreProvider::where('country_code', $config['country'])->where('status', 'active')->get();
-        $providers = [];
-        /** @var SpectreProvider $provider */
-        foreach ($selection as $provider) {
-            $providerId             = $provider->spectre_id;
-            $name                   = $provider->data['name'];
-            $providers[$providerId] = $name;
-        }
-        $country = SelectCountry::$allCountries[$config['country']] ?? $config['country'];
-
-        return compact('providers', 'country');
-    }
-
-    /**
-     * Return possible warning to user.
-     *
-     * @return string
-     */
-    public function getWarningMessage(): string
-    {
-        return '';
-    }
-
-    /**
-     * @param ImportJob $job
-     */
-    public function setJob(ImportJob $job)
-    {
-        $this->job = $job;
-    }
-
-    /**
-     * Store the result.
-     *
-     * @param array $data
-     *
-     * @return bool
-     */
-    public function storeConfiguration(array $data): bool
-    {
-        $config                      = $this->job->configuration;
-        $config['provider']          = intval($data['provider_code']) ?? 0; // default to fake country.
-        $config['selected-provider'] = true;
-        $this->job->configuration    = $config;
-        $this->job->save();
-
-        return true;
-    }
-}
diff --git a/app/Support/Import/Information/SpectreInformation.php b/app/Support/Import/Information/SpectreInformation.php
deleted file mode 100644
index 0cc93f8992..0000000000
--- a/app/Support/Import/Information/SpectreInformation.php
+++ /dev/null
@@ -1,217 +0,0 @@
-.
- */
-declare(strict_types=1);
-
-namespace FireflyIII\Support\Import\Information;
-
-use FireflyIII\Exceptions\FireflyException;
-use FireflyIII\Services\Bunq\Object\Alias;
-use FireflyIII\Services\Bunq\Object\MonetaryAccountBank;
-use FireflyIII\Services\Bunq\Request\DeleteDeviceSessionRequest;
-use FireflyIII\Services\Bunq\Request\DeviceSessionRequest;
-use FireflyIII\Services\Bunq\Request\ListMonetaryAccountRequest;
-use FireflyIII\Services\Bunq\Request\ListUserRequest;
-use FireflyIII\Services\Bunq\Token\SessionToken;
-use FireflyIII\Support\CacheProperties;
-use FireflyIII\User;
-use Illuminate\Support\Collection;
-use Log;
-use Preferences;
-
-/**
- * Class SpectreInformation
- */
-class SpectreInformation implements InformationInterface
-{
-    /** @var User */
-    private $user;
-
-    /**
-     * Returns a collection of accounts. Preferrably, these follow a uniform Firefly III format so they can be managed over banks.
-     *
-     * The format for these bank accounts is basically this:
-     *
-     * id: bank specific id
-     * name: bank appointed name
-     * number: account number (usually IBAN)
-     * currency: ISO code of currency
-     * balance: current balance
-     *
-     *
-     * any other fields are optional but can be useful:
-     * image: logo or account specific thing
-     * color: any associated color.
-     *
-     * @return array
-     *
-     * @throws FireflyException
-     * @throws \Exception
-     */
-    public function getAccounts(): array
-    {
-        // cache for an hour:
-        $cache = new CacheProperties;
-        $cache->addProperty('bunq.get-accounts');
-        $cache->addProperty(date('dmy h'));
-        if ($cache->has()) {
-            return $cache->get(); // @codeCoverageIgnore
-        }
-        Log::debug('Now in getAccounts()');
-        $sessionToken = $this->startSession();
-        $userId       = $this->getUserInformation($sessionToken);
-        // get list of Bunq accounts:
-        $accounts = $this->getMonetaryAccounts($sessionToken, $userId);
-        $return   = [];
-        /** @var MonetaryAccountBank $account */
-        foreach ($accounts as $account) {
-            $current = [
-                'id'       => $account->getId(),
-                'name'     => $account->getDescription(),
-                'currency' => $account->getCurrency(),
-                'balance'  => $account->getBalance()->getValue(),
-                'color'    => $account->getSetting()->getColor(),
-            ];
-            /** @var Alias $alias */
-            foreach ($account->getAliases() as $alias) {
-                if ('IBAN' === $alias->getType()) {
-                    $current['number'] = $alias->getValue();
-                }
-            }
-            $return[] = $current;
-        }
-        $cache->store($return);
-
-        $this->closeSession($sessionToken);
-
-        return $return;
-    }
-
-    /**
-     * Set the user for this Prerequisites-routine. Class is expected to implement and save this.
-     *
-     * @param User $user
-     */
-    public function setUser(User $user): void
-    {
-        $this->user = $user;
-    }
-
-    /**
-     * @param SessionToken $sessionToken
-     *
-     * @throws \Exception
-     */
-    private function closeSession(SessionToken $sessionToken): void
-    {
-        Log::debug('Going to close session');
-        $apiKey          = Preferences::getForUser($this->user, 'bunq_api_key')->data;
-        $serverPublicKey = Preferences::getForUser($this->user, 'bunq_server_public_key')->data;
-        $privateKey      = Preferences::getForUser($this->user, 'bunq_private_key')->data;
-        $request         = new DeleteDeviceSessionRequest();
-        $request->setSecret($apiKey);
-        $request->setPrivateKey($privateKey);
-        $request->setServerPublicKey($serverPublicKey);
-        $request->setSessionToken($sessionToken);
-        $request->call();
-
-        return;
-    }
-
-    /**
-     * @param SessionToken $sessionToken
-     * @param int          $userId
-     *
-     * @return Collection
-     *
-     * @throws \Exception
-     */
-    private function getMonetaryAccounts(SessionToken $sessionToken, int $userId): Collection
-    {
-        $apiKey          = Preferences::getForUser($this->user, 'bunq_api_key')->data;
-        $serverPublicKey = Preferences::getForUser($this->user, 'bunq_server_public_key')->data;
-        $privateKey      = Preferences::getForUser($this->user, 'bunq_private_key')->data;
-        $request         = new ListMonetaryAccountRequest;
-
-        $request->setSessionToken($sessionToken);
-        $request->setSecret($apiKey);
-        $request->setServerPublicKey($serverPublicKey);
-        $request->setPrivateKey($privateKey);
-        $request->setUserId($userId);
-        $request->call();
-
-        return $request->getMonetaryAccounts();
-    }
-
-    /**
-     * @param SessionToken $sessionToken
-     *
-     * @return int
-     *
-     * @throws FireflyException
-     * @throws \Exception
-     */
-    private function getUserInformation(SessionToken $sessionToken): int
-    {
-        $apiKey          = Preferences::getForUser($this->user, 'bunq_api_key')->data;
-        $serverPublicKey = Preferences::getForUser($this->user, 'bunq_server_public_key')->data;
-        $privateKey      = Preferences::getForUser($this->user, 'bunq_private_key')->data;
-        $request         = new ListUserRequest;
-        $request->setSessionToken($sessionToken);
-        $request->setSecret($apiKey);
-        $request->setServerPublicKey($serverPublicKey);
-        $request->setPrivateKey($privateKey);
-        $request->call();
-        // return the first that isn't null?
-        $company = $request->getUserCompany();
-        if ($company->getId() > 0) {
-            return $company->getId();
-        }
-        $user = $request->getUserPerson();
-        if ($user->getId() > 0) {
-            return $user->getId();
-        }
-        throw new FireflyException('Expected user or company from Bunq, but got neither.');
-    }
-
-    /**
-     * @return SessionToken
-     *
-     * @throws \Exception
-     */
-    private function startSession(): SessionToken
-    {
-        Log::debug('Now in startSession.');
-        $apiKey            = Preferences::getForUser($this->user, 'bunq_api_key')->data;
-        $serverPublicKey   = Preferences::getForUser($this->user, 'bunq_server_public_key')->data;
-        $privateKey        = Preferences::getForUser($this->user, 'bunq_private_key')->data;
-        $installationToken = Preferences::getForUser($this->user, 'bunq_installation_token')->data;
-        $request           = new DeviceSessionRequest();
-        $request->setSecret($apiKey);
-        $request->setServerPublicKey($serverPublicKey);
-        $request->setPrivateKey($privateKey);
-        $request->setInstallationToken($installationToken);
-        $request->call();
-        $sessionToken = $request->getSessionToken();
-        Log::debug(sprintf('Now have got session token: %s', serialize($sessionToken)));
-
-        return $sessionToken;
-    }
-}
diff --git a/public/js/ff/import/status.js b/public/js/ff/import/status.js
index 0f65e71b60..9fa0198516 100644
--- a/public/js/ff/import/status.js
+++ b/public/js/ff/import/status.js
@@ -34,10 +34,12 @@ var knownErrors = 0;
 
 $(function () {
     "use strict";
+    console.log('in start');
     timeOutId = setTimeout(checkJobStatus, startInterval);
 
     $('.start-job').click(startJob);
     if (job.configuration['auto-start']) {
+        console.log('Called startJob()!');
         startJob();
     }
 });
@@ -46,6 +48,7 @@ $(function () {
  * Downloads some JSON and responds to its content to see what the status is of the current import.
  */
 function checkJobStatus() {
+    console.log('in checkJobStatus');
     $.getJSON(jobStatusUri).done(reportOnJobStatus).fail(reportFailedJob);
 }
 
@@ -53,6 +56,7 @@ function checkJobStatus() {
  * This method is called when the JSON query returns an error. If possible, this error is relayed to the user.
  */
 function reportFailedJob(jqxhr, textStatus, error) {
+    console.log('in reportFailedJob');
     // hide all possible boxes:
     $('.statusbox').hide();
 
@@ -72,6 +76,7 @@ function reportFailedJob(jqxhr, textStatus, error) {
  * @param data
  */
 function reportOnJobStatus(data) {
+    console.log('in reportOnJobStatus: ' + data.status);
 
     switch (data.status) {
         case "configured":
@@ -80,6 +85,10 @@ function reportOnJobStatus(data) {
                 $('.statusbox').hide();
                 $('.status_configured').show();
             }
+            if (job.configuration['auto-start']) {
+                console.log('Job is auto start. Check status again in 500ms.');
+                timeOutId = setTimeout(checkJobStatus, interval);
+            }
             break;
         case "running":
             // job is running! Show the running box:
@@ -122,7 +131,13 @@ function reportOnJobStatus(data) {
             // show the fatal error box:
             $('.fatal_error').show();
             break;
+        case "configuring":
+            // redirect back to configure screen.
+            console.log('Will now redirect to ' + jobConfigureUri);
+            window.location = jobConfigureUri;
+            break;
         default:
+            console.error('Cannot handle job status ' + data.status);
             break;
 
     }
diff --git a/resources/views/import/spectre/redirect.twig b/resources/views/import/spectre/redirect.twig
new file mode 100644
index 0000000000..e76c8b4bdb
--- /dev/null
+++ b/resources/views/import/spectre/redirect.twig
@@ -0,0 +1,15 @@
+
+
+
+    
+    
+    
+    Page Redirection
+
+
+
+If you are not redirected automatically, follow this link to Spectre..
+
+#}
\ No newline at end of file
diff --git a/resources/views/import/status.twig b/resources/views/import/status.twig
index 2844f818fa..650c224fac 100644
--- a/resources/views/import/status.twig
+++ b/resources/views/import/status.twig
@@ -149,6 +149,7 @@
         var langImportMultiError = '{{ trans('import.status_errors_multi')|escape('js') }}';
         var jobStatusUri = '{{ route('import.status.json', [job.key]) }}';
         var jobStartUri = '{{ route('import.start', [job.key]) }}';
+        var jobConfigureUri = '{{ route('import.configure', [job.key]) }}';
         var token = '{{ csrf_token() }}';
         var job = {{ job|json_encode|raw }};