diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index bde22dd8..5c131af1 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -38,6 +38,7 @@ class DashboardController extends Controller 'categories' => $categories, 'accounts' => $accounts, 'banks' => $banks, + 'showEncryptionPrompt' => session('show_encryption_prompt', false), ]); } } diff --git a/app/Http/Responses/LoginResponse.php b/app/Http/Responses/LoginResponse.php new file mode 100644 index 00000000..87982eca --- /dev/null +++ b/app/Http/Responses/LoginResponse.php @@ -0,0 +1,24 @@ +flash('show_encryption_prompt', true); + + return $request->wantsJson() + ? response()->json(['two_factor' => false]) + : redirect()->intended(Fortify::redirects('login')); + } +} diff --git a/app/Http/Responses/TwoFactorLoginResponse.php b/app/Http/Responses/TwoFactorLoginResponse.php new file mode 100644 index 00000000..1d62c4c4 --- /dev/null +++ b/app/Http/Responses/TwoFactorLoginResponse.php @@ -0,0 +1,24 @@ +flash('show_encryption_prompt', true); + + return $request->wantsJson() + ? new JsonResponse('', 204) + : redirect()->intended(Fortify::redirects('login')); + } +} diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php index 531182d0..f0d21a55 100644 --- a/app/Providers/FortifyServiceProvider.php +++ b/app/Providers/FortifyServiceProvider.php @@ -5,6 +5,8 @@ namespace App\Providers; use App\Actions\CreateDefaultCategories; use App\Actions\Fortify\CreateNewUser; use App\Actions\Fortify\ResetUserPassword; +use App\Http\Responses\LoginResponse; +use App\Http\Responses\TwoFactorLoginResponse; use Illuminate\Auth\Events\Registered; use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Http\Request; @@ -13,6 +15,8 @@ use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; use Inertia\Inertia; +use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract; +use Laravel\Fortify\Contracts\TwoFactorLoginResponse as TwoFactorLoginResponseContract; use Laravel\Fortify\Features; use Laravel\Fortify\Fortify; @@ -23,7 +27,8 @@ class FortifyServiceProvider extends ServiceProvider */ public function register(): void { - // + $this->app->singleton(LoginResponseContract::class, LoginResponse::class); + $this->app->singleton(TwoFactorLoginResponseContract::class, TwoFactorLoginResponse::class); } /** diff --git a/resources/js/pages/dashboard.tsx b/resources/js/pages/dashboard.tsx index 5e10ff56..472c88c5 100644 --- a/resources/js/pages/dashboard.tsx +++ b/resources/js/pages/dashboard.tsx @@ -3,11 +3,14 @@ import { CashflowSummaryCard } from '@/components/dashboard/cashflow-summary-car import { NetWorthChart as NetWorthChartComponent } from '@/components/dashboard/net-worth-chart'; import { TopCategoriesCard } from '@/components/dashboard/top-categories-card'; import HeadingSmall from '@/components/heading-small'; +import UnlockMessageDialog from '@/components/unlock-message-dialog'; +import { useEncryptionKey } from '@/contexts/encryption-key-context'; import { useDashboardData } from '@/hooks/use-dashboard-data'; import AppSidebarLayout from '@/layouts/app/app-sidebar-layout'; import { dashboard } from '@/routes'; import { BreadcrumbItem, SharedData } from '@/types'; import { Head, usePage } from '@inertiajs/react'; +import { useEffect, useState } from 'react'; const breadcrumbs: BreadcrumbItem[] = [ { @@ -16,8 +19,12 @@ const breadcrumbs: BreadcrumbItem[] = [ }, ]; +interface DashboardProps extends SharedData { + showEncryptionPrompt: boolean; +} + export default function Dashboard() { - const { props } = usePage(); + const { props } = usePage(); const { netWorthEvolution, accounts: accountMetrics, @@ -25,11 +32,49 @@ export default function Dashboard() { isLoading, refetch, } = useDashboardData(); + const { isKeySet, encryptedMessageData, fetchEncryptedMessage } = + useEncryptionKey(); + const [showUnlockDialog, setShowUnlockDialog] = useState(false); + + useEffect(() => { + // Fetch encrypted message data if not already loaded + if (!encryptedMessageData) { + fetchEncryptedMessage(); + } + + // Auto-open the unlock dialog only if: + // 1. User just logged in (showEncryptionPrompt is true) + // 2. Encryption key is not set + // 3. Encrypted message data is available + if (props.showEncryptionPrompt && !isKeySet && encryptedMessageData) { + setShowUnlockDialog(true); + } + }, [ + isKeySet, + encryptedMessageData, + fetchEncryptedMessage, + props.showEncryptionPrompt, + ]); + + function handleUnlock() { + setShowUnlockDialog(false); + } return ( + {encryptedMessageData && ( + + )} +