204 lines
5.7 KiB
Go
204 lines
5.7 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"furtuna-be/config"
|
|
"furtuna-be/internal/common/mycontext"
|
|
"furtuna-be/internal/entity"
|
|
"furtuna-be/internal/utils"
|
|
"go.uber.org/zap"
|
|
|
|
"furtuna-be/internal/common/errors"
|
|
"furtuna-be/internal/common/logger"
|
|
"furtuna-be/internal/repository"
|
|
)
|
|
|
|
type AuthServiceImpl struct {
|
|
authRepo repository.Auth
|
|
crypto repository.Crypto
|
|
user repository.User
|
|
emailSvc repository.EmailService
|
|
emailCfg config.Email
|
|
trxRepo repository.TransactionManager
|
|
license repository.License
|
|
}
|
|
|
|
func New(authRepo repository.Auth,
|
|
crypto repository.Crypto, user repository.User, emailSvc repository.EmailService,
|
|
emailCfg config.Email, trxRepo repository.TransactionManager,
|
|
license repository.License,
|
|
) *AuthServiceImpl {
|
|
return &AuthServiceImpl{
|
|
authRepo: authRepo,
|
|
crypto: crypto,
|
|
user: user,
|
|
emailSvc: emailSvc,
|
|
emailCfg: emailCfg,
|
|
trxRepo: trxRepo,
|
|
license: license,
|
|
}
|
|
}
|
|
|
|
func (u *AuthServiceImpl) AuthenticateUser(ctx context.Context, email, password string) (*entity.AuthenticateUser, error) {
|
|
user, err := u.authRepo.CheckExistsUserAccount(ctx, email)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when get user", zap.Error(err))
|
|
return nil, errors.ErrorInternalServer
|
|
}
|
|
|
|
if user == nil {
|
|
return nil, errors.ErrorUserIsNotFound
|
|
}
|
|
|
|
//if ok := u.crypto.CompareHashAndPassword(user.Password, password); !ok {
|
|
// //return nil, errors.ErrorUserInvalidLogin
|
|
//}
|
|
|
|
signedToken, err := u.crypto.GenerateJWT(user.ToUser())
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var licensePartner entity.PartnerLicense
|
|
|
|
if user.PartnerID != nil && *user.PartnerID != 0 {
|
|
partnerLicense, err := u.license.FindByPartnerIDMaxEndDate(ctx, user.PartnerID)
|
|
if err != nil {
|
|
logger.ContextLogger(ctx).Error("error when get user license", zap.Error(err))
|
|
return nil, errors.ErrorInternalServer
|
|
}
|
|
|
|
if partnerLicense == nil {
|
|
return nil, errors.ErrorInvalidLicense
|
|
}
|
|
|
|
licensePartner = partnerLicense.ToPartnerLicense()
|
|
if licensePartner.LicenseStatus == "EXPIRED" || licensePartner.LicenseStatus == "INACTIVE" {
|
|
return nil, errors.ErrorInvalidLicense
|
|
}
|
|
}
|
|
|
|
return user.ToUserAuthenticate(signedToken, licensePartner), 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
|
|
}
|
|
|
|
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 u.emailCfg.CustomReceiver != "" {
|
|
email = u.emailCfg.CustomReceiver
|
|
}
|
|
|
|
sender := u.emailCfg.Sender
|
|
templatePath := u.emailCfg.ResetPassword.TemplatePath
|
|
subject := fmt.Sprintf("Furtuna %s", u.emailCfg.ResetPassword.Subject)
|
|
if user.UserType == "CUSTOMER" {
|
|
sender = u.emailCfg.SenderCustomer
|
|
templatePath = u.emailCfg.ResetPassword.TemplatePathCustomer
|
|
subject = fmt.Sprintf("Ayogo %s", u.emailCfg.ResetPassword.Subject)
|
|
}
|
|
|
|
// Prepare the email notification parameters
|
|
renewPasswordRequest := entity.SendEmailNotificationParam{
|
|
Sender: sender,
|
|
Recipient: email,
|
|
Subject: subject,
|
|
TemplateName: u.emailCfg.ResetPassword.TemplateName,
|
|
TemplatePath: 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.ErrorExternalRequest
|
|
}
|
|
|
|
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
|
|
}
|