-
Notifications
You must be signed in to change notification settings - Fork 123
/
session.go
99 lines (85 loc) · 2.55 KB
/
session.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package ssh
import (
"strings"
"time"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/soft-serve/pkg/access"
"github.com/charmbracelet/soft-serve/pkg/backend"
"github.com/charmbracelet/soft-serve/pkg/config"
"github.com/charmbracelet/soft-serve/pkg/proto"
"github.com/charmbracelet/soft-serve/pkg/ui/common"
"github.com/charmbracelet/ssh"
"github.com/charmbracelet/wish"
"github.com/muesli/termenv"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
var tuiSessionCounter = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: "soft_serve",
Subsystem: "ssh",
Name: "tui_session_total",
Help: "The total number of TUI sessions",
}, []string{"repo", "term"})
var tuiSessionDuration = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: "soft_serve",
Subsystem: "ssh",
Name: "tui_session_seconds_total",
Help: "The total number of TUI sessions",
}, []string{"repo", "term"})
// SessionHandler is the soft-serve bubbletea ssh session handler.
// This middleware must be run after the ContextMiddleware.
func SessionHandler(s ssh.Session) *tea.Program {
pty, _, active := s.Pty()
if !active {
return nil
}
ctx := s.Context()
be := backend.FromContext(ctx)
cfg := config.FromContext(ctx)
cmd := s.Command()
initialRepo := ""
if len(cmd) == 1 {
initialRepo = cmd[0]
auth := be.AccessLevelByPublicKey(ctx, initialRepo, s.PublicKey())
if auth < access.ReadOnlyAccess {
wish.Fatalln(s, proto.ErrUnauthorized)
return nil
}
}
envs := &sessionEnv{s}
output := termenv.NewOutput(s, termenv.WithColorCache(true), termenv.WithEnvironment(envs))
c := common.NewCommon(ctx, output, pty.Window.Width, pty.Window.Height)
c.SetValue(common.ConfigKey, cfg)
m := NewUI(c, initialRepo)
p := tea.NewProgram(m,
tea.WithInput(s),
tea.WithOutput(s),
tea.WithAltScreen(),
tea.WithoutCatchPanics(),
tea.WithMouseCellMotion(),
tea.WithContext(ctx),
)
tuiSessionCounter.WithLabelValues(initialRepo, pty.Term).Inc()
start := time.Now()
go func() {
<-ctx.Done()
tuiSessionDuration.WithLabelValues(initialRepo, pty.Term).Add(time.Since(start).Seconds())
}()
return p
}
var _ termenv.Environ = &sessionEnv{}
type sessionEnv struct {
ssh.Session
}
func (s *sessionEnv) Environ() []string {
pty, _, _ := s.Pty()
return append(s.Session.Environ(), "TERM="+pty.Term)
}
func (s *sessionEnv) Getenv(key string) string {
for _, env := range s.Environ() {
if strings.HasPrefix(env, key+"=") {
return strings.TrimPrefix(env, key+"=")
}
}
return ""
}