160 lines
4.0 KiB
Go
160 lines
4.0 KiB
Go
package repositories
|
|
|
|
import (
|
|
"time"
|
|
|
|
"GoMembership/internal/constants"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
"gorm.io/gorm/clause"
|
|
|
|
"GoMembership/internal/models"
|
|
"GoMembership/pkg/errors"
|
|
"GoMembership/pkg/logger"
|
|
)
|
|
|
|
type UserRepository interface {
|
|
CreateUser(user *models.User) (int64, error)
|
|
UpdateUser(userID int64, user *models.User) error
|
|
FindUserByID(id int64) (*models.User, error)
|
|
FindUserByEmail(email string) (*models.User, error)
|
|
SetVerificationToken(user *models.User, token *string) (int64, error)
|
|
IsVerified(userID *int64) (bool, error)
|
|
VerifyUserOfToken(token *string) (*models.User, error)
|
|
}
|
|
|
|
type userRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewUserRepository(db *gorm.DB) UserRepository {
|
|
return &userRepository{db}
|
|
}
|
|
|
|
func (repo *userRepository) CreateUser(user *models.User) (int64, error) {
|
|
result := repo.db.Create(user)
|
|
if result.Error != nil {
|
|
return 0, result.Error
|
|
}
|
|
return user.ID, nil
|
|
}
|
|
|
|
func (repo *userRepository) UpdateUser(userID int64, user *models.User) error {
|
|
logger.Info.Printf("Updating User: %#v\n", user)
|
|
if user == nil {
|
|
return errors.ErrNoData
|
|
}
|
|
result := repo.db.Session(&gorm.Session{FullSaveAssociations: true}).Updates(&user)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return errors.ErrNoRowsAffected
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (repo *userRepository) FindUserByID(id int64) (*models.User, error) {
|
|
var user models.User
|
|
result := repo.db.Preload("Consents").Preload("BankAccount").Preload("Verification").Preload("Membership").First(&user, id)
|
|
if result.Error != nil {
|
|
if result.Error == gorm.ErrRecordNotFound {
|
|
return nil, gorm.ErrRecordNotFound
|
|
}
|
|
return nil, result.Error
|
|
}
|
|
return &user, nil
|
|
}
|
|
|
|
func (repo *userRepository) FindUserByEmail(email string) (*models.User, error) {
|
|
var user models.User
|
|
result := repo.db.Where("email = ?", email).First(&user)
|
|
if result.Error != nil {
|
|
if result.Error == gorm.ErrRecordNotFound {
|
|
return nil, gorm.ErrRecordNotFound
|
|
}
|
|
return nil, result.Error
|
|
}
|
|
return &user, nil
|
|
}
|
|
|
|
func (repo *userRepository) IsVerified(userID *int64) (bool, error) {
|
|
var user models.User
|
|
result := repo.db.Select("status").First(&user, userID)
|
|
if result.Error != nil {
|
|
if result.Error == gorm.ErrRecordNotFound {
|
|
return false, gorm.ErrRecordNotFound
|
|
}
|
|
return false, result.Error
|
|
}
|
|
return user.Status != constants.UnverifiedStatus, nil
|
|
}
|
|
|
|
func (repo *userRepository) VerifyUserOfToken(token *string) (*models.User, error) {
|
|
var emailVerification models.Verification
|
|
result := repo.db.Where("verification_token = ?", token).First(&emailVerification)
|
|
if result.Error != nil {
|
|
if result.Error == gorm.ErrRecordNotFound {
|
|
return nil, gorm.ErrRecordNotFound
|
|
}
|
|
return nil, result.Error
|
|
}
|
|
|
|
// Check if the user is already verified
|
|
verified, err := repo.IsVerified(&emailVerification.UserID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
user, err := repo.FindUserByID(emailVerification.UserID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if verified {
|
|
return user, errors.ErrAlreadyVerified
|
|
}
|
|
// Update user status to active
|
|
t := time.Now()
|
|
emailVerification.EmailVerifiedAt = &t
|
|
user.Status = constants.VerifiedStatus
|
|
user.Verification = emailVerification
|
|
|
|
err = repo.UpdateUser(emailVerification.UserID, user)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return user, nil
|
|
}
|
|
|
|
func (repo *userRepository) SetVerificationToken(user *models.User, token *string) (int64, error) {
|
|
// Check if user is already verified
|
|
verified, err := repo.IsVerified(&user.ID)
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
if verified {
|
|
return -1, errors.ErrAlreadyVerified
|
|
}
|
|
|
|
// Prepare the Verification record
|
|
verification := models.Verification{
|
|
UserID: user.ID,
|
|
VerificationToken: *token,
|
|
}
|
|
|
|
// Use GORM to insert or update the Verification record
|
|
result := repo.db.Clauses(clause.OnConflict{
|
|
Columns: []clause.Column{{Name: "user_id"}},
|
|
DoUpdates: clause.AssignmentColumns([]string{"verification_token", "created_at"}),
|
|
}).Create(&verification)
|
|
|
|
if result.Error != nil {
|
|
return -1, result.Error
|
|
}
|
|
|
|
return verification.ID, nil
|
|
}
|