Added Configuration Management

This commit is contained in:
2026-02-22 13:27:50 +01:00
parent d441b002b0
commit c492228e22
7 changed files with 158 additions and 10 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,3 @@
database.db appdata
.idea .idea
*.exe *.exe

56
config/config.go Normal file
View File

@@ -0,0 +1,56 @@
package config
import (
"log"
"os"
"path/filepath"
"gopkg.in/yaml.v3"
)
type Config struct {
Port string `yaml:"port"`
DatabasePath string `yaml:"database_path"`
}
const configPath = "./appdata/config.yaml"
func CheckIfExists() error {
_, err := os.Stat(configPath)
if err == nil {
return nil
}
if !os.IsNotExist(err) {
return err
}
log.Printf("Config file %s doesn't exist, creating...", configPath)
err = os.MkdirAll(filepath.Dir(configPath), 0755)
if err != nil {
return err
}
defaultConfig := Config{
Port: "8080",
DatabasePath: "./appdata/database.db",
}
data, err := yaml.Marshal(defaultConfig)
if err != nil {
return err
}
return os.WriteFile(configPath, data, 0644)
}
func LoadConfig() (Config, error) {
var cfg Config
file, err := os.ReadFile(configPath)
if err != nil {
return cfg, err
}
err = yaml.Unmarshal(file, &cfg)
return cfg, err
}

2
go.mod
View File

@@ -4,8 +4,10 @@ go 1.26.0
require ( require (
github.com/glebarez/go-sqlite v1.22.0 github.com/glebarez/go-sqlite v1.22.0
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
golang.org/x/crypto v0.48.0 golang.org/x/crypto v0.48.0
gopkg.in/yaml.v3 v3.0.1
) )
require ( require (

6
go.sum
View File

@@ -2,6 +2,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ= github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc= github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -15,6 +17,10 @@ golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVo
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/libc v1.37.6 h1:orZH3c5wmhIQFTXF+Nt+eeauyd+ZIt2BX6ARe+kD+aw= modernc.org/libc v1.37.6 h1:orZH3c5wmhIQFTXF+Nt+eeauyd+ZIt2BX6ARe+kD+aw=
modernc.org/libc v1.37.6/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE= modernc.org/libc v1.37.6/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=

17
main.go
View File

@@ -2,20 +2,21 @@ package main
import ( import (
"log" "log"
"net/http" "shap-planner-backend/server"
"shap-planner-backend/handlers"
"shap-planner-backend/storage" "shap-planner-backend/storage"
) )
func main() { func main() {
err := storage.InitDB("database.db") var SERVER = server.InitServer()
err := storage.InitDB(SERVER.DatabasePath)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
http.HandleFunc("/register", handlers.Register) SERVER.Run()
http.HandleFunc("/login", handlers.Login) }
log.Println("Server läuft auf :8080") func Setup() {
log.Fatal(http.ListenAndServe(":8080", nil)) //TODO: first configuration
} }

50
server/server.go Normal file
View File

@@ -0,0 +1,50 @@
package server
import (
"log"
"net/http"
"os"
"shap-planner-backend/config"
"shap-planner-backend/handlers"
)
type Server struct {
Port string
JWTSecret []byte
DatabasePath string
}
func InitServer() *Server {
err := config.CheckIfExists()
if err != nil {
log.Fatal(err)
}
cfg, err := config.LoadConfig()
if err != nil {
log.Fatal(err)
}
jwtSecret := os.Getenv("SHAP_JWT_SECRET")
if jwtSecret == "" {
log.Fatal("SHAP_JWT_SECRET environment variable not set.")
}
if len(jwtSecret) < 32 {
log.Fatal("SHAP_JWT_SECRET must be at least 32 characters long.")
}
return &Server{
Port: cfg.Port,
JWTSecret: []byte(jwtSecret),
DatabasePath: cfg.DatabasePath,
}
}
func (server *Server) Run() {
http.HandleFunc("/register", handlers.Register)
http.HandleFunc("/login", handlers.Login)
log.Printf("Listening on port %s", server.Port)
log.Fatal(http.ListenAndServe(":"+server.Port, nil))
}

View File

@@ -1,20 +1,53 @@
package utils package utils
import ( import (
"os"
"time"
"crypto/rand"
"encoding/base64"
"github.com/golang-jwt/jwt/v5"
"github.com/google/uuid" "github.com/google/uuid"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
var secret = []byte(os.Getenv("SHAP_JWT_SECRET"))
// Password Validation
func HashPassword(password string) (string, error) { func HashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14) bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
return string(bytes), err return string(bytes), err
} }
func CheckPasswordHash(password, hash string) bool { func CheckPasswordHash(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil return err == nil
} }
// JWT Validation
func GenerateJWT(userID string) (string, error) {
claims := jwt.MapClaims{
"userId": userID,
"exp": time.Now().Add(time.Hour * 1).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(secret)
}
func ValidateJWT(tokenString string) (*jwt.Token, error) {
return jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return secret, nil
})
}
func GenerateUUID() string { func GenerateUUID() string {
return uuid.New().String() return uuid.New().String()
} }
func GenerateSecret() string {
b := make([]byte, 64)
_, err := rand.Read(b)
if err != nil {
return err.Error()
}
return base64.StdEncoding.EncodeToString(b)
}