diff --git a/config.go b/config.go
deleted file mode 100644
index b6c2665..0000000
--- a/config.go
+++ /dev/null
@@ -1,117 +0,0 @@
-package main
-
-import (
- "log"
- "os"
- "strconv"
-
- "github.com/joho/godotenv"
-)
-
-type Config struct {
- // Server
- Port string
-
- // Database
- PGHost string
- PGPort string
- PGUser string
- PGPassword string
- PGDatabase string
-
- // SMTP
- SMTPServer string
- SMTPPort int
- SMTPUser string
- SMTPPassword string
- SenderEmail string
-
- // Admin
- AdminUsername string
- AdminPassword string
-
- // App
- SecretKey string
- BaseURL string
-}
-
-var config *Config
-
-func loadConfig() *Config {
- // Load .env file
- err := godotenv.Load()
- if err != nil {
- log.Printf("Warning: Could not load .env file: %v", err)
- } else {
- log.Println("Successfully loaded .env file")
- }
-
- // Debug: Print raw values before any processing
- rawPassword := os.Getenv("PG_PASSWORD")
- log.Printf("Raw PG_PASSWORD length: %d, value: [%s]", len(rawPassword), rawPassword)
- log.Printf("Raw PG_USER: [%s]", os.Getenv("PG_USER"))
- log.Printf("Raw PG_HOST: [%s]", os.Getenv("PG_HOST"))
-
- cfg := &Config{
- Port: getEnv("PORT", "5001"),
- PGHost: getEnv("PG_HOST", "localhost"),
- PGPort: getEnv("PG_PORT", "5432"),
- PGUser: getEnv("PG_USER", "postgres"),
- PGPassword: getEnv("PG_PASSWORD", ""),
- PGDatabase: getEnv("PG_DATABASE", "newsletter"),
- SMTPServer: getEnv("SMTP_SERVER", ""),
- SMTPPort: getEnvInt("SMTP_PORT", 465),
- SMTPUser: getEnv("SMTP_USER", ""),
- SMTPPassword: getEnv("SMTP_PASSWORD", ""),
- SenderEmail: getEnv("SENDER_EMAIL", ""),
- AdminUsername: getEnv("ADMIN_USERNAME", "admin"),
- AdminPassword: getEnv("ADMIN_PASSWORD", "changeme"),
- SecretKey: getEnv("SECRET_KEY", "your-secret-key"),
- BaseURL: getEnv("BASE_URL", "localhost:5001"),
- }
-
- // Debug output
- log.Printf("=== Config Loaded ===")
- log.Printf("PG_HOST: %s", cfg.PGHost)
- log.Printf("PG_PORT: %s", cfg.PGPort)
- log.Printf("PG_USER: %s", cfg.PGUser)
- log.Printf("PG_DATABASE: %s", cfg.PGDatabase)
- log.Printf("PG_PASSWORD length: %d", len(cfg.PGPassword))
- log.Printf("BASE_URL: %s", cfg.BaseURL)
- log.Printf("====================")
-
- if cfg.SenderEmail == "" {
- cfg.SenderEmail = cfg.SMTPUser
- }
-
- return cfg
-}
-
-func getEnv(key, defaultValue string) string {
- value := os.Getenv(key)
- if value == "" {
- log.Printf("Env var %s not found, using default: %s", key, defaultValue)
- return defaultValue
- }
- return value
-}
-
-func getEnvInt(key string, defaultValue int) int {
- value := os.Getenv(key)
- if value == "" {
- return defaultValue
- }
- intVal, err := strconv.Atoi(value)
- if err != nil {
- log.Printf("Invalid integer for %s: %v, using default", key, err)
- return defaultValue
- }
- return intVal
-}
-
-func maskPassword(pwd string) string {
- if len(pwd) <= 2 {
- return "***"
- }
- return pwd[:2] + "***" + pwd[len(pwd)-2:]
-}
\ No newline at end of file
diff --git a/database.go b/database.go
deleted file mode 100644
index 6ce4876..0000000
--- a/database.go
+++ /dev/null
@@ -1,149 +0,0 @@
-package main
-
-import (
- "database/sql"
- "fmt"
- "log"
- "net/url"
-
- _ "github.com/lib/pq"
- "golang.org/x/crypto/bcrypt"
-)
-
-var db *sql.DB
-
-type Admin struct {
- Username string
- Password string
-}
-
-func initDB() {
- // Escape special characters in password
- password := url.QueryEscape(config.PGPassword)
-
- psqlInfo := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=require",
- config.PGUser,
- password,
- config.PGHost,
- config.PGPort,
- config.PGDatabase,
- )
-
- log.Printf("Connecting to database: postgres://%s:***@%s:%s/%s",
- config.PGUser, config.PGHost, config.PGPort, config.PGDatabase)
-
- var err error
- db, err = sql.Open("postgres", psqlInfo)
- if err != nil {
- log.Fatalf("Database connection error: %v", err)
- }
-
- db.SetMaxOpenConns(25)
- db.SetMaxIdleConns(5)
-
- if err = db.Ping(); err != nil {
- log.Fatalf("Failed to ping database: %v", err)
- }
-
- log.Println("Database connection successful!")
- createTables()
-}
-
-func createTables() {
- queries := []string{
- `CREATE TABLE IF NOT EXISTS subscribers (
- id SERIAL PRIMARY KEY,
- email TEXT UNIQUE NOT NULL
- )`,
- `CREATE TABLE IF NOT EXISTS admin_users (
- id SERIAL PRIMARY KEY,
- username TEXT UNIQUE NOT NULL,
- password TEXT NOT NULL
- )`,
- `CREATE TABLE IF NOT EXISTS newsletters (
- id SERIAL PRIMARY KEY,
- subject TEXT NOT NULL,
- body TEXT NOT NULL,
- sent_at TIMESTAMP WITH TIME ZONE
- DEFAULT CURRENT_TIMESTAMP
- )`,
- }
-
- for _, query := range queries {
- if _, err := db.Exec(query); err != nil {
- log.Printf("Error creating table: %v", err)
- }
- }
-
- log.Println("Database tables ready.")
-}
-
-func getAllEmails() ([]string, error) {
- rows, err := db.Query("SELECT email FROM subscribers")
- if err != nil {
- log.Printf("Error retrieving emails: %v", err)
- return nil, err
- }
- defer rows.Close()
-
- var emails []string
- for rows.Next() {
- var email string
- if err := rows.Scan(&email); err != nil {
- return nil, err
- }
- emails = append(emails, email)
- }
-
- return emails, rows.Err()
-}
-
-func getAdmin(username string) (*Admin, error) {
- var admin Admin
- err := db.QueryRow(
- "SELECT username, password FROM admin_users WHERE username=$1",
- username,
- ).Scan(&admin.Username, &admin.Password)
-
- if err != nil {
- if err == sql.ErrNoRows {
- return nil, fmt.Errorf("admin not found")
- }
- return nil, err
- }
-
- return &admin, nil
-}
-
-func createDefaultAdmin() {
- hashedPassword, err := hashPassword(config.AdminPassword)
- if err != nil {
- log.Fatalf("Error hashing password: %v", err)
- }
-
- _, err = db.Exec(
- "INSERT INTO admin_users (username, password) "+
- "VALUES ($1, $2) ON CONFLICT (username) DO NOTHING",
- config.AdminUsername, hashedPassword,
- )
- if err != nil {
- log.Printf("Error creating default admin: %v", err)
- } else {
- log.Println("Default admin user ready.")
- }
-}
-
-func hashPassword(password string) (string, error) {
- hash, err := bcrypt.GenerateFromPassword(
- []byte(password),
- bcrypt.DefaultCost,
- )
- return string(hash), err
-}
-
-func verifyPassword(hash, password string) bool {
- return bcrypt.CompareHashAndPassword(
- []byte(hash),
- []byte(password),
- ) == nil
-}
\ No newline at end of file
diff --git a/email.go b/email.go
deleted file mode 100644
index 0d28bb2..0000000
--- a/email.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package main
-
-import (
- "fmt"
- "log"
- "time"
-
- "github.com/wneessen/go-mail"
-)
-
-func sendUpdateEmail(subject, body, recipient string) bool {
- client, err := mail.NewClient(
- config.SMTPServer,
- mail.WithPort(config.SMTPPort),
- mail.WithSMTPAuth(mail.SMTPAuthPlain),
- mail.WithUsername(config.SMTPUser),
- mail.WithPassword(config.SMTPPassword),
- mail.WithTimeout(10*time.Second),
- )
- if err != nil {
- log.Printf("Failed to create mail client: %v", err)
- return false
- }
- defer client.Close()
-
- m := mail.NewMsg()
- if err := m.From(config.SenderEmail); err != nil {
- log.Printf("Failed to set from: %v", err)
- return false
- }
- if err := m.To(recipient); err != nil {
- log.Printf("Failed to set to: %v", err)
- return false
- }
- m.Subject(subject)
-
- unsubLink := fmt.Sprintf(
- "https://%s/unsubscribe?email=%s",
- config.BaseURL,
- recipient,
- )
-
- htmlBody := fmt.Sprintf(
- "%s
If you ever wish to unsubscribe, "+
- "please click here",
- body, unsubLink,
- )
- m.SetBodyString(mail.TypeTextHTML, htmlBody)
-
- if err := client.Send(m); err != nil {
- log.Printf("Failed to send email to %s: %v", recipient, err)
- return false
- }
-
- log.Printf("Update email sent to: %s", recipient)
- return true
-}
-
-func processSendUpdateEmail(subject, body string) (string, error) {
- subscribers, err := getAllEmails()
- if err != nil {
- return "Failed to retrieve subscribers", err
- }
-
- if len(subscribers) == 0 {
- return "No subscribers found.", nil
- }
-
- for _, email := range subscribers {
- if !sendUpdateEmail(subject, body, email) {
- return fmt.Sprintf("Failed to send to %s", email),
- nil
- }
- }
-
- // Log newsletter
- _, err = db.Exec(
- "INSERT INTO newsletters (subject, body) VALUES ($1, $2)",
- subject, body,
- )
- if err != nil {
- log.Printf("Error logging newsletter: %v", err)
- }
-
- return "Email has been sent to all subscribers.", nil
-}
\ No newline at end of file
diff --git a/sessions.go b/sessions.go
deleted file mode 100644
index 0d42a40..0000000
--- a/sessions.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package main
-
-import (
- "log"
-
- "github.com/gorilla/sessions"
-)
-
-var store *sessions.CookieStore
-
-func initSessions() {
- if config.SecretKey == "" {
- log.Fatal("SECRET_KEY not set in configuration")
- }
- store = sessions.NewCookieStore([]byte(config.SecretKey))
- store.Options = &sessions.Options{
- Path: "/",
- MaxAge: 86400 * 7, // 7 days
- HttpOnly: true,
- Secure: false, // Set to true in production with HTTPS
- SameSite: 0,
- }
- log.Println("Sessions initialized")
-}
\ No newline at end of file