Files
tuio/internal/tui/model.go
T
jbandClaude Opus 4.8 d2717de47a refactor: clarify fixed container port with containerAppPort constant
The container always listens on 8080 internally while the user-provided
port is only the host-side mapping. Make this explicit without changing
behavior or the generated config:

- add a named containerAppPort constant and use it in both the docker -p
  mapping and the config.toml generation (was a bare 8080 literal in two
  places)
- document why config.toml hardcodes the port, so it isn't "fixed" back
  to the form value
- relabel the form field to "Porta (host)"

The generated config.toml is byte-identical (port = 8080).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 12:00:54 -03:00

266 lines
6.2 KiB
Go

package tui
import (
"fmt"
"os"
"strconv"
"charm.land/bubbles/v2/spinner"
tea "charm.land/bubbletea/v2"
"github.com/BurntSushi/toml"
)
type Model struct {
currentStep step
cursor int
width int
height int
spinner spinner.Model
loading bool
dockerInstalled bool
checkDockerDone bool
checkProgress float64
downloadDone bool
downloadMessage string
downloadError error
loginData DockerLoginData
isPublicIP bool
loginForm FormStep
wireguardForm FormStep
appForm FormStep
serverForm FormStep
dbForm FormStep
certForm FormStep
configValues ConfigValues
finishedFile bool
configFileError error
finishedDockerRun bool
dockerRunError error
err error
}
type DockerLoginData struct {
Login string
Password string
}
type ConfigValues struct {
Login map[string]string
Wireguard map[string]string
Server map[string]string
Database map[string]string
Cert map[string]string
Application map[string]string
}
type AppConfig struct {
Server struct {
Port int64 `toml:"port"`
Timeout int64 `toml:"timeout_seconds"`
Environment string `toml:"environment"`
} `toml:"server"`
Database struct {
Type string `toml:"type"`
URL string `toml:"url"`
MaxConns int64 `toml:"max_conns"`
MinConns int64 `toml:"min_conns"`
} `toml:"database"`
Certificates struct {
DirPath string `toml:"mapped_dir"`
} `toml:"certificate"`
Application struct {
CentralServerURL string `toml:"central_server_url"`
EnrollmentToken string `toml:"enrollment_token"`
} `toml:"application"`
}
func loadConfig() AppConfig {
var config AppConfig
config.Server.Port = 8081
config.Server.Timeout = 30
config.Server.Environment = "production"
config.Database.Type = "postgres"
config.Database.URL = "postgres://usuario:senha@banco:5432/app_dono_db"
config.Database.MaxConns = 10
config.Database.MinConns = 2
config.Certificates.DirPath = "/caminho/para/diretorio"
config.Application.CentralServerURL = "https://servidor:8443"
_, err := os.Stat("config.toml")
if err == nil {
if _, err := toml.DecodeFile("config.toml", &config); err != nil {
fmt.Printf("Error loading config: %v\n", err)
}
}
return config
}
func InitialModel() Model {
cfg := loadConfig()
s := spinner.New()
s.Spinner = spinner.Dot
s.Style = SpinnerStyle
return Model{
currentStep: StepCheckDocker,
loginForm: NewFormStep("Login no Repositório Docker", []FormField{
{
Id: "user",
Label: "Usuário",
Placeholder: "usuario",
Type: FieldTypeText,
},
{
Id: "password",
Label: "Senha",
Placeholder: "senhaForte123",
Type: FieldTypePassword,
},
}),
wireguardForm: NewFormStep("Configurações vproxy", []FormField{
{
Id: "privkey",
Label: "Chave Privada",
Placeholder: "",
Type: FieldTypeText,
},
{
Id: "vip",
Label: "IP Virtual",
Default: "127.0.0.1",
Placeholder: "127.0.0.1",
Type: FieldTypeText,
},
{
Id: "psk",
Label: "Pre-Shared Key",
Placeholder: "",
Type: FieldTypeText,
},
{
Id: "proxy_edps",
Label: "Proxy EDPS",
Placeholder: "22:127.0.0.1:22",
Type: FieldTypeText,
},
{
Id: "mtu",
Label: "MTU",
Default: "1380",
Placeholder: "1380",
Type: FieldTypeNumber,
},
{
Id: "proto",
Label: "Protocolo",
Default: "UDP",
Type: FieldTypeSelect,
Options: []string{"UDP", "TCP"},
},
}),
serverForm: NewFormStep("Servidor", []FormField{
{
Id: "port",
Label: "Porta (host)",
Placeholder: "8081",
Default: strconv.FormatInt(cfg.Server.Port, 10),
Type: FieldTypeNumber,
CharLimit: 4,
},
{
Id: "timeout",
Label: "Timeout (Segundos)",
Placeholder: "30",
Default: strconv.FormatInt(cfg.Server.Timeout, 10),
Type: FieldTypeNumber,
CharLimit: 3,
},
{
Id: "environment",
Label: "Ambiente",
Default: cfg.Server.Environment,
Type: FieldTypeSelect,
Options: []string{"development", "production"},
},
{
Id: "seccomp_unconfined",
Label: "Modo Compatibilidade (máquinas antigas)",
Default: "Não",
Type: FieldTypeSelect,
Options: []string{"Não", "Sim"},
},
}),
dbForm: NewFormStep("Banco de Dados", []FormField{
{
Id: "database_type",
Label: "Tipo do Banco",
Default: cfg.Database.Type,
Type: FieldTypeSelect,
Options: []string{"postgres", "oracle"},
},
{
Id: "database_url",
Label: "URL de acesso",
Placeholder: "postgres://usuario:senha@banco:5432/app_dono_db",
Default: cfg.Database.URL,
Type: FieldTypeText,
},
{
Id: "max_conns",
Label: "Conexões ativas (máximo)",
Placeholder: "10",
Default: strconv.FormatInt(cfg.Database.MaxConns, 10),
Type: FieldTypeNumber,
},
{
Id: "min_conns",
Label: "Conexões ativas (mínimo)",
Placeholder: "2",
Default: strconv.FormatInt(cfg.Database.MinConns, 10),
Type: FieldTypeNumber,
},
}),
appForm: NewFormStep("Aplicação", []FormField{
{
Id: "central_server_url",
Label: "URL do Servidor Central",
Placeholder: "https://app-dono-api.vitruvio.com.br:8443",
Default: cfg.Application.CentralServerURL,
Type: FieldTypeText,
},
{
Id: "enrollment_token",
Label: "Token de Inscrição",
Placeholder: "token gerado no painel web",
Default: cfg.Application.EnrollmentToken,
Type: FieldTypeText,
},
}),
certForm: NewFormStep("Certificado", []FormField{
{
Id: "cert_dir_path",
Label: "Diretório para armazenar certificados",
Placeholder: "/caminho/para/diretorio",
Default: cfg.Certificates.DirPath,
Type: FieldTypeText,
},
}),
spinner: s,
}
}
func (m Model) Init() tea.Cmd {
return tea.Batch(CheckDockerCmd(), TickCmd(), m.spinner.Tick)
}