serverId = $serverId; if ($cred = Server::find($serverId)?->credential) { $this->name = $cred->name ?? ''; $this->username = $cred->username; $this->authType = $cred->auth_type; // secret/passphrase are never pre-filled (encrypted at rest) } } public static function modalMaxWidth(): string { return 'lg'; } public function save(): void { $this->error = null; $server = Server::find($this->serverId); if (! $server) { $this->error = __('common.server_not_found'); return; } if (trim($this->username) === '' || trim($this->secret) === '') { $this->error = __('modals.edit_credential.error_required'); return; } if (mb_strlen(trim($this->name)) > 120) { $this->error = __('modals.edit_credential.error_name_too_long'); return; } $server->credential()->updateOrCreate([], [ 'name' => trim($this->name) !== '' ? trim($this->name) : null, 'username' => trim($this->username), 'auth_type' => $this->authType === 'key' ? 'key' : 'password', 'secret' => $this->secret, // A passphrase only applies to a private key; never store one for password auth. 'passphrase' => ($this->authType === 'key' && $this->passphrase !== '') ? $this->passphrase : null, ]); AuditEvent::create([ 'user_id' => Auth::id(), 'server_id' => $server->id, 'actor' => Auth::user()?->name ?? 'system', 'action' => 'server.credential_updated', 'target' => $server->name.' ยท '.trim($this->username), 'ip' => request()->ip(), ]); $this->dispatch('credentialChanged'); $this->dispatch('notify', message: __('modals.edit_credential.notify_saved')); $this->closeModal(); } public function render() { return view('livewire.modals.edit-credential'); } }