From da6488adaced39c0cd2427c0a9878bcdeaea14cc Mon Sep 17 00:00:00 2001 From: paulwer Date: Wed, 13 Dec 2023 15:37:19 +0100 Subject: [PATCH] remove credentials on account level + remove ApiException + fixes --- .env.example | 5 ++- app/Exceptions/NordigenApiException.php | 41 ------------------- app/Helpers/Bank/Nordigen/Nordigen.php | 18 +++++--- .../Controllers/Bank/NordigenController.php | 23 +++++++---- .../Controllers/BankIntegrationController.php | 35 ++++++++-------- .../Bank/ProcessBankTransactionsNordigen.php | 16 ++------ app/Jobs/Ninja/BankTransactionSync.php | 23 +++++------ app/Models/Account.php | 4 -- ...3_11_26_082959_add_bank_integration_id.php | 2 - 9 files changed, 64 insertions(+), 103 deletions(-) delete mode 100644 app/Exceptions/NordigenApiException.php diff --git a/.env.example b/.env.example index 17130c1460..ea1f4a3207 100644 --- a/.env.example +++ b/.env.example @@ -68,4 +68,7 @@ MICROSOFT_REDIRECT_URI= APPLE_CLIENT_ID= APPLE_CLIENT_SECRET= -APPLE_REDIRECT_URI= \ No newline at end of file +APPLE_REDIRECT_URI= + +NORDIGEN_SECRET_ID= +NORDIGEN_SECRET_KEY= diff --git a/app/Exceptions/NordigenApiException.php b/app/Exceptions/NordigenApiException.php deleted file mode 100644 index bc81d968a4..0000000000 --- a/app/Exceptions/NordigenApiException.php +++ /dev/null @@ -1,41 +0,0 @@ -getMessage() && strlen($this->getMessage()) >= 1) { - $msg = $this->getMessage(); - } - - return response()->json([ - 'message' => $msg, - ], 400); - } -} diff --git a/app/Helpers/Bank/Nordigen/Nordigen.php b/app/Helpers/Bank/Nordigen/Nordigen.php index b9cddac153..52f4d29a51 100644 --- a/app/Helpers/Bank/Nordigen/Nordigen.php +++ b/app/Helpers/Bank/Nordigen/Nordigen.php @@ -9,15 +9,18 @@ * @license https://www.elastic.co/licensing/elastic-license * * Documentation of Api-Usage: https://developer.gocardless.com/bank-account-data/overview + * + * Institutions: Are Banks or Payment-Providers, which manages bankaccounts. + * + * Accounts: Accounts are existing bank_accounts at a specific institution. + * + * Requisitions: Are registered/active user-flows to authenticate one or many accounts. After completition, the accoundId could be used to fetch data for this account. After the access expires, the user could create a new requisition to connect accounts again. */ namespace App\Helpers\Bank\Nordigen; -use App\Exceptions\NordigenApiException; use App\Helpers\Bank\Nordigen\Transformer\AccountTransformer; use App\Helpers\Bank\Nordigen\Transformer\TransactionTransformer; -use Log; -use Nordigen\NordigenPHP\Exceptions\NordigenExceptions\NordigenException; class Nordigen { @@ -27,11 +30,14 @@ class Nordigen protected \Nordigen\NordigenPHP\API\NordigenClient $client; - public function __construct(string $secret_id, string $secret_key) + public function __construct() { $this->test_mode = config('ninja.nordigen.test_mode'); - $this->client = new \Nordigen\NordigenPHP\API\NordigenClient($secret_id, $secret_key); + if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) + throw new \Exception('missing nordigen credentials'); + + $this->client = new \Nordigen\NordigenPHP\API\NordigenClient(config('ninja.nordigen.secret_id'), config('ninja.nordigen.secret_key')); $this->client->createAccessToken(); // access_token is valid 24h -> so we dont have to implement a refresh-cycle } @@ -51,7 +57,7 @@ class Nordigen if ($this->test_mode && $initutionId != $this->sandbox_institutionId) throw new \Exception('invalid institutionId while in test-mode'); - return $this->client->requisition->createRequisition($redirect, $initutionId, null, $reference); // we dont reuse existing requisitions, to prevent double usage of them. see: deleteAccount + return $this->client->requisition->createRequisition($redirect, $initutionId, null, $reference); } public function getRequisition(string $requisitionId) diff --git a/app/Http/Controllers/Bank/NordigenController.php b/app/Http/Controllers/Bank/NordigenController.php index 47cdcf6013..f277a1836d 100644 --- a/app/Http/Controllers/Bank/NordigenController.php +++ b/app/Http/Controllers/Bank/NordigenController.php @@ -18,6 +18,7 @@ use App\Http\Requests\Nordigen\ConnectNordigenBankIntegrationRequest; use App\Jobs\Bank\ProcessBankTransactionsNordigen; use App\Models\BankIntegration; use App\Models\Company; +use App\Utils\Ninja; use Cache; use Illuminate\Http\Request; use Log; @@ -37,10 +38,13 @@ class NordigenController extends BaseController $company = $request->getCompany(); $account = $company->account; - if (!(($account->bank_integration_nordigen_secret_id && $account->bank_integration_nordigen_secret_key) || (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key')))) + if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) return response()->redirectTo($data["redirect"] . "?action=nordigen_connect&status=failed&reason=account-config-invalid"); - $nordigen = ($account->bank_integration_nordigen_secret_id && $account->bank_integration_nordigen_secret_key) ? new Nordigen($account->bank_integration_nordigen_secret_id, $account->bank_integration_nordigen_secret_key) : new Nordigen(config('ninja.nordigen.secret_id'), config('ninja.nordigen.secret_key')); + if (!(Ninja::isSelfHost() || (Ninja::isHosted() && $account->isPaid() && $account->plan == 'enterprise'))) + return response()->redirectTo($context["redirect"] . "?action=nordigen_connect&status=failed&reason=not-available"); + + $nordigen = new Nordigen(); // show bank_selection_screen, when institution_id is not present if (!array_key_exists("institution_id", $data)) { @@ -157,11 +161,14 @@ class NordigenController extends BaseController $company = Company::where('company_key', $context["company_key"])->firstOrFail(); $account = $company->account; - if (!(($account->bank_integration_nordigen_secret_id && $account->bank_integration_nordigen_secret_key) || (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key')))) + if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) return response()->redirectTo($context["redirect"] . "?action=nordigen_connect&status=failed&reason=account-config-invalid"); + if (!(Ninja::isSelfHost() || (Ninja::isHosted() && $account->isPaid() && $account->plan == 'enterprise'))) + return response()->redirectTo($context["redirect"] . "?action=nordigen_connect&status=failed&reason=not-available"); + // fetch requisition - $nordigen = ($account->bank_integration_nordigen_secret_id && $account->bank_integration_nordigen_secret_key) ? new Nordigen($account->bank_integration_nordigen_secret_id, $account->bank_integration_nordigen_secret_key) : new Nordigen(config('ninja.nordigen.secret_id'), config('ninja.nordigen.secret_key')); + $nordigen = new Nordigen(); $requisition = $nordigen->getRequisition($context["requisitionId"]); // check validity of requisition @@ -222,9 +229,9 @@ class NordigenController extends BaseController } // perform update in background - $company->account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->each(function ($bank_integration) use ($company) { + $company->account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->each(function ($bank_integration) { - ProcessBankTransactionsNordigen::dispatch($company->account, $bank_integration); + ProcessBankTransactionsNordigen::dispatch($bank_integration); }); @@ -304,10 +311,10 @@ class NordigenController extends BaseController { $account = auth()->user()->account; - if (!(($account->bank_integration_nordigen_secret_id && $account->bank_integration_nordigen_secret_key) || (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key')))) + if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) return response()->json(['message' => 'Not yet authenticated with Nordigen Bank Integration service'], 400); - $nordigen = ($account->bank_integration_nordigen_secret_id && $account->bank_integration_nordigen_secret_key) ? new Nordigen($account->bank_integration_nordigen_secret_id, $account->bank_integration_nordigen_secret_key) : new Nordigen(config('ninja.nordigen.secret_id'), config('ninja.nordigen.secret_key')); + $nordigen = new Nordigen(); return response()->json($nordigen->getInstitutions()); } diff --git a/app/Http/Controllers/BankIntegrationController.php b/app/Http/Controllers/BankIntegrationController.php index 69ffebdd7b..36adeda186 100644 --- a/app/Http/Controllers/BankIntegrationController.php +++ b/app/Http/Controllers/BankIntegrationController.php @@ -30,6 +30,7 @@ use App\Models\BankIntegration; use App\Models\User; use App\Repositories\BankIntegrationRepository; use App\Transformers\BankIntegrationTransformer; +use App\Utils\Ninja; use App\Utils\Traits\MakesHash; use Illuminate\Http\JsonResponse; use Illuminate\Http\Response; @@ -206,17 +207,17 @@ class BankIntegrationController extends BaseController return response()->json(BankIntegration::query()->company(), 200); // Processing transactions for each bank account - if ($user->account->bank_integration_yodlee_account_id) + if (Ninja::isHosted() && $user->account->bank_integration_yodlee_account_id) $user_account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_YODLEE)->where('auto_sync', true)->each(function ($bank_integration) use ($user_account) { ProcessBankTransactionsYodlee::dispatch($user_account, $bank_integration); }); - if (($user->account->bank_integration_nordigen_secret_id && $user->account->bank_integration_nordigen_secret_key) || (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) - $user_account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->each(function ($bank_integration) use ($user_account) { + if (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key') && (Ninja::isSelfHost() || (Ninja::isHosted() && $user_account->isPaid() && $user_account->plan == 'enterprise'))) + $user_account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->each(function ($bank_integration) { - ProcessBankTransactionsNordigen::dispatch($user_account, $bank_integration); + ProcessBankTransactionsNordigen::dispatch($bank_integration); }); @@ -265,10 +266,10 @@ class BankIntegrationController extends BaseController { $account = $user->account; - if (!(($account->bank_integration_nordigen_secret_id && $account->bank_integration_nordigen_secret_key) || (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key')))) + if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) return; - $nordigen = ($account->bank_integration_nordigen_secret_id && $account->bank_integration_nordigen_secret_key) ? new Nordigen($account->bank_integration_nordigen_secret_id, $account->bank_integration_nordigen_secret_key) : new Nordigen(config('ninja.nordigen.secret_id'), config('ninja.nordigen.secret_key')); + $nordigen = new Nordigen(); BankIntegration::withTrashed()->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->whereNotNull('nordigen_account_id')->each(function (BankIntegration $bank_integration) use ($nordigen) { $account = $nordigen->getAccount($bank_integration->nordigen_account_id); @@ -334,18 +335,20 @@ class BankIntegrationController extends BaseController */ public function getTransactions(AdminBankIntegrationRequest $request) { - /** @var \App\Models\User $user */ - $user = auth()->user(); + /** @var \App\Models\Account $account */ + $account = auth()->user()->account(); - // Yodlee - $user->account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_YODLEE)->each(function ($bank_integration) use ($user) { - (new ProcessBankTransactionsYodlee($user->account, $bank_integration))->handle(); - }); + if (Ninja::isHosted() && $account->isPaid() && $account->plan == 'enterprise') { + $account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_YODLEE)->where('auto_sync', true)->cursor()->each(function ($bank_integration) use ($account) { + (new ProcessBankTransactionsYodlee($account, $bank_integration))->handle(); + }); + } - // Nordigen - $user->account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->each(function ($bank_integration) use ($user) { - (new ProcessBankTransactionsYodlee($user->account, $bank_integration))->handle(); - }); + if (config("ninja.nortigen.secret_id") && config("ninja.nortigen.secret_key") && (Ninja::isSelfHost() || (Ninja::isHosted() && $account->isPaid() && $account->plan == 'enterprise'))) { + $account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->cursor()->each(function ($bank_integration) { + (new ProcessBankTransactionsNordigen($bank_integration))->handle(); + }); + } return response()->json(['message' => 'Fetching transactions....'], 200); } diff --git a/app/Jobs/Bank/ProcessBankTransactionsNordigen.php b/app/Jobs/Bank/ProcessBankTransactionsNordigen.php index 7f7f110b8a..bd49eb1efd 100644 --- a/app/Jobs/Bank/ProcessBankTransactionsNordigen.php +++ b/app/Jobs/Bank/ProcessBankTransactionsNordigen.php @@ -30,7 +30,6 @@ class ProcessBankTransactionsNordigen implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - private Account $account; private BankIntegration $bank_integration; private string $secret_id; private string $secret_key; @@ -48,9 +47,8 @@ class ProcessBankTransactionsNordigen implements ShouldQueue /** * Create a new job instance. */ - public function __construct(Account $account, BankIntegration $bank_integration) + public function __construct(BankIntegration $bank_integration) { - $this->account = $account; $this->bank_integration = $bank_integration; $this->from_date = $bank_integration->from_date; $this->company = $this->bank_integration->company; @@ -68,18 +66,10 @@ class ProcessBankTransactionsNordigen implements ShouldQueue if ($this->bank_integration->integration_type != BankIntegration::INTEGRATION_TYPE_NORDIGEN) throw new \Exception("Invalid BankIntegration Type"); - if (!(($this->account->bank_integration_nordigen_secret_id && $this->account->bank_integration_nordigen_secret_key) || (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key')))) + if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) throw new \Exception("Missing credentials for bank_integration service nortigen"); - if ($this->account->bank_integration_nordigen_secret_id && $this->account->bank_integration_nordigen_secret_key) { - $this->secret_id = $this->account->bank_integration_nordigen_secret_id; - $this->secret_key = $this->account->bank_integration_nordigen_secret_key; - } else { - $this->secret_id = config('ninja.nordigen.secret_id'); - $this->secret_key = config('ninja.nordigen.secret_key'); - } - - $this->nordigen = new Nordigen($this->secret_id, $this->secret_key); + $this->nordigen = new Nordigen(); set_time_limit(0); diff --git a/app/Jobs/Ninja/BankTransactionSync.php b/app/Jobs/Ninja/BankTransactionSync.php index 786125545d..923743805c 100644 --- a/app/Jobs/Ninja/BankTransactionSync.php +++ b/app/Jobs/Ninja/BankTransactionSync.php @@ -53,30 +53,29 @@ class BankTransactionSync implements ShouldQueue nlog("syncing transactions - yodlee"); Account::with('bank_integrations')->whereNotNull('bank_integration_yodlee_account_id')->cursor()->each(function ($account) { - // $queue = Ninja::isHosted() ? 'bank' : 'default'; if ($account->isPaid() && $account->plan == 'enterprise') { $account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_YODLEE)->where('auto_sync', true)->cursor()->each(function ($bank_integration) use ($account) { (new ProcessBankTransactionsYodlee($account, $bank_integration))->handle(); }); } + }); } - nlog("syncing transactions - nordigen"); + if (config("ninja.nortigen.secret_id") && config("ninja.nortigen.secret_key")) { // @turbo124 check condition, when to execute this should be placed here (isSelfHosted || isPro/isEnterprise) + nlog("syncing transactions - nordigen"); - if (config("ninja.nortigen.secret_id") && config("ninja.nortigen.secret_key")) Account::with('bank_integrations')->cursor()->each(function ($account) { - $account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->cursor()->each(function ($bank_integration) use ($account) { - (new ProcessBankTransactionsNordigen($account, $bank_integration))->handle(); - }); - }); - else - Account::with('bank_integrations')->whereNotNull('bank_integration_nordigen_secret_id')->whereNotNull('bank_integration_nordigen_secret_key')->cursor()->each(function ($account) { - $account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->cursor()->each(function ($bank_integration) use ($account) { - (new ProcessBankTransactionsNordigen($account, $bank_integration))->handle(); - }); + + if ((Ninja::isSelfHost() || (Ninja::isHosted() && $account->isPaid() && $account->plan == 'enterprise'))) { + $account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->cursor()->each(function ($bank_integration) { + (new ProcessBankTransactionsNordigen($bank_integration))->handle(); + }); + } + }); + } nlog("syncing transactions - done"); } diff --git a/app/Models/Account.php b/app/Models/Account.php index 7d95b2b217..888029ee3f 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -70,8 +70,6 @@ use Laracasts\Presenter\PresentableTrait; * @property string|null $account_sms_verification_number * @property bool $account_sms_verified * @property string|null $bank_integration_yodlee_account_id - * @property string|null $bank_integration_nordigen_secret_id - * @property string|null $bank_integration_nordigen_secret_key * @property int $is_trial * @property-read int|null $bank_integrations_count * @property-read int|null $companies_count @@ -128,8 +126,6 @@ class Account extends BaseModel 'platform', 'set_react_as_default_ap', 'inapp_transaction_id', - 'bank_integration_nordigen_secret_id', - 'bank_integration_nordigen_secret_key', ]; protected $casts = [ diff --git a/database/migrations/2023_11_26_082959_add_bank_integration_id.php b/database/migrations/2023_11_26_082959_add_bank_integration_id.php index da6f778877..faa2bd68cb 100644 --- a/database/migrations/2023_11_26_082959_add_bank_integration_id.php +++ b/database/migrations/2023_11_26_082959_add_bank_integration_id.php @@ -29,8 +29,6 @@ return new class extends Migration { // MAYBE migration of account->bank_account_id etc Schema::table('accounts', function (Blueprint $table) { $table->renameColumn('bank_integration_account_id', 'bank_integration_yodlee_account_id'); - $table->string('bank_integration_nordigen_secret_id')->nullable(); - $table->string('bank_integration_nordigen_secret_key')->nullable(); }); }