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 FrontendDomain 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 { UserService domainUser.UserService 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 // Google email provided. type JwtClaims struct { UserId int `json:"Id"` Email string `json:"Email"` jwt.RegisteredClaims } // IsLoggedIn checks the cookies in a request and returns whether the user is logged in. func IsLoggedIn(ctx *gin.Context) bool { _, id := ctx.Get("userId") _, email := ctx.Get("userEmail") return id && email } // LoadEnvironment loads the environment values from either an .env file or docker environment. In // the event that required fields are not provided, an error will return and the caller should handle // the missing value or panic. Toggles between 'dev', 'prod', etc are also handled by this method, // the values can be access assuming they are the proper values based on the provided environment. 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 var frontendDomain 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'.") } frontendDomain = os.Getenv("FRONTEND_DOMAIN_DEV") if frontendDomain == "" { return nil, fmt.Errorf("FRONTEND_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'.") } frontendDomain = os.Getenv("FRONTEND_DOMAIN_PROD") if frontendDomain == "" { return nil, fmt.Errorf("FRONTEND_DOMAIN_PROD environment variable is required when ENVIRONMENT is 'dev'.") } } 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, FrontendDomain: frontendDomain, } fmt.Printf("Environment Config: %+v\n", cfg) return cfg, nil } // SetCookie sets a cookie value with a duration provided. This function handles setting the security // configuration as well as the domain. These values are based on the EnvironmentConfig, therefore // the value should be set. Nothing is returned by this function, but the cookie will be set. // // This function can also be used to clear cookies, if a blank value ("") and invalid duration (-1) // is provided. // // If 0 is provided as the duration, then a session cookie is created, which will be cleared when // the browser is closed. // // DEPRECATED: As of September 4th, 2025. // func SetCookie(ctx *gin.Context, name, value string, duration time.Duration) { // deps := ctx.MustGet("deps").(*InjectedDependencies) // // var ( // path string = "/" // httpOnly bool = true // maxAge int // secure bool // domain string // ) // // if duration < 0 { // // Delete the cookie // maxAge = -1 // } else if duration == 0 { // // Session cookie, clears when browser is closed // maxAge = 0 // } else { // // Normal calculation // maxAge = int(time.Now().Add(duration).Sub(time.Now()).Seconds()) // } // // if deps.EnvironmentConfig.Environment == "prod" { // secure = true // domain = deps.EnvironmentConfig.Domain // // } else if deps.EnvironmentConfig.Environment == "dev" { // secure = false // domain = deps.EnvironmentConfig.Domain // // } else { // // Defaults // secure = false // domain = "" // } // // ctx.SetCookie(name, value, maxAge, path, domain, secure, httpOnly) // }