|
|
@@ -5,32 +5,34 @@ import (
|
|
|
"net/http"
|
|
|
"net/url"
|
|
|
|
|
|
+ "github.com/porter-dev/porter/api/server/handlers"
|
|
|
"github.com/porter-dev/porter/api/server/shared"
|
|
|
"github.com/porter-dev/porter/api/server/shared/apierrors"
|
|
|
"github.com/porter-dev/porter/api/types"
|
|
|
- "github.com/porter-dev/porter/internal/forms"
|
|
|
"github.com/porter-dev/porter/internal/models"
|
|
|
"github.com/porter-dev/porter/internal/notifier"
|
|
|
- "golang.org/x/crypto/bcrypt"
|
|
|
)
|
|
|
|
|
|
type VerifyEmailInitiateHandler struct {
|
|
|
- config *shared.Config
|
|
|
+ handlers.PorterHandler
|
|
|
}
|
|
|
|
|
|
func NewVerifyEmailInitiateHandler(
|
|
|
config *shared.Config,
|
|
|
) *VerifyEmailInitiateHandler {
|
|
|
- return &VerifyEmailInitiateHandler{config}
|
|
|
+ return &VerifyEmailInitiateHandler{
|
|
|
+ PorterHandler: handlers.NewDefaultPorterHandler(config, nil, nil),
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func (v *VerifyEmailInitiateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
user, _ := r.Context().Value(types.UserScope).(*models.User)
|
|
|
|
|
|
- pwReset, rawToken, err := CreateTokenForEmail(v.config, user.Email)
|
|
|
+ pwReset, rawToken, err := CreatePWResetTokenForEmail(v.Repo().PWResetToken(), v.HandleAPIError, w, &types.InitiateResetUserPasswordRequest{
|
|
|
+ Email: user.Email,
|
|
|
+ })
|
|
|
|
|
|
if err != nil {
|
|
|
- apierrors.HandleAPIError(w, v.config.Logger, apierrors.NewErrInternal(err))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -39,29 +41,30 @@ func (v *VerifyEmailInitiateHandler) ServeHTTP(w http.ResponseWriter, r *http.Re
|
|
|
"token_id": []string{fmt.Sprintf("%d", pwReset.ID)},
|
|
|
}
|
|
|
|
|
|
- err = v.config.UserNotifier.SendEmailVerification(
|
|
|
+ err = v.Config().UserNotifier.SendEmailVerification(
|
|
|
¬ifier.SendEmailVerificationOpts{
|
|
|
Email: user.Email,
|
|
|
- URL: fmt.Sprintf("%s/api/email/verify/finalize?%s", v.config.ServerConf.ServerURL, queryVals.Encode()),
|
|
|
+ URL: fmt.Sprintf("%s/api/email/verify/finalize?%s", v.Config().ServerConf.ServerURL, queryVals.Encode()),
|
|
|
},
|
|
|
)
|
|
|
|
|
|
if err != nil {
|
|
|
- apierrors.HandleAPIError(w, v.config.Logger, apierrors.NewErrInternal(err))
|
|
|
+ v.HandleAPIError(w, apierrors.NewErrInternal(err))
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
type VerifyEmailFinalizeHandler struct {
|
|
|
- config *shared.Config
|
|
|
- decoderValidator shared.RequestDecoderValidator
|
|
|
+ handlers.PorterHandlerReader
|
|
|
}
|
|
|
|
|
|
func NewVerifyEmailFinalizeHandler(
|
|
|
config *shared.Config,
|
|
|
decoderValidator shared.RequestDecoderValidator,
|
|
|
) *VerifyEmailFinalizeHandler {
|
|
|
- return &VerifyEmailFinalizeHandler{config, decoderValidator}
|
|
|
+ return &VerifyEmailFinalizeHandler{
|
|
|
+ PorterHandlerReader: handlers.NewDefaultPorterHandler(config, decoderValidator, nil),
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func (v *VerifyEmailFinalizeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
@@ -69,34 +72,27 @@ func (v *VerifyEmailFinalizeHandler) ServeHTTP(w http.ResponseWriter, r *http.Re
|
|
|
|
|
|
request := &types.VerifyEmailFinalizeRequest{}
|
|
|
|
|
|
- if err := v.decoderValidator.DecodeAndValidateNoWrite(r, request); err != nil {
|
|
|
+ if err := v.DecodeAndValidateNoWrite(r, request); err != nil {
|
|
|
http.Redirect(w, r, "/dashboard?error="+url.QueryEscape(err.Error()), 302)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- // verify the token is valid
|
|
|
- token, err := v.config.Repo.PWResetToken().ReadPWResetToken(request.TokenID)
|
|
|
+ token, err := VerifyToken(
|
|
|
+ v.Repo().PWResetToken(),
|
|
|
+ handlers.IgnoreAPIError,
|
|
|
+ w,
|
|
|
+ &request.VerifyTokenFinalizeRequest,
|
|
|
+ user.Email,
|
|
|
+ )
|
|
|
|
|
|
if err != nil {
|
|
|
http.Redirect(w, r, "/dashboard?error="+url.QueryEscape("Email verification error: valid token required"), 302)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- // make sure the token is still valid and has not expired
|
|
|
- if !token.IsValid || token.IsExpired() {
|
|
|
- http.Redirect(w, r, "/dashboard?error="+url.QueryEscape("Email verification error: valid token required"), 302)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // make sure the token is correct
|
|
|
- if err := bcrypt.CompareHashAndPassword([]byte(token.Token), []byte(request.Token)); err != nil {
|
|
|
- http.Redirect(w, r, "/dashboard?error="+url.QueryEscape("Email verification error: valid token required"), 302)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
user.EmailVerified = true
|
|
|
|
|
|
- user, err = v.config.Repo.User().UpdateUser(user)
|
|
|
+ user, err = v.Repo().User().UpdateUser(user)
|
|
|
|
|
|
if err != nil {
|
|
|
http.Redirect(w, r, "/dashboard?error="+url.QueryEscape("Could not verify email address"), 302)
|
|
|
@@ -106,7 +102,7 @@ func (v *VerifyEmailFinalizeHandler) ServeHTTP(w http.ResponseWriter, r *http.Re
|
|
|
// invalidate the token
|
|
|
token.IsValid = false
|
|
|
|
|
|
- _, err = v.config.Repo.PWResetToken().UpdatePWResetToken(token)
|
|
|
+ _, err = v.Repo().PWResetToken().UpdatePWResetToken(token)
|
|
|
|
|
|
if err != nil {
|
|
|
http.Redirect(w, r, "/dashboard?error="+url.QueryEscape("Could not verify email address"), 302)
|
|
|
@@ -116,25 +112,3 @@ func (v *VerifyEmailFinalizeHandler) ServeHTTP(w http.ResponseWriter, r *http.Re
|
|
|
http.Redirect(w, r, "/dashboard", 302)
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
-func CreateTokenForEmail(config *shared.Config, email string) (*models.PWResetToken, string, error) {
|
|
|
- form := &forms.InitiateResetUserPasswordForm{
|
|
|
- Email: email,
|
|
|
- }
|
|
|
-
|
|
|
- // convert the form to a pw reset token model
|
|
|
- pwReset, rawToken, err := form.ToPWResetToken()
|
|
|
-
|
|
|
- if err != nil {
|
|
|
- return nil, "", err
|
|
|
- }
|
|
|
-
|
|
|
- // handle write to the database
|
|
|
- pwReset, err = config.Repo.PWResetToken().CreatePWResetToken(pwReset)
|
|
|
-
|
|
|
- if err != nil {
|
|
|
- return nil, "", err
|
|
|
- }
|
|
|
-
|
|
|
- return pwReset, rawToken, nil
|
|
|
-}
|