1package server
2
3import (
4 "bytes"
5 "errors"
6 "os"
7 "strings"
8 "testing"
9 "time"
10
11 "github.com/charmbracelet/soft-serve/proto"
12 cm "github.com/charmbracelet/soft-serve/server/cmd"
13 "github.com/charmbracelet/soft-serve/server/config"
14 bm "github.com/charmbracelet/wish/bubbletea"
15 "github.com/charmbracelet/wish/testsession"
16 "github.com/gliderlabs/ssh"
17 "github.com/matryer/is"
18 "github.com/muesli/termenv"
19 gossh "golang.org/x/crypto/ssh"
20)
21
22func TestSession(t *testing.T) {
23 is := is.New(t)
24 t.Run("unauthorized repo access", func(t *testing.T) {
25 var out bytes.Buffer
26 s := setup(t)
27 s.Stderr = &out
28 defer s.Close()
29 err := s.RequestPty("xterm", 80, 40, nil)
30 is.NoErr(err)
31 err = s.Run("config")
32 // Session writes error and exits
33 is.True(strings.Contains(out.String(), cm.ErrUnauthorized.Error()))
34 var ee *gossh.ExitError
35 is.True(errors.As(err, &ee) && ee.ExitStatus() == 1)
36 })
37 t.Run("authorized repo access", func(t *testing.T) {
38 s := setup(t)
39 s.Stderr = os.Stderr
40 defer s.Close()
41 err := s.RequestPty("xterm", 80, 40, nil)
42 is.NoErr(err)
43 go func() {
44 time.Sleep(1 * time.Second)
45 s.Signal(gossh.SIGTERM)
46 // FIXME: exit with code 0 instead of forcibly closing the session
47 s.Close()
48 }()
49 err = s.Run("test")
50 var ee *gossh.ExitMissingError
51 is.True(errors.As(err, &ee))
52 })
53}
54
55func setup(tb testing.TB) *gossh.Session {
56 tb.Helper()
57 cfg := &config.Config{
58 Host: "",
59 SSH: config.SSHConfig{Port: randomPort()},
60 Git: config.GitConfig{Port: 9418},
61 DataPath: tb.TempDir(),
62 InitialAdminKeys: []string{
63 "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMJlb/qf2B2kMNdBxfpCQqI2ctPcsOkdZGVh5zTRhKtH",
64 },
65 AnonAccess: proto.ReadOnlyAccess,
66 }
67 return testsession.New(tb, &ssh.Server{
68 Handler: bm.MiddlewareWithProgramHandler(SessionHandler(cfg), termenv.ANSI256)(func(s ssh.Session) {
69 _, _, active := s.Pty()
70 tb.Logf("PTY active %v", active)
71 tb.Log(s.Command())
72 s.Exit(0)
73 }),
74 }, nil)
75}