handle Import by upload vtt json and

handle login, token generation and check
This commit is contained in:
2025-01-04 21:29:33 +01:00
parent 0a5971cea4
commit e32102509c
12 changed files with 594 additions and 104 deletions
-78
View File
@@ -5,12 +5,8 @@ import (
"bamort/models"
"bamort/skills"
"encoding/json"
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/gin-gonic/gin"
)
@@ -109,80 +105,6 @@ func DeleteCharacter(c *gin.Context) {
c.JSON(http.StatusCreated, character)
}
// Upload files
func UploadFiles(c *gin.Context) {
// Get files from the request
file_vtt, err1 := c.FormFile("file_vtt")
file_csv, err2 := c.FormFile("file_csv")
if err1 != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "file_vtt is required"})
return
}
if !isValidFileType(file_vtt.Filename) {
c.JSON(http.StatusBadRequest, gin.H{"error": "File1 must be a .csv or .json file"})
return
}
// Validate file2 if provided
if file_csv != nil && !isValidFileType(file_csv.Filename) {
c.JSON(http.StatusBadRequest, gin.H{"error": "File2 must be a .csv or .json file"})
return
}
// Save File 1
err := c.SaveUploadedFile(file_vtt, fmt.Sprintf("./uploads/%s", file_vtt.Filename))
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save file_vtt"})
return
}
// Save File 2 if provided
if err2 == nil {
err := c.SaveUploadedFile(file_csv, fmt.Sprintf("./uploads/%s", file_csv.Filename))
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save file_csv"})
return
}
}
c.JSON(http.StatusOK, gin.H{"message": "Files uploaded successfully"})
// Open and parse JSON
var character Char
filePath := fmt.Sprintf("./uploads/%s", file_vtt.Filename)
fileContent, err := os.ReadFile(filePath)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read file"})
return
}
if err := json.Unmarshal(fileContent, &character); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON structure"})
return
}
// Save character data to the database
if err := SaveCharacterToDB(&character); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save character to database"})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "Character imported successfully",
"character": character,
})
}
func isValidFileType(filename string) bool {
allowedExtensions := []string{".csv", ".json"}
ext := strings.ToLower(filepath.Ext(filename))
for _, allowedExt := range allowedExtensions {
if ext == allowedExt {
return true
}
}
return false
}
// Add Fertigkeit by putting it directly to the DB
func AddFertigkeit(charID uint, fertigkeit *skills.Fertigkeit) error {
// Set the foreign key for the new Eigenschaft
+79
View File
@@ -0,0 +1,79 @@
package importer
import (
"fmt"
"net/http"
"path/filepath"
"strings"
"github.com/gin-gonic/gin"
)
// Upload files
func UploadFiles(c *gin.Context) {
// Get files from the request
file_vtt, err1 := c.FormFile("file_vtt")
file_csv, err2 := c.FormFile("file_csv")
if err1 != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "file_vtt is required"})
return
}
if !isValidFileType(file_vtt.Filename) {
c.JSON(http.StatusBadRequest, gin.H{"error": "File1 must be a .csv or .json file"})
return
}
vttFileName := fmt.Sprintf("./uploads/%s", file_vtt.Filename)
csvFileName := "./uploads/default.csv"
if file_csv != nil {
csvFileName = fmt.Sprintf("./uploads/%s", file_csv.Filename)
}
// Validate file2 if provided
if file_csv != nil && !isValidFileType(file_csv.Filename) {
c.JSON(http.StatusBadRequest, gin.H{"error": "File2 must be a .csv or .json file"})
return
}
// Save File 1
err := c.SaveUploadedFile(file_vtt, vttFileName)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save file_vtt"})
return
}
// Save File 2 if provided
if err2 == nil {
err := c.SaveUploadedFile(file_csv, csvFileName)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save file_csv"})
return
}
}
character, err3 := ImportVTTJSON(vttFileName)
if err3 != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to Import Character from file %s", err3.Error())})
return
}
if character.ID < 1 {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to Import Character from file ID is < 1"})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "Character imported successfully",
"character": character,
})
}
func isValidFileType(filename string) bool {
allowedExtensions := []string{".csv", ".json"}
ext := strings.ToLower(filepath.Ext(filename))
for _, allowedExt := range allowedExtensions {
if ext == allowedExt {
return true
}
}
return false
}
+250
View File
@@ -0,0 +1,250 @@
package importer
import (
"bamort/character"
"bamort/equipment"
"bamort/models"
"bamort/skills"
"encoding/json"
"os"
)
func readImportChar(fileName string) (*CharacterImport, error) {
// loading file to Modell
fileContent, err := os.ReadFile(fileName)
if err != nil {
return nil, err
}
character := CharacterImport{}
err = json.Unmarshal(fileContent, &character)
return &character, err
}
func ImportVTTJSON(fileName string) (*character.Char, error) {
//fileName = fmt.Sprintf("../testdata/%s", "VTT_Import1.json")
imp, err := readImportChar(fileName)
if err != nil {
return nil, err
}
err = CheckFertigkeiten2GSMaster(imp.Fertigkeiten)
if err != nil {
return nil, err
}
err = CheckWaffenFertigkeiten2GSMaster(imp.Waffenfertigkeiten)
if err != nil {
return nil, err
}
err = CheckSpells2GSMaster(imp.Zauber)
if err != nil {
return nil, err
}
err = CheckWeapons2GSMaster(imp.Waffen)
if err != nil {
return nil, err
}
err = CheckContainers2GSMaster(imp.Behaeltnisse)
if err != nil {
return nil, err
}
err = CheckTransportationss2GSMaster(imp.Transportmittel)
if err != nil {
return nil, err
}
err = CheckEquipments2GSMaster(imp.Ausruestung)
if err != nil {
return nil, err
}
err = CheckBelieve2GSMaster(imp)
if err != nil {
return nil, err
}
char := character.Char{}
char.Name = imp.Name
char.Rasse = imp.Rasse
char.Typ = imp.Typ
char.Alter = imp.Alter
char.Anrede = imp.Anrede
char.Grad = imp.Grad
char.Groesse = imp.Groesse
char.Gewicht = imp.Gewicht
char.Glaube = imp.Glaube
char.Hand = imp.Hand
char.Image = imp.Image
for i := range imp.Fertigkeiten {
char.Fertigkeiten = append(char.Fertigkeiten, skills.Fertigkeit{
BamortCharTrait: models.BamortCharTrait{
BamortBase: models.BamortBase{Name: imp.Fertigkeiten[i].Name},
},
Beschreibung: imp.Fertigkeiten[i].Beschreibung,
Fertigkeitswert: imp.Fertigkeiten[i].Fertigkeitswert,
Bonus: imp.Fertigkeiten[i].Bonus,
Bemerkung: imp.Fertigkeiten[i].Beschreibung,
})
}
for i := range imp.Zauber {
char.Zauber = append(char.Zauber, skills.Zauber{
BamortCharTrait: models.BamortCharTrait{
BamortBase: models.BamortBase{Name: imp.Zauber[i].Name},
},
Beschreibung: imp.Zauber[i].Beschreibung,
Bonus: imp.Zauber[i].Bonus,
Quelle: imp.Zauber[i].Quelle,
})
}
char.Lp.Max = imp.Lp.Max
char.Lp.Value = imp.Lp.Value
char.Eigenschaften = append(char.Eigenschaften, character.Eigenschaft{
Name: "Au",
Value: imp.Eigenschaften.Au,
})
char.Eigenschaften = append(char.Eigenschaften, character.Eigenschaft{
Name: "Gs",
Value: imp.Eigenschaften.Gs,
})
char.Eigenschaften = append(char.Eigenschaften, character.Eigenschaft{
Name: "Gw",
Value: imp.Eigenschaften.Gw,
})
char.Eigenschaften = append(char.Eigenschaften, character.Eigenschaft{
Name: "In",
Value: imp.Eigenschaften.In,
})
char.Eigenschaften = append(char.Eigenschaften, character.Eigenschaft{
Name: "Ko",
Value: imp.Eigenschaften.Ko,
})
char.Eigenschaften = append(char.Eigenschaften, character.Eigenschaft{
Name: "PA",
Value: imp.Eigenschaften.Pa,
})
char.Eigenschaften = append(char.Eigenschaften, character.Eigenschaft{
Name: "St",
Value: imp.Eigenschaften.St,
})
char.Eigenschaften = append(char.Eigenschaften, character.Eigenschaft{
Name: "Wk",
Value: imp.Eigenschaften.Wk,
})
char.Eigenschaften = append(char.Eigenschaften, character.Eigenschaft{
Name: "Zt",
Value: imp.Eigenschaften.Zt,
})
char.Merkmale.Augenfarbe = imp.Merkmale.Augenfarbe
char.Merkmale.Haarfarbe = imp.Merkmale.Haarfarbe
char.Merkmale.Sonstige = imp.Merkmale.Sonstige
char.Bennies = character.Bennies{
BamortCharTrait: models.BamortCharTrait{
BamortBase: models.BamortBase{Name: "bennies"},
},
Gg: imp.Bennies.Gg,
Sg: imp.Bennies.Sg,
Gp: imp.Bennies.Gp,
}
char.Merkmale.Breite = imp.Gestalt.Breite
char.Merkmale.Groesse = imp.Gestalt.Groesse
char.Ap.Max = imp.Ap.Max
char.Ap.Value = imp.Ap.Value
char.B.Max = imp.B.Max
char.B.Value = imp.B.Value
char.Erfahrungsschatz.Value = imp.Erfahrungsschatz.Value
for i := range imp.Transportmittel {
char.Transportmittel = append(char.Transportmittel, equipment.Transportation{
BamortCharTrait: models.BamortCharTrait{
BamortBase: models.BamortBase{Name: imp.Transportmittel[i].Name},
},
Beschreibung: imp.Transportmittel[i].Beschreibung,
BeinhaltetIn: imp.Transportmittel[i].BeinhaltetIn,
Gewicht: float64(imp.Transportmittel[i].Gewicht),
Tragkraft: imp.Transportmittel[i].Tragkraft,
Wert: imp.Transportmittel[i].Wert,
Magisch: models.Magisch{
IstMagisch: imp.Transportmittel[i].Magisch.IstMagisch,
Abw: imp.Transportmittel[i].Magisch.Abw,
Ausgebrannt: imp.Transportmittel[i].Magisch.Ausgebrannt,
},
})
}
for i := range imp.Ausruestung {
char.Ausruestung = append(char.Ausruestung, equipment.Ausruestung{
BamortCharTrait: models.BamortCharTrait{
BamortBase: models.BamortBase{
Name: imp.Ausruestung[i].Name},
},
Beschreibung: imp.Ausruestung[i].Beschreibung,
Anzahl: imp.Ausruestung[i].Anzahl,
BeinhaltetIn: imp.Ausruestung[i].BeinhaltetIn,
Bonus: imp.Ausruestung[i].Bonus,
Gewicht: float64(imp.Ausruestung[i].Gewicht),
Wert: imp.Ausruestung[i].Wert,
Magisch: models.Magisch{
IstMagisch: imp.Ausruestung[i].Magisch.IstMagisch,
Abw: imp.Ausruestung[i].Magisch.Abw,
Ausgebrannt: imp.Ausruestung[i].Magisch.Ausgebrannt,
},
})
}
for i := range imp.Behaeltnisse {
char.Behaeltnisse = append(char.Behaeltnisse, equipment.Behaeltniss{
BamortCharTrait: models.BamortCharTrait{
BamortBase: models.BamortBase{
Name: imp.Behaeltnisse[i].Name},
},
Beschreibung: imp.Behaeltnisse[i].Beschreibung,
BeinhaltetIn: imp.Behaeltnisse[i].BeinhaltetIn,
Tragkraft: imp.Behaeltnisse[i].Tragkraft,
Volumen: imp.Behaeltnisse[i].Volumen,
Gewicht: float64(imp.Behaeltnisse[i].Gewicht),
Wert: imp.Behaeltnisse[i].Wert,
Magisch: models.Magisch{
IstMagisch: imp.Behaeltnisse[i].Magisch.IstMagisch,
Abw: imp.Behaeltnisse[i].Magisch.Abw,
Ausgebrannt: imp.Behaeltnisse[i].Magisch.Ausgebrannt,
},
})
}
for i := range imp.Waffen {
char.Waffen = append(char.Waffen, equipment.Waffe{
BamortCharTrait: models.BamortCharTrait{
BamortBase: models.BamortBase{
Name: imp.Waffen[i].Name},
},
Beschreibung: imp.Waffen[i].Beschreibung,
Abwb: imp.Waffen[i].Abwb,
Anb: imp.Waffen[i].Anb,
Anzahl: imp.Waffen[i].Anzahl,
Schb: imp.Waffen[i].Schb,
BeinhaltetIn: imp.Waffen[i].BeinhaltetIn,
Gewicht: float64(imp.Waffen[i].Gewicht),
Wert: imp.Waffen[i].Wert,
NameFuerSpezialisierung: imp.Waffen[i].NameFuerSpezialisierung,
Magisch: models.Magisch{
IstMagisch: imp.Waffen[i].Magisch.IstMagisch,
Abw: imp.Waffen[i].Magisch.Abw,
Ausgebrannt: imp.Waffen[i].Magisch.Ausgebrannt,
},
})
}
for i := range imp.Waffenfertigkeiten {
char.Waffenfertigkeiten = append(char.Waffenfertigkeiten, skills.Waffenfertigkeit{
Fertigkeit: skills.Fertigkeit{
BamortCharTrait: models.BamortCharTrait{
BamortBase: models.BamortBase{Name: imp.Waffenfertigkeiten[i].Name},
},
Beschreibung: imp.Waffenfertigkeiten[i].Beschreibung,
Fertigkeitswert: imp.Waffenfertigkeiten[i].Fertigkeitswert,
Bonus: imp.Waffenfertigkeiten[i].Bonus,
//Bemerkung: imp.Waffenfertigkeiten[i],
},
})
}
for i := range imp.Spezialisierung {
char.Spezialisierung = append(char.Spezialisierung, imp.Spezialisierung[i])
}
err = char.Create()
if err != nil {
return nil, err
}
return &char, nil
}
+2 -2
View File
@@ -47,7 +47,7 @@ type Waffe struct {
type Behaeltniss struct {
ImportBase
Beschreibung string `json:"beschreibung"`
BeinhaltetIn any `json:"beinhaltet_in"`
BeinhaltetIn string `json:"beinhaltet_in"`
Gewicht float64 `json:"gewicht"`
Magisch Magisch `json:"magisch"`
Tragkraft float64 `json:"tragkraft"`
@@ -58,7 +58,7 @@ type Behaeltniss struct {
type Transportation struct {
ImportBase
Beschreibung string `json:"beschreibung"`
BeinhaltetIn any `json:"beinhaltet_in"`
BeinhaltetIn string `json:"beinhaltet_in"`
Gewicht int `json:"gewicht"`
Tragkraft float64 `json:"tragkraft"`
Wert float64 `json:"wert"`
+2 -2
View File
@@ -1,8 +1,8 @@
package main
import (
"bamort/character"
"bamort/database"
"bamort/importer"
"bamort/maintenance"
"bamort/router"
@@ -39,7 +39,7 @@ func main() {
protected.PUT("/ausruestung/:ausruestung_id", equipment.UpdateAusruestung)
protected.DELETE("/ausruestung/:ausruestung_id", equipment.DeleteAusruestung)
*/
protected.POST("/upload", character.UploadFiles)
protected.POST("/upload", importer.UploadFiles)
protected.GET("/setupcheck", maintenance.SetupCheck)
r.Run(":8180") // Start server on port 8080
+7
View File
@@ -4,6 +4,7 @@ import (
"bamort/character"
"bamort/database"
"bamort/equipment"
"bamort/importer"
"bamort/models"
"bamort/skills"
"encoding/base64"
@@ -782,6 +783,12 @@ func TestAddAusrüstung(t *testing.T) {
func TestImportVTT2Char(t *testing.T) {
SetupTestDB()
fileName := fmt.Sprintf("../testdata/%s", "VTT_Import1.json")
char, err := importer.ImportVTTJSON(fileName)
assert.NoError(t, err, "expected no error when saving imported Char")
var chr2 character.Char
chr2.First(char.Name)
assert.Equal(t, char.ID, chr2.ID)
/*
// loading file to Modell
fileName := fmt.Sprintf("../testdata/%s", "VTT_Import1.json")
+115
View File
@@ -0,0 +1,115 @@
package tests
import (
"bamort/user"
"crypto/md5"
"encoding/hex"
"fmt"
"strconv"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestRegisterUser(t *testing.T) {
SetupTestDB()
usr := user.User{
Username: "bebe",
PasswordHash: "osiris",
Email: "frank@wuenscheonline.de",
}
hashedPassword := md5.Sum([]byte(usr.PasswordHash))
usr.PasswordHash = hex.EncodeToString(hashedPassword[:])
err := usr.Create()
assert.NoError(t, err, "no error expected when creating record")
usr2 := user.User{
Username: "bubnu",
PasswordHash: "osiris",
Email: "spacer@wuenscheonline.de",
}
hashedPassword = md5.Sum([]byte(usr2.PasswordHash))
usr2.PasswordHash = hex.EncodeToString(hashedPassword[:])
err = usr2.Create()
assert.NoError(t, err, "no error expected when creating record")
}
func TestLoginUser(t *testing.T) {
TestRegisterUser(t)
var usr user.User
input := struct {
Username string `json:"username"`
Password string `json:"password"`
HashedPassword string
}{
Username: "bebe",
Password: "osiris",
}
err := usr.First(input.Username)
assert.NoError(t, err, "no error expected when finding record")
hashedPassword := md5.Sum([]byte(input.Password))
input.HashedPassword = hex.EncodeToString(hashedPassword[:])
assert.Equal(t, input.HashedPassword, usr.PasswordHash)
}
func TestHshing(t *testing.T) {
TestRegisterUser(t)
var u1 user.User
u1.First("bebe")
assert.Equal(t, "", u1.Username+u1.CreatedAt.String())
tx := md5.Sum([]byte(u1.Username + u1.CreatedAt.String()))
assert.NotEmpty(t, tx)
// Convert hash to raw string
hashString := hex.EncodeToString(tx[:])
assert.Equal(t, "", hashString)
pos := 7
idm := "." + strconv.Itoa(int(u1.UserID)) + ":"
// Insert the character
token := hashString[:pos] + idm + hashString[pos:]
assert.Equal(t, "", token)
// check
var u user.User
var err error
userid := 0
// Check if a `.` is at position 7 (zero-indexed)
if len(token) > pos && token[pos] == '.' {
assert.Equal(t, ". ", token[pos])
// Find the next `:` after the `.`
colonPos := strings.Index(token[pos+1:], ":") // Start searching after position 7
if colonPos != -1 {
// Extract the substring between `.` and `:`
uu := token[pos+1 : pos+1+colonPos]
assert.Equal(t, "1 ", uu)
//fmt.Println("Extracted Substring:", result)
userid, err = strconv.Atoi(uu)
assert.NoError(t, err, "no error expexted when strconv")
assert.Equal(t, 2, userid)
}
}
if userid > 0 {
err = u.FirstId(uint(userid))
assert.NoError(t, err, "no error expexted when fetching user")
}
}
func TestCors(t *testing.T) {
SetupTestDB()
us := user.User{
Username: "bebe",
UserID: 1,
PasswordHash: "5f29e63a3f26798930e5bf218445164f",
//CreatedAt: "2025-01-04 09:01:44.911",
}
token := user.GenerateToken(&us)
fmt.Print(token)
usr := user.CheckToken("Bearer " + token)
fmt.Print(usr)
}
+89 -15
View File
@@ -6,11 +6,14 @@ Add handlers for user registration and login:
package user
import (
"bamort/database"
"crypto/md5"
"encoding/hex"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/gin-gonic/gin"
"golang.org/x/crypto/bcrypt"
)
func RegisterUser(c *gin.Context) {
@@ -19,18 +22,76 @@ func RegisterUser(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(user.PasswordHash), bcrypt.DefaultCost)
user.PasswordHash = string(hashedPassword)
if err := database.DB.Create(&user).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"})
//fmt.Printf("User input: '%s'", user.PasswordHash)
//hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(user.PasswordHash), bcrypt.DefaultCost)
hashedPassword := md5.Sum([]byte(user.PasswordHash))
user.PasswordHash = hex.EncodeToString(hashedPassword[:])
//fmt.Printf("pwdh: %s", user.PasswordHash)
if err := user.Create(); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to create user: %s", err)})
return
}
//fmt.Printf(" ___ pwdh2: %s", user.PasswordHash)
c.JSON(http.StatusCreated, gin.H{"message": "User registered successfully:"})
}
func GenerateToken(u *User) string {
//u.Username + "lkiuztrew" + u.CreatedAt.String()
tx := md5.Sum([]byte(u.Username + u.CreatedAt.String()))
// Convert hash to raw string
hashString := hex.EncodeToString(tx[:])
pos := 7
idm := "." + fmt.Sprintf("%d", u.UserID) + ":"
// Insert the character
token := hashString[:pos] + string(idm) + hashString[pos:]
return token
}
func CheckToken(token string) *User {
//fmt.Print("CheckToken1: " + token)
var u User
var err error
pos := 7 + len("Bearer ")
userid := 0
// Check if a `.` is at position 7 (zero-indexed)
if len(token) > pos && token[pos] == '.' {
//fmt.Print("CheckToken2: " + token + "\n")
// Find the next `:` after the `.`
colonPos := strings.Index(token[pos+1:], ":") // Start searching after position 7
if colonPos != -1 {
//fmt.Printf("CheckToken3: %v\n", colonPos)
// Extract the substring between `.` and `:`
uu := token[pos+1 : pos+1+colonPos]
//fmt.Println("Extracted Substring:" + uu + "\n")
userid, err = strconv.Atoi(uu)
//fmt.Printf("Extracted UserID: %v \n", userid)
if err != nil {
//fmt.Print("CheckToken4: " + err.Error() + "\n")
return nil
}
} else {
//fmt.Print("CheckToken5: not found\n")
return nil
}
} else {
//fmt.Print("CheckToken6: not found\n")
return nil
}
if userid > 0 {
//fmt.Printf("CheckToken6-1: userid %v\n", userid)
//fmt.Printf("CheckToken6-1: userid %v\n", uint(userid))
err := u.FirstId(uint(userid))
if err != nil {
//fmt.Printf("CheckToken7: not found error %s\n", err.Error())
return nil
}
//fmt.Printf("CheckToken8: found:%s \n", u.Username)
return &u
}
//fmt.Print("CheckToken9: not found\n")
return nil
}
func LoginUser(c *gin.Context) {
var user User
var input struct {
@@ -43,17 +104,26 @@ func LoginUser(c *gin.Context) {
return
}
if err := database.DB.Where("username = ?", input.Username).First(&user).Error; err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid username. or password"})
//if err := database.DB.Where("username = ?", input.Username).First(&user).Error; err != nil {
if err := user.First(input.Username); err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": fmt.Sprintf("Invalid username. or password %v", input)})
return
}
if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(input.Password)); err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid username or password."})
hashedPassword := md5.Sum([]byte(input.Password))
fmt.Printf("pwdh: %s", hex.EncodeToString(hashedPassword[:]))
if user.PasswordHash != hex.EncodeToString(hashedPassword[:]) {
c.JSON(http.StatusUnauthorized, gin.H{"error": fmt.Sprintf("Invalid username. or password. %s %s", input.Password, hex.EncodeToString(hashedPassword[:]))})
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"})
c.JSON(http.StatusOK, gin.H{"message": "Login successful", "token": GenerateToken(&user)})
}
// Apply middleware to protected routes
@@ -65,7 +135,11 @@ func AuthMiddleware() gin.HandlerFunc {
c.Abort()
return
}
if CheckToken(token) == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized."})
c.Abort()
return
}
// Add token validation logic here
c.Next()
+44 -1
View File
@@ -1,14 +1,57 @@
package user
import (
"bamort/database"
"fmt"
"time"
"gorm.io/gorm"
)
type User struct {
UserID uint `gorm:"primaryKey" json:"id"`
Username string `gorm:"unique" json:"name"`
Username string `gorm:"unique" json:"username"`
PasswordHash string `json:"password"`
Email string `gorm:"unique" json:"email"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (object *User) Create() error {
err := database.DB.Transaction(func(tx *gorm.DB) error {
// Save the User record
if err := tx.Create(&object).Error; err != nil {
return fmt.Errorf("failed to save User: %w", err)
}
return nil
})
return err
}
func (object *User) First(value string) error {
err := database.DB.First(&object, "username = ?", value).Error
if err != nil {
// User found
return err
}
return nil
}
func (object *User) FirstId(value uint) error {
err := database.DB.First(&object, "user_id = ?", value).Error
if err != nil {
// User found
return err
}
return nil
}
func (object *User) Save() error {
err := database.DB.Save(&object).Error
if err != nil {
// User found
return err
}
return nil
}
+3 -3
View File
@@ -3,7 +3,7 @@
<h2>Your Characters</h2>
<ul>
<li v-for="character in characters" :key="character.character_id">
{{ character.name }} ({{ character.rasse }})
{{ character.name }} ({{ character.rasse }}, {{ character.typ }}, {{ character.grad }}, {{ character.owner }}, {{ character.public }} )
<button @click="goToAusruestung(character.character_id)">Manage Equipment</button>
</li>
</ul>
@@ -21,14 +21,14 @@ export default {
},
async created() {
const token = localStorage.getItem('token')
const response = await API.get('/characters', {
const response = await API.get('/api/characters', {
headers: { Authorization: `Bearer ${token}` },
})
this.characters = response.data
},
methods: {
goToAusruestung(characterId) {
this.$router.push(`/ausruestung/${characterId}`)
this.$router.push(`/api/ausruestung/${characterId}`)
},
},
}
+1 -1
View File
@@ -29,7 +29,7 @@ export default {
const response = await API.post("/register", {
username: this.username,
email: this.email,
passwordhash: this.password,
password: this.password,
});
this.success = "Registration successful! You can now log in.";
this.error = "";
+2 -2
View File
@@ -7,7 +7,7 @@
<input type="file" id="file_vtt" @change="onFileChange($event, 1)" />
</div>
<div>
<label for="file_csv">Char CSS (optional):</label>
<label for="file_csv">Char CSV (optional):</label>
<input type="file" id="file_csv" @change="onFileChange($event, 2)" />
</div>
<button type="submit" :disabled="!file_vtt">Upload</button>
@@ -59,7 +59,7 @@ export default {
if (this.file_csv) formData.append("file_csv", this.file_csv);
const token = localStorage.getItem("token"); // Get token from storage
const response = await API.post("/upload", formData, {
const response = await API.post("/api/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
"Authorization": `Bearer ${token}`, // Include token in the header