package main import ( "database/sql" "encoding/json" "flag" "fmt" "github.com/gorilla/csrf" "github.com/gorilla/sessions" _ "github.com/lib/pq" "net/http" "os" ) const ( VERSION = "0.1" MAX_DB_CONNS = 10 // already excessive for personal app ) type Config struct { Sql struct { Host string Dbname string Username string Password string } Port string Url string } const ( flash_err = "_flash_err" flash_info = "_flash_info" ) var ( config Config db *sql.DB store = sessions.NewCookieStore([]byte("key-store-auth-secret")) ) func loadConfig(env string) { file, err := os.Open("config/" + env + ".json") if err != nil { fmt.Println("Error: cannot open config file: config/" + env + ".json") os.Exit(-1) } defer file.Close() decoder := json.NewDecoder(file) err = decoder.Decode(&config) if err != nil { fmt.Println("Error: cannot decode config file: ", err) os.Exit(-1) } } func dbConnect() { var err error db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=require", config.Sql.Username, config.Sql.Password, config.Sql.Host, config.Sql.Dbname)) if err != nil { fmt.Println("DB ERROR: ", err) } db.SetMaxIdleConns(MAX_DB_CONNS) err = db.Ping() if err != nil { fmt.Println("DB Error on Ping(): ", err) os.Exit(-1) } } func csrfSecret() string { file, err := os.Open("csrf-secret.txt") if err != nil { fmt.Println("Error: cannot open csrf-secret.txt (run gen-csrf.sh to generate)") os.Exit(-1) } defer file.Close() var bytes []byte = make([]byte, 32) n, err := file.Read(bytes) if err != nil || n != 32 { fmt.Println("Error: cannot open csrf-secret.txt (run gen-csrf.sh to generate)") } return string(bytes) } type CSRFErrorHandler struct{} func (self CSRFErrorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Println("csrf Failure: ") fmt.Println(csrf.FailureReason(r)) fmt.Println("-----") } func main() { fmt.Println("transmet ", VERSION) envFlag := flag.String("env", "local", "load config/{env}.json") flag.Parse() fmt.Println("Loading...") loadConfig(*envFlag) dbConnect() initTemplates() muxRouter := init_route_handlers() errHandler := csrf.ErrorHandler( CSRFErrorHandler{} ) // Terrible. TODO: Get SSL for prod, and then wrap in if(dev) { { csrfSecurityOption := csrf.Secure(false) csrfMaxTimeOption := csrf.MaxAge(3600 * 24 * 3) // 3 Days - a little more wiggle room fmt.Println("Listening on", config.Port, "...") err := http.ListenAndServe(":"+config.Port, csrf.Protect([]byte(csrfSecret()), errHandler, csrfSecurityOption, csrfMaxTimeOption)(muxRouter)) if err != nil { fmt.Println("Fatal Error: ", err) } db.Close() }