internal/httpd/account.go

93b38a063b3b4b161a1baf976e92f53d02b1a221
gitbay/internal/httpd/account.go history · blame · raw

130 lines · 3568 bytes

  1package httpd
  2
  3import (
  4	"encoding/json"
  5	"net/http"
  6	"net/url"
  7	"strings"
  8
  9	"gitbay.org/gitbay/internal/store"
 10)
 11
 12// accountKey is one SSH key as the settings page shows it: enough to
 13// recognise which key this is without printing the whole blob.
 14type accountKey struct {
 15	Fingerprint string
 16	Algo        string
 17	Scope       string
 18}
 19
 20type accountPGP struct {
 21	Fingerprint string
 22	UIDs        []string
 23	Expired     bool
 24	Revoked     bool
 25}
 26
 27// accountForm renders the account's own settings: keys, addresses, and the
 28// commands for everything that stays on SSH.
 29func (s *Server) accountForm(w http.ResponseWriter, r *http.Request, u store.User) {
 30	var keys []accountKey
 31	if list, err := s.st.ListSSHKeys(u.ID); err == nil {
 32		for _, k := range list {
 33			keys = append(keys, accountKey{Fingerprint: k.Fingerprint, Algo: k.Algo, Scope: k.Scope})
 34		}
 35	}
 36	var pgp []accountPGP
 37	if list, err := s.st.ListPGPKeys(u.ID); err == nil {
 38		for _, k := range list {
 39			var uids []string
 40			json.Unmarshal([]byte(k.UIDsJSON), &uids)
 41			pgp = append(pgp, accountPGP{
 42				Fingerprint: k.Fingerprint, UIDs: uids,
 43				Expired: k.ExpiresAt != nil, Revoked: k.RevokedAt != nil,
 44			})
 45		}
 46	}
 47	emails, _ := s.st.ListEmails(u.ID)
 48
 49	s.render(w, "account.html", struct {
 50		basePage
 51		Tab     string // marks the rail's Settings row as current
 52		Keys    []accountKey
 53		PGP     []accountPGP
 54		Emails  []store.Email
 55		Host    string
 56		Notice  string
 57		Message string
 58	}{s.baseFor(u), "account", keys, pgp, emails, s.cfg.SiteHost(),
 59		r.URL.Query().Get("e"), r.URL.Query().Get("m")})
 60}
 61
 62// accountSubmit routes the account forms to their commands. Everything
 63// here is a public key or an address — no secret is accepted over the web.
 64func (s *Server) accountSubmit(w http.ResponseWriter, r *http.Request, u store.User) {
 65	back := func(msg, note string) {
 66		q := ""
 67		switch {
 68		case msg != "":
 69			q = "?e=" + url.QueryEscape(msg)
 70		case note != "":
 71			q = "?m=" + url.QueryEscape(note)
 72		}
 73		http.Redirect(w, r, "/settings"+q, http.StatusSeeOther)
 74	}
 75
 76	switch r.FormValue("field") {
 77	case "key-add":
 78		body := strings.TrimSpace(r.FormValue("key"))
 79		if body == "" {
 80			back("paste a public key in authorized_keys format", "")
 81			return
 82		}
 83		argv := []string{"keys", "add"}
 84		if scope := r.FormValue("scope"); scope == "git" {
 85			argv = append(argv, "--scope", "git")
 86		}
 87		if msg, ok := s.runControlStdin(u, argv, body+"\n"); !ok {
 88			back(msg, "")
 89			return
 90		}
 91		back("", "key registered")
 92	case "key-remove":
 93		if _, msg, ok := s.runControl(u, []string{"keys", "remove", r.FormValue("fingerprint")}); !ok {
 94			back(msg, "")
 95			return
 96		}
 97		back("", "key removed")
 98	case "pgp-add":
 99		body := strings.TrimSpace(r.FormValue("key"))
100		if body == "" {
101			back("paste an armored OpenPGP public key", "")
102			return
103		}
104		if msg, ok := s.runControlStdin(u, []string{"pgp", "add"}, body+"\n"); !ok {
105			back(msg, "")
106			return
107		}
108		back("", "PGP key registered")
109	case "pgp-remove":
110		if _, msg, ok := s.runControl(u, []string{"pgp", "remove", r.FormValue("fingerprint")}); !ok {
111			back(msg, "")
112			return
113		}
114		back("", "PGP key removed")
115	case "email-add":
116		if _, msg, ok := s.runControl(u, []string{"email", "add", strings.TrimSpace(r.FormValue("address"))}); !ok {
117			back(msg, "")
118			return
119		}
120		back("", "check that inbox for a verification code")
121	case "email-verify":
122		if _, msg, ok := s.runControl(u, []string{"email", "verify", strings.TrimSpace(r.FormValue("code"))}); !ok {
123			back(msg, "")
124			return
125		}
126		back("", "address verified")
127	default:
128		back("unknown form", "")
129	}
130}