fix: Delete pending connection and show toast on cancelled bank authorization (#111)
## Summary - When a user cancels the bank authorization flow (e.g. clicks cancel on the bank's page), the pending `BankingConnection` is now soft-deleted so it doesn't remain stuck in `pending` status - Flash messages (`success`/`error`) are now shared with the frontend via Inertia shared data - The connections settings page shows a toast notification with the error message on redirect ## Test plan - [ ] Start a bank connection flow, cancel on the bank's authorization page, and verify: - A toast error appears on the connections page - The pending connection is removed from the list - [x] Complete a successful bank connection and verify the success toast appears - [x] Run `php artisan test tests/Feature/OpenBanking/AuthorizationControllerTest.php`
This commit is contained in:
parent
03fec11705
commit
c7f3f1a978
|
|
@ -60,6 +60,12 @@ class AuthorizationController extends Controller
|
|||
'description' => $request->query('error_description'),
|
||||
]);
|
||||
|
||||
auth()->user()->bankingConnections()
|
||||
->where('status', BankingConnectionStatus::Pending)
|
||||
->latest()
|
||||
->first()
|
||||
?->delete();
|
||||
|
||||
return redirect()->route('settings.connections.index')
|
||||
->with('error', $request->query('error_description', 'Authorization was denied or cancelled.'));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ class HandleInertiaRequests extends Middleware
|
|||
|
||||
return [
|
||||
...parent::share($request),
|
||||
'flash' => [
|
||||
'success' => $request->session()->get('success'),
|
||||
'error' => $request->session()->get('error'),
|
||||
],
|
||||
'name' => config('app.name'),
|
||||
'appUrl' => config('app.url'),
|
||||
'version' => json_decode(file_get_contents(base_path('package.json')))->version ?? '0.0.0',
|
||||
|
|
|
|||
|
|
@ -25,13 +25,14 @@ import { __ } from '@/utils/i18n';
|
|||
import { Head, router, usePage, usePoll } from '@inertiajs/react';
|
||||
import { ArrowRight, MoreHorizontal, RefreshCw, Unplug } from 'lucide-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
interface Props {
|
||||
connections: BankingConnection[];
|
||||
}
|
||||
|
||||
export default function ConnectionsPage({ connections }: Props) {
|
||||
const { auth } = usePage<SharedData>().props;
|
||||
const { auth, flash } = usePage<SharedData>().props;
|
||||
const isDemoAccount = auth?.isDemoAccount ?? false;
|
||||
const [connectDialogOpen, setConnectDialogOpen] = useState(false);
|
||||
const [disconnectConnection, setDisconnectConnection] =
|
||||
|
|
@ -43,6 +44,15 @@ export default function ConnectionsPage({ connections }: Props) {
|
|||
|
||||
const { start, stop } = usePoll(5000, {}, { autoStart: false });
|
||||
|
||||
useEffect(() => {
|
||||
if (flash?.error) {
|
||||
toast.error(flash.error);
|
||||
}
|
||||
if (flash?.success) {
|
||||
toast.success(flash.success);
|
||||
}
|
||||
}, [flash?.error, flash?.success]);
|
||||
|
||||
useEffect(() => {
|
||||
if (hasSyncing) {
|
||||
start();
|
||||
|
|
|
|||
|
|
@ -45,12 +45,18 @@ export interface Features {
|
|||
'account-mapping': boolean;
|
||||
}
|
||||
|
||||
export interface Flash {
|
||||
success: string | null;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
export interface SharedData {
|
||||
name: string;
|
||||
appUrl: string;
|
||||
version: string;
|
||||
quote: { message: string; author: string };
|
||||
auth: Auth;
|
||||
flash: Flash;
|
||||
subscriptionsEnabled: boolean;
|
||||
pricing: PricingConfig;
|
||||
sidebarOpen: boolean;
|
||||
|
|
|
|||
|
|
@ -57,15 +57,22 @@ test('authorization requires aspsp_name and country', function () {
|
|||
$response->assertJsonValidationErrors(['aspsp_name', 'country']);
|
||||
});
|
||||
|
||||
test('callback with error redirects with error message', function () {
|
||||
test('callback with error redirects with error message and deletes pending connection', function () {
|
||||
$user = User::factory()->onboarded()->create();
|
||||
Feature::for($user)->activate('open-banking');
|
||||
|
||||
$connection = BankingConnection::factory()->pending()->create([
|
||||
'user_id' => $user->id,
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)
|
||||
->get('/open-banking/callback?error=access_denied&error_description=User+denied+access');
|
||||
|
||||
$response->assertRedirect(route('settings.connections.index'));
|
||||
$response->assertSessionHas('error');
|
||||
$response->assertSessionHas('error', 'User denied access');
|
||||
|
||||
$connection->refresh();
|
||||
expect($connection->trashed())->toBeTrue();
|
||||
});
|
||||
|
||||
test('callback without code redirects with error', function () {
|
||||
|
|
|
|||
Loading…
Reference in New Issue