Files
nexus/internal/models/defaults.go
T
2026-06-17 08:55:56 +01:00

390 lines
9.4 KiB
Go

package models
import (
"time"
"github.com/google/uuid"
)
// Default port numbers for each protocol.
const (
DefaultSSHPort = 22
DefaultTelnetPort = 23
DefaultRAWPort = 23
DefaultGitHubPort = 443
DefaultVNCPort = 5900
DefaultIRCPort = 6667
DefaultIRCTLSPort = 6697
)
// Default timeout values (in seconds).
const (
DefaultConnectTimeout = 30
DefaultReadTimeout = 0 // no timeout
)
// Default terminal rendering settings.
const (
DefaultScrollback = 10000
DefaultFontSize = 14
DefaultFontFamily = "JetBrains Mono, Menlo, Monaco, Consolas, monospace"
DefaultCursorStyle = "block"
DefaultTerminalType = "xterm-256color"
)
// Default SSH keepalive settings.
const (
DefaultKeepaliveInterval = 30
DefaultKeepaliveCountMax = 3
)
// DefaultAppPreferences returns sensible default application preferences.
func DefaultAppPreferences() AppPreferences {
return AppPreferences{
Theme: "dark",
TerminalTheme: "charcoal",
DefaultProtocol: string(ProtocolSSH),
ConfirmOnClose: true,
ConfirmOnDisconnect: true,
ShowStatusBar: true,
SidebarWidth: 280,
DefaultFontFamily: DefaultFontFamily,
DefaultFontSize: DefaultFontSize,
DefaultScrollback: DefaultScrollback,
DefaultCursorStyle: DefaultCursorStyle,
UseNativePaste: false,
LocalShell: "", // empty means use system default
}
}
// NewProfile creates a new Profile with sensible defaults for the given protocol.
func NewProfile(protocol Protocol) Profile {
now := time.Now()
p := Profile{
ID: uuid.New().String(),
Protocol: protocol,
Tags: []string{},
ConnectTimeout: DefaultConnectTimeout,
ReadTimeout: DefaultReadTimeout,
TerminalFontFamily: DefaultFontFamily,
TerminalFontSize: DefaultFontSize,
TerminalScrollback: DefaultScrollback,
TerminalCursorStyle: DefaultCursorStyle,
CreatedAt: now,
UpdatedAt: now,
}
switch protocol {
case ProtocolSSH:
p.Port = DefaultSSHPort
p.SSH = &SSHConfig{
AuthMethods: []string{"publickey", "password", "keyboard-interactive"},
SecretMode: SecretModeSaved,
KeySecretMode: SecretModeSaved,
HostKeyPolicy: HostKeyAsk,
TerminalType: DefaultTerminalType,
KeepaliveInterval: DefaultKeepaliveInterval,
KeepaliveCountMax: DefaultKeepaliveCountMax,
JumpHosts: []JumpHost{},
PortForwards: []PortForward{},
EnvVars: map[string]string{},
}
case ProtocolTelnet:
p.Port = DefaultTelnetPort
p.Telnet = &TelnetConfig{
LocalEcho: false,
LineEnding: LineEndingCRLF,
TerminalType: DefaultTerminalType,
Encoding: "utf-8",
}
case ProtocolRAW:
p.Port = DefaultRAWPort
p.RAW = &RAWConfig{
LineEnding: LineEndingCRLF,
Encoding: "utf-8",
PayloadPresets: []PayloadPreset{},
}
case ProtocolGitHub:
p.Port = DefaultGitHubPort
p.Host = "github.com"
p.GitHub = &GitHubConfig{
BaseURL: "https://api.github.com",
SecretMode: SecretModeSaved,
RefreshIntervalSecs: 300,
}
case ProtocolVNC:
p.Port = DefaultVNCPort
p.VNC = &VNCConfig{
VNCPort: DefaultVNCPort,
SecretMode: SecretModeSaved,
ScaleToFit: true,
SharedSession: true,
Quality: 6,
SSHPort: DefaultSSHPort,
SSHAuthMethod: "publickey",
SSHSecretMode: SecretModeSaved,
}
case ProtocolIRC:
p.Port = DefaultIRCPort
p.IRC = &IRCConfig{
Nick: "nexus",
RealName: "Nexus Terminal",
ServerPasswordMode: SecretModeAskEveryTime,
NickServMode: SecretModeSaved,
AutoJoinRooms: []string{},
SSHPort: DefaultSSHPort,
SSHAuthMethod: "publickey",
SSHSecretMode: SecretModeSaved,
AutoReconnect: true,
}
}
return p
}
// NormalizeProfileDefaults fills missing default values on profiles loaded
// from older exports, third-party imports, or sparse frontend payloads.
func NormalizeProfileDefaults(p *Profile) {
if p == nil {
return
}
if p.Protocol == "" {
p.Protocol = ProtocolSSH
}
defaults := NewProfile(p.Protocol)
if p.ID == "" {
p.ID = defaults.ID
}
if p.Tags == nil {
p.Tags = []string{}
}
if p.ConnectTimeout == 0 {
p.ConnectTimeout = DefaultConnectTimeout
}
if p.TerminalFontFamily == "" {
p.TerminalFontFamily = DefaultFontFamily
}
if p.TerminalFontSize == 0 {
p.TerminalFontSize = DefaultFontSize
}
if p.TerminalScrollback == 0 {
p.TerminalScrollback = DefaultScrollback
}
if p.TerminalCursorStyle == "" {
p.TerminalCursorStyle = DefaultCursorStyle
}
if p.CreatedAt.IsZero() {
p.CreatedAt = defaults.CreatedAt
}
if p.UpdatedAt.IsZero() {
p.UpdatedAt = defaults.UpdatedAt
}
if p.Port == 0 {
p.Port = defaults.Port
}
if p.DisplayName == "" {
p.DisplayName = defaultProfileName(p)
}
switch p.Protocol {
case ProtocolSSH:
normalizeSSHConfig(p, defaults.SSH)
case ProtocolTelnet:
normalizeTelnetConfig(p, defaults.Telnet)
case ProtocolRAW:
normalizeRAWConfig(p, defaults.RAW)
case ProtocolGitHub:
if p.Host == "" {
p.Host = defaults.Host
}
normalizeGitHubConfig(p, defaults.GitHub)
case ProtocolVNC:
normalizeVNCConfig(p, defaults.VNC)
case ProtocolIRC:
normalizeIRCConfig(p, defaults.IRC)
}
}
func defaultProfileName(p *Profile) string {
if p.Host != "" {
return p.Host
}
if p.VNC != nil && p.VNC.VNCHost != "" {
return p.VNC.VNCHost
}
switch p.Protocol {
case ProtocolGitHub:
return "GitHub"
case ProtocolVNC:
return "VNC"
case ProtocolIRC:
return "IRC"
case ProtocolRAW:
return "RAW TCP"
case ProtocolTelnet:
return "Telnet"
default:
return "SSH"
}
}
func normalizeSecretMode(mode SecretMode, fallback SecretMode) SecretMode {
switch mode {
case SecretModeSaved, SecretModeSessionOnly, SecretModeAskEveryTime:
return mode
case "prompt":
return SecretModeAskEveryTime
case "":
return fallback
default:
return mode
}
}
func normalizeSSHConfig(p *Profile, defaults *SSHConfig) {
if p.SSH == nil {
cfg := *defaults
p.SSH = &cfg
return
}
cfg := p.SSH
if len(cfg.AuthMethods) == 0 {
cfg.AuthMethods = append([]string{}, defaults.AuthMethods...)
}
cfg.SecretMode = normalizeSecretMode(cfg.SecretMode, defaults.SecretMode)
cfg.KeySecretMode = normalizeSecretMode(cfg.KeySecretMode, defaults.KeySecretMode)
if cfg.HostKeyPolicy == "" {
cfg.HostKeyPolicy = defaults.HostKeyPolicy
}
if cfg.TerminalType == "" {
cfg.TerminalType = defaults.TerminalType
}
if cfg.KeepaliveInterval == 0 {
cfg.KeepaliveInterval = defaults.KeepaliveInterval
}
if cfg.KeepaliveCountMax == 0 {
cfg.KeepaliveCountMax = defaults.KeepaliveCountMax
}
if cfg.JumpHosts == nil {
cfg.JumpHosts = []JumpHost{}
}
if cfg.PortForwards == nil {
cfg.PortForwards = []PortForward{}
}
if cfg.EnvVars == nil {
cfg.EnvVars = map[string]string{}
}
}
func normalizeTelnetConfig(p *Profile, defaults *TelnetConfig) {
if p.Telnet == nil {
cfg := *defaults
p.Telnet = &cfg
return
}
cfg := p.Telnet
if cfg.LineEnding == "" {
cfg.LineEnding = defaults.LineEnding
}
if cfg.TerminalType == "" {
cfg.TerminalType = defaults.TerminalType
}
if cfg.Encoding == "" {
cfg.Encoding = defaults.Encoding
}
}
func normalizeRAWConfig(p *Profile, defaults *RAWConfig) {
if p.RAW == nil {
cfg := *defaults
p.RAW = &cfg
return
}
cfg := p.RAW
if cfg.LineEnding == "" {
cfg.LineEnding = defaults.LineEnding
}
if cfg.Encoding == "" {
cfg.Encoding = defaults.Encoding
}
if cfg.PayloadPresets == nil {
cfg.PayloadPresets = []PayloadPreset{}
}
for i := range cfg.PayloadPresets {
if cfg.PayloadPresets[i].ID == "" {
cfg.PayloadPresets[i].ID = uuid.New().String()
}
if cfg.PayloadPresets[i].Format == "" {
cfg.PayloadPresets[i].Format = "text"
}
}
}
func normalizeGitHubConfig(p *Profile, defaults *GitHubConfig) {
if p.GitHub == nil {
cfg := *defaults
p.GitHub = &cfg
return
}
cfg := p.GitHub
if cfg.BaseURL == "" {
cfg.BaseURL = defaults.BaseURL
}
cfg.SecretMode = normalizeSecretMode(cfg.SecretMode, defaults.SecretMode)
if cfg.RefreshIntervalSecs == 0 {
cfg.RefreshIntervalSecs = defaults.RefreshIntervalSecs
}
}
func normalizeVNCConfig(p *Profile, defaults *VNCConfig) {
if p.VNC == nil {
cfg := *defaults
p.VNC = &cfg
return
}
cfg := p.VNC
if cfg.VNCPort == 0 {
cfg.VNCPort = defaults.VNCPort
}
cfg.SecretMode = normalizeSecretMode(cfg.SecretMode, defaults.SecretMode)
if cfg.Quality < 0 {
cfg.Quality = defaults.Quality
}
if cfg.SSHPort == 0 {
cfg.SSHPort = defaults.SSHPort
}
if cfg.SSHAuthMethod == "" {
cfg.SSHAuthMethod = defaults.SSHAuthMethod
}
cfg.SSHSecretMode = normalizeSecretMode(cfg.SSHSecretMode, defaults.SSHSecretMode)
}
func normalizeIRCConfig(p *Profile, defaults *IRCConfig) {
if p.IRC == nil {
cfg := *defaults
cfg.AutoJoinRooms = append([]string{}, defaults.AutoJoinRooms...)
p.IRC = &cfg
return
}
cfg := p.IRC
if cfg.Nick == "" {
cfg.Nick = defaults.Nick
}
if cfg.RealName == "" {
cfg.RealName = defaults.RealName
}
cfg.ServerPasswordMode = normalizeSecretMode(cfg.ServerPasswordMode, defaults.ServerPasswordMode)
cfg.NickServMode = normalizeSecretMode(cfg.NickServMode, defaults.NickServMode)
if cfg.AutoJoinRooms == nil {
cfg.AutoJoinRooms = []string{}
}
if cfg.SSHPort == 0 {
cfg.SSHPort = defaults.SSHPort
}
if cfg.SSHAuthMethod == "" {
cfg.SSHAuthMethod = defaults.SSHAuthMethod
}
cfg.SSHSecretMode = normalizeSecretMode(cfg.SSHSecretMode, defaults.SSHSecretMode)
}