// Statup // Copyright (C) 2018. Hunter Long and the project contributors // Written by Hunter Long and the project contributors // // https://github.com/hunterlong/statup // // The licenses for most software and other practical works are designed // to take away your freedom to share and change the works. By contrast, // the GNU General Public License is intended to guarantee your freedom to // share and change all versions of a program--to make sure it remains free // software for all its users. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . package handlers import ( "encoding/json" "fmt" "github.com/gorilla/sessions" "github.com/hunterlong/statup/core" "github.com/hunterlong/statup/source" "github.com/hunterlong/statup/types" "github.com/hunterlong/statup/utils" "html/template" "net/http" "os" "reflect" "time" ) const ( cookieKey = "statup_auth" ) var ( sessionStore *sessions.CookieStore httpServer *http.Server ) // RunHTTPServer will start a HTTP server on a specific IP and port func RunHTTPServer(ip string, port int) error { host := fmt.Sprintf("%v:%v", ip, port) utils.Log(1, "Statup HTTP Server running on http://"+host) //for _, p := range core.CoreApp.AllPlugins { // info := p.GetInfo() // for _, route := range p.Routes() { // path := fmt.Sprintf("%v", route.URL) // router.Handle(path, http.HandlerFunc(route.Handler)).Methods(route.Method) // utils.Log(1, fmt.Sprintf("Added Route %v for plugin %v\n", path, info.Name)) // } //} router = Router() httpServer = &http.Server{ Addr: host, WriteTimeout: time.Second * 60, ReadTimeout: time.Second * 60, IdleTimeout: time.Second * 60, Handler: router, } resetCookies() return httpServer.ListenAndServe() } // IsAuthenticated returns true if the HTTP request is authenticated. You can set the environment variable GO_ENV=test // to bypass the admin authenticate to the dashboard features. func IsAuthenticated(r *http.Request) bool { if os.Getenv("GO_ENV") == "test" { return true } if core.CoreApp == nil { return false } if sessionStore == nil { return false } session, err := sessionStore.Get(r, cookieKey) if err != nil { return false } if session.Values["authenticated"] == nil { return false } return session.Values["authenticated"].(bool) } var handlerFuncs = func(w http.ResponseWriter, r *http.Request) template.FuncMap { return template.FuncMap{ "js": func(html interface{}) template.JS { return template.JS(utils.ToString(html)) }, "safe": func(html string) template.HTML { return template.HTML(html) }, "Auth": func() bool { return IsAuthenticated(r) }, "VERSION": func() string { return core.VERSION }, "CoreApp": func() *core.Core { return core.CoreApp }, "Services": func() []types.ServiceInterface { return core.CoreApp.Services }, "USE_CDN": func() bool { return core.CoreApp.UseCdn }, "Type": func(g interface{}) []string { fooType := reflect.TypeOf(g) var methods []string methods = append(methods, fooType.String()) for i := 0; i < fooType.NumMethod(); i++ { method := fooType.Method(i) fmt.Println(method.Name) methods = append(methods, method.Name) } return methods }, "ToJSON": func(g interface{}) template.HTML { data, _ := json.Marshal(g) return template.HTML(string(data)) }, "underscore": func(html string) string { return utils.UnderScoreString(html) }, "URL": func() string { return r.URL.String() }, "CHART_DATA": func() string { return "" }, "Error": func() string { return "" }, "ToString": func(v interface{}) string { return utils.ToString(v) }, "Ago": func(t time.Time) string { return utils.Timestamp(t).Ago() }, "Duration": func(t time.Duration) string { duration, _ := time.ParseDuration(fmt.Sprintf("%vs", t.Seconds())) return utils.FormatDuration(duration) }, "ToUnix": func(t time.Time) int64 { return t.UTC().Unix() }, "FromUnix": func(t int64) string { return utils.Timezoner(time.Unix(t, 0), core.CoreApp.Timezone).Format("Monday, January 02") }, "NewService": func() *types.Service { return new(types.Service) }, "NewUser": func() *types.User { return new(types.User) }, } } var mainTmpl = `{{define "main" }} {{ template "base" . }} {{ end }}` // executeResponse will render a HTTP response for the front end user func executeResponse(w http.ResponseWriter, r *http.Request, file string, data interface{}, redirect interface{}) { utils.Http(r) if url, ok := redirect.(string); ok { http.Redirect(w, r, url, http.StatusSeeOther) return } templates := []string{"base.html", "head.html", "nav.html", "footer.html", "scripts.html", "form_service.html", "form_notifier.html", "form_user.html", "form_checkin.html"} javascripts := []string{"charts.js", "chart_index.js"} render, err := source.TmplBox.String(file) if err != nil { utils.Log(4, err) } // setup the main template and handler funcs t := template.New("main") t.Funcs(handlerFuncs(w, r)) t, err = t.Parse(mainTmpl) if err != nil { utils.Log(4, err) } // render all templates for _, temp := range templates { tmp, _ := source.TmplBox.String(temp) t, err = t.Parse(tmp) if err != nil { utils.Log(4, err) } } // render all javascript files for _, temp := range javascripts { tmp, _ := source.JsBox.String(temp) t, err = t.Parse(tmp) if err != nil { utils.Log(4, err) } } // render the page requested _, err = t.Parse(render) if err != nil { utils.Log(4, err) } // execute the template err = t.Execute(w, data) if err != nil { utils.Log(4, err) } } // executeJSResponse will render a Javascript response func executeJSResponse(w http.ResponseWriter, r *http.Request, file string, data interface{}) { render, err := source.JsBox.String(file) if err != nil { utils.Log(4, err) } t := template.New("charts") t.Funcs(template.FuncMap{ "safe": func(html string) template.HTML { return template.HTML(html) }, "Services": func() []types.ServiceInterface { return core.CoreApp.Services }, }) _, err = t.Parse(render) if err != nil { utils.Log(4, err) } err = t.Execute(w, data) if err != nil { utils.Log(4, err) } } // error404Handler is a HTTP handler for 404 error pages func error404Handler(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) executeResponse(w, r, "error_404.html", nil, nil) }