diff --git a/config/email.go b/config/email.go index d85b0bd9..0940ba5c 100644 --- a/config/email.go +++ b/config/email.go @@ -13,3 +13,5 @@ const ( // EmailTimeout = 80 * time.Millisecond EmailTimeout = 10 * time.Second ) + +var EmailTokenHashKey = []byte("CHANGE_THIS_BEFORE_DEPLOYING_YOU_RETARD") diff --git a/router/userHandler.go b/router/userHandler.go index a19f0381..1edc76d2 100644 --- a/router/userHandler.go +++ b/router/userHandler.go @@ -3,6 +3,7 @@ package router import ( "net/http" + "github.com/ewhal/nyaa/model" "github.com/ewhal/nyaa/service/captcha" "github.com/ewhal/nyaa/service/user" "github.com/ewhal/nyaa/service/user/form" @@ -180,7 +181,10 @@ func UserRegisterPostHandler(w http.ResponseWriter, r *http.Request) { } if (len(err) == 0) { languages.SetTranslationFromRequest(viewRegisterSuccessTemplate, r, "en-us") - htv := UserRegisterTemplateVariables{b, err, NewSearchForm(), Navigation{}, GetUser(r), r.URL, mux.CurrentRoute(r)} + u := model.User{ + Email: r.PostFormValue("email"), // indicate whether user had email set + } + htv := UserRegisterTemplateVariables{b, err, NewSearchForm(), Navigation{}, &u, r.URL, mux.CurrentRoute(r)} errorTmpl := viewRegisterSuccessTemplate.ExecuteTemplate(w, "index.html", htv) if errorTmpl != nil { http.Error(w, errorTmpl.Error(), http.StatusInternalServerError) diff --git a/service/user/verification.go b/service/user/verification.go index 6a888b49..07b6e1d1 100644 --- a/service/user/verification.go +++ b/service/user/verification.go @@ -2,51 +2,48 @@ package userService import ( "errors" + "fmt" "net/http" -// "time" + "strconv" + "time" "github.com/ewhal/nyaa/config" "github.com/ewhal/nyaa/db" "github.com/ewhal/nyaa/model" -// "github.com/ewhal/nyaa/util/crypto" "github.com/ewhal/nyaa/util/email" -// "github.com/ewhal/nyaa/util/log" -// "github.com/ewhal/nyaa/util/timeHelper" - + "github.com/ewhal/nyaa/util/timeHelper" + "github.com/gorilla/securecookie" "github.com/nicksnyder/go-i18n/i18n" ) +var verificationHandler = securecookie.New(config.EmailTokenHashKey, nil) + // SendEmailVerfication sends an email verification token via email. -func SendEmailVerfication(to string, token string, locale string) error { +func SendEmailVerification(to string, token string, locale string) error { T, _ := i18n.Tfunc(locale) - err := email.SendEmailFromAdmin(to, - T("verify_email_title"), - T("link")+" : "+config.WebAddress+"/verify/email/"+token, - T("verify_email_content")+"
"+config.WebAddress+"/verify/email/"+token+"") - return err + content := T("link")+" : https://"+config.WebAddress+"/verify/email/"+token + content_html := T("verify_email_content")+"
"+""+config.WebAddress+"/verify/email/"+token+"" + return email.SendEmailFromAdmin(to, T("verify_email_title"), content, content_html) + return nil } // SendVerificationToUser sends an email verification token to user. func SendVerificationToUser(user model.User) (int, error) { - /*var status int - var err error - user.ActivateUntil = timeHelper.TwentyFourHoursLater() - user.ActivationToken, err = crypto.GenerateRandomToken32() + validUntil := timeHelper.TwentyFourHoursLater() // TODO: longer duration? + value := map[string]string{ + "t": strconv.FormatInt(validUntil.Unix(), 10), + "u": strconv.FormatUint(uint64(user.Id), 10), + "e": user.Email, + } + encoded, err := verificationHandler.Encode("", value) if err != nil { return http.StatusInternalServerError, err } - user.Activation = false - log.Debugf("generated token : %s", user.ActivationToken) - status, err = UpdateUserCore(&user) - if err != nil { - return status, err - } - err = SendEmailVerfication(user.Email, user.ActivationToken, "en-us") + err = SendEmailVerification(user.Email, encoded, "en-us") if err != nil { return http.StatusInternalServerError, err } - return http.StatusOK, err*/ - return 0, errors.New("NotImpl") + return http.StatusOK, nil } // SendVerification sends an email verification token. @@ -63,28 +60,22 @@ func SendVerification(r *http.Request) (int, error) { return status, err } -// EmailVerification verifies an email of user. -func EmailVerification(token string,w http.ResponseWriter) (int, error) { - /*var user model.User - log.Debugf("verifyEmailForm.ActivationToken : %s", token) - if db.ORM.Where(&model.User{ActivationToken: token}).First(&user).RecordNotFound() { +// EmailVerification verifies the token used for email verification +func EmailVerification(token string, w http.ResponseWriter) (int, error) { + value := make(map[string]string) + err := verificationHandler.Decode("", token, &value) + if err != nil { + fmt.Printf("%+v\n", err) + return http.StatusForbidden, errors.New("Token is not valid.") + } + time_int, _ := strconv.ParseInt(value["t"], 10, 0) + if timeHelper.IsExpired(time.Unix(time_int, 0)) { + return http.StatusForbidden, errors.New("Token has expired.") + } + var user model.User + if db.ORM.Where("user_id = ?", value["u"]).First(&user).RecordNotFound() { return http.StatusNotFound, errors.New("User is not found.") } - isExpired := timeHelper.IsExpired(user.ActivateUntil) - log.Debugf("passwordResetUntil : %s", user.ActivateUntil.UTC()) - log.Debugf("expired : %t", isExpired) - if isExpired { - return http.StatusForbidden, errors.New("token not valid.") - } - user.ActivationToken = "" - user.ActivateUntil = time.Now() - user.ActivatedAt = time.Now() - user.Activation = true - status, err := UpdateUserCore(&user) - if err != nil { - return status, err - } - status, err = SetCookie(w, user.Token) - return status, err*/ - return 0, errors.New("NotImpl") + user.Email = value["e"] + return UpdateUserCore(&user) }