internal/httpd/settings.go

251a71053c93d2621ad97fa7d1ce8efacb119406
gitbay/internal/httpd/settings.go history · blame · raw

118 lines · 3589 bytes

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