authorize('secrets.manage'); } public function save(string $key): void { $this->guard(); $field = self::field($key); $value = trim((string) ($this->entered[$field] ?? '')); if ($value === '') { $this->addError('entered.'.$field, __('secrets.empty')); return; } try { app(SecretVault::class)->put($key, $value, auth()->user()); } catch (Throwable $e) { $this->addError('entered.'.$field, $e->getMessage()); return; } // Out of the component state as soon as it is stored. $this->entered[$field] = ''; $this->check = null; $this->dispatch('notify', message: __('secrets.saved')); } public function forget(string $key): void { $this->guard(); app(SecretVault::class)->forget($key); $this->check = null; $this->dispatch('notify', message: __('secrets.removed')); } /** * Try the key that is in force — or the one being typed, before storing it. * * Checking the candidate first is the point: a key that is saved and wrong * fails later, somewhere else, usually in front of a customer. */ public function test(string $key): void { $this->guard(); $candidate = trim((string) ($this->entered[self::field($key)] ?? '')) ?: null; $this->check = app(StripeCheck::class)->run($candidate); } /** The dotless form key for a registry key. */ public static function field(string $key): string { return str_replace('.', '_', $key); } /** Capability AND a recent password, on every single action. */ private function guard(): void { $this->authorize('secrets.manage'); abort_unless($this->passwordRecentlyConfirmed(), 403); } public function render() { $vault = app(SecretVault::class); $unlocked = $this->passwordRecentlyConfirmed(); return view('livewire.admin.secrets', [ 'unlocked' => $unlocked, 'usable' => $vault->isUsable(), 'entries' => collect(SecretVault::REGISTRY) ->map(fn (array $meta, string $key) => [ 'key' => $key, 'field' => self::field($key), 'label' => $meta['label'], 'source' => $vault->source($key), // Only ever an outline, and only once unlocked. 'outline' => $unlocked ? $vault->outline($key) : null, 'updated_at' => $unlocked ? $vault->updatedAt($key) : null, ]) ->values() ->all(), ]); } }