add forget password

This commit is contained in:
aditya.siregar
2024-07-23 01:36:25 +07:00
parent 7ea809cc09
commit 5a0dec6128
22 changed files with 907 additions and 76 deletions
+127 -1
View File
@@ -2,7 +2,10 @@ package auth
import (
"context"
"furtuna-be/config"
"furtuna-be/internal/common/mycontext"
"furtuna-be/internal/entity"
"furtuna-be/internal/utils"
"go.uber.org/zap"
@@ -14,12 +17,23 @@ import (
type AuthServiceImpl struct {
authRepo repository.Auth
crypto repository.Crypto
user repository.User
emailSvc repository.EmailService
emailCfg config.Email
trxRepo repository.TransactionManager
}
func New(authRepo repository.Auth, crypto repository.Crypto) *AuthServiceImpl {
func New(authRepo repository.Auth,
crypto repository.Crypto, user repository.User, emailSvc repository.EmailService,
emailCfg config.Email, trxRepo repository.TransactionManager,
) *AuthServiceImpl {
return &AuthServiceImpl{
authRepo: authRepo,
crypto: crypto,
user: user,
emailSvc: emailSvc,
emailCfg: emailCfg,
trxRepo: trxRepo,
}
}
@@ -46,3 +60,115 @@ func (u *AuthServiceImpl) AuthenticateUser(ctx context.Context, email, password
return user.ToUserAuthenticate(signedToken), nil
}
func (u *AuthServiceImpl) SendPasswordResetLink(ctx context.Context, email string) error {
// Check if the user exists
user, err := u.authRepo.CheckExistsUserAccount(ctx, email)
if err != nil {
logger.ContextLogger(ctx).Error("error when getting user", zap.Error(err))
return errors.ErrorInternalServer
}
if user == nil {
return errors.ErrorUserIsNotFound
}
// Begin a transaction
trx, err := u.trxRepo.Begin(ctx)
if err != nil {
logger.ContextLogger(ctx).Error("error when beginning transaction", zap.Error(err))
return errors.ErrorInternalServer
}
defer func() {
if r := recover(); r != nil {
u.trxRepo.Rollback(trx)
logger.ContextLogger(ctx).Error("panic recovered in SendPasswordResetLink", zap.Any("recover", r))
err = errors.ErrorInternalServer
}
}()
// Generate a new password
generatedPassword := utils.GenerateRandomString(10)
hashPassword, err := user.ToUser().HashedPassword(generatedPassword)
if err != nil {
logger.ContextLogger(ctx).Error("error when generating hashed password", zap.Error(err))
u.trxRepo.Rollback(trx)
return errors.ErrorInternalServer
}
// Update the user's password in the database
if err := u.authRepo.UpdatePassword(ctx, trx, hashPassword, user.ID, true); err != nil {
logger.ContextLogger(ctx).Error("error when updating user password", zap.Error(err))
u.trxRepo.Rollback(trx)
return errors.ErrorInternalServer
}
// If a custom receiver is specified, override the email
if u.emailCfg.CustomReceiver != "" {
email = u.emailCfg.CustomReceiver
}
// Prepare the email notification parameters
renewPasswordRequest := entity.SendEmailNotificationParam{
Recipient: email,
Subject: u.emailCfg.ResetPassword.Subject,
TemplateName: u.emailCfg.ResetPassword.TemplateName,
TemplatePath: u.emailCfg.ResetPassword.TemplatePath,
Data: map[string]interface{}{
"Name": user.Name,
"OpeningWord": u.emailCfg.ResetPassword.OpeningWord,
"Password": generatedPassword,
"ClosingWord": u.emailCfg.ResetPassword.ClosingWord,
"Note": u.emailCfg.ResetPassword.Notes,
"Link": u.emailCfg.ResetPassword.Link,
},
}
defer func() {
if r := recover(); r != nil {
u.trxRepo.Rollback(trx)
logger.ContextLogger(ctx).Error("panic recovered in SendPasswordResetLink", zap.Any("recover", r))
err = errors.ErrorInternalServer
}
}()
// Send the email notification
err = u.emailSvc.SendEmailTransactional(ctx, renewPasswordRequest)
if err != nil {
u.trxRepo.Rollback(trx)
logger.ContextLogger(ctx).Error("error when sending password reset email", zap.Error(err))
return errors.ErrorInternalServer
}
trx.Commit()
return nil
}
func (u *AuthServiceImpl) ResetPassword(ctx mycontext.Context, oldPassword, newPassword string) error {
user, err := u.authRepo.CheckExistsUserAccountByID(ctx, ctx.RequestedBy())
if err != nil {
return errors.ErrorInvalidRequest
}
if ok := u.crypto.CompareHashAndPassword(user.Password, oldPassword); !ok {
return errors.ErrorUserInvalidLogin
}
password, err := user.ToUser().HashedPassword(newPassword)
if err != nil {
return errors.ErrorInvalidRequest
}
trx, _ := u.trxRepo.Begin(ctx)
err = u.authRepo.UpdatePassword(ctx, trx, password, user.ID, false)
if err != nil {
return errors.ErrorInternalServer
}
trx.Commit()
return nil
}
+3 -1
View File
@@ -35,7 +35,7 @@ type ServiceManagerImpl struct {
func NewServiceManagerImpl(cfg *config.Config, repo *repository.RepoManagerImpl) *ServiceManagerImpl {
return &ServiceManagerImpl{
AuthSvc: auth.New(repo.Auth, repo.Crypto),
AuthSvc: auth.New(repo.Auth, repo.Crypto, repo.User, repo.EmailService, cfg.Email, repo.Trx),
EventSvc: event.NewEventService(repo.Event),
UserSvc: users.NewUserService(repo.User, repo.Branch),
BranchSvc: branch.NewBranchService(repo.Branch),
@@ -52,6 +52,8 @@ func NewServiceManagerImpl(cfg *config.Config, repo *repository.RepoManagerImpl)
type Auth interface {
AuthenticateUser(ctx context.Context, email, password string) (*entity.AuthenticateUser, error)
SendPasswordResetLink(ctx context.Context, email string) error
ResetPassword(ctx mycontext.Context, oldPassword, newPassword string) error
}
type Event interface {