This commit is contained in:
Alex
2025-04-10 15:40:22 +02:00
parent 87f08dd3be
commit 18f5dadb06
48 changed files with 1650 additions and 981 deletions

View File

@@ -3,7 +3,6 @@ package models
import (
"GoMembership/internal/config"
"GoMembership/internal/constants"
"GoMembership/internal/utils"
"GoMembership/pkg/errors"
"GoMembership/pkg/logger"
"fmt"
@@ -45,7 +44,7 @@ type User struct {
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
if u.BankAccount != nil && u.BankAccount.MandateReference == "" {
u.BankAccount.MandateReference = u.GenerateMandateReference()
u.BankAccount.MandateReference = u.BankAccount.GenerateMandateReference(u.ID)
u.BankAccount.Update(tx)
}
return nil
@@ -53,38 +52,16 @@ func (u *User) AfterCreate(tx *gorm.DB) (err error) {
func (u *User) BeforeSave(tx *gorm.DB) (err error) {
u.Email = strings.ToLower(u.Email)
return nil
}
func (u *User) GenerateMandateReference() string {
return fmt.Sprintf("%s%d%s", time.Now().Format("20060102"), u.ID, u.BankAccount.IBAN)
}
func (u *User) SetPassword(plaintextPassword string) error {
if plaintextPassword == "" {
return nil
if u.Password != "" {
hash, err := argon2id.CreateHash(u.Password, argon2id.DefaultParams)
if err != nil {
return err
}
u.Password = hash
}
hash, err := argon2id.CreateHash(plaintextPassword, argon2id.DefaultParams)
if err != nil {
return err
}
u.Password = hash
return nil
}
func (u *User) PasswordMatches(plaintextPassword string) (bool, error) {
return argon2id.ComparePasswordAndHash(plaintextPassword, u.Password)
}
func (u *User) PasswordExists() bool {
return u.Password != ""
}
func (u *User) Delete(db *gorm.DB) error {
return db.Delete(&User{}, "id = ?", u.ID).Error
}
func (u *User) Create(db *gorm.DB) error {
return db.Transaction(func(tx *gorm.DB) error {
@@ -96,118 +73,6 @@ func (u *User) Create(db *gorm.DB) error {
})
}
// return db.Transaction(func(tx *gorm.DB) error {
// // Initialize slices/pointers if nil
// if u.Verifications == nil {
// u.Verifications = &[]Verification{}
// }
// // Create base user first
// if err := tx.Omit(clause.Associations).Create(u).Error; err != nil {
// return fmt.Errorf("failed to create user: %w", err)
// }
// // Handle BankAccount
// if u.BankAccount != (BankAccount{}) {
// u.BankAccount.MandateReference = u.GenerateMandateReference()
// if err := tx.Create(&u.BankAccount).Error; err != nil {
// return fmt.Errorf("failed to create bank account: %w", err)
// }
// if err := tx.Model(u).Update("bank_account_id", u.BankAccount.ID).Error; err != nil {
// return fmt.Errorf("failed to link bank account: %w", err)
// }
// }
// // Handle Membership and SubscriptionModel
// if u.Membership != (Membership{}) {
// if err := tx.Create(&u.Membership).Error; err != nil {
// return fmt.Errorf("failed to create membership: %w", err)
// }
// if err := tx.Model(u).Update("membership_id", u.Membership.ID).Error; err != nil {
// return fmt.Errorf("failed to link membership: %w", err)
// }
// }
// // Handle Licence and Categories
// if u.Licence != nil {
// u.Licence.UserID = u.ID
// if err := tx.Create(u.Licence).Error; err != nil {
// return fmt.Errorf("failed to create licence: %w", err)
// }
// if len(u.Licence.Categories) > 0 {
// if err := tx.Model(u.Licence).Association("Categories").Replace(u.Licence.Categories); err != nil {
// return fmt.Errorf("failed to link categories: %w", err)
// }
// }
// if err := tx.Model(u).Update("licence_id", u.Licence.ID).Error; err != nil {
// return fmt.Errorf("failed to link licence: %w", err)
// }
// }
// // Handle Consents
// for i := range u.Consents {
// u.Consents[i].UserID = u.ID
// }
// if len(u.Consents) > 0 {
// if err := tx.Create(&u.Consents).Error; err != nil {
// return fmt.Errorf("failed to create consents: %w", err)
// }
// }
// // Handle Verifications
// for i := range *u.Verifications {
// (*u.Verifications)[i].UserID = u.ID
// }
// if len(*u.Verifications) > 0 {
// if err := tx.Create(u.Verifications).Error; err != nil {
// return fmt.Errorf("failed to create verifications: %w", err)
// }
// }
// // Reload the complete user with all associations
// return tx.Preload(clause.Associations).
// Preload("Membership.SubscriptionModel").
// Preload("Licence.Categories").
// First(u, u.ID).Error
// })
// }
// func (u *User) Create(db *gorm.DB) error {
// return db.Transaction(func(tx *gorm.DB) error {
// // Create the base User record (omit associations to handle them separately)
// if err := tx.Create(u).Error; err != nil {
// return err
// }
// for i := range u.Consents {
// u.Consents[i].UserID = u.ID
// }
// for i := range *u.Verifications {
// (*u.Verifications)[i].UserID = u.ID
// }
// if err := tx.Session(&gorm.Session{FullSaveAssociations: true}).Updates(u).Error; err != nil {
// return err
// }
// // Replace associated Categories (assumes Categories already exist)
// if u.Licence != nil && len(u.Licence.Categories) > 0 {
// if err := tx.Model(u.Licence).Association("Categories").Replace(u.Licence.Categories); err != nil {
// return err
// }
// }
// logger.Info.Printf("user created: %#v", u.Safe())
// // Preload all associations to return the fully populated User
// return tx.
// Preload(clause.Associations).
// Preload("Membership.SubscriptionModel").
// Preload("Licence.Categories").
// First(u, u.ID).Error // Refresh the user object with all associations
// })
// }
func (u *User) Update(db *gorm.DB) error {
err := db.Transaction(func(tx *gorm.DB) error {
@@ -220,7 +85,7 @@ func (u *User) Update(db *gorm.DB) error {
return err
}
// Update the user's main fields
result := tx.Session(&gorm.Session{FullSaveAssociations: true}).Omit("Password", "Verifications", "Licence.Categories").Updates(u)
result := tx.Session(&gorm.Session{FullSaveAssociations: true}).Omit("Verifications", "Licence.Categories").Updates(u)
if result.Error != nil {
logger.Error.Printf("User update error in update user: %#v", result.Error)
return result.Error
@@ -229,57 +94,6 @@ func (u *User) Update(db *gorm.DB) error {
return errors.ErrNoRowsAffected
}
if u.Password != "" {
if err := tx.Model(&existingUser).
Update("Password", u.Password).Error; err != nil {
logger.Error.Printf("Password update error in update user: %#v", err)
return err
}
}
// // Update the Membership if provided
// if u.Membership.ID != 0 {
// if err := tx.Model(&existingUser.Membership).Updates(u.Membership).Where("id = ?", existingUser.Membership.ID).Error; err != nil {
// logger.Error.Printf("Membership update error in update user: %#v", err)
// return err
// }
// }
// if u.Licence != nil {
// u.Licence.UserID = existingUser.ID
// if err := tx.Save(u.Licence).Error; err != nil {
// return err
// }
// if err := tx.Model(&existingUser).Update("LicenceID", u.Licence.ID).Error; err != nil {
// return err
// }
// if err := tx.Model(u.Licence).Association("Categories").Replace(u.Licence.Categories); err != nil {
// return err
// }
// }
// if u.Licence != nil {
// if existingUser.Licence == nil || existingUser.LicenceID == 0 {
// u.Licence.UserID = existingUser.ID // Ensure Licence belongs to User
// if err := tx.Create(u.Licence).Error; err != nil {
// return err
// }
// existingUser.Licence = u.Licence
// existingUser.LicenceID = u.Licence.ID
// if err := tx.Model(&existingUser).Update("LicenceID", u.Licence.ID).Error; err != nil {
// return err
// }
// }
// if err := tx.Model(existingUser.Licence).Updates(u.Licence).Error; err != nil {
// return err
// }
// // Update Categories association
// if err := tx.Model(existingUser.Licence).Association("Categories").Replace(u.Licence.Categories); err != nil {
// return err
// }
// }
if u.Verifications != nil {
if err := tx.Save(u.Verifications).Error; err != nil {
return err
@@ -300,16 +114,20 @@ func (u *User) Update(db *gorm.DB) error {
return db.
Preload(clause.Associations).
Preload("Membership.SubscriptionModel").
Preload("Membership.Subscription").
Preload("Licence.Categories").
First(&u, u.ID).Error
}
func (u *User) Delete(db *gorm.DB) error {
return db.Delete(&User{}, "id = ?", u.ID).Error
}
func (u *User) FromID(db *gorm.DB, userID *uint) error {
var user User
result := db.
Preload(clause.Associations).
Preload("Membership.SubscriptionModel").
Preload("Membership.Subscription").
Preload("Licence.Categories").
First(&user, userID)
if result.Error != nil {
@@ -326,7 +144,7 @@ func (u *User) FromEmail(db *gorm.DB, email *string) error {
var user User
result := db.
Preload(clause.Associations).
Preload("Membership.SubscriptionModel").
Preload("Membership.Subscription").
Preload("Licence.Categories").
Where("email = ?", email).First(&user)
if result.Error != nil {
@@ -354,6 +172,14 @@ func (u *User) FromContext(db *gorm.DB, c *gin.Context) error {
return nil
}
func (u *User) PasswordMatches(plaintextPassword string) (bool, error) {
return argon2id.ComparePasswordAndHash(plaintextPassword, u.Password)
}
func (u *User) PasswordExists() bool {
return u.Password != ""
}
func (u *User) IsVerified() bool {
return u.Status > constants.DisabledStatus
}
@@ -378,24 +204,20 @@ func (u *User) SetVerification(verificationType string) (*Verification, error) {
if u.Verifications == nil {
u.Verifications = []Verification{}
}
token, err := utils.GenerateVerificationToken()
v, err := CreateVerification(verificationType)
if err != nil {
return nil, err
}
v := Verification{
UserID: u.ID,
VerificationToken: token,
Type: verificationType,
}
v.UserID = u.ID
if vi := slices.IndexFunc(u.Verifications, func(vsl Verification) bool { return vsl.Type == v.Type }); vi > -1 {
u.Verifications[vi] = v
u.Verifications[vi] = *v
} else {
u.Verifications = append(u.Verifications, v)
u.Verifications = append(u.Verifications, *v)
}
return &v, nil
return v, nil
}
func (u *User) GetVerification(verificationType string) (*Verification, error) {
func (u *User) FindVerification(verificationType string) (*Verification, error) {
if u.Verifications == nil {
return nil, errors.ErrNoData
}
@@ -406,10 +228,10 @@ func (u *User) GetVerification(verificationType string) (*Verification, error) {
return &u.Verifications[vi], nil
}
func (u *User) Verify(token string, verificationType string) bool {
func (u *User) Verify(token string, verificationType string) error {
if token == "" || verificationType == "" {
logger.Error.Printf("token or verification type are empty in user.Verify")
return false
return errors.ErrNoData
}
vi := slices.IndexFunc(u.Verifications, func(vsl Verification) bool {
@@ -418,17 +240,9 @@ func (u *User) Verify(token string, verificationType string) bool {
if vi == -1 {
logger.Error.Printf("Couldn't find verification in users verifications")
return false
return errors.ErrNotFound
}
if u.Verifications[vi].VerifiedAt != nil {
logger.Error.Printf("VerifiedAt is not nil, already verified?: %#v", u.Verifications[vi])
return false
}
t := time.Now()
u.Verifications[vi].VerifiedAt = &t
return true
return u.Verifications[vi].Validate()
}
func (u *User) Safe() map[string]interface{} {
@@ -442,14 +256,14 @@ func (u *User) Safe() map[string]interface{} {
"end_date": u.Membership.EndDate,
"status": u.Membership.Status,
"subscription": map[string]interface{}{
"id": u.Membership.SubscriptionModel.ID,
"name": u.Membership.SubscriptionModel.Name,
"details": u.Membership.SubscriptionModel.Details,
"conditions": u.Membership.SubscriptionModel.Conditions,
"monthly_fee": u.Membership.SubscriptionModel.MonthlyFee,
"hourly_rate": u.Membership.SubscriptionModel.HourlyRate,
"included_per_year": u.Membership.SubscriptionModel.IncludedPerYear,
"included_per_month": u.Membership.SubscriptionModel.IncludedPerMonth,
"id": u.Membership.Subscription.ID,
"name": u.Membership.Subscription.Name,
"details": u.Membership.Subscription.Details,
"conditions": u.Membership.Subscription.Conditions,
"monthly_fee": u.Membership.Subscription.MonthlyFee,
"hourly_rate": u.Membership.Subscription.HourlyRate,
"included_per_year": u.Membership.Subscription.IncludedPerYear,
"included_per_month": u.Membership.Subscription.IncludedPerMonth,
},
}
}
@@ -543,7 +357,7 @@ func GetUsersWhere(db *gorm.DB, where map[string]interface{}) (*[]User, error) {
var users []User
result := db.
Preload(clause.Associations).
Preload("Membership.SubscriptionModel").
Preload("Membership.Subscription").
Preload("Licence.Categories").
Where(where).Find(&users)
if result.Error != nil {