add enviroment variable for golang beckend close #6
This commit is contained in:
1
backend/.gitignore
vendored
Normal file
1
backend/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.env
|
||||||
59
backend/env/env.go
vendored
Normal file
59
backend/env/env.go
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package env
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EnvKey string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Env EnvKey = "ENV"
|
||||||
|
GinMode EnvKey = "GIN_MODE"
|
||||||
|
Debug EnvKey = "DEBUG"
|
||||||
|
PrivKey EnvKey = "PRIVKEY"
|
||||||
|
Fullchain EnvKey = "FULLCHAIN"
|
||||||
|
Https EnvKey = "HTTPS"
|
||||||
|
Url EnvKey = "URL"
|
||||||
|
Port EnvKey = "PORT"
|
||||||
|
WorkingDir EnvKey = "WORKING_DIR"
|
||||||
|
Spa EnvKey = "SPA"
|
||||||
|
AccessSecret EnvKey = "ACCESS_SECRET"
|
||||||
|
RefreshSecret EnvKey = "REFRESH_SECRET"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EnvDevelopment = "development"
|
||||||
|
EnvProduction = "Prodction"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (key EnvKey) GetValue() string {
|
||||||
|
return os.Getenv(string(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (key EnvKey) GetBoolValue() bool {
|
||||||
|
return strings.ToLower(os.Getenv(string(key))) == "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (key EnvKey) GetUIntValue() uint {
|
||||||
|
value, err := strconv.ParseUint(os.Getenv(string(key)), 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return uint(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Load(file string) error {
|
||||||
|
return godotenv.Load(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
func InDevelopmentMode() bool {
|
||||||
|
return Env.GetValue() == EnvDevelopment
|
||||||
|
}
|
||||||
|
|
||||||
|
func InDebugMode() bool {
|
||||||
|
return strings.ToLower(Debug.GetValue()) == "true"
|
||||||
|
}
|
||||||
12
backend/example/example.env
Normal file
12
backend/example/example.env
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
ENV=development
|
||||||
|
GIN_MODE=release
|
||||||
|
DEBUG=false
|
||||||
|
SPA=directory_of_spa_files
|
||||||
|
WORKING_DIR=.
|
||||||
|
URL=your_local_url
|
||||||
|
PORT=your_local_port
|
||||||
|
HTTPS=true
|
||||||
|
PRIVKEY=your_certificate_key_file
|
||||||
|
FULLCHAIN=your_certificate_fullchain_file
|
||||||
|
ACCESS_SECRET=your_32bit_long_access_secret
|
||||||
|
REFRESH_SECRET=your_32bit_long_referesh_secret
|
||||||
@@ -3,12 +3,13 @@ module backend
|
|||||||
go 1.24.5
|
go 1.24.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
gitea.tecamino.com/paadi/access-handler v1.0.19
|
gitea.tecamino.com/paadi/access-handler v1.0.22
|
||||||
gitea.tecamino.com/paadi/memberDB v1.1.2
|
gitea.tecamino.com/paadi/memberDB v1.1.2
|
||||||
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1
|
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1
|
||||||
gitea.tecamino.com/paadi/tecamino-logger v0.2.1
|
gitea.tecamino.com/paadi/tecamino-logger v0.2.1
|
||||||
github.com/gin-contrib/cors v1.7.6
|
github.com/gin-contrib/cors v1.7.6
|
||||||
github.com/gin-gonic/gin v1.11.0
|
github.com/gin-gonic/gin v1.11.0
|
||||||
|
github.com/joho/godotenv v1.5.1
|
||||||
golang.org/x/crypto v0.43.0
|
golang.org/x/crypto v0.43.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
gitea.tecamino.com/paadi/access-handler v1.0.19 h1:L51Qg5RNjdIGeQsHwGUTV+ADRpUqPt3qdnu7A7UQbsw=
|
gitea.tecamino.com/paadi/access-handler v1.0.22 h1:XFi2PQ1gWqe9YuSye4Ti1o5TpdV0AFpt4Fb58MFMagk=
|
||||||
gitea.tecamino.com/paadi/access-handler v1.0.19/go.mod h1:wKsB5/Rvaj580gdg3+GbUf5V/0N00XN6cID+C/8135M=
|
gitea.tecamino.com/paadi/access-handler v1.0.22/go.mod h1:wKsB5/Rvaj580gdg3+GbUf5V/0N00XN6cID+C/8135M=
|
||||||
gitea.tecamino.com/paadi/dbHandler v1.0.8 h1:ZWSBM/KFtLwTv2cBqwK1mOxWAxAfL0BcWEC3kJ9JALU=
|
gitea.tecamino.com/paadi/dbHandler v1.0.8 h1:ZWSBM/KFtLwTv2cBqwK1mOxWAxAfL0BcWEC3kJ9JALU=
|
||||||
gitea.tecamino.com/paadi/dbHandler v1.0.8/go.mod h1:y/xn/POJg1DO++67uKvnO23lJQgh+XFQq7HZCS9Getw=
|
gitea.tecamino.com/paadi/dbHandler v1.0.8/go.mod h1:y/xn/POJg1DO++67uKvnO23lJQgh+XFQq7HZCS9Getw=
|
||||||
gitea.tecamino.com/paadi/memberDB v1.1.2 h1:j/Tsr7JnzAkdOvgjG77TzTVBWd4vBrmEFzPXNpW7GYk=
|
gitea.tecamino.com/paadi/memberDB v1.1.2 h1:j/Tsr7JnzAkdOvgjG77TzTVBWd4vBrmEFzPXNpW7GYk=
|
||||||
@@ -56,6 +56,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
|||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"backend/env"
|
||||||
"backend/models"
|
"backend/models"
|
||||||
"backend/server"
|
"backend/server"
|
||||||
"backend/utils"
|
"backend/utils"
|
||||||
@@ -27,20 +28,27 @@ func main() {
|
|||||||
|
|
||||||
flag.Var(&allowOrigins, "allowOrigin", "Allowed origin (can repeat this flag)")
|
flag.Var(&allowOrigins, "allowOrigin", "Allowed origin (can repeat this flag)")
|
||||||
|
|
||||||
spa := flag.String("spa", "./dist/spa", "quasar spa files")
|
envFile := flag.String("env", ".env", "enviroment file")
|
||||||
workingDir := flag.String("workingDirectory", ".", "quasar spa files")
|
|
||||||
ip := flag.String("ip", "0.0.0.0", "server listening ip")
|
|
||||||
organization := flag.String("organization", "", "self signed ciertificate organization")
|
organization := flag.String("organization", "", "self signed ciertificate organization")
|
||||||
port := flag.Uint("port", 9500, "server listening port")
|
|
||||||
https := flag.Bool("https", false, "serves as https needs flag -cert and -chain")
|
|
||||||
sslKey := flag.String("privkey", "", "ssl private key path")
|
|
||||||
sslFullchain := flag.String("fullchain", "", "ssl fullchain path")
|
|
||||||
debug := flag.Bool("debug", false, "log debug")
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
// load enviroment file if exists
|
||||||
|
if err := env.Load(*envFile); err != nil {
|
||||||
|
fmt.Println("no .env found path: ", *envFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
devMode := env.InDevelopmentMode()
|
||||||
|
// set gin mode
|
||||||
|
if !devMode {
|
||||||
|
gin.SetMode(env.GinMode.GetValue())
|
||||||
|
}
|
||||||
|
|
||||||
|
workingDir := env.WorkingDir.GetValue()
|
||||||
|
spa := env.Spa.GetValue()
|
||||||
|
|
||||||
//change working directory only if value is given
|
//change working directory only if value is given
|
||||||
if *workingDir != "." && *workingDir != "" {
|
if workingDir != "." && workingDir != "" {
|
||||||
os.Chdir(*workingDir)
|
os.Chdir(workingDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
wd, err := os.Getwd()
|
wd, err := os.Getwd()
|
||||||
@@ -55,7 +63,7 @@ func main() {
|
|||||||
MaxSize: 1,
|
MaxSize: 1,
|
||||||
MaxBackup: 3,
|
MaxBackup: 3,
|
||||||
MaxAge: 28,
|
MaxAge: 28,
|
||||||
Debug: *debug,
|
Debug: env.InDebugMode(),
|
||||||
TerminalOut: true,
|
TerminalOut: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -82,11 +90,11 @@ func main() {
|
|||||||
|
|
||||||
//get local ip
|
//get local ip
|
||||||
httpString := "http://"
|
httpString := "http://"
|
||||||
if *https {
|
if env.Https.GetBoolValue() {
|
||||||
httpString = "https://"
|
httpString = "https://"
|
||||||
|
|
||||||
}
|
}
|
||||||
allowOrigins = append(allowOrigins, httpString+"localhost:9000", httpString+"localhost:9500", httpString+"127.0.0.1:9500", httpString+"0.0.0.0:9500")
|
allowOrigins = append(allowOrigins, httpString+"localhost:9000", httpString+"localhost:9500", httpString+"127.0.0.1:9000", httpString+"0.0.0.0:9500")
|
||||||
|
|
||||||
localIP, err := utils.GetLocalIP()
|
localIP, err := utils.GetLocalIP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -153,7 +161,7 @@ func main() {
|
|||||||
api.POST("/login/refresh", accessHandler.Refresh)
|
api.POST("/login/refresh", accessHandler.Refresh)
|
||||||
|
|
||||||
// Serve static files
|
// Serve static files
|
||||||
s.Routes.StaticFS("/assets", gin.Dir(filepath.Join(*spa, "assets"), true))
|
s.Routes.StaticFS("/assets", gin.Dir(filepath.Join(spa, "assets"), true))
|
||||||
s.Routes.NoRoute(func(c *gin.Context) {
|
s.Routes.NoRoute(func(c *gin.Context) {
|
||||||
// Disallow fallback for /api paths
|
// Disallow fallback for /api paths
|
||||||
if strings.HasPrefix(c.Request.URL.Path, "/api") {
|
if strings.HasPrefix(c.Request.URL.Path, "/api") {
|
||||||
@@ -161,44 +169,44 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Try to serve file from SPA directory
|
// Try to serve file from SPA directory
|
||||||
filePath := filepath.Join(*spa, c.Request.URL.Path)
|
filePath := filepath.Join(spa, c.Request.URL.Path)
|
||||||
if _, err := os.Stat(filePath); err == nil {
|
if _, err := os.Stat(filePath); err == nil {
|
||||||
c.File(filePath)
|
c.File(filePath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Fallback to index.html for SPA routing
|
// Fallback to index.html for SPA routing
|
||||||
c.File(filepath.Join(*spa, "index.html"))
|
c.File(filepath.Join(spa, "index.html"))
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(500 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
if err := utils.OpenBrowser(fmt.Sprintf("%slocalhost:%d", httpString, *port), logger); err != nil {
|
if err := utils.OpenBrowser(fmt.Sprintf("%slocalhost:%s", httpString, env.Port.GetValue()), logger); err != nil {
|
||||||
logger.Error("main", fmt.Sprintf("starting browser error : %s", err))
|
logger.Error("main", fmt.Sprintf("starting browser error : %s", err))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if *https {
|
if env.Https.GetBoolValue() {
|
||||||
if *sslFullchain == "" {
|
if env.Fullchain.GetValue() == "" {
|
||||||
logger.Error("ssl certificate", "-cert flag not given for https server")
|
logger.Error("ssl certificate", "-cert flag not given for https server")
|
||||||
log.Fatal("-cert flag not given for https server")
|
log.Fatal("-cert flag not given for https server")
|
||||||
}
|
}
|
||||||
if *sslKey == "" {
|
if env.PrivKey.GetValue() == "" {
|
||||||
logger.Error("ssl key", "-chain flag not given for https server")
|
logger.Error("ssl key", "-chain flag not given for https server")
|
||||||
log.Fatal("-chain flag not given for https server")
|
log.Fatal("-chain flag not given for https server")
|
||||||
}
|
}
|
||||||
|
|
||||||
// start https server
|
// start https server
|
||||||
logger.Info("main", fmt.Sprintf("https listen on ip: %s port: %d", *ip, *port))
|
logger.Info("main", fmt.Sprintf("https listen on ip: %s port: %s", env.Url.GetValue(), env.Port.GetValue()))
|
||||||
if err := s.ServeHttps(*ip, *port, cert.Cert{Organization: *organization, CertFile: *sslFullchain, KeyFile: *sslKey}); err != nil {
|
if err := s.ServeHttps(env.Url.GetValue(), env.Port.GetUIntValue(), cert.Cert{Organization: *organization, CertFile: env.Fullchain.GetValue(), KeyFile: env.PrivKey.GetValue()}); err != nil {
|
||||||
logger.Error("main", "error https server "+err.Error())
|
logger.Error("main", "error https server "+err.Error())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// start http server
|
// start http server
|
||||||
logger.Info("main", fmt.Sprintf("http listen on ip: %s port: %d", *ip, *port))
|
logger.Info("main", fmt.Sprintf("http listen on ip: %s port: %s", env.Url.GetValue(), env.Port.GetValue()))
|
||||||
if err := s.ServeHttp(*ip, *port); err != nil {
|
if err := s.ServeHttp(env.Url.GetValue(), env.Port.GetUIntValue()); err != nil {
|
||||||
logger.Error("main", "error http server "+err.Error())
|
logger.Error("main", "error http server "+err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
// type Rights struct {
|
|
||||||
// Name string `json:"name"`
|
|
||||||
// Rights int `json:"rights"`
|
|
||||||
// }
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
// type Role struct {
|
|
||||||
// Id int `json:"id"`
|
|
||||||
// Role string `json:"role"`
|
|
||||||
// Rights []Rights `json:"rights"`
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (r *Role) IsValid() bool {
|
|
||||||
// return r.Role != ""
|
|
||||||
// }
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
// type Settings struct {
|
|
||||||
// PrimaryColor string `json:"primaryColor,omitempty"`
|
|
||||||
// PrimaryColorText string `json:"primaryColorText,omitempty"`
|
|
||||||
// SecondaryColor string `json:"secondaryColor,omitempty"`
|
|
||||||
// SecondaryColorText string `json:"secondaryColorText,omitempty"`
|
|
||||||
// Icon string `json:"icon,omitempty"`
|
|
||||||
// DatabaseName string `json:"databaseName,omitempty"`
|
|
||||||
// DatabaseToken string `json:"databaseToken,omitempty"`
|
|
||||||
// }
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
// type User struct {
|
|
||||||
// Id int `json:"id"`
|
|
||||||
// Name string `json:"user"`
|
|
||||||
// Email string `json:"email"`
|
|
||||||
// Role string `json:"role"`
|
|
||||||
// Password string `json:"password,omitempty"`
|
|
||||||
// Settings Settings `json:"settings"`
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (u *User) IsValid() bool {
|
|
||||||
// return u.Name != ""
|
|
||||||
// }
|
|
||||||
Reference in New Issue
Block a user