authorize('site.manage'); // modals bypass the route middleware if ($uuid === null) { return; } $target = ExportTarget::query()->where('uuid', $uuid)->firstOrFail(); $this->uuid = $uuid; $this->name = $target->name; $this->driver = $target->driver; $this->path = $target->path; $this->host = (string) $target->host; $this->port = $target->port ?: 22; $this->username = (string) $target->username; $this->active = (bool) $target->active; $this->hasPassword = $target->secret_key !== null && app(SecretVault::class)->has($target->secret_key); } public function save() { $this->authorize('site.manage'); $rules = [ 'name' => 'required|string|max:120', 'driver' => 'required|in:local,sftp', 'path' => 'required|string|max:255', 'active' => 'boolean', ]; if ($this->driver === ExportTarget::SFTP) { $rules += [ 'host' => 'required|string|max:190', 'port' => 'required|integer|min:1|max:65535', 'username' => 'required|string|max:120', // Required only when there is nothing stored yet. Blank on an // existing target means "unchanged" — the field cannot show // what is stored, so treating blank as a deletion would wipe // the credential on every unrelated edit. 'password' => $this->hasPassword ? 'nullable|string|max:255' : 'required|string|max:255', ]; } $data = $this->validate($rules); $target = $this->uuid !== '' ? ExportTarget::query()->where('uuid', $this->uuid)->firstOrFail() : new ExportTarget; $target->fill([ 'name' => $data['name'], 'driver' => $data['driver'], 'path' => rtrim($data['path'], '/') ?: '/', 'host' => $this->driver === ExportTarget::SFTP ? $this->host : null, 'port' => $this->driver === ExportTarget::SFTP ? $this->port : null, 'username' => $this->driver === ExportTarget::SFTP ? $this->username : null, 'active' => $data['active'] ?? true, ]); $target->save(); if ($this->driver === ExportTarget::SFTP && $this->password !== '') { $key = 'export_target.'.$target->uuid; app(SecretVault::class)->put($key, $this->password, auth('operator')->user()); $target->forceFill(['secret_key' => $key])->save(); } $this->dispatch('notify', message: __('finance.targets_saved')); return $this->redirectRoute('admin.finance', navigate: true); } public function render() { return view('livewire.admin.edit-export-target'); } }