Files
GoMembership/internal/services/user_service.go
2025-02-12 20:30:59 +01:00

206 lines
4.9 KiB
Go

package services
import (
"net/http"
"strings"
"GoMembership/internal/constants"
"GoMembership/internal/models"
"GoMembership/internal/repositories"
"GoMembership/internal/utils"
"GoMembership/pkg/errors"
"GoMembership/pkg/logger"
"github.com/alexedwards/argon2id"
"gorm.io/gorm"
"time"
)
type UserServiceInterface interface {
RegisterUser(user *models.User) (uint, string, error)
GetUserByEmail(email string) (*models.User, error)
GetUserByID(id uint) (*models.User, error)
GetUsers(where map[string]interface{}) (*[]models.User, error)
VerifyUser(token *string) (*models.User, error)
UpdateUser(user *models.User) (*models.User, error)
DeleteUser(lastname string, id uint) error
}
type UserService struct {
Repo repositories.UserRepositoryInterface
Licences repositories.LicenceInterface
}
func (service *UserService) DeleteUser(lastname string, id uint) error {
if id == 0 || lastname == "" {
return errors.ErrNoData
}
user, err := service.GetUserByID(id)
if err != nil {
return err
}
if user == nil {
return errors.ErrUserNotFound
}
return service.Repo.DeleteUser(id)
}
func (service *UserService) UpdateUser(user *models.User) (*models.User, error) {
if user.ID == 0 {
return nil, errors.ErrUserNotFound
}
if user.Password != "" {
setPassword(user.Password, user)
}
// Validate subscription model
selectedModel, err := repositories.GetSubscriptionByName(&user.Membership.SubscriptionModel.Name)
if err != nil {
return nil, errors.ErrSubscriptionNotFound
}
user.Membership.SubscriptionModel = *selectedModel
user.Membership.SubscriptionModelID = selectedModel.ID
existingUser, err := service.GetUserByID(user.ID)
if err != nil {
return nil, err
}
user.Membership.ID = existingUser.Membership.ID
user.MembershipID = existingUser.MembershipID
if existingUser.Licence != nil {
user.Licence.ID = existingUser.Licence.ID
}
user.LicenceID = existingUser.LicenceID
user.BankAccount.ID = existingUser.BankAccount.ID
user.BankAccountID = existingUser.BankAccountID
// if user.Licence.Status == 0 {
// // This is a new drivers licence
// user.Licence.Status = constants.UnverifiedStatus
// }
updatedUser, err := service.Repo.UpdateUser(user)
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, errors.ErrUserNotFound
}
if strings.Contains(err.Error(), "UNIQUE constraint failed") {
return nil, errors.ErrDuplicateEntry
}
return nil, err
}
return updatedUser, nil
}
func (service *UserService) RegisterUser(user *models.User) (uint, string, error) {
setPassword(user.Password, user)
user.Status = constants.UnverifiedStatus
user.CreatedAt = time.Now()
user.UpdatedAt = time.Now()
user.PaymentStatus = constants.AwaitingPaymentStatus
// if user.Licence == nil {
// user.Licence = &models.Licence{Status: constants.UnverifiedStatus}
// }
user.BankAccount.MandateDateSigned = time.Now()
id, err := service.Repo.CreateUser(user)
if err != nil {
return 0, "", err
}
user.ID = id
token, err := utils.GenerateVerificationToken()
if err != nil {
return 0, "", err
}
logger.Info.Printf("TOKEN: %v", token)
// Check if user is already verified
verified, err := service.Repo.IsVerified(&user.ID)
if err != nil {
return 0, "", err
}
if verified {
return 0, "", errors.ErrAlreadyVerified
}
// Prepare the Verification record
verification := models.Verification{
UserID: user.ID,
VerificationToken: token,
}
if _, err = service.Repo.SetVerificationToken(&verification); err != nil {
return http.StatusInternalServerError, "", err
}
return id, token, nil
}
func (service *UserService) GetUserByID(id uint) (*models.User, error) {
return repositories.GetUserByID(&id)
}
func (service *UserService) GetUserByEmail(email string) (*models.User, error) {
return service.Repo.GetUserByEmail(email)
}
func (service *UserService) GetUsers(where map[string]interface{}) (*[]models.User, error) {
if where == nil {
where = map[string]interface{}{}
}
return service.Repo.GetUsers(where)
}
func (service *UserService) VerifyUser(token *string) (*models.User, error) {
verification, err := service.Repo.GetVerificationOfToken(token)
if err != nil {
return nil, err
}
// Check if the user is already verified
verified, err := service.Repo.IsVerified(&verification.UserID)
if err != nil {
return nil, err
}
user, err := repositories.GetUserByID(&verification.UserID)
if err != nil {
return nil, err
}
if verified {
return user, errors.ErrAlreadyVerified
}
// Update user status to active
t := time.Now()
verification.EmailVerifiedAt = &t
user.Status = constants.VerifiedStatus
user.Verification = *verification
user.ID = verification.UserID
service.Repo.UpdateUser(user)
return user, nil
}
func setPassword(plaintextPassword string, u *models.User) error {
hash, err := argon2id.CreateHash(plaintextPassword, argon2id.DefaultParams)
if err != nil {
return err
}
u.Password = hash
return nil
}