repos / git-pr

a self-hosted git collaboration server
git clone https://github.com/picosh/git-pr.git

git-pr / util
Eric Bower  ·  2024-10-23

util.go

  1package util
  2
  3import (
  4	"crypto/ed25519"
  5	"crypto/rand"
  6	"fmt"
  7	"io"
  8	"os"
  9	"path/filepath"
 10	"strings"
 11
 12	"golang.org/x/crypto/ssh"
 13)
 14
 15func CreateTmpDir() string {
 16	tmp, err := os.MkdirTemp(os.TempDir(), "git-pr*")
 17	if err != nil {
 18		panic(err)
 19	}
 20	return tmp
 21}
 22
 23func CreateCfgFile(dataDir, cfgTmpl string, adminKey UserSSH) string {
 24	cfgPath := filepath.Join(dataDir, "git-pr.toml")
 25	cfgFi, err := os.Create(cfgPath)
 26	if err != nil {
 27		panic(err)
 28	}
 29	_, _ = cfgFi.WriteString(fmt.Sprintf(cfgTmpl, dataDir, adminKey.Public()))
 30	cfgFi.Close()
 31	return cfgPath
 32}
 33
 34type UserSSH struct {
 35	username string
 36	signer   ssh.Signer
 37}
 38
 39func NewUserSSH(username string, signer ssh.Signer) *UserSSH {
 40	return &UserSSH{
 41		username: username,
 42		signer:   signer,
 43	}
 44}
 45
 46func (s UserSSH) Public() string {
 47	pubkey := s.signer.PublicKey()
 48	return string(ssh.MarshalAuthorizedKey(pubkey))
 49}
 50
 51func (s UserSSH) MustCmd(patch []byte, cmd string) string {
 52	res, err := s.Cmd(patch, cmd)
 53	if err != nil {
 54		panic(err)
 55	}
 56	return res
 57}
 58
 59func (s UserSSH) Cmd(patch []byte, cmd string) (string, error) {
 60	host := "localhost:2222"
 61
 62	config := &ssh.ClientConfig{
 63		User: s.username,
 64		Auth: []ssh.AuthMethod{
 65			ssh.PublicKeys(s.signer),
 66		},
 67		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
 68	}
 69
 70	client, err := ssh.Dial("tcp", host, config)
 71	if err != nil {
 72		return "", err
 73	}
 74	defer client.Close()
 75
 76	session, err := client.NewSession()
 77	if err != nil {
 78		return "", err
 79	}
 80	defer session.Close()
 81
 82	stdinPipe, err := session.StdinPipe()
 83	if err != nil {
 84		return "", err
 85	}
 86
 87	stdoutPipe, err := session.StdoutPipe()
 88	if err != nil {
 89		return "", err
 90	}
 91
 92	if err := session.Start(cmd); err != nil {
 93		return "", err
 94	}
 95
 96	if patch != nil {
 97		_, err = stdinPipe.Write(patch)
 98		if err != nil {
 99			return "", err
100		}
101	}
102
103	stdinPipe.Close()
104
105	if err := session.Wait(); err != nil {
106		return "", err
107	}
108
109	buf := new(strings.Builder)
110	_, err = io.Copy(buf, stdoutPipe)
111	if err != nil {
112		return "", err
113	}
114
115	return buf.String(), nil
116}
117
118func GenerateKeys() (UserSSH, UserSSH) {
119	_, adminKey, err := ed25519.GenerateKey(rand.Reader)
120	if err != nil {
121		panic(err)
122	}
123
124	adminSigner, err := ssh.NewSignerFromKey(adminKey)
125	if err != nil {
126		panic(err)
127	}
128
129	_, userKey, err := ed25519.GenerateKey(rand.Reader)
130	if err != nil {
131		panic(err)
132	}
133
134	userSigner, err := ssh.NewSignerFromKey(userKey)
135	if err != nil {
136		panic(err)
137	}
138
139	return UserSSH{
140			username: "admin",
141			signer:   adminSigner,
142		}, UserSSH{
143			username: "contributor",
144			signer:   userSigner,
145		}
146}