package controllers import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "net/url" "os" "path/filepath" "strconv" "testing" "time" "log" "github.com/gin-gonic/gin" "GoMembership/internal/config" "GoMembership/internal/constants" "GoMembership/internal/database" "GoMembership/internal/models" "GoMembership/internal/repositories" "GoMembership/internal/services" "GoMembership/internal/utils" "GoMembership/internal/validation" "GoMembership/pkg/logger" ) type TestCase interface { SetupContext() (*gin.Context, *httptest.ResponseRecorder, *gin.Engine) RunHandler(*gin.Context, *gin.Engine) ValidateResponse(*httptest.ResponseRecorder) error ValidateResult() error } const ( Host = "127.0.0.1" Port int = 2525 ) type loginInput struct { Email string `json:"email"` Password string `json:"password"` } var ( Uc *UserController Mc *MembershipController Cc *ContactController AdminCookie *http.Cookie MemberCookie *http.Cookie ) func TestMain(t *testing.T) { _ = deleteTestDB("test.db") cwd, err := os.Getwd() if err != nil { log.Fatalf("Failed to get current working directory: %v", err) } // Build paths relative to the current working directory configFilePath := filepath.Join(cwd, "..", "..", "configs", "config.json") templateHTMLPath := filepath.Join(cwd, "..", "..", "templates", "html") templateMailPath := filepath.Join(cwd, "..", "..", "templates", "email") if err := os.Setenv("TEMPLATE_MAIL_PATH", templateMailPath); err != nil { log.Fatalf("Error setting environment variable: %v", err) } if err := os.Setenv("TEMPLATE_HTML_PATH", templateHTMLPath); err != nil { log.Fatalf("Error setting environment variable: %v", err) } if err := os.Setenv("CONFIG_FILE_PATH", configFilePath); err != nil { log.Fatalf("Error setting environment variable: %v", err) } if err := os.Setenv("SMTP_HOST", Host); err != nil { log.Fatalf("Error setting environment variable: %v", err) } if err := os.Setenv("SMTP_PORT", strconv.Itoa(Port)); err != nil { log.Fatalf("Error setting environment variable: %v", err) } if err := os.Setenv("BASE_URL", "http://"+Host+":2525"); err != nil { log.Fatalf("Error setting environment variable: %v", err) } if err := os.Setenv("DB_PATH", "test.db"); err != nil { log.Fatalf("Error setting environment variable: %v", err) } config.LoadConfig() db, err := database.Open("test.db", config.Recipients.AdminEmail, true) if err != nil { log.Fatalf("Failed to create DB: %#v", err) } utils.SMTPStart(Host, Port) emailService := services.NewEmailService(config.SMTP.Host, config.SMTP.Port, config.SMTP.User, config.SMTP.Password) var consentRepo repositories.ConsentRepositoryInterface = &repositories.ConsentRepository{} consentService := &services.ConsentService{Repo: consentRepo} var bankAccountRepo repositories.BankAccountRepositoryInterface = &repositories.BankAccountRepository{} bankAccountService := &services.BankAccountService{Repo: bankAccountRepo} var membershipRepo repositories.MembershipRepositoryInterface = &repositories.MembershipRepository{} var subscriptionRepo repositories.SubscriptionModelsRepositoryInterface = &repositories.SubscriptionModelsRepository{} membershipService := &services.MembershipService{Repo: membershipRepo, SubscriptionRepo: subscriptionRepo} var licenceRepo repositories.LicenceInterface = &repositories.LicenceRepository{} userService := &services.UserService{DB: db, Licences: licenceRepo} licenceService := &services.LicenceService{Repo: licenceRepo} Uc = &UserController{Service: userService, LicenceService: licenceService, EmailService: emailService, ConsentService: consentService, BankAccountService: bankAccountService, MembershipService: membershipService} Mc = &MembershipController{UserService: userService, Service: membershipService} Cc = &ContactController{EmailService: emailService} if err := initSubscriptionPlans(); err != nil { log.Fatalf("Failed to init Subscription plans: %#v", err) } if err := initLicenceCategories(); err != nil { log.Fatalf("Failed to init Categories: %v", err) } admin := models.User{ FirstName: "Ad", LastName: "min", Email: "admin@example.com", DateOfBirth: time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC), Company: "SampleCorp", Phone: "+123456789", Address: "123 Main Street", ZipCode: "12345", City: "SampleCity", Status: constants.ActiveStatus, Password: "", Notes: "", RoleID: constants.Roles.Admin, Consents: nil, Verifications: nil, Membership: nil, BankAccount: nil, Licence: &models.Licence{ Status: constants.UnverifiedStatus, }} admin.SetPassword("securepassword") admin.Create(db) validation.SetupValidators(db) t.Run("userController", func(t *testing.T) { testUserController(t) }) t.Run("Password_Controller", func(t *testing.T) { }) t.Run("SQL_Injection", func(t *testing.T) { testSQLInjectionAttempt(t) }) t.Run("contactController", func(t *testing.T) { testContactController(t) }) t.Run("membershipController", func(t *testing.T) { testMembershipController(t) }) t.Run("XSSAttempt", func(t *testing.T) { testXSSAttempt(t) }) if err := utils.SMTPStop(); err != nil { log.Fatalf("Failed to stop SMTP Mockup Server: %#v", err) } // if err := deleteTestDB("test.db"); err != nil { // log.Fatalf("Failed to tear down DB: %#v", err) // } } func initLicenceCategories() error { categories := []models.Category{ {Name: "AM"}, {Name: "A1"}, {Name: "A2"}, {Name: "A"}, {Name: "B"}, {Name: "C1"}, {Name: "C"}, {Name: "D1"}, {Name: "D"}, {Name: "BE"}, {Name: "C1E"}, {Name: "CE"}, {Name: "D1E"}, {Name: "DE"}, {Name: "T"}, {Name: "L"}, } for _, category := range categories { result := database.DB.Create(&category) if result.Error != nil { return result.Error } } return nil } func initSubscriptionPlans() error { subscriptions := []models.SubscriptionModel{ { Name: "Basic", Details: "Test Plan", MonthlyFee: 2, HourlyRate: 3, }, { Name: "additional", Details: "This plan needs another membership id to validate", RequiredMembershipField: "ParentMembershipID", MonthlyFee: 2, HourlyRate: 3, }, } for _, subscription := range subscriptions { result := database.DB.Create(&subscription) if result.Error != nil { return result.Error } } return nil } func GetMockedJSONContext(jsonStr []byte, url string) (*gin.Context, *httptest.ResponseRecorder, *gin.Engine) { gin.SetMode(gin.TestMode) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) router := gin.New() // Load HTML templates router.LoadHTMLGlob(config.Templates.HTMLPath + "/*") var err error c.Request, err = http.NewRequest("POST", url, bytes.NewBuffer(jsonStr)) if err != nil { log.Fatalf("Failed to create new Request: %#v", err) } c.Request.Header.Set("Content-Type", "application/json") return c, w, router } func GetMockedFormContext(formData url.Values, url string) (*gin.Context, *httptest.ResponseRecorder, *gin.Engine) { gin.SetMode(gin.TestMode) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) router := gin.New() // Load HTML templates router.LoadHTMLGlob(config.Templates.HTMLPath + "/*") req, err := http.NewRequest("POST", url, bytes.NewBufferString(formData.Encode())) if err != nil { log.Fatalf("Failed to create new Request: %#v", err) } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") c.Request = req return c, w, router } func getBaseUser() models.User { return models.User{ DateOfBirth: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC), FirstName: "John", LastName: "Doe", Email: "john.doe@example.com", Address: "Pablo Escobar Str. 4", ZipCode: "25474", City: "Hasloh", Phone: "01738484993", BankAccount: &models.BankAccount{IBAN: "DE89370400440532013000"}, Membership: &models.Membership{SubscriptionModel: models.SubscriptionModel{Name: "Basic"}}, Licence: nil, Password: "passw@#$#%$!-ord123", Company: "", RoleID: 1, } } func getBaseSupporter() models.User { return models.User{ DateOfBirth: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC), FirstName: "John", LastName: "Rich", Email: "john.supporter@example.com", Address: "Pablo Escobar Str. 4", ZipCode: "25474", City: "Hasloh", Phone: "01738484993", BankAccount: &models.BankAccount{IBAN: "DE89370400440532013000"}, Membership: &models.Membership{SubscriptionModel: models.SubscriptionModel{Name: "Basic"}}, Licence: nil, Password: "passw@#$#%$!-ord123", Company: "", RoleID: 0, } } func deleteTestDB(dbPath string) error { err := os.Remove(dbPath) if err != nil { return err } return nil } func runSingleTest(tc TestCase) error { c, w, router := tc.SetupContext() tc.RunHandler(c, router) if err := tc.ValidateResponse(w); err != nil { return err } return tc.ValidateResult() } func GenerateInputJSON(aStruct interface{}) string { // Marshal the object into JSON jsonBytes, err := json.Marshal(aStruct) if err != nil { logger.Error.Fatalf("Couldn't generate JSON: %#v\nERROR: %#v", aStruct, err) return "" } return string(jsonBytes) }