package hub import ( "encoding/json" "errors" "log" "net/http" "net/netip" "strings" "vppn/hub/api" "vppn/m" "git.crumpington.com/lib/go/webutil" "golang.org/x/crypto/bcrypt" ) func (a *App) _root(s *api.Session, w http.ResponseWriter, r *http.Request) error { if s.SignedIn { return a.redirect(w, r, "/admin/config/") } else { return a.redirect(w, r, "/sign-in/") } } func (a *App) _signin(s *api.Session, w http.ResponseWriter, r *http.Request) error { return a.render("/sign-in.html", w, struct{ Session *api.Session }{s}) } func (a *App) _signinSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error { var pwd string err := webutil.NewFormScanner(r.Form). Scan("Password", &pwd). Error() if err != nil { return err } if err := a.api.Session_SignIn(s, pwd); err != nil { return err } return a.redirect(w, r, "/") } func (a *App) _adminSignOut(s *api.Session, w http.ResponseWriter, r *http.Request) error { return a.render("/admin-sign-out.html", w, struct{ Session *api.Session }{s}) } func (a *App) _adminSignOutSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error { if err := a.api.Session_Delete(s.SessionID); err != nil { log.Printf("Failed to delete session cookie %s: %v", s.SessionID, err) } a.deleteCookie(w, SESSION_ID_COOKIE_NAME) return a.redirect(w, r, "/") } func (a *App) _adminConfig(s *api.Session, w http.ResponseWriter, r *http.Request) error { peers, err := a.api.Peer_List() if err != nil { return err } return a.render("/admin-config.html", w, struct { Session *api.Session Peers []*api.Peer Config *api.Config }{ s, peers, a.api.Config_Get(), }) } func (a *App) _adminConfigEdit(s *api.Session, w http.ResponseWriter, r *http.Request) error { return a.render("/admin-config-edit.html", w, struct { Session *api.Session Config *api.Config }{ s, a.api.Config_Get(), }) } func (a *App) _adminConfigEditSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error { var ( conf = a.api.Config_Get() ipStr string ) err := webutil.NewFormScanner(r.Form). Scan("HubAddress", &conf.HubAddress). Scan("VPNNetwork", &ipStr). Error() if err != nil { return err } if conf.VPNNetwork, err = stringToIP(ipStr); err != nil { return err } if err := a.api.Config_Update(conf); err != nil { return err } return a.redirect(w, r, "/admin/config/") } func (a *App) _adminPasswordEdit(s *api.Session, w http.ResponseWriter, r *http.Request) error { return a.render("/admin-password-edit.html", w, struct{ Session *api.Session }{s}) } func (a *App) _adminPasswordSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error { var ( conf = a.api.Config_Get() curPwd string newPwd string newPwd2 string ) err := webutil.NewFormScanner(r.Form). Scan("CurrentPassword", &curPwd). Scan("NewPassword", &newPwd). Scan("NewPassword2", &newPwd2). Error() if err != nil { return err } if len(newPwd) < 8 { return errors.New("password is too short") } if newPwd != newPwd2 { return errors.New("passwords don't match") } err = bcrypt.CompareHashAndPassword(conf.Password, []byte(curPwd)) if err != nil { return err } hash, err := bcrypt.GenerateFromPassword([]byte(newPwd), bcrypt.DefaultCost) if err != nil { return err } if err := a.api.Config_UpdatePassword(hash); err != nil { return err } return a.redirect(w, r, "/admin/config/") } func (a *App) _adminHosts(s *api.Session, w http.ResponseWriter, r *http.Request) error { conf := a.api.Config_Get() peers, err := a.api.Peer_List() if err != nil { return err } b := strings.Builder{} for _, peer := range peers { ip := conf.VPNNetwork ip[3] = peer.PeerIP b.WriteString(netip.AddrFrom4([4]byte(ip)).String()) b.WriteString(" ") b.WriteString(peer.Name) b.WriteString("\n") } w.Write([]byte(b.String())) return nil } func (a *App) _adminPeerCreate(s *api.Session, w http.ResponseWriter, r *http.Request) error { return a.render("/admin-peer-create.html", w, struct{ Session *api.Session }{s}) } func (a *App) _adminPeerCreateSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error { var ipStr string p := &api.Peer{} err := webutil.NewFormScanner(r.Form). Scan("IP", &p.PeerIP). Scan("Name", &p.Name). Scan("PublicIP", &ipStr). Scan("Port", &p.Port). Scan("Relay", &p.Relay). Error() if err != nil { return err } if p.PublicIP, err = stringToIP(ipStr); err != nil { return err } if err := a.api.Peer_CreateNew(p); err != nil { return err } return a.redirect(w, r, "/admin/peer/view/?PeerIP=%d", p.PeerIP) } func (a *App) _adminPeerView(s *api.Session, w http.ResponseWriter, r *http.Request) error { var peerIP byte err := webutil.NewFormScanner(r.Form).Scan("PeerIP", &peerIP).Error() if err != nil { return err } peer, err := a.api.Peer_Get(peerIP) if err != nil { return err } return a.render("/admin-peer-view.html", w, struct { Session *api.Session Peer *api.Peer }{s, peer}) } func (a *App) _adminPeerEdit(s *api.Session, w http.ResponseWriter, r *http.Request) error { var peerIP byte err := webutil.NewFormScanner(r.Form).Scan("PeerIP", &peerIP).Error() if err != nil { return err } peer, err := a.api.Peer_Get(peerIP) if err != nil { return err } return a.render("/admin-peer-edit.html", w, struct { Session *api.Session Peer *api.Peer }{s, peer}) } func (a *App) _adminPeerEditSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error { var ( peerIP byte ipStr string ) err := webutil.NewFormScanner(r.Form).Scan("PeerIP", &peerIP).Error() if err != nil { return err } peer, err := a.api.Peer_Get(peerIP) if err != nil { return err } err = webutil.NewFormScanner(r.Form). Scan("Name", &peer.Name). Scan("PublicIP", &ipStr). Scan("Port", &peer.Port). Scan("Relay", &peer.Relay). Error() if err != nil { return err } if peer.PublicIP, err = stringToIP(ipStr); err != nil { return err } if err = a.api.Peer_Update(peer); err != nil { return err } return a.redirect(w, r, "/admin/peer/view/?PeerIP=%d", peer.PeerIP) } func (a *App) _adminPeerDelete(s *api.Session, w http.ResponseWriter, r *http.Request) error { var peerIP byte err := webutil.NewFormScanner(r.Form).Scan("PeerIP", &peerIP).Error() if err != nil { return err } peer, err := a.api.Peer_Get(peerIP) if err != nil { return err } return a.render("/admin-peer-delete.html", w, struct { Session *api.Session Peer *api.Peer }{s, peer}) } func (a *App) _adminPeerDeleteSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error { var peerIP byte err := webutil.NewFormScanner(r.Form).Scan("PeerIP", &peerIP).Error() if err != nil { return err } if err := a.api.Peer_Delete(peerIP); err != nil { return err } return a.redirect(w, r, "/admin/peer/list/") } func (a *App) _peerInit(peer *api.Peer, w http.ResponseWriter, r *http.Request) error { args := m.PeerInitArgs{} if err := json.NewDecoder(r.Body).Decode(&args); err != nil { return err } conf, err := a.api.Peer_Init(peer, args) if err != nil { return err } return a.sendJSON(w, conf) } func (a *App) _peerFetchState(peer *api.Peer, w http.ResponseWriter, r *http.Request) error { peers, err := a.api.Peer_List() if err != nil { return err } state := m.NetworkState{} for _, p := range peers { if len(p.PubKey) != 0 { state.Peers[p.PeerIP] = &m.Peer{ PeerIP: p.PeerIP, Version: p.Version, Name: p.Name, PublicIP: p.PublicIP, Port: p.Port, Relay: p.Relay, PubKey: p.PubKey, PubSignKey: p.PubSignKey, } } } return a.sendJSON(w, state) }