Implement SSH port forwarding and improve jump host UI

Port Forwarding (new):
- Add PortForward model with local/remote direction, bind/dest addresses
- Implement ForwardManager in sshclient/portforward.go with full
  bidirectional tunnel support for both local and remote forwarding
- Integrate ForwardManager into SSH client lifecycle (auto-start on
  connect, clean shutdown on close)
- Add session manager methods: ListPortForwards, StartPortForward,
  StopPortForward with event emission
- Add API surface: ListPortForwards, StartPortForward, StopPortForward
- Add validation for port-forward rules in ValidateSSHConfig
- Add port forwarding section to profile editor with direction, bind/dest
  host/port, label, and enable toggle
- Add frontend event handling for forward:started/stopped/error
- Style port-forward rows with charcoal card design matching jump hosts

Jump Host UI improvements:
- Add private key path field to jump host editor rows
- Collect privateKeyPath in form value collection
- Restyle jump host rows as two-line cards with clear field grouping
This commit is contained in:
2026-04-16 00:00:00 +01:00
parent 5e397195b9
commit 6d300f7dba
13 changed files with 664 additions and 8 deletions
+19
View File
@@ -624,6 +624,25 @@ func (s *Service) RefreshGitHubRepos(sessionID string) ([]models.GitHubRepo, err
return s.sessions.FetchGitHubRepos(sessionID)
}
// ---------------------------------------------------------------------------
// Port forwarding
// ---------------------------------------------------------------------------
// ListPortForwards returns the active port-forwarding tunnels for an SSH session.
func (s *Service) ListPortForwards(sessionID string) ([]models.PortForward, error) {
return s.sessions.ListPortForwards(sessionID)
}
// StartPortForward activates a new forwarding tunnel on a live SSH session.
func (s *Service) StartPortForward(sessionID string, rule models.PortForward) error {
return s.sessions.StartPortForward(sessionID, rule)
}
// StopPortForward terminates an active forwarding tunnel.
func (s *Service) StopPortForward(sessionID string, forwardID string) error {
return s.sessions.StopPortForward(sessionID, forwardID)
}
// TestConnection performs a basic TCP reachability check to the given host and port.
// This verifies the network path without establishing a full protocol session.
func (s *Service) TestConnection(host string, port int) (map[string]interface{}, error) {