CluPilotCloud/tests/Feature/Admin/StripeWebhookSecretInVaultT...

105 lines
4.4 KiB
PHP

<?php
use App\Livewire\Admin\Integrations;
use App\Models\Operator;
use App\Services\Secrets\SecretVault;
use App\Support\OperatingMode;
use App\Support\Readiness\BillingChecks;
use App\Support\StripeWebhookSecret;
use Livewire\Livewire;
/**
* Ein Stripe-Wert in der Konsole und zwei in der Serverdatei ist keine
* Entscheidung, sondern ein Zustand. Die alte Begründung — „wird bei jedem
* eingehenden Zahlungsereignis gelesen, ein Datenbankproblem ließe die
* Signaturprüfung still fehlschlagen" — hält nicht: der Secret Key, mit dem
* das Geld eingezogen wird, liegt längst im Tresor und wird bei jeder Buchung
* gelesen. Und die AUSWAHL zwischen Test- und Live-Signaturschlüssel fragte
* ohnehin schon die Datenbank (OperatingMode::current()).
*
* Beide Werte sind jetzt ein Tresoreintrag mit den zwei Plätzen, die der
* Tresor für Test und Live sowieso führt.
*/
beforeEach(function () {
config()->set('admin_access.secrets_key', 'base64:'.base64_encode(random_bytes(32)));
});
it('prefers the stored signing secret over the server file', function () {
config()->set('services.stripe.webhook_secret_test', 'whsec_from_env');
OperatingMode::set(OperatingMode::Test);
app(SecretVault::class)->put('stripe.webhook_secret', 'whsec_from_console', Operator::factory()->create());
expect(StripeWebhookSecret::current())->toBe('whsec_from_console');
});
it('keeps the two modes apart, stored just as in the server file', function () {
// Der Grund, warum es überhaupt zwei Werte gibt: Stripe stellt je
// Betriebsmodus ein eigenes Signaturgeheimnis aus. Ein Platz, der auf den
// anderen zurückfällt, würde ein Testereignis mit dem Live-Schlüssel
// prüfen — es scheitert, aber die Konsole sagt „gesetzt".
$by = Operator::factory()->create();
$vault = app(SecretVault::class);
$vault->put('stripe.webhook_secret', 'whsec_test_slot', $by, OperatingMode::Test);
$vault->put('stripe.webhook_secret', 'whsec_live_slot', $by, OperatingMode::Live);
OperatingMode::set(OperatingMode::Test);
expect(StripeWebhookSecret::current())->toBe('whsec_test_slot');
OperatingMode::set(OperatingMode::Live);
expect(StripeWebhookSecret::current())->toBe('whsec_live_slot');
});
it('still reads the server file when nothing is stored, per mode', function () {
// Eine bestehende Installation hat beide Zeilen in der .env und darf sich
// durch diesen Umzug nicht ändern — sonst weist sie ab morgen jedes
// eingehende Zahlungsereignis ab.
config()->set('services.stripe.webhook_secret', 'whsec_live_env');
config()->set('services.stripe.webhook_secret_test', 'whsec_test_env');
OperatingMode::set(OperatingMode::Test);
expect(StripeWebhookSecret::current())->toBe('whsec_test_env');
OperatingMode::set(OperatingMode::Live);
expect(StripeWebhookSecret::current())->toBe('whsec_live_env');
});
it('does not call an unset slot "from the server file" when the server file is empty for that mode', function () {
// Die Herkunftsplakette auf der Karte muss zum Wert gehören, der WIRKLICH
// gilt — genau der Fehler, den source() für dns.token schon einmal hatte.
config()->set('services.stripe.webhook_secret', 'whsec_live_env');
config()->set('services.stripe.webhook_secret_test', '');
OperatingMode::set(OperatingMode::Test);
expect(app(SecretVault::class)->source('stripe.webhook_secret'))->toBe('none')
->and(StripeWebhookSecret::current())->toBe('');
});
it('reports the source as the server file when that mode does have a line', function () {
config()->set('services.stripe.webhook_secret_test', 'whsec_test_env');
OperatingMode::set(OperatingMode::Test);
expect(app(SecretVault::class)->source('stripe.webhook_secret'))->toBe('environment');
});
it('offers the signing secret as a field on the payments card', function () {
Livewire::actingAs(operator('Owner'), 'operator')
->test(Integrations::class)
->set('confirmablePassword', 'password')
->call('confirmPassword')
->assertSee('STRIPE_WEBHOOK_SECRET');
});
it('sends the readiness check to that card instead of the raw .env editor', function () {
foreach (BillingChecks::all() as $check) {
if ($check->key === 'billing.stripe_webhook_secret') {
expect($check->tab)->toBe('services');
return;
}
}
throw new RuntimeException('billing.stripe_webhook_secret check is gone');
});