From 9bd8d482439d3e45162b39756c46980380952bec Mon Sep 17 00:00:00 2001 From: "$(pass /github/name)" <$(pass /github/email)> Date: Tue, 2 Jul 2024 00:27:43 +0200 Subject: [PATCH] wip --- go.mod | 11 +++-- go.sum | 15 ++++-- internal/config/config.go | 38 +++++++++++---- internal/controllers/user_controller.go | 60 +++++++++++++++++------- internal/database/db.go | 48 +++++++++++++------ internal/models/user.go | 19 ++++---- internal/repositories/user_repository.go | 31 ++++++++---- internal/server/server.go | 42 ++++++++--------- internal/services/user_service.go | 29 +++++++----- src/go.mod | 3 ++ src/main.go | 57 ++++++++++++++++++++++ 11 files changed, 251 insertions(+), 102 deletions(-) create mode 100644 src/go.mod create mode 100644 src/main.go diff --git a/go.mod b/go.mod index 3ea80f2..20a147f 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,12 @@ module GoMembership -go 1.18 +go 1.22.2 require ( - github.com/gorilla/mux v1.8.0 - golang.org/x/crypto v0.0.0-20220411214040-896ed404bb0e + github.com/go-sql-driver/mysql v1.8.1 + github.com/gorilla/mux v1.8.1 + github.com/mattn/go-sqlite3 v1.14.22 + golang.org/x/crypto v0.24.0 ) -replace golang.org/x/crypto => golang.org/x/crypto v0.0.0-20220411214040-896ed404bb0e - +require filippo.io/edwards25519 v1.1.0 // indirect diff --git a/go.sum b/go.sum index 2be86d7..2708fe6 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,10 @@ -github.com/gorilla/mux v1.8.0 h1:vGHr6G7CRByRCFwUmpxP8Cj8ljy1OV8ZrRH6qrOEzXM= -github.com/gorilla/mux v1.8.0/go.mod h1:vGHr6G7CRByRCFwUmpxP8Cj8ljy1OV8ZrRH6qrOEzXM= -golang.org/x/crypto v0.0.0-20220411214040-896ed404bb0e h1:aIjQLr9igSCqCxL1cOsTSG91TtOGStlwrPvHxGpQuWk= -golang.org/x/crypto v0.0.0 - +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= diff --git a/internal/config/config.go b/internal/config/config.go index 82a131d..b47def0 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,20 +1,38 @@ package config import ( - "os" + "encoding/json" + "log" + "os" + "path/filepath" ) +type DatabaseConfig struct { + DBPath string `json:"DBPath"` +} + type Config struct { - DBUser string - DBPassword string - DBName string + DB DatabaseConfig `json:"db"` } func LoadConfig() *Config { - return &Config{ - DBUser: os.Getenv("DB_USER"), - DBPassword: os.Getenv("DB_PASSWORD"), - DBName: os.Getenv("DB_NAME"), - } -} + path, err := os.Getwd() + if err != nil { + log.Fatalf("could not get working directory: %v", err) + } + configFile, err := os.Open(filepath.Join(path, "configs", "config.json")) + if err != nil { + log.Fatalf("could not open config file: %v", err) + } + defer configFile.Close() + + decoder := json.NewDecoder(configFile) + config := &Config{} + err = decoder.Decode(config) + if err != nil { + log.Fatalf("could not decode config file: %v", err) + } + + return config +} diff --git a/internal/controllers/user_controller.go b/internal/controllers/user_controller.go index fdf937b..3ef74d5 100644 --- a/internal/controllers/user_controller.go +++ b/internal/controllers/user_controller.go @@ -1,31 +1,57 @@ - package controllers import ( - "encoding/json" - "net/http" - "GoMembership/internal/models" - "GoMembership/internal/services" + "GoMembership/internal/models" + "GoMembership/internal/services" + "encoding/json" + // "github.com/gorilla/mux" + "net/http" + // "strconv" ) type UserController struct { - service services.UserService + service services.UserService } func NewUserController(service services.UserService) *UserController { - return &UserController{service} + return &UserController{service} } func (uc *UserController) RegisterUser(w http.ResponseWriter, r *http.Request) { - var user models.User - if err := json.NewDecoder(r.Body).Decode(&user); err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - if err := uc.service.RegisterUser(&user); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.WriteHeader(http.StatusCreated) + var user models.User + if err := json.NewDecoder(r.Body).Decode(&user); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if err := uc.service.RegisterUser(&user); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusCreated) } +/* func (uc *UserController) LoginUser(w http.ResponseWriter, r *http.Request) { + var credentials struct { + Email string `json:"email"` + Password string `json:"password"` + } + user, err := uc.service.AuthenticateUser(credentials.Email, credentials.Password) + if err != nil { + http.Error(w, err.Error(), http.StatusUnauthorized) + return + } + json.NewEncoder(w).Encode(user) +} */ + +/* func (uc *UserController) GetUserID(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + id, err := strconv.Atoi(vars["id"]) + if err != nil { + http.Error(w, "Invalid user ID", http.StatusBadRequest) + return + } + user, err := uc.service.GetUserByID(id) + if err != nil { + http.Error(w, "User not found: "+err.Error(), http.StatusNotFound) + } +} */ diff --git a/internal/database/db.go b/internal/database/db.go index 253b271..1f03ff9 100644 --- a/internal/database/db.go +++ b/internal/database/db.go @@ -1,23 +1,41 @@ package database import ( - "database/sql" - "log" - "GoMembership/internal/config" + "GoMembership/internal/config" + "database/sql" + "log" + "os" - _ "github.com/go-sql-driver/mysql" + _ "github.com/mattn/go-sqlite3" ) -func Connect() *sql.DB { - cfg := config.LoadConfig() - dsn := cfg.DBUser + ":" + cfg.DBPassword + "@/" + cfg.DBName - db, err := sql.Open("mysql", dsn) - if err != nil { - log.Fatal(err) - } - if err := db.Ping(); err != nil { - log.Fatal(err) - } - return db +func initializeDB(dbPath string, schemaPath string) error { + db, err := sql.Open("sqlite3", dbPath) + if err != nil { + return err + } + defer db.Close() + + schema, err := os.ReadFile(schemaPath) + if err != nil { + return err + } + _, err = db.Exec(string(schema)) + if err != nil { + return err + } + return nil } +func Connect() *sql.DB { + cfg := config.LoadConfig() + dsn := cfg.DB.DBPath + db, err := sql.Open("sqlite3", dsn) + if err != nil { + log.Fatal(err) + } + if err := db.Ping(); err != nil { + log.Fatal(err) + } + return db +} diff --git a/internal/models/user.go b/internal/models/user.go index 09df5b5..a25fc11 100644 --- a/internal/models/user.go +++ b/internal/models/user.go @@ -3,12 +3,15 @@ package models import "time" type User struct { - ID int `json:"id"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` - Email string `json:"email"` - Password string `json:"password"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + MandateDateSigned time.Time `json:"mandate_date_signed"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + Email string `json:"email"` + Password string `json:"password"` + IBAN string `json:"iban"` + BIC string `json:"bic"` + MandateReference string `json:"mandate_reference"` + ID int `json:"id"` } - diff --git a/internal/repositories/user_repository.go b/internal/repositories/user_repository.go index 8264106..e22a32e 100644 --- a/internal/repositories/user_repository.go +++ b/internal/repositories/user_repository.go @@ -1,25 +1,40 @@ package repositories import ( - "database/sql" - "GoMembership/internal/models" + "GoMembership/internal/models" + "GoMembership/pkg/errors" + "database/sql" ) type UserRepository interface { - CreateUser(user *models.User) error + CreateUser(user *models.User) error + FindUserByID(id int) (*models.User, error) + // FindUserByEmail(email string) (*models.User, error) } type userRepository struct { - db *sql.DB + db *sql.DB } func NewUserRepository(db *sql.DB) UserRepository { - return &userRepository{db} + return &userRepository{db} } func (r *userRepository) CreateUser(user *models.User) error { - query := "INSERT INTO users (first_name, last_name, email, password, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)" - _, err := r.db.Exec(query, user.FirstName, user.LastName, user.Email, user.Password, user.CreatedAt, user.UpdatedAt) - return err + query := "INSERT INTO users (first_name, last_name, email, password, iban, bic, mandate_reference, mandate_date_signed, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + _, err := r.db.Exec(query, user.FirstName, user.LastName, user.Email, user.Password, user.CreatedAt, user.UpdatedAt) + return err } +func (r *userRepository) FindUserByID(id int) (*models.User, error) { + var user models.User + query := "SELECT id, first_name, last_name, email, iban, bic, mandate_reference FROM users WHERE id = ?" + err := r.db.QueryRow(query, id).Scan(&user.ID, &user.FirstName, &user.LastName, &user.Email, &user.IBAN, &user.BIC, &user.MandateReference) + if err != nil { + if err == sql.ErrNoRows { + return nil, errors.ErrUserNotFound + } + return nil, err + } + return &user, nil +} diff --git a/internal/server/server.go b/internal/server/server.go index 4e16c63..d15b404 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -1,32 +1,32 @@ package server import ( - "database/sql" - "log" - "GoMembership/internal/controllers" - "GoMembership/internal/repositories" - "GoMembership/internal/routes" - "GoMembership/internal/services" - "net/http" + // "GoMembership/internal/config" + "GoMembership/internal/controllers" + "GoMembership/internal/database" + "GoMembership/internal/repositories" + "GoMembership/internal/routes" + "GoMembership/internal/services" + "log" + "net/http" - "github.com/gorilla/mux" - _ "github.com/go-sql-driver/mysql" + "github.com/gorilla/mux" ) func Run() { - db, err := sql.Open("mysql", "user:password@/dbname") - if err != nil { - log.Fatal(err) - } - defer db.Close() + // cfg := config.LoadConfig() + db := database.Connect() + defer db.Close() - userRepo := repositories.NewUserRepository(db) - userService := services.NewUserService(userRepo) - userController := controllers.NewUserController(userService) + userRepo := repositories.NewUserRepository(db) + userService := services.NewUserService(userRepo) + userController := controllers.NewUserController(userService) - router := mux.NewRouter() - routes.RegisterRoutes(router, userController) + router := mux.NewRouter() + routes.RegisterRoutes(router, userController) - log.Fatal(http.ListenAndServe(":8080", router)) + log.Println("Starting server on :8080") + if err := http.ListenAndServe(":8080", router); err != nil { + log.Fatalf("could not start server: %v", err) + } } - diff --git a/internal/services/user_service.go b/internal/services/user_service.go index 556e51f..bf2e685 100644 --- a/internal/services/user_service.go +++ b/internal/services/user_service.go @@ -1,29 +1,32 @@ package services import ( - "GoMembership/internal/models" - "GoMembership/internal/repositories" - "golang.org/x/crypto/bcrypt" + "GoMembership/internal/models" + "GoMembership/internal/repositories" + "golang.org/x/crypto/bcrypt" + "time" ) type UserService interface { - RegisterUser(user *models.User) error + RegisterUser(user *models.User) error } type userService struct { - repo repositories.UserRepository + repo repositories.UserRepository } func NewUserService(repo repositories.UserRepository) UserService { - return &userService{repo} + return &userService{repo} } func (s *userService) RegisterUser(user *models.User) error { - hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost) - if err != nil { - return err - } - user.Password = string(hashedPassword) - return s.repo.CreateUser(user) + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost) + if err != nil { + return err + } + user.Password = string(hashedPassword) + user.CreatedAt = time.Now() + user.UpdatedAt = time.Now() + user.MandateDateSigned = time.Now() + return s.repo.CreateUser(user) } - diff --git a/src/go.mod b/src/go.mod new file mode 100644 index 0000000..74edfe1 --- /dev/null +++ b/src/go.mod @@ -0,0 +1,3 @@ +module git.stoelti.land/Alex/GoMembership + +go 1.22.4 diff --git a/src/main.go b/src/main.go new file mode 100644 index 0000000..58e050a --- /dev/null +++ b/src/main.go @@ -0,0 +1,57 @@ +// main.go + +package main + +import ( + "strconv" + + "github.com/astaxie/beego" +) + + +func main() { + /* This would match routes like the following: + /sum/3/5 + /product/6/23 + ... + */ + beego.Router("/:operation/:num1:int/:num2:int", &mainController{}) + beego.Run() +} + +type mainController struct { + beego.Controller +} + + +func (c *mainController) Get() { + + //Obtain the values of the route parameters defined in the route above + operation := c.Ctx.Input.Param(":operation") + num1, _ := strconv.Atoi(c.Ctx.Input.Param(":num1")) + num2, _ := strconv.Atoi(c.Ctx.Input.Param(":num2")) + + //Set the values for use in the template + c.Data["operation"] = operation + c.Data["num1"] = num1 + c.Data["num2"] = num2 + c.TplName = "result.html" + + // Perform the calculation depending on the 'operation' route parameter + switch operation { + case "sum": + c.Data["result"] = add(num1, num2) + case "product": + c.Data["result"] = multiply(num1, num2) + default: + c.TplName = "invalid-route.html" + } +} + +func add(n1, n2 int) int { + return n1 + n2 +} + +func multiply(n1, n2 int) int { + return n1 * n2 +}