internal/httpd/account.go

332a13feaa444362bb4cc872ca95c62ccafcb64c
gitbay/internal/httpd/account.go history · blame · raw

128 lines · 3518 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		s.takeFlash(w, r), 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		if note != "" {
 68			q = "?m=" + url.QueryEscape(note)
 69		}
 70		s.setFlash(w, msg)
 71		http.Redirect(w, r, "/settings"+q, http.StatusSeeOther)
 72	}
 73
 74	switch r.FormValue("field") {
 75	case "key-add":
 76		body := strings.TrimSpace(r.FormValue("key"))
 77		if body == "" {
 78			back("paste a public key in authorized_keys format", "")
 79			return
 80		}
 81		argv := []string{"keys", "add"}
 82		if scope := r.FormValue("scope"); scope == "git" {
 83			argv = append(argv, "--scope", "git")
 84		}
 85		if msg, ok := s.runControlStdin(u, argv, body+"\n"); !ok {
 86			back(msg, "")
 87			return
 88		}
 89		back("", "key registered")
 90	case "key-remove":
 91		if _, msg, ok := s.runControl(u, []string{"keys", "remove", r.FormValue("fingerprint")}); !ok {
 92			back(msg, "")
 93			return
 94		}
 95		back("", "key removed")
 96	case "pgp-add":
 97		body := strings.TrimSpace(r.FormValue("key"))
 98		if body == "" {
 99			back("paste an armored OpenPGP public key", "")
100			return
101		}
102		if msg, ok := s.runControlStdin(u, []string{"pgp", "add"}, body+"\n"); !ok {
103			back(msg, "")
104			return
105		}
106		back("", "PGP key registered")
107	case "pgp-remove":
108		if _, msg, ok := s.runControl(u, []string{"pgp", "remove", r.FormValue("fingerprint")}); !ok {
109			back(msg, "")
110			return
111		}
112		back("", "PGP key removed")
113	case "email-add":
114		if _, msg, ok := s.runControl(u, []string{"email", "add", strings.TrimSpace(r.FormValue("address"))}); !ok {
115			back(msg, "")
116			return
117		}
118		back("", "check that inbox for a verification code")
119	case "email-verify":
120		if _, msg, ok := s.runControl(u, []string{"email", "verify", strings.TrimSpace(r.FormValue("code"))}); !ok {
121			back(msg, "")
122			return
123		}
124		back("", "address verified")
125	default:
126		back("unknown form", "")
127	}
128}