(FEAT): Dev/prod environment toggle is complete!
We can now use environment values to dictate which values are used for the DB and the domain. This is a simple solution, but for now, it works! This will merge into master and we can then see it live in action!
This commit is contained in:
parent
94740b4b54
commit
e0e1230660
@ -5,7 +5,7 @@ import "github.com/haydenhargreaves/Potion/internal/app/server"
|
||||
const PORT = 3000
|
||||
|
||||
func main() {
|
||||
s := server.Init(PORT).ConfigureAuth().ConnectDatabase().Setup()
|
||||
s := server.Init(PORT).Setup()
|
||||
defer s.DB.Close()
|
||||
|
||||
s.Start()
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
@ -189,7 +188,7 @@ func RecipePage(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
title := "Potion - View Recipe"
|
||||
page := pages.RecipePage(*recipe, *user, loggedIn, os.Getenv("DOMAIN"))
|
||||
page := pages.RecipePage(*recipe, *user, loggedIn, deps.EnvironmentConfig.Domain)
|
||||
|
||||
ctx.HTML(http.StatusOK, "", layouts.AppLayout(title, page))
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/a-h/templ/examples/integration-gin/gintemplrenderer"
|
||||
@ -15,7 +14,6 @@ import (
|
||||
domain "github.com/haydenhargreaves/Potion/internal/domain/server"
|
||||
"github.com/haydenhargreaves/Potion/internal/infrastructure/auth"
|
||||
"github.com/haydenhargreaves/Potion/internal/infrastructure/database/repository"
|
||||
"github.com/joho/godotenv"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
@ -53,18 +51,26 @@ func Init(port int) *Server {
|
||||
return server
|
||||
}
|
||||
|
||||
func (s *Server) ConfigureAuth() *Server {
|
||||
err := godotenv.Load(".env")
|
||||
if err != nil {
|
||||
fmt.Printf("No .env file found or error loading .env: %v. Relying on system environment variables.", err)
|
||||
// Start starts the server on the port provided when the server was initialized
|
||||
func (s *Server) Start() {
|
||||
s.Router.Run(fmt.Sprintf(":%d", s.port))
|
||||
}
|
||||
|
||||
redirect_domain := os.Getenv("DOMAIN")
|
||||
func (s *Server) Setup() *Server {
|
||||
// SETUP THE ENVIRONMENT CONFIGURATION
|
||||
cfg, err := domain.LoadEnvironment()
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
if cfg == nil {
|
||||
panic("Environment configuration is nil, crashing.")
|
||||
}
|
||||
|
||||
// SETUP GOOGLE AUTH
|
||||
var (
|
||||
redirectUrl string = fmt.Sprintf("%s%s", redirect_domain, domain.API_AUTH_CALLBACK)
|
||||
clientId string = os.Getenv("GOOGLE_CLIENT_ID")
|
||||
clientSecret string = os.Getenv("GOOGLE_CLIENT_SECRET")
|
||||
redirectUrl string = fmt.Sprintf("%s%s", cfg.Domain, domain.API_AUTH_CALLBACK)
|
||||
clientId string = cfg.GoogleClientId
|
||||
clientSecret string = cfg.GoogleClientSecret
|
||||
scope []string = []string{
|
||||
"https://www.googleapis.com/auth/userinfo.email",
|
||||
"https://www.googleapis.com/auth/userinfo.profile",
|
||||
@ -74,18 +80,8 @@ func (s *Server) ConfigureAuth() *Server {
|
||||
// Setup Google OAuth
|
||||
auth.NewGoogleConfig(redirectUrl, clientId, clientSecret, scope)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Server) ConnectDatabase() *Server {
|
||||
err := godotenv.Load(".env")
|
||||
if err != nil {
|
||||
fmt.Printf("No .env file found or error loading .env: %v. Relying on system environment variables.", err)
|
||||
}
|
||||
|
||||
var connUrl string = os.Getenv("DATABASE_URL")
|
||||
|
||||
db, err := sql.Open("postgres", connUrl)
|
||||
// SETUP DATABASE
|
||||
db, err := sql.Open("postgres", cfg.DatabaseUrl)
|
||||
if err != nil {
|
||||
panic("Could not connect to database: " + err.Error())
|
||||
}
|
||||
@ -96,21 +92,8 @@ func (s *Server) ConnectDatabase() *Server {
|
||||
|
||||
s.DB = db
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// Start starts the server on the port provided when the server was initialized
|
||||
func (s *Server) Start() {
|
||||
s.Router.Run(fmt.Sprintf(":%d", s.port))
|
||||
}
|
||||
|
||||
func (s *Server) Setup() *Server {
|
||||
err := godotenv.Load(".env")
|
||||
if err != nil {
|
||||
fmt.Printf("No .env file found or error loading .env: %v. Relying on system environment variables.", err)
|
||||
}
|
||||
|
||||
jwtSecret := []byte(os.Getenv("JWT_SECRET"))
|
||||
// SETUP JWT
|
||||
jwtSecret := []byte(cfg.JwtSecret)
|
||||
|
||||
// Initialize and inject dependencies
|
||||
userRepo := repository.NewUserRepository(s.DB)
|
||||
@ -126,6 +109,7 @@ func (s *Server) Setup() *Server {
|
||||
AuthService: authService,
|
||||
RecipeService: recipeService,
|
||||
EngagementService: engagementService,
|
||||
EnvironmentConfig: *cfg,
|
||||
}
|
||||
|
||||
// Apply middleware
|
||||
@ -150,15 +134,8 @@ func (s *Server) Setup() *Server {
|
||||
// API router endpoints
|
||||
router_api.GET("/", func(ctx *gin.Context) { ctx.JSON(200, gin.H{"message": "Server is active."}) })
|
||||
router_api.GET("/tmp", func(ctx *gin.Context) {
|
||||
if !domain.IsLoggedIn(ctx) {
|
||||
ctx.JSON(200, gin.H{"error": "User is not logged in. Please login to continue"})
|
||||
return
|
||||
}
|
||||
|
||||
userId := ctx.MustGet("userId").(int)
|
||||
userEmail := ctx.MustGet("userEmail").(string)
|
||||
|
||||
ctx.JSON(200, gin.H{"id": userId, "email": userEmail})
|
||||
deps := ctx.MustGet("deps").(*domain.InjectedDependencies)
|
||||
ctx.JSON(200, gin.H{"config": deps.EnvironmentConfig})
|
||||
})
|
||||
|
||||
// WEB router endpoints
|
||||
|
||||
@ -1,14 +1,30 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
domainAuth "github.com/haydenhargreaves/Potion/internal/domain/auth"
|
||||
domainEngagement "github.com/haydenhargreaves/Potion/internal/domain/engagement"
|
||||
domainRecipe "github.com/haydenhargreaves/Potion/internal/domain/recipe"
|
||||
domainUser "github.com/haydenhargreaves/Potion/internal/domain/user"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
// EnvironmentConfig stores the configuration of the environment. Anything loaded from the .env
|
||||
// or docker environment will be stored here and can be accessed from the InjectedDependencies
|
||||
// struct, which this is attached to.
|
||||
type EnvironmentConfig struct {
|
||||
GoogleClientId string
|
||||
GoogleClientSecret string
|
||||
JwtSecret string
|
||||
DatabaseUrl string
|
||||
Environment string
|
||||
Domain string
|
||||
}
|
||||
|
||||
// InjectedDependencies is a collection of dependencies that are injected into the application. They
|
||||
// are stored in the context and can be accessed by handlers via the context.
|
||||
type InjectedDependencies struct {
|
||||
@ -16,6 +32,7 @@ type InjectedDependencies struct {
|
||||
AuthService domainAuth.AuthService
|
||||
RecipeService domainRecipe.RecipeService
|
||||
EngagementService domainEngagement.EngagementService
|
||||
EnvironmentConfig EnvironmentConfig
|
||||
}
|
||||
|
||||
// JwtClaims is the data stored in the JSON web token. All that is needed is the users ID and their
|
||||
@ -32,3 +49,71 @@ func IsLoggedIn(ctx *gin.Context) bool {
|
||||
_, email := ctx.Get("userEmail")
|
||||
return id && email
|
||||
}
|
||||
|
||||
func LoadEnvironment() (*EnvironmentConfig, error) {
|
||||
err := godotenv.Load(".env")
|
||||
if err != nil {
|
||||
fmt.Printf("No .env file found or error loading .env: %v. Relying on system environment variables.", err)
|
||||
}
|
||||
|
||||
env := os.Getenv("ENVIRONMENT")
|
||||
if env == "" {
|
||||
return nil, fmt.Errorf("ENVIRONMENT environment variable is required.")
|
||||
}
|
||||
|
||||
googleClientId := os.Getenv("GOOGLE_CLIENT_ID")
|
||||
if googleClientId == "" {
|
||||
return nil, fmt.Errorf("GOOGLE_CLIENT_ID environment variable is required.")
|
||||
}
|
||||
|
||||
googleClientSecret := os.Getenv("GOOGLE_CLIENT_SECRET")
|
||||
if googleClientSecret == "" {
|
||||
return nil, fmt.Errorf("GOOGLE_CLIENT_SECRET environment variable is required.")
|
||||
}
|
||||
|
||||
jwtSecret := os.Getenv("JWT_SECRET")
|
||||
if jwtSecret == "" {
|
||||
return nil, fmt.Errorf("JWT_SECRET environment variable is required.")
|
||||
}
|
||||
|
||||
var domain string
|
||||
if env == "dev" {
|
||||
domain = os.Getenv("DOMAIN_DEV")
|
||||
if domain == "" {
|
||||
return nil, fmt.Errorf("DOMAIN_DEV environment variable is required when ENVIRONMENT is 'dev'.")
|
||||
}
|
||||
} else if env == "prod" {
|
||||
domain = os.Getenv("DOMAIN_PROD")
|
||||
if domain == "" {
|
||||
return nil, fmt.Errorf("DOMAIN_PROD environment variable is required when ENVIRONMENT is 'prod'.")
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("ENVIRONMENT environment variable is required and must be 'dev' or 'prod'.")
|
||||
}
|
||||
|
||||
var dbUrl string
|
||||
if env == "dev" {
|
||||
dbUrl = os.Getenv("DATABASE_URL_DEV")
|
||||
if dbUrl == "" {
|
||||
return nil, fmt.Errorf("DATABASE_URL_DEV environment variable is required when ENVIRONMENT is 'dev'.")
|
||||
}
|
||||
} else if env == "prod" {
|
||||
dbUrl = os.Getenv("DATABASE_URL_PROD")
|
||||
if dbUrl == "" {
|
||||
return nil, fmt.Errorf("DATABASE_URL_PROD environment variable is required when ENVIRONMENT is 'prod'.")
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("ENVIRONMENT environment variable is required and must be 'dev' or 'prod'.")
|
||||
}
|
||||
|
||||
cfg := &EnvironmentConfig{
|
||||
GoogleClientId: googleClientId,
|
||||
GoogleClientSecret: googleClientSecret,
|
||||
JwtSecret: jwtSecret,
|
||||
DatabaseUrl: dbUrl,
|
||||
Environment: env,
|
||||
Domain: domain,
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user