This commit is contained in:
$(pass /github/name)
2024-07-02 00:27:43 +02:00
parent fbb3bdfcb3
commit 9bd8d48243
11 changed files with 251 additions and 102 deletions

11
go.mod
View File

@@ -1,11 +1,12 @@
module GoMembership module GoMembership
go 1.18 go 1.22.2
require ( require (
github.com/gorilla/mux v1.8.0 github.com/go-sql-driver/mysql v1.8.1
golang.org/x/crypto v0.0.0-20220411214040-896ed404bb0e 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

15
go.sum
View File

@@ -1,5 +1,10 @@
github.com/gorilla/mux v1.8.0 h1:vGHr6G7CRByRCFwUmpxP8Cj8ljy1OV8ZrRH6qrOEzXM= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
github.com/gorilla/mux v1.8.0/go.mod h1:vGHr6G7CRByRCFwUmpxP8Cj8ljy1OV8ZrRH6qrOEzXM= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
golang.org/x/crypto v0.0.0-20220411214040-896ed404bb0e h1:aIjQLr9igSCqCxL1cOsTSG91TtOGStlwrPvHxGpQuWk= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
golang.org/x/crypto v0.0.0 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=

View File

@@ -1,20 +1,38 @@
package config package config
import ( import (
"os" "encoding/json"
"log"
"os"
"path/filepath"
) )
type DatabaseConfig struct {
DBPath string `json:"DBPath"`
}
type Config struct { type Config struct {
DBUser string DB DatabaseConfig `json:"db"`
DBPassword string
DBName string
} }
func LoadConfig() *Config { func LoadConfig() *Config {
return &Config{ path, err := os.Getwd()
DBUser: os.Getenv("DB_USER"), if err != nil {
DBPassword: os.Getenv("DB_PASSWORD"), log.Fatalf("could not get working directory: %v", err)
DBName: os.Getenv("DB_NAME"), }
}
}
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
}

View File

@@ -1,31 +1,57 @@
package controllers package controllers
import ( import (
"encoding/json" "GoMembership/internal/models"
"net/http" "GoMembership/internal/services"
"GoMembership/internal/models" "encoding/json"
"GoMembership/internal/services" // "github.com/gorilla/mux"
"net/http"
// "strconv"
) )
type UserController struct { type UserController struct {
service services.UserService service services.UserService
} }
func NewUserController(service services.UserService) *UserController { func NewUserController(service services.UserService) *UserController {
return &UserController{service} return &UserController{service}
} }
func (uc *UserController) RegisterUser(w http.ResponseWriter, r *http.Request) { func (uc *UserController) RegisterUser(w http.ResponseWriter, r *http.Request) {
var user models.User var user models.User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil { if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
return return
} }
if err := uc.service.RegisterUser(&user); err != nil { if err := uc.service.RegisterUser(&user); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
w.WriteHeader(http.StatusCreated) 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)
}
} */

View File

@@ -1,23 +1,41 @@
package database package database
import ( import (
"database/sql" "GoMembership/internal/config"
"log" "database/sql"
"GoMembership/internal/config" "log"
"os"
_ "github.com/go-sql-driver/mysql" _ "github.com/mattn/go-sqlite3"
) )
func Connect() *sql.DB { func initializeDB(dbPath string, schemaPath string) error {
cfg := config.LoadConfig() db, err := sql.Open("sqlite3", dbPath)
dsn := cfg.DBUser + ":" + cfg.DBPassword + "@/" + cfg.DBName if err != nil {
db, err := sql.Open("mysql", dsn) return err
if err != nil { }
log.Fatal(err) defer db.Close()
}
if err := db.Ping(); err != nil { schema, err := os.ReadFile(schemaPath)
log.Fatal(err) if err != nil {
} return err
return db }
_, 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
}

View File

@@ -3,12 +3,15 @@ package models
import "time" import "time"
type User struct { type User struct {
ID int `json:"id"` CreatedAt time.Time `json:"created_at"`
FirstName string `json:"first_name"` UpdatedAt time.Time `json:"updated_at"`
LastName string `json:"last_name"` MandateDateSigned time.Time `json:"mandate_date_signed"`
Email string `json:"email"` FirstName string `json:"first_name"`
Password string `json:"password"` LastName string `json:"last_name"`
CreatedAt time.Time `json:"created_at"` Email string `json:"email"`
UpdatedAt time.Time `json:"updated_at"` Password string `json:"password"`
IBAN string `json:"iban"`
BIC string `json:"bic"`
MandateReference string `json:"mandate_reference"`
ID int `json:"id"`
} }

View File

@@ -1,25 +1,40 @@
package repositories package repositories
import ( import (
"database/sql" "GoMembership/internal/models"
"GoMembership/internal/models" "GoMembership/pkg/errors"
"database/sql"
) )
type UserRepository interface { 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 { type userRepository struct {
db *sql.DB db *sql.DB
} }
func NewUserRepository(db *sql.DB) UserRepository { func NewUserRepository(db *sql.DB) UserRepository {
return &userRepository{db} return &userRepository{db}
} }
func (r *userRepository) CreateUser(user *models.User) error { func (r *userRepository) CreateUser(user *models.User) error {
query := "INSERT INTO users (first_name, last_name, email, password, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)" 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) _, err := r.db.Exec(query, user.FirstName, user.LastName, user.Email, user.Password, user.CreatedAt, user.UpdatedAt)
return err 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
}

View File

@@ -1,32 +1,32 @@
package server package server
import ( import (
"database/sql" // "GoMembership/internal/config"
"log" "GoMembership/internal/controllers"
"GoMembership/internal/controllers" "GoMembership/internal/database"
"GoMembership/internal/repositories" "GoMembership/internal/repositories"
"GoMembership/internal/routes" "GoMembership/internal/routes"
"GoMembership/internal/services" "GoMembership/internal/services"
"net/http" "log"
"net/http"
"github.com/gorilla/mux" "github.com/gorilla/mux"
_ "github.com/go-sql-driver/mysql"
) )
func Run() { func Run() {
db, err := sql.Open("mysql", "user:password@/dbname") // cfg := config.LoadConfig()
if err != nil { db := database.Connect()
log.Fatal(err) defer db.Close()
}
defer db.Close()
userRepo := repositories.NewUserRepository(db) userRepo := repositories.NewUserRepository(db)
userService := services.NewUserService(userRepo) userService := services.NewUserService(userRepo)
userController := controllers.NewUserController(userService) userController := controllers.NewUserController(userService)
router := mux.NewRouter() router := mux.NewRouter()
routes.RegisterRoutes(router, userController) 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)
}
} }

View File

@@ -1,29 +1,32 @@
package services package services
import ( import (
"GoMembership/internal/models" "GoMembership/internal/models"
"GoMembership/internal/repositories" "GoMembership/internal/repositories"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"time"
) )
type UserService interface { type UserService interface {
RegisterUser(user *models.User) error RegisterUser(user *models.User) error
} }
type userService struct { type userService struct {
repo repositories.UserRepository repo repositories.UserRepository
} }
func NewUserService(repo repositories.UserRepository) UserService { func NewUserService(repo repositories.UserRepository) UserService {
return &userService{repo} return &userService{repo}
} }
func (s *userService) RegisterUser(user *models.User) error { func (s *userService) RegisterUser(user *models.User) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost) hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
if err != nil { if err != nil {
return err return err
} }
user.Password = string(hashedPassword) user.Password = string(hashedPassword)
return s.repo.CreateUser(user) user.CreatedAt = time.Now()
user.UpdatedAt = time.Now()
user.MandateDateSigned = time.Now()
return s.repo.CreateUser(user)
} }

3
src/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module git.stoelti.land/Alex/GoMembership
go 1.22.4

57
src/main.go Normal file
View File

@@ -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
}