Added Configuration Management
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,3 @@
|
||||
database.db
|
||||
appdata
|
||||
.idea
|
||||
*.exe
|
||||
56
config/config.go
Normal file
56
config/config.go
Normal 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
2
go.mod
@@ -4,8 +4,10 @@ go 1.26.0
|
||||
|
||||
require (
|
||||
github.com/glebarez/go-sqlite v1.22.0
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||
github.com/google/uuid v1.6.0
|
||||
golang.org/x/crypto v0.48.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
6
go.sum
6
go.sum
@@ -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/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/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/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
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.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
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/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE=
|
||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||
|
||||
17
main.go
17
main.go
@@ -2,20 +2,21 @@ package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"shap-planner-backend/handlers"
|
||||
"shap-planner-backend/server"
|
||||
"shap-planner-backend/storage"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := storage.InitDB("database.db")
|
||||
var SERVER = server.InitServer()
|
||||
|
||||
err := storage.InitDB(SERVER.DatabasePath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
http.HandleFunc("/register", handlers.Register)
|
||||
http.HandleFunc("/login", handlers.Login)
|
||||
|
||||
log.Println("Server läuft auf :8080")
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
SERVER.Run()
|
||||
}
|
||||
|
||||
func Setup() {
|
||||
//TODO: first configuration
|
||||
}
|
||||
|
||||
50
server/server.go
Normal file
50
server/server.go
Normal 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))
|
||||
}
|
||||
@@ -1,20 +1,53 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
var secret = []byte(os.Getenv("SHAP_JWT_SECRET"))
|
||||
|
||||
// Password Validation
|
||||
func HashPassword(password string) (string, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
func CheckPasswordHash(password, hash string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user