103 lines
3.7 KiB
PHP
103 lines
3.7 KiB
PHP
<?php
|
|
|
|
use App\Livewire\Admin\Secrets as SecretsPage;
|
|
use App\Services\Secrets\SecretVault;
|
|
use Livewire\Livewire;
|
|
|
|
/**
|
|
* The credentials page has two gates, and the second one is the point.
|
|
*
|
|
* The capability decides who may open it. The password decides whether THIS
|
|
* session may see or change anything — because the realistic threat is not a
|
|
* stranger but an unlocked machine, and a session is exactly what that gives
|
|
* away.
|
|
*/
|
|
|
|
beforeEach(function () {
|
|
config()->set('admin_access.secrets_key', 'base64:'.base64_encode(random_bytes(32)));
|
|
});
|
|
|
|
it('is not reachable without the capability', function () {
|
|
// Every operator has console.view. That must not mean "can read the
|
|
// payment key".
|
|
Livewire::actingAs(operator('Admin'))
|
|
->test(SecretsPage::class)
|
|
->assertForbidden();
|
|
});
|
|
|
|
it('shows nothing until the password is confirmed', function () {
|
|
$owner = operator('Owner');
|
|
app(SecretVault::class)->put('stripe.secret', 'sk_live_ABCDEFGH9999', $owner);
|
|
|
|
$page = Livewire::actingAs($owner)->test(SecretsPage::class);
|
|
|
|
$page->assertSee(__('secrets.locked_title'))
|
|
// Not even the outline before unlocking.
|
|
->assertDontSee('9999')
|
|
->assertViewHas('unlocked', false);
|
|
});
|
|
|
|
it('refuses every action while locked, not merely hiding the buttons', function () {
|
|
// A Livewire action is reachable by anyone who can post to /livewire/update.
|
|
$owner = operator('Owner');
|
|
|
|
foreach ([['save', 'stripe.secret'], ['forget', 'stripe.secret'], ['test', 'stripe.secret']] as [$action, $arg]) {
|
|
Livewire::actingAs($owner)
|
|
->test(SecretsPage::class)
|
|
->call($action, $arg)
|
|
->assertForbidden();
|
|
}
|
|
});
|
|
|
|
it('unlocks with the password, then stores and clears the entered value', function () {
|
|
$owner = operator('Owner');
|
|
|
|
$page = Livewire::actingAs($owner)
|
|
->test(SecretsPage::class)
|
|
->set('confirmablePassword', 'password')
|
|
->call('confirmPassword')
|
|
->assertHasNoErrors()
|
|
->assertViewHas('unlocked', true);
|
|
|
|
$page->set('entered.stripe_secret', 'sk_live_NEWKEY1234')
|
|
->call('save', 'stripe.secret')
|
|
->assertHasNoErrors();
|
|
|
|
expect(app(SecretVault::class)->get('stripe.secret'))->toBe('sk_live_NEWKEY1234')
|
|
// Out of the component state as soon as it is stored: a Livewire
|
|
// property travels to the browser and back in the snapshot.
|
|
->and($page->get('entered')['stripe_secret'])->toBe('');
|
|
});
|
|
|
|
it('never puts a stored secret into the component snapshot', function () {
|
|
$owner = operator('Owner');
|
|
app(SecretVault::class)->put('stripe.secret', 'sk_live_TOPSECRET42', $owner);
|
|
|
|
$page = Livewire::actingAs($owner)
|
|
->test(SecretsPage::class)
|
|
->set('confirmablePassword', 'password')
|
|
->call('confirmPassword');
|
|
|
|
expect(json_encode($page->snapshot))->not->toContain('sk_live_TOPSECRET42');
|
|
});
|
|
|
|
it('can be locked again without signing out', function () {
|
|
$owner = operator('Owner');
|
|
|
|
Livewire::actingAs($owner)
|
|
->test(SecretsPage::class)
|
|
->set('confirmablePassword', 'password')
|
|
->call('confirmPassword')
|
|
->assertViewHas('unlocked', true)
|
|
->call('forgetPasswordConfirmation')
|
|
->assertViewHas('unlocked', false);
|
|
});
|
|
|
|
it('binds the form to a key Livewire can actually write to', function () {
|
|
// A dot in a Livewire property path means nesting, so a registry key with a
|
|
// dot in it would be written to entered['stripe']['secret'] and the value
|
|
// would never reach the save.
|
|
expect(App\Livewire\Admin\Secrets::field('stripe.secret'))->toBe('stripe_secret')
|
|
->and(str_contains(App\Livewire\Admin\Secrets::field('stripe.secret'), '.'))->toBeFalse();
|
|
});
|