package main import ( "fmt" "log" "net/http" "os" "github.com/google/uuid" "markdownhub/internal/api" "markdownhub/internal/auth" "markdownhub/internal/collab" "markdownhub/internal/db" "markdownhub/internal/files" ) func main() { dataDir := envOr("MH_DATA_DIR", "./data") port := envOr("MH_PORT", "8080") secret := envOr("MH_SECRET", "dev-secret-change-me") database, err := db.Open(dataDir + "/db/markdownhub.db") if err != nil { log.Fatalf("Failed to open database: %v", err) } defer database.Close() if err := db.Migrate(database); err != nil { log.Fatalf("Failed to run migrations: %v", err) } ensureAdminUser(database, dataDir) router := api.NewRouter(database, dataDir, secret) // Collab WebSocket hub hub := collab.NewHub(database) mux := http.NewServeMux() mux.Handle("/ws/collab/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { hub.HandleWebSocket(w, r, secret) })) mux.Handle("/", router) fmt.Printf("MarkdownHub listening on :%s\n", port) log.Fatal(http.ListenAndServe(":"+port, mux)) } func ensureAdminUser(database *db.DB, dataDir string) { var count int database.QueryRow("SELECT COUNT(*) FROM users").Scan(&count) if count > 0 { return } email := envOr("MH_ADMIN_EMAIL", "admin@localhost") password := envOr("MH_ADMIN_PASSWORD", "admin") hash, err := auth.HashPassword(password) if err != nil { log.Fatalf("Failed to hash admin password: %v", err) } id := uuid.New().String() _, err = database.Exec( "INSERT INTO users (id, username, email, password_hash, is_admin) VALUES (?, ?, ?, ?, ?)", id, "admin", email, hash, true, ) if err != nil { log.Fatalf("Failed to create admin user: %v", err) } files.EnsureUserDir(dataDir, id) fmt.Printf("Created admin user: %s\n", email) } func envOr(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback }