internal/httpd/control.go
75 lines · 2067 bytes
1package httpd
2
3import (
4 "bytes"
5 "encoding/json"
6 "strings"
7
8 "gitbay.org/gitbay/internal/control"
9 "gitbay.org/gitbay/internal/protocol"
10 "gitbay.org/gitbay/internal/store"
11)
12
13// runControl executes a control command as the browser session's user,
14// through the same registry the CLI and the JSON API reach. Web writes
15// never reimplement command logic — merge gates, review rules, and audit
16// entries stay in one place — so the surfaces cannot drift apart.
17//
18// ViaAPI is set, which refuses SSHOnly commands: anything whose input is a
19// credential (secrets, mirror tokens, session minting) stays on SSH.
20func (s *Server) runControl(u store.User, argv []string) (out string, msg string, ok bool) {
21 var stdout, stderr bytes.Buffer
22 ctx := &control.Ctx{
23 User: u,
24 Source: "web",
25 Scope: "full",
26 Store: s.st,
27 Cfg: s.cfg,
28 Stdin: strings.NewReader(""),
29 Stdout: &stdout,
30 Stderr: &stderr,
31 ViaAPI: true,
32 }
33 code := control.Dispatch(ctx, argv)
34 m := strings.TrimSpace(stderr.String())
35 if m == "" {
36 m = strings.TrimSpace(stdout.String())
37 }
38 return stdout.String(), m, code == protocol.ExitOK
39}
40
41// runControlJSON runs a command in JSON mode and returns its data object.
42// In JSON mode a failure is an envelope carrying the message rather than
43// stderr text, so both paths are read from the same envelope.
44func (s *Server) runControlJSON(u store.User, argv []string) (data map[string]any, msg string, ok bool) {
45 var stdout, stderr bytes.Buffer
46 ctx := &control.Ctx{
47 User: u,
48 Source: "web",
49 Scope: "full",
50 Store: s.st,
51 Cfg: s.cfg,
52 Stdin: strings.NewReader(""),
53 Stdout: &stdout,
54 Stderr: &stderr,
55 JSON: true,
56 ViaAPI: true,
57 }
58 code := control.Dispatch(ctx, argv)
59 var env struct {
60 Data map[string]any `json:"data"`
61 Error string `json:"error"`
62 }
63 json.Unmarshal(stdout.Bytes(), &env)
64 if code != protocol.ExitOK {
65 m := env.Error
66 if m == "" {
67 m = strings.TrimSpace(stderr.String())
68 }
69 if m == "" {
70 m = "the command failed"
71 }
72 return nil, m, false
73 }
74 return env.Data, "", true
75}