1package ssh23import (4 "time"56 tea "charm.land/bubbletea/v2"7 "charm.land/wish/v2"8 bm "charm.land/wish/v2/bubbletea"9 "github.com/charmbracelet/soft-serve/pkg/access"10 "github.com/charmbracelet/soft-serve/pkg/backend"11 "github.com/charmbracelet/soft-serve/pkg/config"12 "github.com/charmbracelet/soft-serve/pkg/proto"13 "github.com/charmbracelet/soft-serve/pkg/ui/common"14 "github.com/charmbracelet/ssh"15 "github.com/prometheus/client_golang/prometheus"16 "github.com/prometheus/client_golang/prometheus/promauto"17)1819var tuiSessionCounter = promauto.NewCounterVec(prometheus.CounterOpts{20 Namespace: "soft_serve",21 Subsystem: "ssh",22 Name: "tui_session_total",23 Help: "The total number of TUI sessions",24}, []string{"repo", "term"})2526var tuiSessionDuration = promauto.NewCounterVec(prometheus.CounterOpts{27 Namespace: "soft_serve",28 Subsystem: "ssh",29 Name: "tui_session_seconds_total",30 Help: "The total time spent in TUI sessions",31}, []string{"repo", "term"})3233// SessionHandler is the soft-serve bubbletea ssh session handler.34// This middleware must be run after the ContextMiddleware.35func SessionHandler(s ssh.Session) *tea.Program {36 pty, _, active := s.Pty()37 if !active {38 return nil39 }4041 ctx := s.Context()42 be := backend.FromContext(ctx)43 cfg := config.FromContext(ctx)44 cmd := s.Command()45 initialRepo := ""46 if len(cmd) == 1 {47 initialRepo = cmd[0]48 }4950 auth := be.AccessLevelByPublicKey(ctx, initialRepo, s.PublicKey())51 if auth < access.ReadOnlyAccess {52 wish.Fatalln(s, proto.ErrUnauthorized)53 return nil54 }5556 opts := bm.MakeOptions(s)57 opts = append(opts,58 tea.WithoutCatchPanics(),59 tea.WithContext(ctx),60 tea.WithColorProfile(common.DefaultColorProfile),61 )6263 c := common.NewCommon(ctx, pty.Window.Width, pty.Window.Height)64 c.SetValue(common.ConfigKey, cfg)65 m := NewUI(c, initialRepo)66 p := tea.NewProgram(m, opts...)6768 tuiSessionCounter.WithLabelValues(initialRepo, pty.Term).Inc()6970 start := time.Now()71 go func() {72 <-ctx.Done()73 tuiSessionDuration.WithLabelValues(initialRepo, pty.Term).Add(time.Since(start).Seconds())74 }()7576 return p77}