func userContextHandler(handler webapp.Handler) webapp.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) *webapp.Error { c := appengine.NewContext(r) u := user.Current(c) if u == nil { webapp.RedirectToLogin(w, r, r.URL.Path) return nil } switch acct, err := maybeOldAccount(c, u); err { case nil: setUserContext(r, acct) return handler.Serve(w, r) case account.ErrUserNotFound: http.Redirect(w, r, "/login/new", http.StatusSeeOther) return nil default: return webapp.InternalError(fmt.Errorf("failed to look up current user: %s", err)) } } }
func newAccount(w http.ResponseWriter, r *http.Request) *webapp.Error { target := continueTarget(r) c := appengine.NewContext(r) u := user.Current(c) if u == nil { webapp.RedirectToLogin(w, r, "/") return nil } if _, err := account.ForUser(c, u); err != account.ErrUserNotFound { if err != nil { return webapp.InternalError(fmt.Errorf("failed to account for current user: %s", err)) } http.Redirect(w, r, "/", http.StatusFound) return nil } id, err := account.ID(u) if err != nil { return webapp.InternalError(err) } if r.Method == "POST" { token, err := auth.TokenForRequest(c, id, r.URL.Path) if err != nil { return webapp.UnauthorizedError(fmt.Errorf("no stored token for request")) } if !token.IsValid(r.FormValue(auth.TokenFieldName), time.Now()) { return webapp.UnauthorizedError(fmt.Errorf("invalid XSRF token")) } fields, err := webapp.ParseRequiredValues(r, "email", "firstname", "lastname") if err != nil { // TODO(rwsims): Clean up this error reporting. w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, "Please go back and enter all required data.") return nil } claim := account.NewClaimedEmail(c, id, fields["email"]) switch err := claim.Claim(c); { case err == nil: break case err == account.ErrEmailAlreadyClaimed: // TODO(rwsims): Clean up this error reporting. w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, "That email is already in use; please use a different email") return nil default: return webapp.InternalError(fmt.Errorf("failed to claim email %q: %s", claim.Email, err)) } info := account.Info{ FirstName: fields["firstname"], LastName: fields["lastname"], Email: fields["email"], } if phone := r.FormValue("phone"); phone != "" { info.Phone = phone } acct, err := account.New(u, info) if err != nil { return webapp.InternalError(fmt.Errorf("failed to create user account: %s", err)) } if err := acct.Put(c); err != nil { return webapp.InternalError(fmt.Errorf("failed to write new user account: %s", err)) } if err := acct.SendConfirmation(c); err != nil { c.Errorf("Failed to send confirmation email to %q: %s", acct.Email, err) } http.Redirect(w, r, target, http.StatusSeeOther) token.Delete(c) return nil } token, err := auth.NewToken(id, r.URL.Path, time.Now()) if err != nil { return webapp.InternalError(fmt.Errorf("failed to create auth token: %s", err)) } if err := token.Store(c); err != nil { return webapp.InternalError(fmt.Errorf("failed to store token: %s", err)) } data := map[string]interface{}{ "Target": target, "Token": token.Encode(), } if err := newAccountPage.Execute(w, data); err != nil { return webapp.InternalError(err) } return nil }