Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/service/ep_reset_password.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package service

import (
"apiboy/backend/src/errors"
"context"
"strings"
"time"

"apiboy/backend/src/errors"
"encoding/base64"

"github.com/go-kit/kit/endpoint"
"github.com/google/uuid"
Expand All @@ -31,11 +33,14 @@ func (s *Service) ResetPassword(ctx context.Context, input *ResetPasswordInput)
if user == nil {
return nil, errors.Unauthorized{Msg: "Invalid user"}
}
timeNow := time.Now().UTC()

decode := user.ID + "|" + timeNow.Format(time.UnixDate) + "|" + uuid.New().String()

user.TempCode = uuid.New().String()
user.TempCode = base64.StdEncoding.EncodeToString([]byte(decode))

if err = s.Store.UpdateUser(ctx, user.ID, user); err != nil {
return nil, errors.InternalServer{Msg: "Could not generate temp password", Err: err}
return nil, errors.InternalServer{Msg: "Could not generate temp code", Err: err}
}

return &ResetPasswordOutput{}, nil
Expand Down
96 changes: 96 additions & 0 deletions src/service/ep_set_new_password.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package service

import (
"apiboy/backend/src/authutils"
"apiboy/backend/src/errors"
"context"
"encoding/base64"
"strings"
"time"

"github.com/go-kit/kit/endpoint"
)

// SetNewPasswordInput is the input of the endpoint
type SetNewPasswordInput struct {
Password string `json:"password" validate:"omitempty,min=6"`
TempCode string `json:"temp_code" validate:"required"`
}

// SetNewPasswordOutput is the output of the endpoint
type SetNewPasswordOutput struct{}

// SetNewPassword implements the business logic for the endpoint
func (s *Service) SetNewPassword(ctx context.Context, input *SetNewPasswordInput) (*SetNewPasswordOutput, error) {
password := strings.TrimSpace(input.Password)
tempCode := strings.TrimSpace(input.TempCode)

decode, err := base64.StdEncoding.DecodeString(tempCode)
if err != nil {
return nil, errors.InternalServer{Msg: "Could not format temp code", Err: err}
}

elements := strings.Split(string(decode), "|")
if len(elements) != 3 {
return nil, errors.Unauthorized{Msg: "Invalid code"}
}

strDateTimeCode := elements[1]
dateTimeCode, err := time.Parse(time.UnixDate, strDateTimeCode)
if err != nil { // Always check errors even if they should not happen.
return nil, errors.InternalServer{Msg: "Could not format date time", Err: err}
}

timeNow := time.Now().UTC()
hrs := timeNow.Sub(dateTimeCode)

if hrs.Hours() > 24 {
return nil, errors.Unauthorized{Msg: "Invalid code"}
}

userID := elements[0]
// get user
user, err := s.Store.GetUserByID(ctx, userID)
if err != nil {
return nil, errors.InternalServer{Msg: "Could not get user", Err: err}
} else if user == nil {
return nil, errors.NotFound{Obj: "User"}
}

if user.TempCode != tempCode {
return nil, errors.Unauthorized{Msg: "Invalid code"}
}

// hash new password
hashedPassword, err := authutils.HashPassword(password)
if err != nil {
return nil, errors.InternalServer{Msg: "Could not hash password", Err: err}
}

user.Password = hashedPassword
user.TempCode = ""

if err = s.Store.UpdateUser(ctx, user.ID, user); err != nil {
return nil, errors.InternalServer{Msg: "Could not update user", Err: err}
}

return &SetNewPasswordOutput{}, nil
}

// MakeSetNewPasswordEndpoint creates the endpoint
func MakeSetNewPasswordEndpoint(s *Service, m ...endpoint.Middleware) endpoint.Endpoint {
e := func(ctx context.Context, request interface{}) (response interface{}, err error) {
input, ok := request.(*SetNewPasswordInput)
if !ok {
return nil, errors.BadRequest{}
}

return s.SetNewPassword(ctx, input)
}

for _, mw := range m {
e = mw(e)
}

return e
}
2 changes: 2 additions & 0 deletions src/service/http_endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type HTTPEndpoints struct {
LogoutEndpoint endpoint.Endpoint
SignupEndpoint endpoint.Endpoint
ResetPasswordEndpoint endpoint.Endpoint
SetNewPasswordEndpoint endpoint.Endpoint
UpdateUserEndpoint endpoint.Endpoint
DeleteUserEndpoint endpoint.Endpoint
CreateProjectEndpoint endpoint.Endpoint
Expand Down Expand Up @@ -46,6 +47,7 @@ func MakeHTTPEndpoints(s *Service) HTTPEndpoints {
LogoutEndpoint: MakeLogoutEndpoint(s, vm, am),
SignupEndpoint: MakeSignupEndpoint(s, vm),
ResetPasswordEndpoint: MakeResetPasswordEndpoint(s, vm),
SetNewPasswordEndpoint: MakeSetNewPasswordEndpoint(s, vm),
UpdateUserEndpoint: MakeUpdateUserEndpoint(s, vm, am),
DeleteUserEndpoint: MakeDeleteUserEndpoint(s, vm, am),
CreateProjectEndpoint: MakeCreateProjectEndpoint(s, vm, am),
Expand Down
7 changes: 7 additions & 0 deletions src/service/http_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ func MakeHTTPHandler(ctx context.Context, log *logger.Logger, e HTTPEndpoints) h
defaultOptions...,
)).Name("ResetPassword")

r.Methods("POST").Path("/auth/set_new_password").Handler(kithttp.NewServer(
e.SetNewPasswordEndpoint,
httputils.DecodeRPCRequest(&SetNewPasswordInput{}),
httputils.ResponseEncoder(log),
defaultOptions...,
)).Name("SetNewPassword")

r.Methods("POST").Path("/users/update").Handler(kithttp.NewServer(
e.UpdateUserEndpoint,
httputils.DecodeRPCRequest(&UpdateUserInput{}),
Expand Down