Compare commits
5 Commits
490b29295f
...
2af4575ff2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2af4575ff2 | ||
|
|
560623788a | ||
|
|
5d55f5a8d9 | ||
|
|
28dfe7ecde | ||
|
|
741145b960 |
@@ -18,7 +18,7 @@ func main() {
|
|||||||
|
|
||||||
config.LoadConfig()
|
config.LoadConfig()
|
||||||
|
|
||||||
db, err := database.Open(config.DB.Path, config.Recipients.AdminEmail)
|
db, err := database.Open(config.DB.Path, config.Recipients.AdminEmail, config.Env == "development")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error.Fatalf("Couldn't init database: %v", err)
|
logger.Error.Fatalf("Couldn't init database: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,12 +77,14 @@ var Priviliges = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var Roles = struct {
|
var Roles = struct {
|
||||||
|
Opponent int8
|
||||||
Supporter int8
|
Supporter int8
|
||||||
Member int8
|
Member int8
|
||||||
Viewer int8
|
Viewer int8
|
||||||
Editor int8
|
Editor int8
|
||||||
Admin int8
|
Admin int8
|
||||||
}{
|
}{
|
||||||
|
Opponent: -5,
|
||||||
Supporter: 0,
|
Supporter: 0,
|
||||||
Member: 1,
|
Member: 1,
|
||||||
Viewer: 2,
|
Viewer: 2,
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func TestMain(t *testing.T) {
|
|||||||
log.Fatalf("Error setting environment variable: %v", err)
|
log.Fatalf("Error setting environment variable: %v", err)
|
||||||
}
|
}
|
||||||
config.LoadConfig()
|
config.LoadConfig()
|
||||||
db, err := database.Open("test.db", config.Recipients.AdminEmail)
|
db, err := database.Open("test.db", config.Recipients.AdminEmail, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to create DB: %#v", err)
|
log.Fatalf("Failed to create DB: %#v", err)
|
||||||
}
|
}
|
||||||
@@ -130,10 +130,18 @@ func TestMain(t *testing.T) {
|
|||||||
ZipCode: "12345",
|
ZipCode: "12345",
|
||||||
City: "SampleCity",
|
City: "SampleCity",
|
||||||
Status: constants.ActiveStatus,
|
Status: constants.ActiveStatus,
|
||||||
RoleID: 8,
|
Password: "",
|
||||||
}
|
Notes: "",
|
||||||
|
RoleID: constants.Roles.Admin,
|
||||||
|
Consents: nil,
|
||||||
|
Verifications: nil,
|
||||||
|
Membership: nil,
|
||||||
|
BankAccount: nil,
|
||||||
|
Licence: &models.Licence{
|
||||||
|
Status: constants.UnverifiedStatus,
|
||||||
|
}}
|
||||||
admin.SetPassword("securepassword")
|
admin.SetPassword("securepassword")
|
||||||
database.DB.Create(&admin)
|
admin.Create(db)
|
||||||
validation.SetupValidators(db)
|
validation.SetupValidators(db)
|
||||||
t.Run("userController", func(t *testing.T) {
|
t.Run("userController", func(t *testing.T) {
|
||||||
testUserController(t)
|
testUserController(t)
|
||||||
@@ -275,10 +283,9 @@ func getBaseUser() models.User {
|
|||||||
ZipCode: "25474",
|
ZipCode: "25474",
|
||||||
City: "Hasloh",
|
City: "Hasloh",
|
||||||
Phone: "01738484993",
|
Phone: "01738484993",
|
||||||
BankAccount: models.BankAccount{IBAN: "DE89370400440532013000"},
|
BankAccount: &models.BankAccount{IBAN: "DE89370400440532013000"},
|
||||||
Membership: models.Membership{SubscriptionModel: models.SubscriptionModel{Name: "Basic"}},
|
Membership: &models.Membership{SubscriptionModel: models.SubscriptionModel{Name: "Basic"}},
|
||||||
Licence: nil,
|
Licence: nil,
|
||||||
ProfilePicture: "",
|
|
||||||
Password: "passw@#$#%$!-ord123",
|
Password: "passw@#$#%$!-ord123",
|
||||||
Company: "",
|
Company: "",
|
||||||
RoleID: 1,
|
RoleID: 1,
|
||||||
@@ -295,10 +302,9 @@ func getBaseSupporter() models.User {
|
|||||||
ZipCode: "25474",
|
ZipCode: "25474",
|
||||||
City: "Hasloh",
|
City: "Hasloh",
|
||||||
Phone: "01738484993",
|
Phone: "01738484993",
|
||||||
BankAccount: models.BankAccount{IBAN: "DE89370400440532013000"},
|
BankAccount: &models.BankAccount{IBAN: "DE89370400440532013000"},
|
||||||
Membership: models.Membership{SubscriptionModel: models.SubscriptionModel{Name: "Basic"}},
|
Membership: &models.Membership{SubscriptionModel: models.SubscriptionModel{Name: "Basic"}},
|
||||||
Licence: nil,
|
Licence: nil,
|
||||||
ProfilePicture: "",
|
|
||||||
Password: "passw@#$#%$!-ord123",
|
Password: "passw@#$#%$!-ord123",
|
||||||
Company: "",
|
Company: "",
|
||||||
RoleID: 0,
|
RoleID: 0,
|
||||||
|
|||||||
@@ -31,8 +31,10 @@ func setupTestContext() (*TestContext, error) {
|
|||||||
testEmail := "john.doe@example.com"
|
testEmail := "john.doe@example.com"
|
||||||
user, err := Uc.Service.FromEmail(&testEmail)
|
user, err := Uc.Service.FromEmail(&testEmail)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logger.Error.Printf("error fetching user: %#v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
logger.Error.Printf("found user: %#v", user)
|
||||||
return &TestContext{
|
return &TestContext{
|
||||||
router: gin.Default(),
|
router: gin.Default(),
|
||||||
response: httptest.NewRecorder(),
|
response: httptest.NewRecorder(),
|
||||||
@@ -60,7 +62,6 @@ func testCreatePasswordHandler(t *testing.T) {
|
|||||||
req, _ := http.NewRequest("POST", "/password", bytes.NewBuffer(body))
|
req, _ := http.NewRequest("POST", "/password", bytes.NewBuffer(body))
|
||||||
req.AddCookie(AdminCookie)
|
req.AddCookie(AdminCookie)
|
||||||
tc.router.ServeHTTP(tc.response, req)
|
tc.router.ServeHTTP(tc.response, req)
|
||||||
logger.Error.Printf("Test results for %#v", t.Name())
|
|
||||||
assert.Equal(t, http.StatusAccepted, tc.response.Code)
|
assert.Equal(t, http.StatusAccepted, tc.response.Code)
|
||||||
assert.JSONEq(t, `{"message":"password_change_requested"}`, tc.response.Body.String())
|
assert.JSONEq(t, `{"message":"password_change_requested"}`, tc.response.Body.String())
|
||||||
err = checkEmailDelivery(tc.user, true)
|
err = checkEmailDelivery(tc.user, true)
|
||||||
|
|||||||
@@ -137,9 +137,7 @@ func (uc *UserController) DeleteUser(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type deleteData struct {
|
type deleteData struct {
|
||||||
User struct {
|
|
||||||
ID uint `json:"id" binding:"required,numeric"`
|
ID uint `json:"id" binding:"required,numeric"`
|
||||||
} `json:"user"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var data deleteData
|
var data deleteData
|
||||||
@@ -148,13 +146,13 @@ func (uc *UserController) DeleteUser(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !requestUser.HasPrivilege(constants.Priviliges.Delete) && data.User.ID != requestUser.ID {
|
if !requestUser.HasPrivilege(constants.Priviliges.Delete) && data.ID != requestUser.ID {
|
||||||
utils.RespondWithError(c, errors.ErrNotAuthorized, "Not allowed to delete user", http.StatusForbidden, errors.Responses.Fields.User, errors.Responses.Keys.Unauthorized)
|
utils.RespondWithError(c, errors.ErrNotAuthorized, "Not allowed to delete user", http.StatusForbidden, errors.Responses.Fields.User, errors.Responses.Keys.Unauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Error.Printf("Deleting user: %v", data.User)
|
logger.Error.Printf("Deleting user: %v", data)
|
||||||
if err := uc.Service.Delete(&data.User.ID); err != nil {
|
if err := uc.Service.Delete(&data.ID); err != nil {
|
||||||
utils.HandleDeleteUserError(c, err)
|
utils.HandleDeleteUserError(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -291,12 +289,14 @@ func (uc *UserController) RegisterUser(c *gin.Context) {
|
|||||||
LastName: regData.User.LastName,
|
LastName: regData.User.LastName,
|
||||||
Email: regData.User.Email,
|
Email: regData.User.Email,
|
||||||
ConsentType: "TermsOfService",
|
ConsentType: "TermsOfService",
|
||||||
|
UserID: regData.User.ID,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
FirstName: regData.User.FirstName,
|
FirstName: regData.User.FirstName,
|
||||||
LastName: regData.User.LastName,
|
LastName: regData.User.LastName,
|
||||||
Email: regData.User.Email,
|
Email: regData.User.Email,
|
||||||
ConsentType: "Privacy",
|
ConsentType: "Privacy",
|
||||||
|
UserID: regData.User.ID,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ func testUserController(t *testing.T) {
|
|||||||
database.DB.Model(&models.User{}).Where("email = ?", "john.doe@example.com").Update("status", constants.ActiveStatus)
|
database.DB.Model(&models.User{}).Where("email = ?", "john.doe@example.com").Update("status", constants.ActiveStatus)
|
||||||
loginEmail := testLoginHandler(t)
|
loginEmail := testLoginHandler(t)
|
||||||
testCurrentUserHandler(t, loginEmail)
|
testCurrentUserHandler(t, loginEmail)
|
||||||
|
|
||||||
// creating a admin cookie
|
// creating a admin cookie
|
||||||
c, w, _ := GetMockedJSONContext([]byte(`{
|
c, w, _ := GetMockedJSONContext([]byte(`{
|
||||||
"email": "admin@example.com",
|
"email": "admin@example.com",
|
||||||
@@ -402,7 +401,6 @@ func validateUser(assert bool, wantDBData map[string]interface{}) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error in database ops: %#v", err)
|
return fmt.Errorf("Error in database ops: %#v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if assert != (len(*users) != 0) {
|
if assert != (len(*users) != 0) {
|
||||||
return fmt.Errorf("User entry query didn't met expectation: %v != %#v", assert, *users)
|
return fmt.Errorf("User entry query didn't met expectation: %v != %#v", assert, *users)
|
||||||
}
|
}
|
||||||
@@ -575,7 +573,7 @@ func testUpdateUser(t *testing.T) {
|
|||||||
var licenceRepo repositories.LicenceInterface = &repositories.LicenceRepository{}
|
var licenceRepo repositories.LicenceInterface = &repositories.LicenceRepository{}
|
||||||
category, err := licenceRepo.FindCategoryByName("B")
|
category, err := licenceRepo.FindCategoryByName("B")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.Licence.Categories = []models.Category{category}
|
u.Licence.Categories = []*models.Category{&category}
|
||||||
},
|
},
|
||||||
expectedStatus: http.StatusAccepted,
|
expectedStatus: http.StatusAccepted,
|
||||||
},
|
},
|
||||||
@@ -594,7 +592,7 @@ func testUpdateUser(t *testing.T) {
|
|||||||
category, err := licenceRepo.FindCategoryByName("A")
|
category, err := licenceRepo.FindCategoryByName("A")
|
||||||
category2, err := licenceRepo.FindCategoryByName("BE")
|
category2, err := licenceRepo.FindCategoryByName("BE")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.Licence.Categories = []models.Category{category, category2}
|
u.Licence.Categories = []*models.Category{&category, &category2}
|
||||||
},
|
},
|
||||||
expectedStatus: http.StatusAccepted,
|
expectedStatus: http.StatusAccepted,
|
||||||
},
|
},
|
||||||
@@ -612,7 +610,7 @@ func testUpdateUser(t *testing.T) {
|
|||||||
var licenceRepo repositories.LicenceInterface = &repositories.LicenceRepository{}
|
var licenceRepo repositories.LicenceInterface = &repositories.LicenceRepository{}
|
||||||
category, err := licenceRepo.FindCategoryByName("A")
|
category, err := licenceRepo.FindCategoryByName("A")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
u.Licence.Categories = []models.Category{category}
|
u.Licence.Categories = []*models.Category{&category}
|
||||||
},
|
},
|
||||||
expectedStatus: http.StatusAccepted,
|
expectedStatus: http.StatusAccepted,
|
||||||
},
|
},
|
||||||
@@ -627,7 +625,7 @@ func testUpdateUser(t *testing.T) {
|
|||||||
u.LastName = "Doe Updated"
|
u.LastName = "Doe Updated"
|
||||||
u.Phone = "01738484994"
|
u.Phone = "01738484994"
|
||||||
u.Licence.Number = "B072RRE2I50"
|
u.Licence.Number = "B072RRE2I50"
|
||||||
u.Licence.Categories = []models.Category{}
|
u.Licence.Categories = []*models.Category{}
|
||||||
},
|
},
|
||||||
expectedStatus: http.StatusAccepted,
|
expectedStatus: http.StatusAccepted,
|
||||||
},
|
},
|
||||||
@@ -806,11 +804,9 @@ func testUpdateUser(t *testing.T) {
|
|||||||
assert.Equal(t, updatedUser.Company, updatedUserFromDB.Company, "Company mismatch")
|
assert.Equal(t, updatedUser.Company, updatedUserFromDB.Company, "Company mismatch")
|
||||||
assert.Equal(t, updatedUser.Phone, updatedUserFromDB.Phone, "Phone mismatch")
|
assert.Equal(t, updatedUser.Phone, updatedUserFromDB.Phone, "Phone mismatch")
|
||||||
assert.Equal(t, updatedUser.Notes, updatedUserFromDB.Notes, "Notes mismatch")
|
assert.Equal(t, updatedUser.Notes, updatedUserFromDB.Notes, "Notes mismatch")
|
||||||
assert.Equal(t, updatedUser.ProfilePicture, updatedUserFromDB.ProfilePicture, "ProfilePicture mismatch")
|
|
||||||
assert.Equal(t, updatedUser.Address, updatedUserFromDB.Address, "Address mismatch")
|
assert.Equal(t, updatedUser.Address, updatedUserFromDB.Address, "Address mismatch")
|
||||||
assert.Equal(t, updatedUser.ZipCode, updatedUserFromDB.ZipCode, "ZipCode mismatch")
|
assert.Equal(t, updatedUser.ZipCode, updatedUserFromDB.ZipCode, "ZipCode mismatch")
|
||||||
assert.Equal(t, updatedUser.City, updatedUserFromDB.City, "City mismatch")
|
assert.Equal(t, updatedUser.City, updatedUserFromDB.City, "City mismatch")
|
||||||
assert.Equal(t, updatedUser.PaymentStatus, updatedUserFromDB.PaymentStatus, "PaymentStatus mismatch")
|
|
||||||
assert.Equal(t, updatedUser.Status, updatedUserFromDB.Status, "Status mismatch")
|
assert.Equal(t, updatedUser.Status, updatedUserFromDB.Status, "Status mismatch")
|
||||||
assert.Equal(t, updatedUser.RoleID, updatedUserFromDB.RoleID, "RoleID mismatch")
|
assert.Equal(t, updatedUser.RoleID, updatedUserFromDB.RoleID, "RoleID mismatch")
|
||||||
|
|
||||||
@@ -839,8 +835,17 @@ func testUpdateUser(t *testing.T) {
|
|||||||
assert.Equal(t, updatedUser.Licence.IssuingCountry, updatedUserFromDB.Licence.IssuingCountry, "Licence.IssuingCountry mismatch")
|
assert.Equal(t, updatedUser.Licence.IssuingCountry, updatedUserFromDB.Licence.IssuingCountry, "Licence.IssuingCountry mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
// For slices or more complex nested structures, you might want to use deep equality checks
|
if len(updatedUser.Consents) > 0 {
|
||||||
assert.ElementsMatch(t, updatedUser.Consents, updatedUserFromDB.Consents, "Consents mismatch")
|
for i := range updatedUser.Consents {
|
||||||
|
assert.Equal(t, updatedUser.Consents[i].ConsentType, updatedUserFromDB.Consents[i].ConsentType, "ConsentType mismatch at index %d", i)
|
||||||
|
assert.Equal(t, updatedUser.Consents[i].Email, updatedUserFromDB.Consents[i].Email, "ConsentEmail mismatch at index %d", i)
|
||||||
|
assert.Equal(t, updatedUser.Consents[i].FirstName, updatedUserFromDB.Consents[i].FirstName, "ConsentFirstName mismatch at index %d", i)
|
||||||
|
assert.Equal(t, updatedUser.Consents[i].LastName, updatedUserFromDB.Consents[i].LastName, "ConsentLastName mismatch at index %d", i)
|
||||||
|
assert.Equal(t, updatedUser.Consents[i].UserID, updatedUserFromDB.Consents[i].UserID, "Consent UserId mismatch at index %d", i)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert.Emptyf(t, updatedUserFromDB.Licence.Categories, "Categories aren't empty when they should")
|
||||||
|
}
|
||||||
if len(updatedUser.Licence.Categories) > 0 {
|
if len(updatedUser.Licence.Categories) > 0 {
|
||||||
for i := range updatedUser.Licence.Categories {
|
for i := range updatedUser.Licence.Categories {
|
||||||
assert.Equal(t, updatedUser.Licence.Categories[i].Name, updatedUserFromDB.Licence.Categories[i].Name, "Category Category mismatch at index %d", i)
|
assert.Equal(t, updatedUser.Licence.Categories[i].Name, updatedUserFromDB.Licence.Categories[i].Name, "Category Category mismatch at index %d", i)
|
||||||
@@ -1272,7 +1277,7 @@ func getTestUsers() []RegisterUserTest {
|
|||||||
{
|
{
|
||||||
Name: "Correct Licence number, should pass",
|
Name: "Correct Licence number, should pass",
|
||||||
WantResponse: http.StatusCreated,
|
WantResponse: http.StatusCreated,
|
||||||
WantDBData: map[string]interface{}{"email": "john.correctLicenceNumber@example.com"},
|
WantDBData: map[string]interface{}{"email": "john.correctlicencenumber@example.com"},
|
||||||
Assert: true,
|
Assert: true,
|
||||||
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
|
Input: GenerateInputJSON(customizeInput(func(user models.User) models.User {
|
||||||
user.Email = "john.correctLicenceNumber@example.com"
|
user.Email = "john.correctLicenceNumber@example.com"
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
"GoMembership/pkg/logger"
|
"GoMembership/pkg/logger"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alexedwards/argon2id"
|
"github.com/alexedwards/argon2id"
|
||||||
@@ -15,27 +17,55 @@ import (
|
|||||||
|
|
||||||
var DB *gorm.DB
|
var DB *gorm.DB
|
||||||
|
|
||||||
func Open(dbPath string, adminMail string) (*gorm.DB, error) {
|
func Open(dbPath string, adminMail string, debug bool) (*gorm.DB, error) {
|
||||||
|
// Add foreign key support and WAL journal mode to DSN
|
||||||
|
dsn := fmt.Sprintf("%s?_foreign_keys=1&_journal_mode=WAL", dbPath)
|
||||||
|
|
||||||
db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
|
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{
|
||||||
|
// Enable PrepareStmt for better performance
|
||||||
|
PrepareStmt: true,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed to connect database: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify foreign key support is enabled
|
||||||
|
var foreignKeyEnabled int
|
||||||
|
if err := db.Raw("PRAGMA foreign_keys").Scan(&foreignKeyEnabled).Error; err != nil {
|
||||||
|
return nil, fmt.Errorf("foreign key check failed: %w", err)
|
||||||
|
}
|
||||||
|
if foreignKeyEnabled != 1 {
|
||||||
|
return nil, errors.New("SQLite foreign key constraints not enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
db = db.Debug()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure connection pool
|
||||||
|
sqlDB, err := db.DB()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get DB instance: %w", err)
|
||||||
|
}
|
||||||
|
sqlDB.SetMaxOpenConns(1) // Required for SQLite in production
|
||||||
|
sqlDB.SetMaxIdleConns(1)
|
||||||
|
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||||
|
|
||||||
if err := db.AutoMigrate(
|
if err := db.AutoMigrate(
|
||||||
&models.User{},
|
&models.User{},
|
||||||
&models.SubscriptionModel{},
|
&models.SubscriptionModel{},
|
||||||
&models.Membership{},
|
&models.Membership{},
|
||||||
&models.Consent{},
|
&models.Consent{},
|
||||||
&models.Verification{},
|
&models.Verification{},
|
||||||
|
&models.BankAccount{},
|
||||||
&models.Licence{},
|
&models.Licence{},
|
||||||
&models.Category{},
|
&models.Category{},
|
||||||
&models.Insurance{},
|
|
||||||
&models.Car{},
|
&models.Car{},
|
||||||
&models.Location{},
|
&models.Location{},
|
||||||
&models.Damage{},
|
&models.Damage{},
|
||||||
&models.BankAccount{}); err != nil {
|
&models.Insurance{},
|
||||||
logger.Error.Fatalf("Couldn't create database: %v", err)
|
); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed to migrate database: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info.Print("Opened DB")
|
logger.Info.Print("Opened DB")
|
||||||
@@ -78,14 +108,11 @@ func Open(dbPath string, adminMail string) (*gorm.DB, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
admin, err := createAdmin(adminMail, createdModel.ID)
|
admin, err := createAdmin(adminMail)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
result := db.Session(&gorm.Session{FullSaveAssociations: true}).Create(&admin)
|
admin.Create(db)
|
||||||
if result.Error != nil {
|
|
||||||
return nil, result.Error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return db, nil
|
return db, nil
|
||||||
@@ -125,7 +152,7 @@ func createLicenceCategories() []models.Category {
|
|||||||
|
|
||||||
// TODO: Landing page to create an admin
|
// TODO: Landing page to create an admin
|
||||||
|
|
||||||
func createAdmin(userMail string, subscriptionModelID uint) (*models.User, error) {
|
func createAdmin(userMail string) (*models.User, error) {
|
||||||
passwordBytes := make([]byte, 12)
|
passwordBytes := make([]byte, 12)
|
||||||
_, err := rand.Read(passwordBytes)
|
_, err := rand.Read(passwordBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -146,26 +173,24 @@ func createAdmin(userMail string, subscriptionModelID uint) (*models.User, error
|
|||||||
logger.Error.Print("==============================================================")
|
logger.Error.Print("==============================================================")
|
||||||
|
|
||||||
return &models.User{
|
return &models.User{
|
||||||
FirstName: "ad",
|
FirstName: "Ad",
|
||||||
LastName: "min",
|
LastName: "Min",
|
||||||
DateOfBirth: time.Now().AddDate(-20, 0, 0),
|
DateOfBirth: time.Now().AddDate(-20, 0, 0),
|
||||||
Password: hash,
|
Password: hash,
|
||||||
Address: "Downhill 4",
|
Company: "",
|
||||||
ZipCode: "99999",
|
Address: "",
|
||||||
City: "TechTown",
|
ZipCode: "",
|
||||||
Phone: "0123455678",
|
City: "",
|
||||||
|
Phone: "",
|
||||||
|
Notes: "",
|
||||||
Email: userMail,
|
Email: userMail,
|
||||||
Status: constants.ActiveStatus,
|
Status: constants.ActiveStatus,
|
||||||
RoleID: constants.Roles.Admin,
|
RoleID: constants.Roles.Admin,
|
||||||
Membership: models.Membership{
|
Consents: nil,
|
||||||
Status: constants.DisabledStatus,
|
Verifications: nil,
|
||||||
StartDate: time.Now(),
|
Membership: nil,
|
||||||
SubscriptionModelID: subscriptionModelID,
|
BankAccount: nil,
|
||||||
},
|
Licence: nil,
|
||||||
BankAccount: models.BankAccount{},
|
|
||||||
Licence: &models.Licence{
|
|
||||||
Status: constants.UnverifiedStatus,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
//"DE49700500000008447644", //fake
|
//"DE49700500000008447644", //fake
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,50 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"GoMembership/pkg/logger"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
type BankAccount struct {
|
type BankAccount struct {
|
||||||
ID uint `gorm:"primaryKey"`
|
ID uint `gorm:"primaryKey"`
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
MandateDateSigned time.Time `gorm:"not null" json:"mandate_date_signed"`
|
UserID uint `gorm:"index" json:"user_id"`
|
||||||
|
MandateDateSigned time.Time `json:"mandate_date_signed"`
|
||||||
Bank string `json:"bank_name" binding:"safe_content"`
|
Bank string `json:"bank_name" binding:"safe_content"`
|
||||||
AccountHolderName string `json:"account_holder_name" binding:"safe_content"`
|
AccountHolderName string `json:"account_holder_name" binding:"safe_content"`
|
||||||
IBAN string `json:"iban" binding:"safe_content"`
|
IBAN string `json:"iban" binding:"safe_content"`
|
||||||
BIC string `json:"bic" binding:"safe_content"`
|
BIC string `json:"bic" binding:"safe_content"`
|
||||||
MandateReference string `gorm:"not null" json:"mandate_reference" binding:"safe_content"`
|
MandateReference string `json:"mandate_reference" binding:"safe_content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BankAccount) Create(db *gorm.DB) error {
|
||||||
|
// b.ID = 0
|
||||||
|
// only the children the belongs to association gets a reference id
|
||||||
|
if err := db.Create(b).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger.Info.Printf("BankAccount created: %#v", b)
|
||||||
|
return db.First(b, b.ID).Error // Refresh the object with all associations
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BankAccount) Update(db *gorm.DB) error {
|
||||||
|
var existingBankAccount BankAccount
|
||||||
|
|
||||||
|
logger.Info.Printf("updating BankAccount: %#v", b)
|
||||||
|
if err := db.First(&existingBankAccount, b.ID).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Model(&existingBankAccount).Updates(b).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return db.First(b, b.ID).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BankAccount) Delete(db *gorm.DB) error {
|
||||||
|
return db.Delete(&b).Error
|
||||||
}
|
}
|
||||||
|
|||||||
48
go-backend/internal/models/category.go
Normal file
48
go-backend/internal/models/category.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"GoMembership/pkg/logger"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Category struct {
|
||||||
|
ID uint `json:"id" gorm:"primaryKey"`
|
||||||
|
Name string `json:"category" binding:"safe_content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Category) 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(c).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger.Info.Printf("Category created: %#v", c)
|
||||||
|
// Preload all associations to return the fully populated User
|
||||||
|
return tx.
|
||||||
|
First(c, c.ID).Error // Refresh the user object with all associations
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Category) Update(db *gorm.DB) error {
|
||||||
|
|
||||||
|
return db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
// Check if the user exists in the database
|
||||||
|
var existingCategory Category
|
||||||
|
|
||||||
|
logger.Info.Printf("updating Category: %#v", c)
|
||||||
|
if err := tx.First(&existingCategory, c.ID).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Model(&existingCategory).Updates(c).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return tx.First(c, c.ID).Error
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Category) Delete(db *gorm.DB) error {
|
||||||
|
return db.Delete(&c).Error
|
||||||
|
}
|
||||||
@@ -1,17 +1,55 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"GoMembership/pkg/logger"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Consent struct {
|
type Consent struct {
|
||||||
|
ID uint `gorm:"primaryKey" json:"id"`
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
FirstName string `gorm:"not null" json:"first_name" binding:"safe_content"`
|
FirstName string `gorm:"not null" json:"first_name" binding:"safe_content"`
|
||||||
LastName string `gorm:"not null" json:"last_name" binding:"safe_content"`
|
LastName string `gorm:"not null" json:"last_name" binding:"safe_content"`
|
||||||
Email string `json:"email" binding:"email,safe_content"`
|
Email string `json:"email" binding:"email,safe_content"`
|
||||||
ConsentType string `gorm:"not null" json:"consent_type" binding:"safe_content"`
|
ConsentType string `gorm:"not null" json:"consent_type" binding:"safe_content"`
|
||||||
ID uint `gorm:"primaryKey"`
|
UserID uint `gorm:"not null" json:"user_id"`
|
||||||
User User
|
}
|
||||||
UserID uint
|
|
||||||
|
func (c *Consent) BeforeSave(tx *gorm.DB) (err error) {
|
||||||
|
c.Email = strings.ToLower(c.Email)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (c *Consent) Create(db *gorm.DB) error {
|
||||||
|
if err := db.Create(c).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger.Info.Printf("Consent created: %#v", c)
|
||||||
|
return db.First(c, c.ID).Error // Refresh the user object with all associations
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Consent) Update(db *gorm.DB) error {
|
||||||
|
|
||||||
|
return db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
// Check if the user exists in the database
|
||||||
|
var existingConsent Consent
|
||||||
|
|
||||||
|
logger.Info.Printf("updating Consent: %#v", c)
|
||||||
|
if err := tx.First(&existingConsent, c.ID).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Model(&existingConsent).Updates(c).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return tx.First(c, c.ID).Error
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Consent) Delete(db *gorm.DB) error {
|
||||||
|
return db.Delete(&c).Error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"GoMembership/pkg/logger"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Licence struct {
|
type Licence struct {
|
||||||
@@ -14,10 +18,49 @@ type Licence struct {
|
|||||||
IssuedDate time.Time `json:"issued_date" binding:"omitempty"`
|
IssuedDate time.Time `json:"issued_date" binding:"omitempty"`
|
||||||
ExpirationDate time.Time `json:"expiration_date" binding:"omitempty"`
|
ExpirationDate time.Time `json:"expiration_date" binding:"omitempty"`
|
||||||
IssuingCountry string `json:"country" binding:"safe_content"`
|
IssuingCountry string `json:"country" binding:"safe_content"`
|
||||||
Categories []Category `json:"categories" gorm:"many2many:licence_2_categories"`
|
Categories []*Category `json:"categories" gorm:"many2many:licence_2_categories"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Category struct {
|
func (l *Licence) BeforeSafe(tx *gorm.DB) error {
|
||||||
ID uint `json:"id" gorm:"primaryKey"`
|
if err := tx.Model(l).Association("Categories").Replace(l.Categories); err != nil {
|
||||||
Name string `json:"category" binding:"safe_content"`
|
return fmt.Errorf("failed to link categories: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Licence) Create(db *gorm.DB) error {
|
||||||
|
if err := db.Omit("Categories").Create(l).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Model(&l).Association("Categories").Replace(l.Categories); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info.Printf("Licence created: %#v", l)
|
||||||
|
return db.Preload("Categories").First(l, l.ID).Error // Refresh the object with Categories
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Licence) Update(db *gorm.DB) error {
|
||||||
|
|
||||||
|
return db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
// Check if the user exists in the database
|
||||||
|
var existingLicence Licence
|
||||||
|
|
||||||
|
logger.Info.Printf("updating Licence: %#v", l)
|
||||||
|
if err := tx.First(&existingLicence, l.ID).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Model(&existingLicence).Updates(l).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return tx.First(l, l.ID).Error
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Licence) Delete(db *gorm.DB) error {
|
||||||
|
return db.Delete(&l).Error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"GoMembership/pkg/logger"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
type Membership struct {
|
type Membership struct {
|
||||||
|
ID uint `gorm:"primaryKey" json:"id"`
|
||||||
|
UserID uint `gorm:"index" json:"user_id"`
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
StartDate time.Time `json:"start_date"`
|
StartDate time.Time `json:"start_date"`
|
||||||
@@ -11,5 +18,41 @@ type Membership struct {
|
|||||||
SubscriptionModel SubscriptionModel `gorm:"foreignKey:SubscriptionModelID" json:"subscription_model"`
|
SubscriptionModel SubscriptionModel `gorm:"foreignKey:SubscriptionModelID" json:"subscription_model"`
|
||||||
SubscriptionModelID uint `json:"subsription_model_id"`
|
SubscriptionModelID uint `json:"subsription_model_id"`
|
||||||
ParentMembershipID uint `json:"parent_member_id" binding:"omitempty,omitnil,number"`
|
ParentMembershipID uint `json:"parent_member_id" binding:"omitempty,omitnil,number"`
|
||||||
ID uint `json:"id"`
|
}
|
||||||
|
|
||||||
|
func (m *Membership) BeforeSave(tx *gorm.DB) error {
|
||||||
|
m.SubscriptionModelID = m.SubscriptionModel.ID
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Membership) Create(db *gorm.DB) error {
|
||||||
|
if err := db.Create(m).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger.Info.Printf("Membership created: %#v", m)
|
||||||
|
|
||||||
|
return db.Preload("SubscriptionModel").First(m, m.ID).Error // Refresh the user object with SubscriptionModel
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Membership) Update(db *gorm.DB) error {
|
||||||
|
|
||||||
|
return db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
// Check if the user exists in the database
|
||||||
|
var existingMembership Membership
|
||||||
|
|
||||||
|
logger.Info.Printf("updating Membership: %#v", m)
|
||||||
|
if err := tx.First(&existingMembership, m.ID).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Model(&existingMembership).Updates(m).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return tx.First(m, m.ID).Error
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Membership) Delete(db *gorm.DB) error {
|
||||||
|
return db.Delete(&m).Error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"GoMembership/pkg/logger"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SubscriptionModel struct {
|
type SubscriptionModel struct {
|
||||||
@@ -17,3 +20,39 @@ type SubscriptionModel struct {
|
|||||||
IncludedPerYear int16 `json:"included_hours_per_year"`
|
IncludedPerYear int16 `json:"included_hours_per_year"`
|
||||||
IncludedPerMonth int16 `json:"included_hours_per_month"`
|
IncludedPerMonth int16 `json:"included_hours_per_month"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SubscriptionModel) 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(s).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger.Info.Printf("SubscriptionModel created: %#v", s)
|
||||||
|
// Preload all associations to retuvn the fully populated User
|
||||||
|
return tx.
|
||||||
|
First(s, s.ID).Error // Refresh the user object with all associations
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SubscriptionModel) Update(db *gorm.DB) error {
|
||||||
|
|
||||||
|
return db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
// Check if the user exists in the database
|
||||||
|
var existingSubscriptionModel SubscriptionModel
|
||||||
|
|
||||||
|
logger.Info.Printf("updating SubscriptionModel: %#v", s)
|
||||||
|
if err := tx.First(&existingSubscriptionModel, s.ID).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Model(&existingSubscriptionModel).Updates(s).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return tx.First(s, s.ID).Error
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SubscriptionModel) Delete(db *gorm.DB) error {
|
||||||
|
return db.Delete(&s).Error
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"GoMembership/pkg/logger"
|
"GoMembership/pkg/logger"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alexedwards/argon2id"
|
"github.com/alexedwards/argon2id"
|
||||||
@@ -18,7 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID uint `gorm:"primarykey" json:"id"`
|
ID uint `gorm:"primaryKey" json:"id"`
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
DeletedAt *time.Time
|
DeletedAt *time.Time
|
||||||
@@ -30,32 +31,31 @@ type User struct {
|
|||||||
Password string `json:"password" binding:"safe_content"`
|
Password string `json:"password" binding:"safe_content"`
|
||||||
Email string `gorm:"uniqueIndex:idx_users_email,not null" json:"email" binding:"required,email,safe_content"`
|
Email string `gorm:"uniqueIndex:idx_users_email,not null" json:"email" binding:"required,email,safe_content"`
|
||||||
LastName string `gorm:"not null" json:"last_name" binding:"required,safe_content"`
|
LastName string `gorm:"not null" json:"last_name" binding:"required,safe_content"`
|
||||||
ProfilePicture string `json:"profile_picture" binding:"omitempty,omitnil,image,safe_content"`
|
|
||||||
Address string `gorm:"not null" json:"address" binding:"required,safe_content"`
|
Address string `gorm:"not null" json:"address" binding:"required,safe_content"`
|
||||||
ZipCode string `gorm:"not null" json:"zip_code" binding:"required,alphanum,safe_content"`
|
ZipCode string `gorm:"not null" json:"zip_code" binding:"required,alphanum,safe_content"`
|
||||||
City string `form:"not null" json:"city" binding:"required,alphaunicode,safe_content"`
|
City string `form:"not null" json:"city" binding:"required,alphaunicode,safe_content"`
|
||||||
Consents []Consent `gorm:"constraint:OnUpdate:CASCADE"`
|
Consents []Consent `gorm:"constraint:OnUpdate:CASCADE"`
|
||||||
BankAccount BankAccount `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"bank_account"`
|
BankAccount *BankAccount `gorm:"foreignkey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"bank_account"`
|
||||||
BankAccountID uint
|
Verifications []Verification `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
|
||||||
Verifications *[]Verification `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
|
Membership *Membership `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"membership"`
|
||||||
Membership Membership `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"membership"`
|
|
||||||
MembershipID uint
|
|
||||||
Licence *Licence `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"licence"`
|
Licence *Licence `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"licence"`
|
||||||
LicenceID uint
|
|
||||||
PaymentStatus int8 `json:"payment_status"`
|
|
||||||
Status int8 `json:"status"`
|
Status int8 `json:"status"`
|
||||||
RoleID int8 `json:"role_id"`
|
RoleID int8 `json:"role_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
|
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
|
||||||
if u.BankAccount.ID != 0 && u.BankAccount.MandateReference == "" {
|
if u.BankAccount != nil && u.BankAccount.MandateReference == "" {
|
||||||
mandateReference := u.GenerateMandateReference()
|
u.BankAccount.MandateReference = u.GenerateMandateReference()
|
||||||
|
u.BankAccount.Update(tx)
|
||||||
return tx.Model(&u.BankAccount).Update("MandateReference", mandateReference).Error
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *User) BeforeSave(tx *gorm.DB) (err error) {
|
||||||
|
u.Email = strings.ToLower(u.Email)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (u *User) GenerateMandateReference() string {
|
func (u *User) GenerateMandateReference() string {
|
||||||
return fmt.Sprintf("%s%d%s", time.Now().Format("20060102"), u.ID, u.BankAccount.IBAN)
|
return fmt.Sprintf("%s%d%s", time.Now().Format("20060102"), u.ID, u.BankAccount.IBAN)
|
||||||
}
|
}
|
||||||
@@ -86,29 +86,128 @@ func (u *User) Delete(db *gorm.DB) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) Create(db *gorm.DB) error {
|
func (u *User) Create(db *gorm.DB) error {
|
||||||
|
|
||||||
return db.Transaction(func(tx *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.Preload(clause.Associations).Create(u).Error; err != nil {
|
||||||
if err := tx.Create(u).Error; err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace associated Categories (assumes Categories already exist)
|
return nil
|
||||||
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("Membership").
|
|
||||||
Preload("Membership.SubscriptionModel").
|
|
||||||
Preload("Licence").
|
|
||||||
Preload("Licence.Categories").
|
|
||||||
First(u, u.ID).Error // Refresh the user object with all associations
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
func (u *User) Update(db *gorm.DB) error {
|
||||||
|
|
||||||
err := db.Transaction(func(tx *gorm.DB) error {
|
err := db.Transaction(func(tx *gorm.DB) error {
|
||||||
@@ -117,16 +216,11 @@ func (u *User) Update(db *gorm.DB) error {
|
|||||||
|
|
||||||
logger.Info.Printf("updating user: %#v", u)
|
logger.Info.Printf("updating user: %#v", u)
|
||||||
if err := tx.
|
if err := tx.
|
||||||
Preload("Membership").
|
|
||||||
Preload("Membership.SubscriptionModel").
|
|
||||||
Preload("Licence").
|
|
||||||
Preload("Licence.Categories").
|
|
||||||
Preload("Verifications").
|
|
||||||
First(&existingUser, u.ID).Error; err != nil {
|
First(&existingUser, u.ID).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Update the user's main fields
|
// Update the user's main fields
|
||||||
result := tx.Session(&gorm.Session{FullSaveAssociations: true}).Omit("Password", "Membership", "Licence", "Verifications").Updates(u)
|
result := tx.Session(&gorm.Session{FullSaveAssociations: true}).Omit("Password", "Verifications", "Licence.Categories").Updates(u)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
logger.Error.Printf("User update error in update user: %#v", result.Error)
|
logger.Error.Printf("User update error in update user: %#v", result.Error)
|
||||||
return result.Error
|
return result.Error
|
||||||
@@ -143,28 +237,28 @@ func (u *User) Update(db *gorm.DB) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the Membership if provided
|
// // Update the Membership if provided
|
||||||
if u.Membership.ID != 0 {
|
// if u.Membership.ID != 0 {
|
||||||
if err := tx.Model(&existingUser.Membership).Updates(u.Membership).Error; err != nil {
|
// 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)
|
// logger.Error.Printf("Membership update error in update user: %#v", err)
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if u.Licence != nil {
|
// if u.Licence != nil {
|
||||||
u.Licence.UserID = existingUser.ID
|
// u.Licence.UserID = existingUser.ID
|
||||||
|
|
||||||
if err := tx.Save(u.Licence).Error; err != nil {
|
// if err := tx.Save(u.Licence).Error; err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
|
|
||||||
if err := tx.Model(&existingUser).Update("LicenceID", u.Licence.ID).Error; err != nil {
|
// if err := tx.Model(&existingUser).Update("LicenceID", u.Licence.ID).Error; err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
|
|
||||||
if err := tx.Model(u.Licence).Association("Categories").Replace(u.Licence.Categories); err != nil {
|
// if err := tx.Model(u.Licence).Association("Categories").Replace(u.Licence.Categories); err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
// if u.Licence != nil {
|
// if u.Licence != nil {
|
||||||
// if existingUser.Licence == nil || existingUser.LicenceID == 0 {
|
// if existingUser.Licence == nil || existingUser.LicenceID == 0 {
|
||||||
// u.Licence.UserID = existingUser.ID // Ensure Licence belongs to User
|
// u.Licence.UserID = existingUser.ID // Ensure Licence belongs to User
|
||||||
@@ -187,7 +281,13 @@ func (u *User) Update(db *gorm.DB) error {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
if u.Verifications != nil {
|
if u.Verifications != nil {
|
||||||
if err := tx.Save(*u.Verifications).Error; err != nil {
|
if err := tx.Save(u.Verifications).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Licence != nil {
|
||||||
|
if err := tx.Model(u.Licence).Association("Categories").Replace(u.Licence.Categories); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -199,11 +299,9 @@ func (u *User) Update(db *gorm.DB) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return db.
|
return db.
|
||||||
Preload("Membership").
|
Preload(clause.Associations).
|
||||||
Preload("Membership.SubscriptionModel").
|
Preload("Membership.SubscriptionModel").
|
||||||
Preload("Licence").
|
|
||||||
Preload("Licence.Categories").
|
Preload("Licence.Categories").
|
||||||
Preload("Verifications").
|
|
||||||
First(&u, u.ID).Error
|
First(&u, u.ID).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,11 +309,8 @@ func (u *User) FromID(db *gorm.DB, userID *uint) error {
|
|||||||
var user User
|
var user User
|
||||||
result := db.
|
result := db.
|
||||||
Preload(clause.Associations).
|
Preload(clause.Associations).
|
||||||
Preload("Membership").
|
|
||||||
Preload("Membership.SubscriptionModel").
|
Preload("Membership.SubscriptionModel").
|
||||||
Preload("Licence").
|
|
||||||
Preload("Licence.Categories").
|
Preload("Licence.Categories").
|
||||||
Preload("Verifications").
|
|
||||||
First(&user, userID)
|
First(&user, userID)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
if result.Error == gorm.ErrRecordNotFound {
|
if result.Error == gorm.ErrRecordNotFound {
|
||||||
@@ -231,11 +326,8 @@ func (u *User) FromEmail(db *gorm.DB, email *string) error {
|
|||||||
var user User
|
var user User
|
||||||
result := db.
|
result := db.
|
||||||
Preload(clause.Associations).
|
Preload(clause.Associations).
|
||||||
Preload("Membership").
|
|
||||||
Preload("Membership.SubscriptionModel").
|
Preload("Membership.SubscriptionModel").
|
||||||
Preload("Licence").
|
|
||||||
Preload("Licence.Categories").
|
Preload("Licence.Categories").
|
||||||
Preload("Verifications").
|
|
||||||
Where("email = ?", email).First(&user)
|
Where("email = ?", email).First(&user)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
if result.Error == gorm.ErrRecordNotFound {
|
if result.Error == gorm.ErrRecordNotFound {
|
||||||
@@ -284,7 +376,7 @@ func (u *User) IsSupporter() bool {
|
|||||||
|
|
||||||
func (u *User) SetVerification(verificationType string) (*Verification, error) {
|
func (u *User) SetVerification(verificationType string) (*Verification, error) {
|
||||||
if u.Verifications == nil {
|
if u.Verifications == nil {
|
||||||
u.Verifications = new([]Verification)
|
u.Verifications = []Verification{}
|
||||||
}
|
}
|
||||||
token, err := utils.GenerateVerificationToken()
|
token, err := utils.GenerateVerificationToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -295,10 +387,10 @@ func (u *User) SetVerification(verificationType string) (*Verification, error) {
|
|||||||
VerificationToken: token,
|
VerificationToken: token,
|
||||||
Type: verificationType,
|
Type: verificationType,
|
||||||
}
|
}
|
||||||
if vi := slices.IndexFunc(*u.Verifications, func(vsl Verification) bool { return vsl.Type == v.Type }); vi > -1 {
|
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 {
|
} else {
|
||||||
*u.Verifications = append(*u.Verifications, v)
|
u.Verifications = append(u.Verifications, v)
|
||||||
}
|
}
|
||||||
return &v, nil
|
return &v, nil
|
||||||
}
|
}
|
||||||
@@ -307,11 +399,11 @@ func (u *User) GetVerification(verificationType string) (*Verification, error) {
|
|||||||
if u.Verifications == nil {
|
if u.Verifications == nil {
|
||||||
return nil, errors.ErrNoData
|
return nil, errors.ErrNoData
|
||||||
}
|
}
|
||||||
vi := slices.IndexFunc(*u.Verifications, func(vsl Verification) bool { return vsl.Type == verificationType })
|
vi := slices.IndexFunc(u.Verifications, func(vsl Verification) bool { return vsl.Type == verificationType })
|
||||||
if vi == -1 {
|
if vi == -1 {
|
||||||
return nil, errors.ErrNotFound
|
return nil, errors.ErrNotFound
|
||||||
}
|
}
|
||||||
return &(*u.Verifications)[vi], nil
|
return &u.Verifications[vi], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) Verify(token string, verificationType string) bool {
|
func (u *User) Verify(token string, verificationType string) bool {
|
||||||
@@ -320,7 +412,7 @@ func (u *User) Verify(token string, verificationType string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
vi := slices.IndexFunc(*u.Verifications, func(vsl Verification) bool {
|
vi := slices.IndexFunc(u.Verifications, func(vsl Verification) bool {
|
||||||
return vsl.Type == verificationType && vsl.VerificationToken == token
|
return vsl.Type == verificationType && vsl.VerificationToken == token
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -329,32 +421,22 @@ func (u *User) Verify(token string, verificationType string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*u.Verifications)[vi].VerifiedAt != nil {
|
if u.Verifications[vi].VerifiedAt != nil {
|
||||||
logger.Error.Printf("VerifiedAt is not nil, already verified?: %#v", (*u.Verifications)[vi])
|
logger.Error.Printf("VerifiedAt is not nil, already verified?: %#v", u.Verifications[vi])
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
(*u.Verifications)[vi].VerifiedAt = &t
|
u.Verifications[vi].VerifiedAt = &t
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) Safe() map[string]interface{} {
|
func (u *User) Safe() map[string]interface{} {
|
||||||
result := map[string]interface{}{
|
var membership map[string]interface{} = nil
|
||||||
"email": u.Email,
|
var licence map[string]interface{} = nil
|
||||||
"first_name": u.FirstName,
|
var bankAccount map[string]interface{} = nil
|
||||||
"last_name": u.LastName,
|
if u.Membership != nil {
|
||||||
"phone": u.Phone,
|
membership = map[string]interface{}{
|
||||||
"notes": u.Notes,
|
|
||||||
"address": u.Address,
|
|
||||||
"zip_code": u.ZipCode,
|
|
||||||
"city": u.City,
|
|
||||||
"status": u.Status,
|
|
||||||
"id": u.ID,
|
|
||||||
"role_id": u.RoleID,
|
|
||||||
"company": u.Company,
|
|
||||||
"dateofbirth": u.DateOfBirth,
|
|
||||||
"membership": map[string]interface{}{
|
|
||||||
"id": u.Membership.ID,
|
"id": u.Membership.ID,
|
||||||
"start_date": u.Membership.StartDate,
|
"start_date": u.Membership.StartDate,
|
||||||
"end_date": u.Membership.EndDate,
|
"end_date": u.Membership.EndDate,
|
||||||
@@ -369,23 +451,11 @@ func (u *User) Safe() map[string]interface{} {
|
|||||||
"included_per_year": u.Membership.SubscriptionModel.IncludedPerYear,
|
"included_per_year": u.Membership.SubscriptionModel.IncludedPerYear,
|
||||||
"included_per_month": u.Membership.SubscriptionModel.IncludedPerMonth,
|
"included_per_month": u.Membership.SubscriptionModel.IncludedPerMonth,
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
"licence": map[string]interface{}{
|
|
||||||
"id": 0,
|
|
||||||
},
|
|
||||||
"bank_account": map[string]interface{}{
|
|
||||||
"id": u.BankAccount.ID,
|
|
||||||
"mandate_date_signed": u.BankAccount.MandateDateSigned,
|
|
||||||
"bank": u.BankAccount.Bank,
|
|
||||||
"account_holder_name": u.BankAccount.AccountHolderName,
|
|
||||||
"iban": u.BankAccount.IBAN,
|
|
||||||
"bic": u.BankAccount.BIC,
|
|
||||||
"mandate_reference": u.BankAccount.MandateReference,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.Licence != nil {
|
if u.Licence != nil {
|
||||||
result["licence"] = map[string]interface{}{
|
licence = map[string]interface{}{
|
||||||
"id": u.Licence.ID,
|
"id": u.Licence.ID,
|
||||||
"number": u.Licence.Number,
|
"number": u.Licence.Number,
|
||||||
"status": u.Licence.Status,
|
"status": u.Licence.Status,
|
||||||
@@ -396,6 +466,36 @@ func (u *User) Safe() map[string]interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if u.BankAccount != nil {
|
||||||
|
bankAccount = map[string]interface{}{
|
||||||
|
"id": u.BankAccount.ID,
|
||||||
|
"mandate_date_signed": u.BankAccount.MandateDateSigned,
|
||||||
|
"bank": u.BankAccount.Bank,
|
||||||
|
"account_holder_name": u.BankAccount.AccountHolderName,
|
||||||
|
"iban": u.BankAccount.IBAN,
|
||||||
|
"bic": u.BankAccount.BIC,
|
||||||
|
"mandate_reference": u.BankAccount.MandateReference,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result := map[string]interface{}{
|
||||||
|
"email": u.Email,
|
||||||
|
"first_name": u.FirstName,
|
||||||
|
"last_name": u.LastName,
|
||||||
|
"phone": u.Phone,
|
||||||
|
"notes": u.Notes,
|
||||||
|
"address": u.Address,
|
||||||
|
"zip_code": u.ZipCode,
|
||||||
|
"city": u.City,
|
||||||
|
"status": u.Status,
|
||||||
|
"id": u.ID,
|
||||||
|
"role_id": u.RoleID,
|
||||||
|
"company": u.Company,
|
||||||
|
"dateofbirth": u.DateOfBirth,
|
||||||
|
"membership": membership,
|
||||||
|
"licence": licence,
|
||||||
|
"bank_account": bankAccount,
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,14 +539,12 @@ func extractUserIDFrom(tokenString string) (uint, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetUsersWhere(db *gorm.DB, where map[string]interface{}) (*[]User, error) {
|
func GetUsersWhere(db *gorm.DB, where map[string]interface{}) (*[]User, error) {
|
||||||
|
logger.Error.Printf("where: %#v", where)
|
||||||
var users []User
|
var users []User
|
||||||
result := db.
|
result := db.
|
||||||
Preload(clause.Associations).
|
Preload(clause.Associations).
|
||||||
Preload("Membership").
|
|
||||||
Preload("Membership.SubscriptionModel").
|
Preload("Membership.SubscriptionModel").
|
||||||
Preload("Licence").
|
|
||||||
Preload("Licence.Categories").
|
Preload("Licence.Categories").
|
||||||
Preload("Verifications").
|
|
||||||
Where(where).Find(&users)
|
Where(where).Find(&users)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
if result.Error == gorm.ErrRecordNotFound {
|
if result.Error == gorm.ErrRecordNotFound {
|
||||||
|
|||||||
@@ -1,15 +1,48 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"GoMembership/pkg/logger"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Verification struct {
|
type Verification struct {
|
||||||
UpdatedAt time.Time
|
gorm.Model
|
||||||
CreatedAt time.Time
|
|
||||||
VerifiedAt *time.Time `json:"verified_at"`
|
VerifiedAt *time.Time `json:"verified_at"`
|
||||||
VerificationToken string `json:"token"`
|
VerificationToken string `json:"token"`
|
||||||
ID uint `gorm:"primaryKey"`
|
|
||||||
UserID uint `json:"user_id"`
|
UserID uint `json:"user_id"`
|
||||||
Type string
|
Type string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *Verification) Create(db *gorm.DB) error {
|
||||||
|
if err := db.Create(v).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger.Info.Printf("verification created: %#v", v)
|
||||||
|
// Preload all associations to return the fully populated object
|
||||||
|
return db.First(v, v.ID).Error // Refresh the verification object with all associations
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Verification) Update(db *gorm.DB) error {
|
||||||
|
|
||||||
|
return db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
// Check if the user exists in the database
|
||||||
|
var existingVerification Verification
|
||||||
|
|
||||||
|
logger.Info.Printf("updating verification: %#v", v)
|
||||||
|
if err := tx.First(&existingVerification, v.ID).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Model(&existingVerification).Updates(v).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return tx.First(v, v.ID).Error
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Verification) Delete(db *gorm.DB) error {
|
||||||
|
return db.Delete(&v).Error
|
||||||
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ func GetUsersBySubscription(subscriptionID uint) (*[]models.User, error) {
|
|||||||
Preload("BankAccount").
|
Preload("BankAccount").
|
||||||
Preload("Licence").
|
Preload("Licence").
|
||||||
Preload("Licence.Categories").
|
Preload("Licence.Categories").
|
||||||
Joins("JOIN memberships ON users.membership_id = memberships.id").
|
Joins("JOIN memberships ON users.id = memberships.user_id").
|
||||||
Joins("JOIN subscription_models ON memberships.subscription_model_id = subscription_models.id").
|
Joins("JOIN subscription_models ON memberships.subscription_model_id = subscription_models.id").
|
||||||
Where("subscription_models.id = ?", subscriptionID).
|
Where("subscription_models.id = ?", subscriptionID).
|
||||||
Find(&users).Error
|
Find(&users).Error
|
||||||
|
|||||||
@@ -68,14 +68,11 @@ func (s *UserService) Update(user *models.User) (*models.User, error) {
|
|||||||
if err := existingUser.FromID(s.DB, &user.ID); err != nil {
|
if err := existingUser.FromID(s.DB, &user.ID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
user.MembershipID = existingUser.MembershipID
|
|
||||||
user.Membership.ID = existingUser.Membership.ID
|
user.Membership.ID = existingUser.Membership.ID
|
||||||
if existingUser.Licence != nil {
|
if existingUser.Licence != nil {
|
||||||
user.Licence.ID = existingUser.Licence.ID
|
user.Licence.ID = existingUser.Licence.ID
|
||||||
user.LicenceID = existingUser.LicenceID
|
|
||||||
}
|
}
|
||||||
user.BankAccount.ID = existingUser.BankAccount.ID
|
user.BankAccount.ID = existingUser.BankAccount.ID
|
||||||
user.BankAccountID = existingUser.BankAccountID
|
|
||||||
|
|
||||||
user.SetPassword(user.Password)
|
user.SetPassword(user.Password)
|
||||||
|
|
||||||
@@ -109,7 +106,6 @@ func (s *UserService) Register(user *models.User) (id uint, token string, err er
|
|||||||
user.Membership.SubscriptionModel = *selectedModel
|
user.Membership.SubscriptionModel = *selectedModel
|
||||||
user.Membership.SubscriptionModelID = selectedModel.ID
|
user.Membership.SubscriptionModelID = selectedModel.ID
|
||||||
user.Status = constants.UnverifiedStatus
|
user.Status = constants.UnverifiedStatus
|
||||||
user.PaymentStatus = constants.AwaitingPaymentStatus
|
|
||||||
user.BankAccount.MandateDateSigned = time.Now()
|
user.BankAccount.MandateDateSigned = time.Now()
|
||||||
v, err := user.SetVerification(constants.VerificationTypes.Email)
|
v, err := user.SetVerification(constants.VerificationTypes.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ type User struct {
|
|||||||
Age int
|
Age int
|
||||||
Address *Address
|
Address *Address
|
||||||
Tags []string
|
Tags []string
|
||||||
License License
|
Licence Licence
|
||||||
}
|
}
|
||||||
|
|
||||||
type Address struct {
|
type Address struct {
|
||||||
@@ -18,7 +18,7 @@ type Address struct {
|
|||||||
Country string
|
Country string
|
||||||
}
|
}
|
||||||
|
|
||||||
type License struct {
|
type Licence struct {
|
||||||
ID string
|
ID string
|
||||||
Categories []string
|
Categories []string
|
||||||
}
|
}
|
||||||
@@ -98,22 +98,22 @@ func TestFilterAllowedStructFields(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "Filter slice of structs",
|
name: "Filter slice of structs",
|
||||||
input: &User{
|
input: &User{
|
||||||
License: License{
|
Licence: Licence{
|
||||||
ID: "123",
|
ID: "123",
|
||||||
Categories: []string{"A", "B"},
|
Categories: []string{"A", "B"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
existing: &User{
|
existing: &User{
|
||||||
License: License{
|
Licence: Licence{
|
||||||
ID: "456",
|
ID: "456",
|
||||||
Categories: []string{"C"},
|
Categories: []string{"C"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
allowedFields: map[string]bool{
|
allowedFields: map[string]bool{
|
||||||
"License.ID": true,
|
"Licence.ID": true,
|
||||||
},
|
},
|
||||||
expectedResult: &User{
|
expectedResult: &User{
|
||||||
License: License{
|
Licence: Licence{
|
||||||
ID: "123", // Allowed field
|
ID: "123", // Allowed field
|
||||||
Categories: []string{"C"}, // Kept from existing
|
Categories: []string{"C"}, // Kept from existing
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user