Files
GoMembership/internal/repositories/user_repository.go
$(pass /github/name) 6ac5491053 switched to gorm..
2024-07-10 14:22:56 +02:00

153 lines
3.8 KiB
Go

package repositories
import (
"GoMembership/internal/constants"
"time"
"gorm.io/gorm"
"GoMembership/internal/models"
"GoMembership/pkg/errors"
"gorm.io/gorm/clause"
)
type UserRepository interface {
CreateUser(user *models.User) (int64, 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) (int64, 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, updates map[string]interface{}) error {
if len(updates) == 0 {
return errors.ErrNoData
}
result := repo.db.Session(&gorm.Session{FullSaveAssociations: true}).Model(&models.User{}).Where("id = ?", userID).Updates(&updates)
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.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) (int64, error) {
var emailVerification models.Verification
result := repo.db.Where("verification_token = ?", token).First(&emailVerification)
if result.Error != nil {
if result.Error == gorm.ErrRecordNotFound {
return 0, gorm.ErrRecordNotFound
}
return 0, result.Error
}
// Check if the user is already verified
verified, err := repo.IsVerified(&emailVerification.UserID)
if err != nil {
return 0, err
}
if verified {
return emailVerification.UserID, gorm.ErrRecordNotFound
}
// Update user status to active
t := time.Now()
emailVerification.EmailVerifiedAt = &t
update := map[string]interface{}{
"status": constants.VerifiedStatus,
"verifications": emailVerification,
}
err = repo.UpdateUser(emailVerification.UserID, update)
if err != nil {
return 0, err
}
return emailVerification.UserID, 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
}