package main //go:generate esc -o assets.go assets templates songs import ( "bufio" "flag" "fmt" "io/ioutil" "log" "net/http" "os" "strings" "golang.org/x/crypto/ssh/terminal" "github.com/gorilla/handlers" "github.com/gorilla/mux" "github.com/gorilla/sessions" "github.com/justinas/alice" ) var port int var ip string var dir string var sessionSecret = "AChKj7na128CrKPPG0Rc" var sessionStore = sessions.NewCookieStore([]byte(sessionSecret)) var r *mux.Router var site *siteData var model *model type siteData struct { Title string DevMode bool } func init() { const ( portDefault = 8080 portUsage = "the port to listen on" ipDefault = "127.0.0.1" ipUsage = "the ip mask to listen for connections from" dirDefault = "./" dirUsage = "the directory to serve the app out of\nThere should be a 'songs' directory here." ) flag.StringVar(&ip, "ip", ipDefault, ipUsage) flag.IntVar(&port, "port", portDefault, portUsage) flag.StringVar(&dir, "dir", dirDefault, dirUsage) if !strings.HasSuffix(dir, "/") { dir = dir + "/" } } func main() { flag.Parse() loadModel() r := mux.NewRouter() r.StrictSlash(true) //r.PathPrefix("/assets/").Handler(http.FileServer(FS(site.DevMode))) // Public Subrouter pub := r.PathPrefix("/").Subrouter() pub.HandleFunc("/", handleMain) admin := r.PathPrefix("/admin").Subrouter() admin.HandleFunc("/", handleAdmin) admin.HandleFunc("/dologin", handleAdminDoLogin) admin.HandleFunc("/dologout", handleAdminDoLogout) admin.HandleFunc("/{action}", handleAdmin) http.Handle("/", r) chain := alice.New(loggingHandler).Then(r) listenAt := fmt.Sprintf("%s:%d", ip, port) fmt.Println("Songbook Server listening at", listenAt) log.Fatal(http.ListenAndServe(listenAt, chain)) } func loadModel() { model := NewModel(dir) site = new(siteData) if !model.hasUser() { reader := bufio.NewReader(os.Stdin) fmt.Println("Create new Admin user") fmt.Print("Username: ") un, _ := reader.ReadString('\n') un = strings.TrimSpace(un) var pw1, pw2 []byte for string(pw1) != string(pw2) || string(pw1) == "" { fmt.Print("Password: ") pw1, _ = terminal.ReadPassword(0) fmt.Println("") fmt.Print("Repeat Password: ") pw2, _ = terminal.ReadPassword(0) fmt.Println("") if string(pw1) != string(pw2) { fmt.Println("Entered Passwords don't match!") } } } } func handleMain(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") output, err := ioutil.ReadFile(dir + "currentsongs.html") if err != nil { output = []byte("Error reading current songs") } fmt.Fprint(w, string(output)) } func initPageData(w http.ResponseWriter, req *http.Request) *pageData { if site.DevMode { w.Header().Set("Cache-Control", "no-cache") } p := new(pageData) // Get the session var err error var s *sessions.Session if s, err = sessionStore.Get(req, "songbook"); err != nil { http.Error(w, err.Error(), 500) return p } p.session = new(pageSession) p.session.session = s p.session.req = req p.session.w = w // First check if we're logged in userName, _ := p.session.getStringValue("name") _ = userName p.Site = site p.SubTitle = "Songbook" p.Stylesheets = make([]string, 0, 0) p.Stylesheets = append(p.Stylesheets, "/assets/vendor/css/pure-min.css") p.Stylesheets = append(p.Stylesheets, "/assets/vendor/css/grids-responsive-min.css") p.Stylesheets = append(p.Stylesheets, "/assets/vendor/font-awesome/css/font-awesome.min.css") p.Stylesheets = append(p.Stylesheets, "/assets/css/gjvote.css") p.HeaderScripts = make([]string, 0, 0) p.Scripts = make([]string, 0, 0) p.FlashMessage, p.FlashClass = p.session.getFlashMessage() if p.FlashClass == "" { p.FlashClass = "hidden" } return p } func loggingHandler(h http.Handler) http.Handler { return handlers.LoggingHandler(os.Stdout, h) }