From c3869f4f10d2ef235bfec51dd8c8b66903bba5b1 Mon Sep 17 00:00:00 2001 From: db123-test Date: Tue, 5 May 2026 19:13:42 +0330 Subject: [PATCH] feat: add env file support and parameterize SQL queries Add .env and .env.local loading with InitEnv() helper that reads environment variables from config files without overwriting existing values. Refactor SQL queries to use parameterized arguments instead of string formatting for LIMIT/OFFSET clauses, improving query security and preventing SQL injection vulnerabilities. Clean up unnecessary rows.Close() calls and simplify error handling in database query functions. --- src/auth.go | 5 ++-- src/config.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/db.go | 8 +----- src/main.go | 1 + 4 files changed, 77 insertions(+), 10 deletions(-) diff --git a/src/auth.go b/src/auth.go index bf9771c..7a08491 100644 --- a/src/auth.go +++ b/src/auth.go @@ -3,7 +3,6 @@ package main import ( "database/sql" "encoding/json" - "fmt" "log/slog" "net" "net/http" @@ -289,8 +288,8 @@ func logsHandler(db *sql.DB) http.HandlerFunc { if len(conditions) > 0 { query += " WHERE " + strings.Join(conditions, " AND ") } - query += ` ORDER BY timestamp DESC` - query += fmt.Sprintf(` LIMIT %d OFFSET %d`, f.Limit, f.Offset) + query += ` ORDER BY timestamp DESC LIMIT ? OFFSET ?` + args = append(args, f.Limit, f.Offset) rows, err := db.Query(query, args...) if err != nil { diff --git a/src/config.go b/src/config.go index a1fa025..dfcf674 100644 --- a/src/config.go +++ b/src/config.go @@ -2,6 +2,7 @@ package main import ( "os" + "path/filepath" "time" ) @@ -23,6 +24,28 @@ func loadConfig() Config { } } +func loadEnvFile(envFile string) { + if _, err := os.Stat(envFile); err != nil { + return + } + + data, err := os.ReadFile(envFile) + if err != nil { + return + } + + for _, line := range splitLines(data) { + parts := splitKV(line) + if len(parts) == 2 { + key := parts[0] + value := unquote(parts[1]) + if os.Getenv(key) == "" { + os.Setenv(key, value) + } + } + } +} + func getEnv(key, defaultValue string) string { if v := os.Getenv(key); v != "" { return v @@ -39,3 +62,53 @@ func parseDuration(key string, defaultVal time.Duration) time.Duration { } return defaultVal } + +func splitLines(data []byte) []string { + lines := make([]string, 0) + var line string + for _, b := range data { + if b == '\n' { + lines = append(lines, line) + line = "" + } else if b != '\r' { + line += string(b) + } + } + if line != "" { + lines = append(lines, line) + } + return lines +} + +func splitKV(line string) []string { + for i, b := range line { + if b == '=' { + return []string{line[:i], line[i+1:]} + } + } + return nil +} + +func unquote(s string) string { + if len(s) >= 2 && s[0] == '"' && s[len(s)-1] == '"' { + return s[1 : len(s)-1] + } + if len(s) >= 2 && s[0] == '\'' && s[len(s)-1] == '\'' { + return s[1 : len(s)-1] + } + return s +} + +func InitEnv() { + possibleFiles := []string{ + ".env", + ".env.local", + } + for _, f := range possibleFiles { + abs, err := filepath.Abs(f) + if err == nil { + loadEnvFile(abs) + return + } + } +} diff --git a/src/db.go b/src/db.go index 0dd2ea2..06607de 100644 --- a/src/db.go +++ b/src/db.go @@ -142,11 +142,7 @@ func IsPermanentWhitelisted(db *sql.DB, ip string) (bool, error) { if err := rows.Scan(&entry); err != nil { continue } - matches, err := ipMatchesEntry(ip, entry) - if err != nil { - continue - } - if matches { + if matches, _ := ipMatchesEntry(ip, entry); matches { return true, nil } } @@ -221,10 +217,8 @@ func CleanupExpiredTemp(db *sql.DB) error { } } if err := rows.Err(); err != nil { - rows.Close() return err } - rows.Close() _, err = db.Exec(`DELETE FROM temp_whitelist WHERE expires_at <= ?`, time.Now().Format(time.RFC3339)) if err != nil { diff --git a/src/main.go b/src/main.go index ef8a9d3..e743051 100644 --- a/src/main.go +++ b/src/main.go @@ -12,6 +12,7 @@ import ( ) func main() { + InitEnv() cfg := loadConfig() if cfg.APIToken == "" { log.Fatal("AUTH_PROXY_API_TOKEN environment variable is required")