Enable Coinbase for all users (#398)

## Summary
- remove CoinbaseIntegration Pennant feature flag
- always show Coinbase in open banking institution picker
- drop shared Coinbase feature flag type

## Tests
- vendor/bin/pint --dirty --format agent
- php artisan test --compact tests/Feature/InertiaSharedDataTest.php
- php artisan test --compact
tests/Feature/OpenBanking/CoinbaseControllerTest.php
- npx eslint
resources/js/components/open-banking/connect-account-inline.tsx
resources/js/components/open-banking/connect-account-dialog.tsx
resources/js/types/index.d.ts

Note: npm run types still fails on existing project-wide Wayfinder/type
issues.
This commit is contained in:
Víctor Falcón 2026-05-14 11:47:47 +01:00 committed by GitHub
parent fc419c6cae
commit 4ba130f310
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 22 additions and 41 deletions

View File

@ -1,19 +0,0 @@
<?php
namespace App\Features;
use App\Models\User;
/**
* @api
*/
class CoinbaseIntegration
{
/**
* Off by default. Enable per-user with `php artisan feature:enable CoinbaseIntegration user@example.com`.
*/
public function resolve(User $user): bool
{
return false;
}
}

View File

@ -3,12 +3,10 @@
namespace App\Http\Middleware;
use App\Enums\AccountType;
use App\Features\CoinbaseIntegration;
use App\Services\CurrencyOptions;
use Illuminate\Foundation\Inspiring;
use Illuminate\Http\Request;
use Inertia\Middleware;
use Laravel\Pennant\Feature;
class HandleInertiaRequests extends Middleware
{
@ -152,11 +150,8 @@ class HandleInertiaRequests extends Middleware
*/
protected function resolveFeatureFlags(): array
{
$user = request()->user();
return [
'cashflow' => true,
'coinbase' => $user ? Feature::for($user)->active(CoinbaseIntegration::class) : false,
];
}

View File

@ -8,7 +8,6 @@ import {
DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Label } from '@/components/ui/label';
import {
Select,
@ -17,13 +16,12 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
import type {
BankingConnection,
EnableBankingInstitution,
} from '@/types/banking';
import { __ } from '@/utils/i18n';
import { usePage } from '@inertiajs/react';
import type { SharedData } from '@/types';
import { useCallback, useEffect, useMemo, useState } from 'react';
const COUNTRIES = [
@ -97,7 +95,6 @@ export function ConnectAccountDialog({
onOpenChange,
connections = [],
}: ConnectAccountDialogProps) {
const { features } = usePage<SharedData>().props;
const [step, setStep] = useState<Step>('country');
const [country, setCountry] = useState<string>('');
const [institutions, setInstitutions] = useState<
@ -204,10 +201,11 @@ export function ConnectAccountDialog({
const hasProvider = (provider: string) =>
connections.some((c) => c.provider === provider);
const extraInstitutions = [BINANCE_INSTITUTION, BITPANDA_INSTITUTION];
if (features.coinbase) {
extraInstitutions.push(COINBASE_INSTITUTION);
}
const extraInstitutions = [
BINANCE_INSTITUTION,
BITPANDA_INSTITUTION,
COINBASE_INSTITUTION,
];
if (countryCode === 'ES') {
extraInstitutions.push(INDEXA_CAPITAL_INSTITUTION);
}

View File

@ -2,7 +2,6 @@ import { BankLogo } from '@/components/bank-logo';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import {
Select,
SelectContent,
@ -10,14 +9,13 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
import { useWebHaptics } from '@/hooks/use-web-haptics';
import type {
BankingConnection,
EnableBankingInstitution,
} from '@/types/banking';
import { __ } from '@/utils/i18n';
import { usePage } from '@inertiajs/react';
import type { SharedData } from '@/types';
import { ArrowLeft } from 'lucide-react';
import { useCallback, useEffect, useMemo, useState } from 'react';
@ -90,7 +88,6 @@ export function ConnectAccountInline({
onBack,
connections = [],
}: ConnectAccountInlineProps) {
const { features } = usePage<SharedData>().props;
const [step, setStep] = useState<Step>('country');
const { trigger } = useWebHaptics();
const [country, setCountry] = useState<string>('');
@ -185,10 +182,11 @@ export function ConnectAccountInline({
const hasProvider = (provider: string) =>
connections.some((c) => c.provider === provider);
const extraInstitutions = [BINANCE_INSTITUTION, BITPANDA_INSTITUTION];
if (features.coinbase) {
extraInstitutions.push(COINBASE_INSTITUTION);
}
const extraInstitutions = [
BINANCE_INSTITUTION,
BITPANDA_INSTITUTION,
COINBASE_INSTITUTION,
];
if (countryCode === 'ES') {
extraInstitutions.push(INDEXA_CAPITAL_INSTITUTION);
}

View File

@ -41,7 +41,6 @@ export interface NavDivider {
export interface Features {
cashflow: boolean;
coinbase: boolean;
}
export interface Flash {

View File

@ -33,6 +33,16 @@ test('all pages receive app url in shared props', function () {
);
});
test('shared feature flags do not include coinbase flag', function () {
$response = $this->withoutVite()->get(route('home'));
$props = $response->viewData('page')['props'];
expect($props['features'])->toBe([
'cashflow' => true,
]);
});
test('shared currency options split profile and account currencies', function () {
$response = $this->withoutVite()->get(route('home'));