internal/httpd/settings.go
134 lines · 4402 bytes
1package httpd
2
3import (
4 "fmt"
5 "net/http"
6 "strings"
7
8 "gitbay.org/gitbay/internal/control"
9 "gitbay.org/gitbay/internal/gitutil"
10 "gitbay.org/gitbay/internal/store"
11)
12
13// Repository settings for repo admins. Every control dispatches the
14// command the CLI runs; the page only groups them. Destructive lifecycle
15// — delete and transfer — stays on the CLI, where a typed confirmation
16// is the norm.
17
18type settingsPage struct {
19 repoPage
20 Topics []string
21 Branches []gitutil.Ref
22 DepsEnabled bool
23 Deps control.DepsOut
24 Notice string
25}
26
27func (s *Server) settingsForm(w http.ResponseWriter, r *http.Request, u store.User) {
28 repo, ok := s.repoForUser(w, r, u, policyCanAdmin)
29 if !ok {
30 return
31 }
32 p, ok := s.repoFor(w, r, "")
33 if !ok {
34 return
35 }
36 p.Tab = "settings"
37 topics, _ := s.st.ListTopics(repo.ID)
38 branches, _ := gitutil.Refs(p.Dir, "heads")
39 // The toggle's state comes from the store; what the last run found
40 // comes from the command, so the page shows the same report the CLI
41 // prints (#164).
42 var deps control.DepsOut
43 s.runControlInto(u, []string{"repo", "deps", "status", repo.Path()}, &deps)
44 s.render(w, "settings.html", settingsPage{
45 repoPage: p, Topics: topics, Branches: branches,
46 DepsEnabled: deps.Enabled, Deps: deps,
47 Notice: s.takeFlash(w, r),
48 })
49}
50
51func (s *Server) settingsRedirect(w http.ResponseWriter, r *http.Request, msg string) {
52 dest := fmt.Sprintf("/%s/%s/settings", r.PathValue("owner"), r.PathValue("repo"))
53 s.setFlash(w, msg)
54 http.Redirect(w, r, dest, http.StatusSeeOther)
55}
56
57// settingsSubmit routes one form to its command. Keeping the mapping in
58// one place makes what the page can reach obvious.
59func (s *Server) settingsSubmit(w http.ResponseWriter, r *http.Request, u store.User) {
60 repo := r.PathValue("owner") + "/" + r.PathValue("repo")
61 v := func(k string) string { return strings.TrimSpace(r.FormValue(k)) }
62
63 var argv []string
64 switch r.FormValue("field") {
65 case "description":
66 argv = []string{"repo", "settings", "description", repo, v("description")}
67 case "website":
68 argv = []string{"repo", "settings", "website", repo, v("website")}
69 case "visibility":
70 argv = []string{"repo", "settings", "visibility", repo, v("visibility")}
71 case "default-branch":
72 argv = []string{"repo", "settings", "default-branch", repo, v("default-branch")}
73 case "git-daemon":
74 argv = []string{"repo", "settings", "git-daemon", repo, onOff(v("git-daemon"))}
75 case "require-checks":
76 argv = []string{"repo", "settings", "require-checks", repo, onOff(v("require-checks"))}
77 case "require-resolved":
78 argv = []string{"repo", "settings", "require-resolved", repo, onOff(v("require-resolved"))}
79 case "require-codeowners":
80 argv = []string{"repo", "settings", "require-codeowners", repo, onOff(v("require-codeowners"))}
81 case "require-mr":
82 argv = []string{"repo", "settings", "require-mr", repo, onOff(v("require-mr"))}
83 case "require-signed":
84 argv = []string{"repo", "settings", "require-signed", repo, onOff(v("require-signed"))}
85 case "require-approvals":
86 argv = []string{"repo", "settings", "require-approvals", repo, v("approvals")}
87 case "protect":
88 argv = []string{"repo", "settings", "protect", repo, v("branch")}
89 case "unprotect":
90 argv = []string{"repo", "settings", "unprotect", repo, v("branch")}
91 case "protect-tag":
92 argv = []string{"repo", "settings", "protect-tag", repo, v("glob")}
93 case "unprotect-tag":
94 argv = []string{"repo", "settings", "unprotect-tag", repo, v("glob")}
95 case "deps":
96 verb := "disable"
97 if v("deps") == "on" {
98 verb = "enable"
99 }
100 argv = []string{"repo", "deps", verb, repo}
101 case "archive":
102 verb := "archive"
103 if v("archive") != "on" {
104 verb = "unarchive"
105 }
106 argv = []string{"repo", verb, repo}
107 case "topics":
108 if add := strings.Fields(v("add")); len(add) > 0 {
109 argv = append([]string{"repo", "topics", "add", repo}, add...)
110 } else if rm := strings.Fields(v("remove")); len(rm) > 0 {
111 argv = append([]string{"repo", "topics", "remove", repo}, rm...)
112 } else {
113 s.settingsRedirect(w, r, "name at least one topic")
114 return
115 }
116 default:
117 s.settingsRedirect(w, r, "unknown setting")
118 return
119 }
120
121 _, msg, ok := s.runControl(u, argv)
122 if ok {
123 msg = ""
124 }
125 s.settingsRedirect(w, r, msg)
126}
127
128// onOff normalises a checkbox to the on|off the commands take.
129func onOff(v string) string {
130 if v == "on" || v == "true" {
131 return "on"
132 }
133 return "off"
134}