chore: removed temp go files
This commit is contained in:
117
config.go
117
config.go
@@ -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:]
|
||||
}
|
||||
149
database.go
149
database.go
@@ -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
|
||||
}
|
||||
86
email.go
86
email.go
@@ -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<br><br>If you ever wish to unsubscribe, "+
|
||||
"please click <a href='%s'>here</a>",
|
||||
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
|
||||
}
|
||||
24
sessions.go
24
sessions.go
@@ -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")
|
||||
}
|
||||
Reference in New Issue
Block a user