From 17eaa801357f39029f8659d763a29b6e902435df Mon Sep 17 00:00:00 2001 From: Kevin Adametz Date: Fri, 3 Jul 2026 07:58:30 +0000 Subject: [PATCH] R0.4: Seeder produktionssicher (PlanSeeder, keine Fake-Stripe-IDs, Dev-User-Guard) - PlanSeeder (Starter/Business/Pro/Agency) haengt jetzt im DatabaseSeeder - PaymentOptionSeeder erfindet keine prod_/price_placeholder-IDs mehr (Spalten nullable; echte Verknuepfung via Stripe-Sync/Pflege) - Demo-Zugaenge admin@pressekonto.test/test@example.com (Passwort "password") werden nur noch in local/testing angelegt Co-Authored-By: Claude Fable 5 --- database/seeders/DatabaseSeeder.php | 7 ++++ database/seeders/PaymentOptionSeeder.php | 12 +++--- tests/Feature/DatabaseSeederTest.php | 48 ++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 tests/Feature/DatabaseSeederTest.php diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index ba4a5f73..26afb5ed 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -19,10 +19,17 @@ class DatabaseSeeder extends Seeder $this->call([ RolesAndPermissionsSeeder::class, AdminPresetSeeder::class, + PlanSeeder::class, PaymentOptionSeeder::class, // CategorySeeder::class, ]); + // Demo-Zugänge (Passwort "password") nur in lokalen Umgebungen – + // niemals in Produktion anlegen. + if (! app()->environment(['local', 'testing'])) { + return; + } + $adminUser = User::firstOrCreate([ 'email' => 'admin@pressekonto.test', ], [ diff --git a/database/seeders/PaymentOptionSeeder.php b/database/seeders/PaymentOptionSeeder.php index 6de29c44..a0aa1b9b 100644 --- a/database/seeders/PaymentOptionSeeder.php +++ b/database/seeders/PaymentOptionSeeder.php @@ -21,8 +21,8 @@ class PaymentOptionSeeder extends Seeder 'currency' => 'EUR', 'interval' => 'monthly', 'is_hidden' => false, - 'stripe_product_id' => 'prod_placeholder_monthly', - 'stripe_price_id' => 'price_placeholder_monthly', + 'stripe_product_id' => null, + 'stripe_price_id' => null, 'translations' => [ 'de' => ['name' => 'Monatspaket', 'description' => 'Monatliche Veroeffentlichungen'], 'en' => ['name' => 'Monthly package', 'description' => 'Monthly publication package'], @@ -35,8 +35,8 @@ class PaymentOptionSeeder extends Seeder 'currency' => 'EUR', 'interval' => 'yearly', 'is_hidden' => false, - 'stripe_product_id' => 'prod_placeholder_yearly', - 'stripe_price_id' => 'price_placeholder_yearly', + 'stripe_product_id' => null, + 'stripe_price_id' => null, 'translations' => [ 'de' => ['name' => 'Jahrespaket', 'description' => 'Jaehrliche Veroeffentlichungen'], 'en' => ['name' => 'Yearly package', 'description' => 'Yearly publication package'], @@ -49,8 +49,8 @@ class PaymentOptionSeeder extends Seeder 'currency' => 'EUR', 'interval' => 'once', 'is_hidden' => false, - 'stripe_product_id' => 'prod_placeholder_onetime', - 'stripe_price_id' => 'price_placeholder_onetime', + 'stripe_product_id' => null, + 'stripe_price_id' => null, 'translations' => [ 'de' => ['name' => 'Reichweiten-Boost', 'description' => 'Einmaliger Promotion-Boost'], 'en' => ['name' => 'Reach boost', 'description' => 'One-time promotion boost'], diff --git a/tests/Feature/DatabaseSeederTest.php b/tests/Feature/DatabaseSeederTest.php new file mode 100644 index 00000000..f458ced5 --- /dev/null +++ b/tests/Feature/DatabaseSeederTest.php @@ -0,0 +1,48 @@ +seed(DatabaseSeeder::class); + + expect(Plan::query()->count())->toBe(4); + expect(PaymentOption::query()->count())->toBe(3); +}); + +test('payment option seeder does not invent stripe ids', function () { + /** @var TestCase $this */ + $this->seed(DatabaseSeeder::class); + + expect(PaymentOption::query()->whereNotNull('stripe_price_id')->exists())->toBeFalse(); + expect(PaymentOption::query()->whereNotNull('stripe_product_id')->exists())->toBeFalse(); +}); + +test('dev users are seeded outside production', function () { + /** @var TestCase $this */ + $this->seed(DatabaseSeeder::class); + + expect(User::findByEmail('admin@pressekonto.test'))->not->toBeNull(); + expect(User::findByEmail('test@example.com'))->not->toBeNull(); +}); + +test('dev users are not seeded in production', function () { + /** @var TestCase $this */ + $originalEnv = $this->app['env']; + $this->app['env'] = 'production'; + + try { + // Direkt statt über artisan db:seed – das Command würde in + // "production" interaktiv um Bestätigung bitten. + (new DatabaseSeeder)->setContainer($this->app)->__invoke(); + } finally { + $this->app['env'] = $originalEnv; + } + + expect(User::query()->count())->toBe(0); + expect(Plan::query()->count())->toBe(4); +});