From 7be388c9f92109ddc77e65575a5bc7726a9ac1c6 Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 21 Dec 2024 07:26:27 +0100 Subject: [PATCH] Golang backend implementation to interact with the MySQL schema using a REST API. The backend will use the Gin framework for routing and GORM for database interaction. --- bamort/config.go | 23 +++++ bamort/main.go | 109 ++++++++++++++++++++ bamort/models.go | 43 ++++++++ bamort/scripts/initial_steps.md | 6 ++ bamort/{sql => scripts}/mysql_structure.sql | 0 bamort/tests/api_test.md | 18 ++++ 6 files changed, 199 insertions(+) create mode 100644 bamort/config.go create mode 100644 bamort/main.go create mode 100644 bamort/models.go create mode 100644 bamort/scripts/initial_steps.md rename bamort/{sql => scripts}/mysql_structure.sql (100%) create mode 100644 bamort/tests/api_test.md diff --git a/bamort/config.go b/bamort/config.go new file mode 100644 index 0000000..6ec7f3e --- /dev/null +++ b/bamort/config.go @@ -0,0 +1,23 @@ +package main + +import ( + "log" + + "gorm.io/driver/mysql" + "gorm.io/gorm" +) + +var DB *gorm.DB + +func ConnectDatabase() { + dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local" + database, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) + if err != nil { + log.Fatal("Failed to connect to database:", err) + } + DB = database +} + +/* +Replace user, password, and dbname with your MySQL credentials and database name. +*/ diff --git a/bamort/main.go b/bamort/main.go new file mode 100644 index 0000000..cf6c769 --- /dev/null +++ b/bamort/main.go @@ -0,0 +1,109 @@ +package main + +import ( + "github.com/gin-gonic/gin" +) + +func main() { + ConnectDatabase() + DB.AutoMigrate(&User{}, &Character{}, &Eigenschaften{}) // Add other models here + + r := gin.Default() + + // Routes + r.POST("/register", RegisterUser) + r.POST("/login", LoginUser) + r.GET("/characters", GetCharacters) + r.POST("/characters", CreateCharacter) + + r.Run(":8080") // Start server on port 8080 +} + + +/* +User Handlers + +Add handlers for user registration and login: +*/ +package main + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "golang.org/x/crypto/bcrypt" +) + +func RegisterUser(c *gin.Context) { + var user User + if err := c.ShouldBindJSON(&user); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(user.PasswordHash), bcrypt.DefaultCost) + user.PasswordHash = string(hashedPassword) + + if err := DB.Create(&user).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"}) + return + } + + c.JSON(http.StatusCreated, gin.H{"message": "User registered successfully"}) +} + +func LoginUser(c *gin.Context) { + var user User + var input struct { + Username string `json:"username"` + Password string `json:"password"` + } + + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + if err := DB.Where("username = ?", input.Username).First(&user).Error; err != nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid username or password"}) + return + } + + if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(input.Password)); err != nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid username or password"}) + return + } + + c.JSON(http.StatusOK, gin.H{"message": "Login successful"}) +} + + +/* +Character Handlers + +Add CRUD operations for characters: +*/ + +func GetCharacters(c *gin.Context) { + var characters []Character + if err := DB.Find(&characters).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve characters"}) + return + } + c.JSON(http.StatusOK, characters) +} + +func CreateCharacter(c *gin.Context) { + var character Character + if err := c.ShouldBindJSON(&character); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + if err := DB.Create(&character).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create character"}) + return + } + + c.JSON(http.StatusCreated, character) +} diff --git a/bamort/models.go b/bamort/models.go new file mode 100644 index 0000000..1749456 --- /dev/null +++ b/bamort/models.go @@ -0,0 +1,43 @@ +package main + +type User struct { + UserID uint `gorm:"primaryKey"` + Username string `gorm:"unique"` + PasswordHash string + Email string `gorm:"unique"` +} + +type Character struct { + CharacterID uint `gorm:"primaryKey"` + UserID uint `gorm:"index"` + Name string + Rasse string + Typ string + Alter int + Anrede string + Grad int + Groesse int + Gewicht int + Glaube string + Hand string + Image string +} + +type Eigenschaften struct { + EigenschaftenID uint `gorm:"primaryKey"` + CharacterID uint `gorm:"index"` + Au int + Gs int + Gw int + In int + Ko int + Pa int + St int + Wk int + Zt int +} + +/* +Define models for each table +Add other models for Ausruestung, Fertigkeiten, etc., following the same pattern. +*/ diff --git a/bamort/scripts/initial_steps.md b/bamort/scripts/initial_steps.md new file mode 100644 index 0000000..f0906b1 --- /dev/null +++ b/bamort/scripts/initial_steps.md @@ -0,0 +1,6 @@ +# Install Dependencies +## Install the necessary packages: + +go get -u github.com/gin-gonic/gin +go get -u gorm.io/gorm +go get -u gorm.io/driver/mysql diff --git a/bamort/sql/mysql_structure.sql b/bamort/scripts/mysql_structure.sql similarity index 100% rename from bamort/sql/mysql_structure.sql rename to bamort/scripts/mysql_structure.sql diff --git a/bamort/tests/api_test.md b/bamort/tests/api_test.md new file mode 100644 index 0000000..1e886b9 --- /dev/null +++ b/bamort/tests/api_test.md @@ -0,0 +1,18 @@ +/* +API Testing + + Register User: + POST /register + Body: { "username": "test", "password": "12345", "email": "test@example.com" } + + Login User: + POST /login + Body: { "username": "test", "password": "12345" } + + Create Character: + POST /characters + Body: { "user_id": 1, "name": "Hero", "rasse": "Elf", "typ": "Warrior", "alter": 25 } + + Get Characters: + GET /characters +*/ \ No newline at end of file