|
|
@@ -6,20 +6,20 @@ import (
|
|
|
"net/url"
|
|
|
"time"
|
|
|
|
|
|
+ "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/models"
|
|
|
"github.com/porter-dev/porter/internal/notifier"
|
|
|
"github.com/porter-dev/porter/internal/random"
|
|
|
+ "github.com/porter-dev/porter/internal/repository"
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
|
"gorm.io/gorm"
|
|
|
)
|
|
|
|
|
|
type UserPasswordInitiateResetHandler struct {
|
|
|
- config *shared.Config
|
|
|
- decoderValidator shared.RequestDecoderValidator
|
|
|
- writer shared.ResultWriter
|
|
|
+ handlers.PorterHandlerReader
|
|
|
}
|
|
|
|
|
|
func NewUserPasswordInitiateResetHandler(
|
|
|
@@ -27,55 +27,42 @@ func NewUserPasswordInitiateResetHandler(
|
|
|
decoderValidator shared.RequestDecoderValidator,
|
|
|
writer shared.ResultWriter,
|
|
|
) *UserPasswordInitiateResetHandler {
|
|
|
- return &UserPasswordInitiateResetHandler{config, decoderValidator, writer}
|
|
|
+ return &UserPasswordInitiateResetHandler{
|
|
|
+ PorterHandlerReader: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func (c *UserPasswordInitiateResetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
request := &types.InitiateResetUserPasswordRequest{}
|
|
|
|
|
|
- ok := c.decoderValidator.DecodeAndValidate(w, r, request)
|
|
|
+ ok := c.DecodeAndValidate(w, r, request)
|
|
|
|
|
|
if !ok {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// check that the email exists; return 200 status code even if it doesn't
|
|
|
- user, err := c.config.Repo.User().ReadUserByEmail(request.Email)
|
|
|
+ user, err := c.Repo().User().ReadUserByEmail(request.Email)
|
|
|
|
|
|
if err == gorm.ErrRecordNotFound {
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
-
|
|
|
return
|
|
|
} else if err != nil {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- c.config.Logger,
|
|
|
- apierrors.NewErrInternal(
|
|
|
- err,
|
|
|
- ),
|
|
|
- )
|
|
|
-
|
|
|
+ c.HandleAPIError(w, apierrors.NewErrInternal(err))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// if the user is a Github user, send them a Github email
|
|
|
if user.GithubUserID != 0 {
|
|
|
- err := c.config.UserNotifier.SendGithubRelinkEmail(
|
|
|
+ err := c.Config().UserNotifier.SendGithubRelinkEmail(
|
|
|
¬ifier.SendGithubRelinkEmailOpts{
|
|
|
Email: user.Email,
|
|
|
- URL: fmt.Sprintf("%s/api/oauth/login/github", c.config.ServerConf.ServerURL),
|
|
|
+ URL: fmt.Sprintf("%s/api/oauth/login/github", c.Config().ServerConf.ServerURL),
|
|
|
},
|
|
|
)
|
|
|
|
|
|
if err != nil {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- c.config.Logger,
|
|
|
- apierrors.NewErrInternal(
|
|
|
- err,
|
|
|
- ),
|
|
|
- )
|
|
|
-
|
|
|
+ c.HandleAPIError(w, apierrors.NewErrInternal(err))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -89,28 +76,14 @@ func (c *UserPasswordInitiateResetHandler) ServeHTTP(w http.ResponseWriter, r *h
|
|
|
rawToken, err := random.StringWithCharset(32, "")
|
|
|
|
|
|
if err != nil {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- c.config.Logger,
|
|
|
- apierrors.NewErrInternal(
|
|
|
- err,
|
|
|
- ),
|
|
|
- )
|
|
|
-
|
|
|
+ c.HandleAPIError(w, apierrors.NewErrInternal(err))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
hashedToken, err := bcrypt.GenerateFromPassword([]byte(rawToken), 8)
|
|
|
|
|
|
if err != nil {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- c.config.Logger,
|
|
|
- apierrors.NewErrInternal(
|
|
|
- err,
|
|
|
- ),
|
|
|
- )
|
|
|
-
|
|
|
+ c.HandleAPIError(w, apierrors.NewErrInternal(err))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -122,17 +95,10 @@ func (c *UserPasswordInitiateResetHandler) ServeHTTP(w http.ResponseWriter, r *h
|
|
|
}
|
|
|
|
|
|
// handle write to the database
|
|
|
- pwReset, err = c.config.Repo.PWResetToken().CreatePWResetToken(pwReset)
|
|
|
+ pwReset, err = c.Repo().PWResetToken().CreatePWResetToken(pwReset)
|
|
|
|
|
|
if err != nil {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- c.config.Logger,
|
|
|
- apierrors.NewErrInternal(
|
|
|
- err,
|
|
|
- ),
|
|
|
- )
|
|
|
-
|
|
|
+ c.HandleAPIError(w, apierrors.NewErrInternal(err))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -142,22 +108,15 @@ func (c *UserPasswordInitiateResetHandler) ServeHTTP(w http.ResponseWriter, r *h
|
|
|
"token_id": []string{fmt.Sprintf("%d", pwReset.ID)},
|
|
|
}
|
|
|
|
|
|
- err = c.config.UserNotifier.SendPasswordResetEmail(
|
|
|
+ err = c.Config().UserNotifier.SendPasswordResetEmail(
|
|
|
¬ifier.SendPasswordResetEmailOpts{
|
|
|
Email: user.Email,
|
|
|
- URL: fmt.Sprintf("%s/password/reset/finalize?%s", c.config.ServerConf.ServerURL, queryVals.Encode()),
|
|
|
+ URL: fmt.Sprintf("%s/password/reset/finalize?%s", c.Config().ServerConf.ServerURL, queryVals.Encode()),
|
|
|
},
|
|
|
)
|
|
|
|
|
|
if err != nil {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- c.config.Logger,
|
|
|
- apierrors.NewErrInternal(
|
|
|
- err,
|
|
|
- ),
|
|
|
- )
|
|
|
-
|
|
|
+ c.HandleAPIError(w, apierrors.NewErrInternal(err))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -166,9 +125,7 @@ func (c *UserPasswordInitiateResetHandler) ServeHTTP(w http.ResponseWriter, r *h
|
|
|
}
|
|
|
|
|
|
type UserPasswordVerifyResetHandler struct {
|
|
|
- config *shared.Config
|
|
|
- decoderValidator shared.RequestDecoderValidator
|
|
|
- writer shared.ResultWriter
|
|
|
+ handlers.PorterHandlerReader
|
|
|
}
|
|
|
|
|
|
func NewUserPasswordVerifyResetHandler(
|
|
|
@@ -176,19 +133,21 @@ func NewUserPasswordVerifyResetHandler(
|
|
|
decoderValidator shared.RequestDecoderValidator,
|
|
|
writer shared.ResultWriter,
|
|
|
) *UserPasswordVerifyResetHandler {
|
|
|
- return &UserPasswordVerifyResetHandler{config, decoderValidator, writer}
|
|
|
+ return &UserPasswordVerifyResetHandler{
|
|
|
+ PorterHandlerReader: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func (c *UserPasswordVerifyResetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
request := &types.VerifyResetUserPasswordRequest{}
|
|
|
|
|
|
- ok := c.decoderValidator.DecodeAndValidate(w, r, request)
|
|
|
+ ok := c.DecodeAndValidate(w, r, request)
|
|
|
|
|
|
if !ok {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- ok, _ = VerifyPasswordResetToken(c.config, w, request)
|
|
|
+ ok, _ = VerifyPasswordResetToken(c.Repo().PWResetToken(), c.HandleAPIError, w, request)
|
|
|
|
|
|
if ok {
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
@@ -198,9 +157,7 @@ func (c *UserPasswordVerifyResetHandler) ServeHTTP(w http.ResponseWriter, r *htt
|
|
|
}
|
|
|
|
|
|
type UserPasswordFinalizeResetHandler struct {
|
|
|
- config *shared.Config
|
|
|
- decoderValidator shared.RequestDecoderValidator
|
|
|
- writer shared.ResultWriter
|
|
|
+ handlers.PorterHandlerReader
|
|
|
}
|
|
|
|
|
|
func NewUserPasswordFinalizeResetHandler(
|
|
|
@@ -208,44 +165,35 @@ func NewUserPasswordFinalizeResetHandler(
|
|
|
decoderValidator shared.RequestDecoderValidator,
|
|
|
writer shared.ResultWriter,
|
|
|
) *UserPasswordFinalizeResetHandler {
|
|
|
- return &UserPasswordFinalizeResetHandler{config, decoderValidator, writer}
|
|
|
+ return &UserPasswordFinalizeResetHandler{
|
|
|
+ PorterHandlerReader: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func (c *UserPasswordFinalizeResetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
request := &types.FinalizeResetUserPasswordRequest{}
|
|
|
|
|
|
- ok := c.decoderValidator.DecodeAndValidate(w, r, request)
|
|
|
+ ok := c.DecodeAndValidate(w, r, request)
|
|
|
|
|
|
if !ok {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- ok, token := VerifyPasswordResetToken(c.config, w, &request.VerifyResetUserPasswordRequest)
|
|
|
+ ok, token := VerifyPasswordResetToken(c.Repo().PWResetToken(), c.HandleAPIError, w, &request.VerifyResetUserPasswordRequest)
|
|
|
|
|
|
if ok {
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
}
|
|
|
|
|
|
// check that the email exists
|
|
|
- user, err := c.config.Repo.User().ReadUserByEmail(request.Email)
|
|
|
+ user, err := c.Repo().User().ReadUserByEmail(request.Email)
|
|
|
|
|
|
if err != nil {
|
|
|
if err == gorm.ErrRecordNotFound {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- c.config.Logger,
|
|
|
- apierrors.NewErrForbidden(
|
|
|
- fmt.Errorf("finalize password reset failed: email does not exist"),
|
|
|
- ),
|
|
|
- )
|
|
|
+ err = fmt.Errorf("finalize password reset failed: email does not exist")
|
|
|
+ c.HandleAPIError(w, apierrors.NewErrForbidden(err))
|
|
|
} else {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- c.config.Logger,
|
|
|
- apierrors.NewErrInternal(
|
|
|
- err,
|
|
|
- ),
|
|
|
- )
|
|
|
+ c.HandleAPIError(w, apierrors.NewErrInternal(err))
|
|
|
}
|
|
|
|
|
|
return
|
|
|
@@ -254,47 +202,26 @@ func (c *UserPasswordFinalizeResetHandler) ServeHTTP(w http.ResponseWriter, r *h
|
|
|
hashedPW, err := bcrypt.GenerateFromPassword([]byte(request.NewPassword), 8)
|
|
|
|
|
|
if err != nil {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- c.config.Logger,
|
|
|
- apierrors.NewErrInternal(
|
|
|
- err,
|
|
|
- ),
|
|
|
- )
|
|
|
-
|
|
|
+ c.HandleAPIError(w, apierrors.NewErrInternal(err))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
user.Password = string(hashedPW)
|
|
|
|
|
|
- user, err = c.config.Repo.User().UpdateUser(user)
|
|
|
+ user, err = c.Repo().User().UpdateUser(user)
|
|
|
|
|
|
if err != nil {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- c.config.Logger,
|
|
|
- apierrors.NewErrInternal(
|
|
|
- err,
|
|
|
- ),
|
|
|
- )
|
|
|
-
|
|
|
+ c.HandleAPIError(w, apierrors.NewErrInternal(err))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// invalidate the token
|
|
|
token.IsValid = false
|
|
|
|
|
|
- _, err = c.config.Repo.PWResetToken().UpdatePWResetToken(token)
|
|
|
+ _, err = c.Repo().PWResetToken().UpdatePWResetToken(token)
|
|
|
|
|
|
if err != nil {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- c.config.Logger,
|
|
|
- apierrors.NewErrInternal(
|
|
|
- err,
|
|
|
- ),
|
|
|
- )
|
|
|
-
|
|
|
+ c.HandleAPIError(w, apierrors.NewErrInternal(err))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -303,29 +230,19 @@ func (c *UserPasswordFinalizeResetHandler) ServeHTTP(w http.ResponseWriter, r *h
|
|
|
}
|
|
|
|
|
|
func VerifyPasswordResetToken(
|
|
|
- config *shared.Config,
|
|
|
+ pwResetRepo repository.PWResetTokenRepository,
|
|
|
+ handleErr func(w http.ResponseWriter, apiErr apierrors.RequestError),
|
|
|
w http.ResponseWriter,
|
|
|
request *types.VerifyResetUserPasswordRequest,
|
|
|
) (bool, *models.PWResetToken) {
|
|
|
- token, err := config.Repo.PWResetToken().ReadPWResetToken(request.TokenID)
|
|
|
+ token, err := pwResetRepo.ReadPWResetToken(request.TokenID)
|
|
|
|
|
|
if err != nil {
|
|
|
if err == gorm.ErrRecordNotFound {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- config.Logger,
|
|
|
- apierrors.NewErrForbidden(
|
|
|
- fmt.Errorf("verify/finalize password reset failed: token does not exist"),
|
|
|
- ),
|
|
|
- )
|
|
|
+ err = fmt.Errorf("verify/finalize password reset failed: token does not exist")
|
|
|
+ handleErr(w, apierrors.NewErrForbidden(err))
|
|
|
} else {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- config.Logger,
|
|
|
- apierrors.NewErrInternal(
|
|
|
- err,
|
|
|
- ),
|
|
|
- )
|
|
|
+ handleErr(w, apierrors.NewErrInternal(err))
|
|
|
}
|
|
|
|
|
|
return false, nil
|
|
|
@@ -333,39 +250,24 @@ func VerifyPasswordResetToken(
|
|
|
|
|
|
// make sure the token is still valid and has not expired
|
|
|
if !token.IsValid || token.IsExpired() {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- config.Logger,
|
|
|
- apierrors.NewErrForbidden(
|
|
|
- fmt.Errorf("verify password reset failed: expired %t, valid %t", token.IsExpired(), token.IsValid),
|
|
|
- ),
|
|
|
- )
|
|
|
+ err = fmt.Errorf("verify password reset failed: expired %t, valid %t", token.IsExpired(), token.IsValid)
|
|
|
+ handleErr(w, apierrors.NewErrForbidden(err))
|
|
|
|
|
|
return false, nil
|
|
|
}
|
|
|
|
|
|
// check that the email matches
|
|
|
if token.Email != request.Email {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- config.Logger,
|
|
|
- apierrors.NewErrForbidden(
|
|
|
- fmt.Errorf("verify password reset failed: token email does not match request email"),
|
|
|
- ),
|
|
|
- )
|
|
|
+ err = fmt.Errorf("verify password reset failed: token email does not match request email")
|
|
|
+ handleErr(w, apierrors.NewErrForbidden(err))
|
|
|
|
|
|
return false, nil
|
|
|
}
|
|
|
|
|
|
// make sure the token is correct
|
|
|
if err := bcrypt.CompareHashAndPassword([]byte(token.Token), []byte(request.Token)); err != nil {
|
|
|
- apierrors.HandleAPIError(
|
|
|
- w,
|
|
|
- config.Logger,
|
|
|
- apierrors.NewErrForbidden(
|
|
|
- fmt.Errorf("verify password reset failed: %s", err),
|
|
|
- ),
|
|
|
- )
|
|
|
+ err = fmt.Errorf("verify password reset failed: %s", err)
|
|
|
+ handleErr(w, apierrors.NewErrForbidden(err))
|
|
|
|
|
|
return false, nil
|
|
|
}
|