work/app.go

251 lines
6 KiB
Go

package main
import (
"fmt"
"log"
"os"
"os/exec"
"strings"
"time"
"github.com/charmbracelet/huh"
"golang.org/x/crypto/ssh"
)
type App struct {
cfg Config
flags Flags
tracker *SQLiteTimeTracker // Hinzufügen
}
func NewApp(tracker *SQLiteTimeTracker) (*App, error) {
cfg, err := loadConfig()
if err != nil {
return nil, fmt.Errorf("error loading config: %w", err)
}
return &App{
cfg: cfg,
tracker: tracker, // Speichern
}, nil
}
func (a *App) connect() {
// tw := NewTimeWarrior()
// tw.StartWork()
a.tracker.StartWork()
a.wakeWorkstation()
sshCon, err := a.newSSHConnection()
if err != nil {
log.Fatalf("failed to establish ssh-connection: %v", err)
}
defer sshCon.Close()
sshFowarder := NewPortForwarder(sshCon.client, "2048", "22", a.cfg.WorkstationIP)
go sshFowarder.forward()
rdpFowarder := NewPortForwarder(sshCon.client, "6000", "3389", a.cfg.WorkstationIP)
go rdpFowarder.forward()
a.connectToWorkstation()
}
func (a *App) makeSSHClient() *ssh.ClientConfig {
keypath := os.ExpandEnv("$HOME/.ssh/hegenberg")
keyBytes, err := os.ReadFile(keypath)
if err != nil {
log.Fatalf("Failed to read private key: %s", err)
}
key, err := ssh.ParsePrivateKeyWithPassphrase(keyBytes, []byte(a.cfg.RDPPassword))
if err != nil {
log.Fatalf("Failed to parse private key: %s", err)
}
return &ssh.ClientConfig{
User: a.cfg.SSHUser,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(key),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout: 5 * time.Second,
}
}
func (a *App) runCommand(name string, args ...string) {
cmd := exec.Command(name, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
err := cmd.Run()
if err != nil {
fmt.Println("Error:", err)
}
}
func (a *App) wakeWorkstation() {
sshCommand := fmt.Sprintf("ssh -tt -p %s %s@%s ssh -tt %s@%s \"wakeonlan %s && exit\"",
fmt.Sprintf("%v", a.cfg.SSHPort),
a.cfg.SSHUser,
a.cfg.SSHHost,
a.cfg.JumpUser,
a.cfg.JumpHost,
a.cfg.WorkstationMac)
args := strings.Split(sshCommand, " ")
log.Println(args)
a.runCommand("ssh", args[1:]...)
}
func (a *App) connectToJump() {
sshCommand := fmt.Sprintf("ssh -tt -L 2048:%s:22 %s@%s",
a.cfg.WorkstationHost,
a.cfg.SSHUser,
a.cfg.SSHHost)
args := strings.Split(sshCommand, " ")
a.runCommand("ssh", args[1:]...)
}
func (a *App) connectToWorkstation() {
sshCommand := fmt.Sprintf("ssh -tt -L 6000:%s:3389 -p 2048 %s@127.0.0.1",
a.cfg.WorkstationHost,
a.cfg.SSHUser)
args := strings.Split(sshCommand, " ")
a.runCommand("ssh", args[1:]...)
}
func (a *App) startRDPConnection() {
rdpCommand := fmt.Sprintf("xfreerdp /u:%s /p:%s /v:127.0.0.1:6000 /size:3000x1350",
a.cfg.RDPUser,
a.cfg.RDPPassword)
a.runCommand("bash", "-c", rdpCommand)
}
func (a *App) makeChoice() {
var choice string
// tw := NewTimeWarrior()
form := huh.NewForm(
huh.NewGroup(
huh.NewSelect[string]().
Title("What would you like to do?").
Options(
huh.NewOption("Start Work", "start work"),
huh.NewOption("Stop Work", "stop work"),
huh.NewOption("Show Week Summary", "show week summary"),
huh.NewOption("Show Month Summary", "show month summary"),
huh.NewOption("Start Break", "start break"),
huh.NewOption("Stop Break", "stop break"),
huh.NewOption("Export Timetable", "export"),
huh.NewOption("Connect to Jump", "connect to jump"),
huh.NewOption("Connect to Workstation", "connect to workstation"),
huh.NewOption("Start RDP Connection", "start rdp connection"),
).
Value(&choice),
),
)
err := form.Run()
if err != nil {
fmt.Println("Error:", err)
return
}
switch choice {
case "start work":
a.connect() // connect nutzt jetzt a.tracker
case "stop work":
a.tracker.StopWork()
case "start break":
a.tracker.StartBreak()
case "stop break":
a.tracker.StopBreak()
case "show week summary":
a.tracker.ShowSummary(":week")
case "show month summary":
a.tracker.ShowSummary(":month")
case "export":
if err := a.tracker.ExportSummary(a.flags.ExportName); err != nil {
log.Printf("Error exporting summary: %v", err)
}
}
// switch choice {
// case "start work":
// a.connect()
// case "stop work":
// tw.StopWork()
// case "start break":
// tw.StartBreak()
// case "stop break":
// tw.StopBreak()
// case "show week summary":
// tw.ShowSummary(":week")
// case "show month summary":
// tw.ShowSummary(":month")
// case "connect to jump":
// a.connectToJump()
// case "connect to workstation":
// a.connectToWorkstation()
// case "start rdp connection":
// a.startRDPConnection()
// case "export":
// tw.ExportSummary(a.flags.ExportName)
// }
}
func (a *App) getSSHAuth() ssh.AuthMethod {
keypath := os.ExpandEnv("$HOME/.ssh/hegenberg")
keyBytes, err := os.ReadFile(keypath)
if err != nil {
fmt.Printf("unable to read private key: %v", err)
return nil
}
key, err := ssh.ParsePrivateKeyWithPassphrase(keyBytes, []byte(a.cfg.RDPPassword))
if err != nil {
fmt.Printf("unable to parse privat key: %v", err)
return nil
}
return ssh.PublicKeys(key)
}
func (a *App) newSSHConnection() (*SSHConnection, error) {
config := &ssh.ClientConfig{
User: a.cfg.SSHUser,
Auth: []ssh.AuthMethod{a.getSSHAuth()},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout: 5 * time.Second,
}
client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", a.cfg.SSHHost, a.cfg.SSHPort), config)
if err != nil {
return nil, fmt.Errorf("ssh dial failed: %w", err)
}
session, err := client.NewSession()
if err != nil {
client.Close()
return nil, fmt.Errorf("creating ssh session failed: %w", err)
}
return &SSHConnection{
client: client,
session: session,
}, nil
}
func (a *App) killForwardings() error {
ports := []string{"2048", "6000"}
for _, port := range ports {
cmd := exec.Command("lsof", "-ti", "tcp:"+port)
output, err := cmd.Output()
if err != nil {
continue
}
pids := strings.Split(string(output), "\n")
pid := strings.TrimSpace(pids[0])
killCmd := exec.Command("kill", pid)
killCmd.Run()
}
return nil
}