func (r *userRepo) Create(tx repo.Transaction, usr user.User) (err error) { if usr.ID == "" { return user.ErrorInvalidID } _, err = r.get(tx, usr.ID) if err == nil { return user.ErrorDuplicateID } if err != user.ErrorNotFound { return err } if !user.ValidEmail(usr.Email) { return user.ErrorInvalidEmail } // make sure there's no other user with the same Email _, err = r.getByEmail(tx, usr.Email) if err == nil { return user.ErrorDuplicateEmail } if err != user.ErrorNotFound { return err } err = r.insert(tx, usr) return err }
func (r *userRepo) Update(tx repo.Transaction, usr user.User) error { if usr.ID == "" { return user.ErrorInvalidID } if !user.ValidEmail(usr.Email) { return user.ErrorInvalidEmail } // make sure this user exists already _, err := r.get(tx, usr.ID) if err != nil { return err } // make sure there's no other user with the same Email otherUser, err := r.getByEmail(tx, usr.Email) if err != user.ErrorNotFound { if err != nil { return err } if otherUser.ID != usr.ID { return user.ErrorDuplicateEmail } } err = r.update(tx, usr) if err != nil { return err } return nil }
func (m *UserManager) insertNewUser(tx repo.Transaction, email string, emailVerified bool) (user.User, error) { if !user.ValidEmail(email) { return user.User{}, user.ErrorInvalidEmail } var err error if _, err = m.userRepo.GetByEmail(tx, email); err == nil { return user.User{}, user.ErrorDuplicateEmail } if err != user.ErrorNotFound { return user.User{}, err } userID, err := m.userIDGenerator() if err != nil { return user.User{}, err } usr := user.User{ ID: userID, Email: email, EmailVerified: emailVerified, CreatedAt: m.Clock.Now(), } err = m.userRepo.Create(tx, usr) if err != nil { return user.User{}, err } return usr, nil }
func (h *SendResetPasswordEmailHandler) handlePOST(w http.ResponseWriter, r *http.Request) { data := sendResetPasswordEmailData{} h.fillData(r, &data) if !user.ValidEmail(data.Email) { h.errPage(w, "Please supply a valid email addresss.", http.StatusBadRequest, &data) return } data.EmailSent = true execTemplate(w, h.tpl, data) // We spawn this in new goroutine because we don't want anyone using timing // attacks to guess if an email address exists or not. go h.emailer.SendResetPasswordEmail(data.Email, data.RedirectURLParsed, data.ClientID) }
func handleRegisterFunc(s *Server, tpl Template) http.HandlerFunc { errPage := func(w http.ResponseWriter, msg string, code string, status int) { data := registerTemplateData{ Error: true, Message: msg, Code: code, } execTemplateWithStatus(w, tpl, data, status) } internalError := func(w http.ResponseWriter, err error) { log.Errorf("Internal Error during registration: %v", err) errPage(w, "There was a problem processing your request.", "", http.StatusInternalServerError) } idx := makeConnectorMap(s.Connectors) return func(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { internalError(w, err) return } // verify the user has a valid code. key := r.Form.Get("code") sessionID, err := s.SessionManager.ExchangeKey(key) if err != nil { errPage(w, "Please authenticate before registering.", "", http.StatusUnauthorized) return } // create a new code for them to use next time they hit the server. code, err := s.SessionManager.NewSessionKey(sessionID) if err != nil { internalError(w, err) return } ses, err := s.SessionManager.Get(sessionID) if err != nil || ses == nil { 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] if !ok { internalError(w, fmt.Errorf("no such IDPC: %v", ses.ConnectorID)) return } _, local := idpc.(*connector.LocalConnector) // Does the email comes from a trusted provider? trustedEmail := ses.Identity.Email != "" && idpc.TrustedEmailProvider() validate := r.Form.Get("validate") == "1" formErrors := []formError{} email := strings.TrimSpace(r.Form.Get("email")) // only auto-populate the first time the page is GETted, not on // subsequent POSTs if email == "" && r.Method == "GET" { email = ses.Identity.Email } password := r.Form.Get("password") if validate { if email == "" || !user.ValidEmail(email) { formErrors = append(formErrors, formError{"email", "Please supply a valid email"}) } if local && password == "" { formErrors = append(formErrors, formError{"password", "Please supply a valid password"}) } } data := registerTemplateData{ Code: code, Email: email, Password: password, Local: local, } // If there are form errors or this is the initial request // (i.e. validate==false), and we are not going to auto-submit a // trusted email, then show the form. if (len(formErrors) > 0 || !validate) && !trustedEmail { data.FormErrors = formErrors if !validate { execTemplate(w, tpl, data) } else { execTemplateWithStatus(w, tpl, data, http.StatusBadRequest) } return } var userID string if local { userID, err = registerFromLocalConnector( s.UserManager, s.SessionManager, ses, email, password) } else { if trustedEmail { // in the case of a trusted email provider, make sure we are // getting the email address from the session, not from the // query string, to prevent forgeries. email = ses.Identity.Email } userID, err = registerFromRemoteConnector( s.UserManager, ses, email, trustedEmail) } if err == user.ErrorDuplicateEmail { // In this case, the user probably just forgot that they registered. connID, err := getConnectorForUserByEmail(s.UserRepo, email) if err != nil { internalError(w, err) } loginURL := newLoginURLFromSession( s.IssuerURL, ses, false, []string{connID}, "login-maybe") if err = s.KillSession(code); err != nil { log.Errorf("Error killing session: %v", err) } http.Redirect(w, r, loginURL.String(), http.StatusSeeOther) return } if err != nil { formErrors := errToFormErrors(err) if len(formErrors) > 0 { data.FormErrors = formErrors execTemplate(w, tpl, data) return } if err == user.ErrorDuplicateRemoteIdentity { errPage(w, "You already registered an account with this identity", "", http.StatusConflict) return } internalError(w, err) return } ses, err = s.SessionManager.AttachUser(sessionID, userID) if err != nil { internalError(w, err) return } usr, err := s.UserRepo.Get(nil, userID) if err != nil { internalError(w, err) return } if !trustedEmail { _, err = s.UserEmailer.SendEmailVerification(usr.ID, ses.ClientID, ses.RedirectURL) if err != nil { log.Errorf("Error sending email verification: %v", err) } } w.Header().Set("Location", makeClientRedirectURL( ses.RedirectURL, code, ses.ClientState).String()) w.WriteHeader(http.StatusSeeOther) return } }