Skip to content

Commit

Permalink
Merge pull request #246 from bobbyrullo/maybe
Browse files Browse the repository at this point in the history
server: better UX when remote ID already exists
  • Loading branch information
bobbyrullo committed Dec 24, 2015
2 parents 9f04875 + dc82882 commit 71f5021
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 52 deletions.
9 changes: 7 additions & 2 deletions server/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"html/template"
"io"
"net/http"
"net/url"
"strings"
Expand Down Expand Up @@ -129,11 +130,15 @@ var connectorDisplayNameMap = map[string]string{
"bitbucket": "Bitbucket",
}

func execTemplate(w http.ResponseWriter, tpl *template.Template, data interface{}) {
type Template interface {
Execute(io.Writer, interface{}) error
}

func execTemplate(w http.ResponseWriter, tpl Template, data interface{}) {
execTemplateWithStatus(w, tpl, data, http.StatusOK)
}

func execTemplateWithStatus(w http.ResponseWriter, tpl *template.Template, data interface{}, status int) {
func execTemplateWithStatus(w http.ResponseWriter, tpl Template, data interface{}, status int) {
w.WriteHeader(status)
if err := tpl.Execute(w, data); err != nil {
log.Errorf("Error loading page: %q", err)
Expand Down
100 changes: 84 additions & 16 deletions server/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,21 @@ type formError struct {
Error string
}

type remoteExistsData struct {
Login string

Register string
}

type registerTemplateData struct {
Error bool
FormErrors []formError
Message string
Email string
Code string
Password string
Local bool
Error bool
FormErrors []formError
Message string
Email string
Code string
Password string
Local bool
RemoteExists *remoteExistsData
}

var (
Expand All @@ -47,8 +54,7 @@ var (
}
)

func handleRegisterFunc(s *Server) http.HandlerFunc {
tpl := s.RegisterTemplate
func handleRegisterFunc(s *Server, tpl Template) http.HandlerFunc {

errPage := func(w http.ResponseWriter, msg string, code string, status int) {
data := registerTemplateData{
Expand Down Expand Up @@ -92,6 +98,46 @@ func handleRegisterFunc(s *Server) http.HandlerFunc {
return
}

var exists bool
exists, err = remoteIdentityExists(s.UserRepo, ses.ConnectorID, ses.Identity.ID)
if err != nil {
internalError(w, err)
return
}

if exists {
// we have to create a new session to be able to run the server.Login function
newSessionKey, err := s.NewSession(ses.ConnectorID, ses.ClientID,
ses.ClientState, ses.RedirectURL, ses.Nonce, false, ses.Scope)
if err != nil {
internalError(w, err)
return
}
// make sure to clean up the old session
if err = s.KillSession(code); err != nil {
internalError(w, err)
}

// finally, we can create a valid redirect URL for them.
redirURL, err := s.Login(ses.Identity, newSessionKey)
if err != nil {
internalError(w, err)
return
}

registerURL := newLoginURLFromSession(
s.IssuerURL, ses, true, []string{}, "")

execTemplate(w, tpl, registerTemplateData{
RemoteExists: &remoteExistsData{
Login: redirURL,
Register: registerURL.String(),
},
})

return
}

// determine whether or not this is a local or remote ID that is going
// to be registered.
idpc, ok := idx[ses.ConnectorID]
Expand Down Expand Up @@ -175,7 +221,7 @@ func handleRegisterFunc(s *Server) http.HandlerFunc {
log.Errorf("Error killing session: %v", err)
}
http.Redirect(w, r, loginURL.String(), http.StatusSeeOther)

return
}

if err != nil {
Expand Down Expand Up @@ -212,17 +258,22 @@ func handleRegisterFunc(s *Server) http.HandlerFunc {
}
}

ru := ses.RedirectURL
q := ru.Query()
q.Set("code", code)
q.Set("state", ses.ClientState)
ru.RawQuery = q.Encode()
w.Header().Set("Location", ru.String())
w.Header().Set("Location", makeClientRedirectURL(
ses.RedirectURL, code, ses.ClientState).String())
w.WriteHeader(http.StatusSeeOther)
return
}
}

func makeClientRedirectURL(baseRedirURL url.URL, code, clientState string) *url.URL {
ru := baseRedirURL
q := ru.Query()
q.Set("code", code)
q.Set("state", clientState)
ru.RawQuery = q.Encode()
return &ru
}

func registerFromLocalConnector(userManager *manager.UserManager, sessionManager *session.SessionManager, ses *session.Session, email, password string) (string, error) {
userID, err := userManager.RegisterWithPassword(email, password, ses.ConnectorID)
if err != nil {
Expand Down Expand Up @@ -304,3 +355,20 @@ func newLoginURLFromSession(issuer url.URL, ses *session.Session, register bool,
loginURL.RawQuery = v.Encode()
return &loginURL
}

func remoteIdentityExists(ur user.UserRepo, connectorID, id string) (bool, error) {
_, err := ur.GetByRemoteIdentity(nil, user.RemoteIdentity{
ConnectorID: connectorID,
ID: id,
})

if err == user.ErrorNotFound {
return false, nil
}

if err == nil {
return true, nil
}

return false, err
}

0 comments on commit 71f5021

Please sign in to comment.