diff --git a/Makefile b/Makefile index 2d617e39..b42604d6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION=0.79.86 +VERSION=0.79.87 BINARY_NAME=statup GOPATH:=$(GOPATH) GOCMD=go @@ -232,6 +232,7 @@ clean: rm -rf dev/test/cypress/videos rm -f coverage.* sass rm -f source/rice-box.go + rm -f *.db-journal find . -name "*.out" -type f -delete find . -name "*.cpu" -type f -delete find . -name "*.mem" -type f -delete diff --git a/cmd/cli.go b/cmd/cli.go index c8e0e1bf..ff8ab0f7 100644 --- a/cmd/cli.go +++ b/cmd/cli.go @@ -23,10 +23,12 @@ import ( "github.com/hunterlong/statup/handlers" "github.com/hunterlong/statup/plugin" "github.com/hunterlong/statup/source" + "github.com/hunterlong/statup/types" "github.com/hunterlong/statup/utils" "github.com/joho/godotenv" "io/ioutil" "net/http" + "net/http/httptest" "time" ) @@ -85,13 +87,15 @@ func catchCLI(args []string) error { case "export": var err error fmt.Printf("Statup v%v Exporting Static 'index.html' page...\n", VERSION) + utils.InitLogs() core.Configs, err = core.LoadConfigFile(dir) if err != nil { utils.Log(4, "config.yml file not found") return err } - indexSource := core.ExportIndexHTML() - err = utils.SaveFile("./index.html", []byte(indexSource)) + indexSource := ExportIndexHTML() + core.CloseDB() + err = utils.SaveFile(dir+"/index.html", indexSource) if err != nil { utils.Log(4, err) return err @@ -103,6 +107,7 @@ func catchCLI(args []string) error { case "run": utils.Log(1, "Running 1 time and saving to database...") RunOnce() + core.CloseDB() fmt.Println("Check is complete.") return errors.New("end") case "env": @@ -121,6 +126,22 @@ func catchCLI(args []string) error { return errors.New("end") } +// ExportIndexHTML returns the HTML of the index page as a string +func ExportIndexHTML() []byte { + source.Assets() + core.Configs.Connect(false, utils.Directory) + core.CoreApp.SelectAllServices(false) + core.CoreApp.UseCdn = types.NewNullBool(true) + for _, srv := range core.CoreApp.Services { + service := srv.(*core.Service) + service.Check(true) + } + w := httptest.NewRecorder() + r := httptest.NewRequest("GET", "/", nil) + handlers.ExecuteResponse(w, r, "index.html", nil, nil) + return w.Body.Bytes() +} + // RunOnce will initialize the Statup application and check each service 1 time, will not run HTTP server func RunOnce() { var err error @@ -141,9 +162,7 @@ func RunOnce() { utils.Log(4, err) } for _, out := range core.CoreApp.Services { - service := out.Select() out.Check(true) - fmt.Printf(" Service %v | URL: %v | Latency: %0.0fms | Online: %v\n", service.Name, service.Domain, (service.Latency * 1000), service.Online) } } @@ -155,16 +174,32 @@ func HelpEcho() { fmt.Println(" statup - Main command to run Statup server") fmt.Println(" statup version - Returns the current version of Statup") fmt.Println(" statup run - Check all services 1 time and then quit") - fmt.Println(" statup test plugins - Test all plugins for required information") fmt.Println(" statup assets - Dump all assets used locally to be edited.") - fmt.Println(" statup sass - Compile .scss files into the css directory") - fmt.Println(" statup env - Show all environment variables being used for Statup") fmt.Println(" statup export - Exports the index page as a static HTML for pushing") + fmt.Println(" statup sass - Compile .scss files into the css directory") + fmt.Println(" statup test plugins - Test all plugins for required information") + fmt.Println(" statup env - Show all environment variables being used for Statup") fmt.Println(" statup update - Attempts to update to the latest version") fmt.Println(" statup help - Shows the user basic information about Statup") fmt.Printf("Flags:\n") fmt.Println(" -ip 127.0.0.1 - Run HTTP server on specific IP address (default: localhost)") fmt.Println(" -port 8080 - Run HTTP server on Port (default: 8080)") + fmt.Printf("Environment Variables:\n") + fmt.Println(" STATUP_DIR - Set a absolute path for the root path of Statup server (logs, assets, SQL db)") + fmt.Println(" DB_CONN - Automatic Database connection (sqlite, postgres, mysql)") + fmt.Println(" DB_HOST - Database hostname or IP address") + fmt.Println(" DB_USER - Database username") + fmt.Println(" DB_PASS - Database password") + fmt.Println(" DB_PORT - Database port (5432, 3306, ...") + fmt.Println(" DB_DATABASE - Database connection's database name") + fmt.Println(" GO_ENV - Run Statup in testmode, will bypass HTTP authentication (if set as 'true')") + fmt.Println(" NAME - Set a name for the Statup status page") + fmt.Println(" DESCRIPTION - Set a description for the Statup status page") + fmt.Println(" DOMAIN - Set a URL for the Statup status page") + fmt.Println(" ADMIN_USER - Username for administrator account (default: admin)") + fmt.Println(" ADMIN_PASS - Password for administrator account (default: admin)") + fmt.Println(" * You can insert environment variables into a '.env' file in root directory.") + fmt.Println("Give Statup a Star at https://github.com/hunterlong/statup") } diff --git a/cmd/cli_test.go b/cmd/cli_test.go index 5f25209f..18d89714 100644 --- a/cmd/cli_test.go +++ b/cmd/cli_test.go @@ -16,20 +16,35 @@ package main import ( + "github.com/hunterlong/statup/core" + "github.com/hunterlong/statup/utils" "github.com/rendon/testcli" "github.com/stretchr/testify/assert" + "os" + "os/exec" "testing" + "time" ) -func TestRunSQLiteApp(t *testing.T) { - t.SkipNow() - run := catchCLI([]string{"app"}) - assert.Nil(t, run) +var ( + dir string +) + +func init() { + dir = utils.Directory } -func TestConfirmVersion(t *testing.T) { - t.SkipNow() - assert.NotEmpty(t, VERSION) +func TestStartServerCommand(t *testing.T) { + Clean() + os.Setenv("DB_CONN", "sqlite") + cmd := helperCommand(nil, "") + var got = make(chan string) + commandAndSleep(cmd, time.Duration(8*time.Second), got) + os.Unsetenv("DB_CONN") + gg, _ := <-got + assert.Contains(t, gg, "DB_CONN environment variable was found") + assert.Contains(t, gg, "Core database does not exist, creating now!") + assert.Contains(t, gg, "Starting monitoring process for 5 Services") } func TestVersionCommand(t *testing.T) { @@ -46,14 +61,23 @@ func TestHelpCommand(t *testing.T) { } func TestExportCommand(t *testing.T) { - t.SkipNow() - c := testcli.Command("statup", "export") - c.Run() - t.Log(c.Stdout()) - assert.True(t, c.StdoutContains("Exporting Static 'index.html' page")) + cmd := helperCommand(nil, "export") + var got = make(chan string) + commandAndSleep(cmd, time.Duration(4*time.Second), got) + gg, _ := <-got + t.Log(gg) + assert.Contains(t, gg, "Exporting Static 'index.html' page...") + assert.Contains(t, gg, "Exported Statup index page: 'index.html'") assert.True(t, fileExists(dir+"/index.html")) } +func TestUpdateCommand(t *testing.T) { + c := testcli.Command("statup", "update") + c.Run() + assert.True(t, c.StdoutContains("Statup Version: "+VERSION)) + assert.True(t, c.StdoutContains("Latest Version:")) +} + func TestAssetsCommand(t *testing.T) { c := testcli.Command("statup", "assets") c.Run() @@ -63,6 +87,22 @@ func TestAssetsCommand(t *testing.T) { assert.FileExists(t, dir+"/assets/scss/base.scss") } +func TestRunCommand(t *testing.T) { + cmd := helperCommand(nil, "run") + var got = make(chan string) + commandAndSleep(cmd, time.Duration(5*time.Second), got) + gg, _ := <-got + t.Log(gg) + assert.Contains(t, gg, "Running 1 time and saving to database...") + assert.Contains(t, gg, "Check is complete.") +} + +func TestEnvironmentVarsCommand(t *testing.T) { + c := testcli.Command("statup", "env") + c.Run() + assert.True(t, c.StdoutContains("Statup Environment Variable")) +} + func TestVersionCLI(t *testing.T) { run := catchCLI([]string{"version"}) assert.EqualError(t, run, "end") @@ -82,7 +122,6 @@ func TestSassCLI(t *testing.T) { } func TestUpdateCLI(t *testing.T) { - t.SkipNow() run := catchCLI([]string{"update"}) assert.EqualError(t, run, "end") } @@ -100,10 +139,30 @@ func TestHelpCLI(t *testing.T) { func TestRunOnceCLI(t *testing.T) { t.SkipNow() run := catchCLI([]string{"run"}) - assert.Nil(t, run) + assert.EqualError(t, run, "end") } func TestEnvCLI(t *testing.T) { run := catchCLI([]string{"env"}) assert.Error(t, run) + core.CloseDB() + Clean() +} + +func commandAndSleep(cmd *exec.Cmd, duration time.Duration, out chan<- string) { + go func(out chan<- string) { + runCommand(cmd, out) + }(out) + time.Sleep(duration) + cmd.Process.Kill() +} + +func helperCommand(envs []string, s ...string) *exec.Cmd { + cmd := exec.Command("statup", s...) + return cmd +} + +func runCommand(c *exec.Cmd, out chan<- string) { + bout, _ := c.CombinedOutput() + out <- string(bout) } diff --git a/cmd/main.go b/cmd/main.go index a95ffde1..a50c4ff5 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -26,6 +26,7 @@ import ( "github.com/hunterlong/statup/utils" "github.com/joho/godotenv" "os" + "os/signal" ) var ( @@ -73,14 +74,23 @@ func main() { } } utils.Log(1, fmt.Sprintf("Starting Statup v%v", VERSION)) + defer core.CloseDB() + + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + go func() { + <-c + core.CloseDB() + os.Exit(1) + }() + core.Configs, err = core.LoadConfigFile(utils.Directory) if err != nil { utils.Log(3, err) core.SetupMode = true - fmt.Println(handlers.RunHTTPServer(ipAddress, port)) + utils.Log(1, handlers.RunHTTPServer(ipAddress, port)) os.Exit(1) } - defer core.CloseDB() mainProcess() } diff --git a/cmd/main_test.go b/cmd/main_test.go index 6e60c863..bf223004 100644 --- a/cmd/main_test.go +++ b/cmd/main_test.go @@ -35,7 +35,6 @@ import ( var ( route *mux.Router - dir string ) func init() { @@ -50,6 +49,7 @@ func Clean() { } func RunInit(db string, t *testing.T) { + Clean() if db == "mssql" { os.Setenv("DB_DATABASE", "tempdb") os.Setenv("DB_PASS", "PaSsW0rD123") @@ -57,19 +57,18 @@ func RunInit(db string, t *testing.T) { os.Setenv("DB_USER", "sa") } source.Assets() - Clean() route = handlers.Router() core.CoreApp = core.NewCore() } -func TestMain(m *testing.M) { - m.Run() -} +//func TestMain(m *testing.M) { +// m.Run() +//} func TestRunAll(t *testing.T) { //t.Parallel() - databases := []string{"postgres", "sqlite", "mysql"} + databases := []string{"sqlite", "postgres", "mysql"} if os.Getenv("ONLY_DB") != "" { databases = []string{os.Getenv("ONLY_DB")} } diff --git a/core/configs.go b/core/configs.go index 727fbe0d..8e3d70bf 100644 --- a/core/configs.go +++ b/core/configs.go @@ -127,7 +127,7 @@ func DefaultPort(db string) int64 { // EnvToConfig converts environment variables to a DbConfig variable func EnvToConfig() *DbConfig { - port := utils.StringInt(os.Getenv("DB_PORT")) + port := utils.ToInt(os.Getenv("DB_PORT")) if port == 0 { port = DefaultPort(os.Getenv("DB_PORT")) } @@ -139,6 +139,17 @@ func EnvToConfig() *DbConfig { if description == "" { description = "Statup Monitoring Sample Data" } + + adminUser := os.Getenv("ADMIN_USER") + if adminUser == "" { + adminUser = "admin" + } + + adminPass := os.Getenv("ADMIN_PASS") + if adminPass == "" { + adminPass = "admin" + } + data := &DbConfig{ DbConn: os.Getenv("DB_CONN"), DbHost: os.Getenv("DB_HOST"), @@ -150,8 +161,8 @@ func EnvToConfig() *DbConfig { Description: description, Domain: os.Getenv("DOMAIN"), Email: "", - Username: "admin", - Password: "admin", + Username: adminUser, + Password: adminPass, Error: nil, Location: utils.Directory, } diff --git a/core/core_test.go b/core/core_test.go index 4c33f0ab..d61aae15 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -121,11 +121,3 @@ func TestInsertNotifierDB(t *testing.T) { err := InsertNotifierDB() assert.Nil(t, err) } - -func TestExportStaticHTML(t *testing.T) { - t.SkipNow() - data := ExportIndexHTML() - assert.Contains(t, data, "https://github.com/hunterlong/statupī¸") - assert.Contains(t, data, "") - assert.Contains(t, data, "") -} diff --git a/core/database.go b/core/database.go index 06b30974..d8e83c78 100644 --- a/core/database.go +++ b/core/database.go @@ -297,7 +297,7 @@ func DatabaseMaintence() { // DeleteAllSince will delete a specific table's records based on a time. func DeleteAllSince(table string, date time.Time) { sql := fmt.Sprintf("DELETE FROM %v WHERE created_at < '%v';", table, date.Format("2006-01-02")) - db := DbSession.Raw(sql) + db := DbSession.Exec(sql) if db.Error != nil { utils.Log(2, db.Error) } diff --git a/core/export.go b/core/export.go index 70512e33..ab765043 100644 --- a/core/export.go +++ b/core/export.go @@ -17,73 +17,11 @@ package core import ( "bytes" - "fmt" "github.com/hunterlong/statup/source" - "github.com/hunterlong/statup/types" "github.com/hunterlong/statup/utils" "html/template" ) -func injectDatabase() { - Configs.Connect(false, utils.Directory) -} - -// ExportIndexHTML returns the HTML of the index page as a string -func ExportIndexHTML() string { - source.Assets() - injectDatabase() - CoreApp.SelectAllServices(false) - CoreApp.UseCdn = types.NewNullBool(true) - for _, srv := range CoreApp.Services { - service := srv.(*Service) - service.Check(true) - fmt.Println(service.Name, service.Online, service.Latency) - } - nav, _ := source.TmplBox.String("nav.html") - footer, _ := source.TmplBox.String("footer.html") - render, err := source.TmplBox.String("index.html") - if err != nil { - utils.Log(3, err) - } - - t := template.New("message") - t.Funcs(template.FuncMap{ - "js": func(html string) template.JS { - return template.JS(html) - }, - "safe": func(html string) template.HTML { - return template.HTML(html) - }, - "VERSION": func() string { - return VERSION - }, - "CoreApp": func() *Core { - return CoreApp - }, - "USE_CDN": func() bool { - return CoreApp.UseCdn.Bool - }, - "underscore": func(html string) string { - return utils.UnderScoreString(html) - }, - "URL": func() string { - return "/" - }, - "CHART_DATA": func() string { - return ExportChartsJs() - }, - }) - t, _ = t.Parse(nav) - t, _ = t.Parse(footer) - t.Parse(render) - var tpl bytes.Buffer - if err := t.Execute(&tpl, CoreApp); err != nil { - utils.Log(3, err) - } - result := tpl.String() - return result -} - // ExportChartsJs renders the charts for the index page func ExportChartsJs() string { render, err := source.JsBox.String("charts.js") diff --git a/handlers/api.go b/handlers/api.go index d08057bf..3f5b55d9 100644 --- a/handlers/api.go +++ b/handlers/api.go @@ -36,21 +36,8 @@ type apiResponse struct { Output interface{} `json:"output,omitempty"` } -func isAuthorized(r *http.Request) bool { - var token string - tokens, ok := r.Header["Authorization"] - if ok && len(tokens) >= 1 { - token = tokens[0] - token = strings.TrimPrefix(token, "Bearer ") - } - if token == core.CoreApp.ApiSecret { - return true - } - return false -} - func apiIndexHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } @@ -59,7 +46,7 @@ func apiIndexHandler(w http.ResponseWriter, r *http.Request) { } func apiRenewHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } @@ -142,7 +129,7 @@ func sendUnauthorizedJson(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(output) } -func isAPIAuthorized(r *http.Request) bool { +func isAuthorized(r *http.Request) bool { utils.Http(r) if os.Getenv("GO_ENV") == "test" { return true @@ -150,7 +137,13 @@ func isAPIAuthorized(r *http.Request) bool { if IsAuthenticated(r) { return true } - if isAuthorized(r) { + var token string + tokens, ok := r.Header["Authorization"] + if ok && len(tokens) >= 1 { + token = tokens[0] + token = strings.TrimPrefix(token, "Bearer ") + } + if token == core.CoreApp.ApiSecret { return true } return false diff --git a/handlers/checkin.go b/handlers/checkin.go index 9ab84353..2767a84b 100644 --- a/handlers/checkin.go +++ b/handlers/checkin.go @@ -27,7 +27,7 @@ import ( ) func apiAllCheckinsHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } @@ -41,7 +41,7 @@ func apiAllCheckinsHandler(w http.ResponseWriter, r *http.Request) { } func apiCheckinHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } diff --git a/handlers/dashboard.go b/handlers/dashboard.go index 6ad157c0..24ee5339 100644 --- a/handlers/dashboard.go +++ b/handlers/dashboard.go @@ -31,9 +31,9 @@ import ( func dashboardHandler(w http.ResponseWriter, r *http.Request) { if !IsAuthenticated(r) { err := core.ErrorResponse{} - executeResponse(w, r, "login.html", err, nil) + ExecuteResponse(w, r, "login.html", err, nil) } else { - executeResponse(w, r, "dashboard.html", core.CoreApp, nil) + ExecuteResponse(w, r, "dashboard.html", core.CoreApp, nil) } } @@ -53,7 +53,7 @@ func loginHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/dashboard", http.StatusSeeOther) } else { err := core.ErrorResponse{Error: "Incorrect login information submitted, try again."} - executeResponse(w, r, "login.html", err, nil) + ExecuteResponse(w, r, "login.html", err, nil) } } @@ -70,7 +70,7 @@ func helpHandler(w http.ResponseWriter, r *http.Request) { return } help := source.HelpMarkdown() - executeResponse(w, r, "help.html", help, nil) + ExecuteResponse(w, r, "help.html", help, nil) } func logsHandler(w http.ResponseWriter, r *http.Request) { @@ -86,7 +86,7 @@ func logsHandler(w http.ResponseWriter, r *http.Request) { logs = append(logs, utils.LastLines[i].FormatForHtml()+"\r\n") } utils.LockLines.Unlock() - executeResponse(w, r, "logs.html", logs, nil) + ExecuteResponse(w, r, "logs.html", logs, nil) } func logsLineHandler(w http.ResponseWriter, r *http.Request) { diff --git a/handlers/handlers.go b/handlers/handlers.go index a2fc41d9..67f0d423 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -177,8 +177,8 @@ var handlerFuncs = func(w http.ResponseWriter, r *http.Request) template.FuncMap 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{}) { +// 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) @@ -262,5 +262,5 @@ func executeJSResponse(w http.ResponseWriter, r *http.Request, file string, data // 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) + ExecuteResponse(w, r, "error_404.html", nil, nil) } diff --git a/handlers/index.go b/handlers/index.go index 1b1aeb24..b6cd3f19 100644 --- a/handlers/index.go +++ b/handlers/index.go @@ -28,7 +28,7 @@ func indexHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/setup", http.StatusSeeOther) return } - executeResponse(w, r, "index.html", core.CoreApp, nil) + ExecuteResponse(w, r, "index.html", core.CoreApp, nil) } func healthCheckHandler(w http.ResponseWriter, r *http.Request) { @@ -41,7 +41,7 @@ func healthCheckHandler(w http.ResponseWriter, r *http.Request) { } func trayHandler(w http.ResponseWriter, r *http.Request) { - executeResponse(w, r, "tray.html", core.CoreApp, nil) + ExecuteResponse(w, r, "tray.html", core.CoreApp, nil) } // DesktopInit will run the Statup server on a specific IP and port using SQLite database diff --git a/handlers/messages.go b/handlers/messages.go index fc72ed79..678f7f0f 100644 --- a/handlers/messages.go +++ b/handlers/messages.go @@ -31,7 +31,7 @@ func messagesHandler(w http.ResponseWriter, r *http.Request) { return } messages, _ := core.SelectMessages() - executeResponse(w, r, "messages.html", messages, nil) + ExecuteResponse(w, r, "messages.html", messages, nil) } func viewMessageHandler(w http.ResponseWriter, r *http.Request) { @@ -40,17 +40,17 @@ func viewMessageHandler(w http.ResponseWriter, r *http.Request) { return } vars := mux.Vars(r) - id := utils.StringInt(vars["id"]) + id := utils.ToInt(vars["id"]) message, err := core.SelectMessage(id) if err != nil { w.WriteHeader(http.StatusNotFound) return } - executeResponse(w, r, "message.html", message, nil) + ExecuteResponse(w, r, "message.html", message, nil) } func apiAllMessagesHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } @@ -64,7 +64,7 @@ func apiAllMessagesHandler(w http.ResponseWriter, r *http.Request) { } func apiMessageCreateHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } @@ -85,12 +85,12 @@ func apiMessageCreateHandler(w http.ResponseWriter, r *http.Request) { } func apiMessageGetHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } vars := mux.Vars(r) - message, err := core.SelectMessage(utils.StringInt(vars["id"])) + message, err := core.SelectMessage(utils.ToInt(vars["id"])) if err != nil { sendErrorJson(err, w, r) return @@ -100,12 +100,12 @@ func apiMessageGetHandler(w http.ResponseWriter, r *http.Request) { } func apiMessageDeleteHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } vars := mux.Vars(r) - message, err := core.SelectMessage(utils.StringInt(vars["id"])) + message, err := core.SelectMessage(utils.ToInt(vars["id"])) if err != nil { sendErrorJson(err, w, r) return @@ -119,12 +119,12 @@ func apiMessageDeleteHandler(w http.ResponseWriter, r *http.Request) { } func apiMessageUpdateHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } vars := mux.Vars(r) - message, err := core.SelectMessage(utils.StringInt(vars["id"])) + message, err := core.SelectMessage(utils.ToInt(vars["id"])) if err != nil { sendErrorJson(fmt.Errorf("message #%v was not found", vars["id"]), w, r) return diff --git a/handlers/notifications.go b/handlers/notifications.go index 043d755a..9dd660fc 100644 --- a/handlers/notifications.go +++ b/handlers/notifications.go @@ -27,7 +27,7 @@ import ( ) func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } @@ -41,7 +41,7 @@ func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) { } func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } @@ -56,7 +56,7 @@ func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) { } func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } @@ -92,19 +92,19 @@ func testNotificationHandler(w http.ResponseWriter, r *http.Request) { method := vars["method"] enabled := form.Get("enable") host := form.Get("host") - port := int(utils.StringInt(form.Get("port"))) + port := int(utils.ToInt(form.Get("port"))) username := form.Get("username") password := form.Get("password") var1 := form.Get("var1") var2 := form.Get("var2") apiKey := form.Get("api_key") apiSecret := form.Get("api_secret") - limits := int(utils.StringInt(form.Get("limits"))) + limits := int(utils.ToInt(form.Get("limits"))) fakeNotifer, notif, err := notifier.SelectNotifier(method) if err != nil { utils.Log(3, fmt.Sprintf("issue saving notifier %v: %v", method, err)) - executeResponse(w, r, "settings.html", core.CoreApp, "/settings") + ExecuteResponse(w, r, "settings.html", core.CoreApp, "/settings") return } diff --git a/handlers/plugins.go b/handlers/plugins.go index 66771df2..8329c8d9 100644 --- a/handlers/plugins.go +++ b/handlers/plugins.go @@ -27,8 +27,7 @@ type PluginSelect struct { } func pluginSavedHandler(w http.ResponseWriter, r *http.Request) { - auth := IsAuthenticated(r) - if !auth { + if !isAuthorized(r) { http.Redirect(w, r, "/", http.StatusSeeOther) return } diff --git a/handlers/prometheus.go b/handlers/prometheus.go index d521f67b..b245f05c 100644 --- a/handlers/prometheus.go +++ b/handlers/prometheus.go @@ -18,7 +18,6 @@ package handlers import ( "fmt" "github.com/hunterlong/statup/core" - "github.com/hunterlong/statup/utils" "net/http" "strings" ) @@ -34,7 +33,6 @@ import ( // func prometheusHandler(w http.ResponseWriter, r *http.Request) { - utils.Log(1, fmt.Sprintf("Prometheus /metrics Request From IP: %v\n", r.RemoteAddr)) if !isAuthorized(r) { http.Redirect(w, r, "/", http.StatusSeeOther) return diff --git a/handlers/services.go b/handlers/services.go index 2c60f51b..6fd5ad26 100644 --- a/handlers/services.go +++ b/handlers/services.go @@ -51,7 +51,7 @@ func servicesHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/", http.StatusSeeOther) return } - executeResponse(w, r, "services.html", core.CoreApp.Services, nil) + ExecuteResponse(w, r, "services.html", core.CoreApp.Services, nil) } type serviceOrder struct { @@ -80,10 +80,10 @@ func servicesViewHandler(w http.ResponseWriter, r *http.Request) { fields := parseGet(r) r.ParseForm() - startField := utils.StringInt(fields.Get("start")) - endField := utils.StringInt(fields.Get("end")) + startField := utils.ToInt(fields.Get("start")) + endField := utils.ToInt(fields.Get("end")) group := r.Form.Get("group") - serv := core.SelectService(utils.StringInt(vars["id"])) + serv := core.SelectService(utils.ToInt(vars["id"])) if serv == nil { w.WriteHeader(http.StatusNotFound) return @@ -113,16 +113,16 @@ func servicesViewHandler(w http.ResponseWriter, r *http.Request) { Data string }{serv, start.Format(utils.FlatpickrReadable), end.Format(utils.FlatpickrReadable), start.Unix(), end.Unix(), data.ToString()} - executeResponse(w, r, "service.html", out, nil) + ExecuteResponse(w, r, "service.html", out, nil) } func apiServiceHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } vars := mux.Vars(r) - servicer := core.SelectServicer(utils.StringInt(vars["id"])) + servicer := core.SelectServicer(utils.ToInt(vars["id"])) if servicer == nil { sendErrorJson(errors.New("service not found"), w, r) return @@ -133,7 +133,7 @@ func apiServiceHandler(w http.ResponseWriter, r *http.Request) { } func apiCreateServiceHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } @@ -154,12 +154,12 @@ func apiCreateServiceHandler(w http.ResponseWriter, r *http.Request) { } func apiServiceUpdateHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } vars := mux.Vars(r) - service := core.SelectServicer(utils.StringInt(vars["id"])) + service := core.SelectServicer(utils.ToInt(vars["id"])) if service.Select() == nil { sendErrorJson(errors.New("service not found"), w, r) return @@ -178,7 +178,7 @@ func apiServiceUpdateHandler(w http.ResponseWriter, r *http.Request) { func apiServiceDataHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - service := core.SelectService(utils.StringInt(vars["id"])) + service := core.SelectService(utils.ToInt(vars["id"])) if service == nil { sendErrorJson(errors.New("service data not found"), w, r) return @@ -188,8 +188,8 @@ func apiServiceDataHandler(w http.ResponseWriter, r *http.Request) { if grouping == "" { grouping = "hour" } - startField := utils.StringInt(fields.Get("start")) - endField := utils.StringInt(fields.Get("end")) + startField := utils.ToInt(fields.Get("start")) + endField := utils.ToInt(fields.Get("end")) if startField == 0 || endField == 0 { startField = 0 @@ -203,15 +203,15 @@ func apiServiceDataHandler(w http.ResponseWriter, r *http.Request) { func apiServicePingDataHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - service := core.SelectService(utils.StringInt(vars["id"])) + service := core.SelectService(utils.ToInt(vars["id"])) if service == nil { sendErrorJson(errors.New("service not found"), w, r) return } fields := parseGet(r) grouping := fields.Get("group") - startField := utils.StringInt(fields.Get("start")) - endField := utils.StringInt(fields.Get("end")) + startField := utils.ToInt(fields.Get("start")) + endField := utils.ToInt(fields.Get("end")) obj := core.GraphDataRaw(service, time.Unix(startField, 0), time.Unix(endField, 0), grouping, "ping_time") w.Header().Set("Content-Type", "application/json") @@ -219,12 +219,12 @@ func apiServicePingDataHandler(w http.ResponseWriter, r *http.Request) { } func apiServiceDeleteHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } vars := mux.Vars(r) - service := core.SelectService(utils.StringInt(vars["id"])) + service := core.SelectService(utils.ToInt(vars["id"])) if service == nil { sendErrorJson(errors.New("service not found"), w, r) return @@ -238,7 +238,7 @@ func apiServiceDeleteHandler(w http.ResponseWriter, r *http.Request) { } func apiAllServicesHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } @@ -253,7 +253,7 @@ func servicesDeleteFailuresHandler(w http.ResponseWriter, r *http.Request) { return } vars := mux.Vars(r) - service := core.SelectService(utils.StringInt(vars["id"])) + service := core.SelectService(utils.ToInt(vars["id"])) service.DeleteFailures() - executeResponse(w, r, "services.html", core.CoreApp.Services, "/services") + ExecuteResponse(w, r, "services.html", core.CoreApp.Services, "/services") } diff --git a/handlers/settings.go b/handlers/settings.go index 94446bcb..427ffb0c 100644 --- a/handlers/settings.go +++ b/handlers/settings.go @@ -31,7 +31,7 @@ func settingsHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/", http.StatusSeeOther) return } - executeResponse(w, r, "settings.html", core.CoreApp, nil) + ExecuteResponse(w, r, "settings.html", core.CoreApp, nil) } func saveSettingsHandler(w http.ResponseWriter, r *http.Request) { @@ -68,7 +68,7 @@ func saveSettingsHandler(w http.ResponseWriter, r *http.Request) { app.UseCdn = types.NewNullBool(r.PostForm.Get("enable_cdn") == "on") core.CoreApp, _ = core.UpdateCore(app) //notifiers.OnSettingsSaved(core.CoreApp.ToCore()) - executeResponse(w, r, "settings.html", core.CoreApp, "/settings") + ExecuteResponse(w, r, "settings.html", core.CoreApp, "/settings") } func saveSASSHandler(w http.ResponseWriter, r *http.Request) { @@ -85,7 +85,7 @@ func saveSASSHandler(w http.ResponseWriter, r *http.Request) { source.SaveAsset([]byte(mobile), utils.Directory, "scss/mobile.scss") source.CompileSASS(utils.Directory) resetRouter() - executeResponse(w, r, "settings.html", core.CoreApp, "/settings") + ExecuteResponse(w, r, "settings.html", core.CoreApp, "/settings") } func saveAssetsHandler(w http.ResponseWriter, r *http.Request) { @@ -105,7 +105,7 @@ func saveAssetsHandler(w http.ResponseWriter, r *http.Request) { utils.Log(3, "Default 'base.css' was inserted because SASS did not work.") } resetRouter() - executeResponse(w, r, "settings.html", core.CoreApp, "/settings") + ExecuteResponse(w, r, "settings.html", core.CoreApp, "/settings") } func deleteAssetsHandler(w http.ResponseWriter, r *http.Request) { @@ -115,12 +115,12 @@ func deleteAssetsHandler(w http.ResponseWriter, r *http.Request) { } source.DeleteAllAssets(utils.Directory) resetRouter() - executeResponse(w, r, "settings.html", core.CoreApp, "/settings") + ExecuteResponse(w, r, "settings.html", core.CoreApp, "/settings") } func parseId(r *http.Request) int64 { vars := mux.Vars(r) - return utils.StringInt(vars["id"]) + return utils.ToInt(vars["id"]) } func parseForm(r *http.Request) url.Values { diff --git a/handlers/setup.go b/handlers/setup.go index 0bbb3592..9543b078 100644 --- a/handlers/setup.go +++ b/handlers/setup.go @@ -34,7 +34,7 @@ func setupHandler(w http.ResponseWriter, r *http.Request) { data, _ = core.LoadUsingEnv() } w.WriteHeader(http.StatusOK) - executeResponse(w, r, "setup.html", data, nil) + ExecuteResponse(w, r, "setup.html", data, nil) } func processSetupHandler(w http.ResponseWriter, r *http.Request) { @@ -49,7 +49,7 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) { dbPass := r.PostForm.Get("db_password") dbDatabase := r.PostForm.Get("db_database") dbConn := r.PostForm.Get("db_connection") - dbPort := utils.StringInt(r.PostForm.Get("db_port")) + dbPort := utils.ToInt(r.PostForm.Get("db_port")) project := r.PostForm.Get("project") username := r.PostForm.Get("username") password := r.PostForm.Get("password") @@ -126,5 +126,5 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) { } func setupResponseError(w http.ResponseWriter, r *http.Request, a interface{}) { - executeResponse(w, r, "setup.html", a, nil) + ExecuteResponse(w, r, "setup.html", a, nil) } diff --git a/handlers/users.go b/handlers/users.go index d6abf4ed..06a51778 100644 --- a/handlers/users.go +++ b/handlers/users.go @@ -33,7 +33,7 @@ func usersHandler(w http.ResponseWriter, r *http.Request) { return } users, _ := core.SelectAllUsers() - executeResponse(w, r, "users.html", users, nil) + ExecuteResponse(w, r, "users.html", users, nil) } func usersEditHandler(w http.ResponseWriter, r *http.Request) { @@ -44,16 +44,16 @@ func usersEditHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) id, _ := strconv.Atoi(vars["id"]) user, _ := core.SelectUser(int64(id)) - executeResponse(w, r, "user.html", user, nil) + ExecuteResponse(w, r, "user.html", user, nil) } func apiUserHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } vars := mux.Vars(r) - user, err := core.SelectUser(utils.StringInt(vars["id"])) + user, err := core.SelectUser(utils.ToInt(vars["id"])) if err != nil { sendErrorJson(err, w, r) return @@ -64,12 +64,12 @@ func apiUserHandler(w http.ResponseWriter, r *http.Request) { } func apiUserUpdateHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } vars := mux.Vars(r) - user, err := core.SelectUser(utils.StringInt(vars["id"])) + user, err := core.SelectUser(utils.ToInt(vars["id"])) if err != nil { sendErrorJson(fmt.Errorf("user #%v was not found", vars["id"]), w, r) return @@ -85,7 +85,7 @@ func apiUserUpdateHandler(w http.ResponseWriter, r *http.Request) { } func apiUserDeleteHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } @@ -95,7 +95,7 @@ func apiUserDeleteHandler(w http.ResponseWriter, r *http.Request) { sendErrorJson(errors.New("cannot delete the last user"), w, r) return } - user, err := core.SelectUser(utils.StringInt(vars["id"])) + user, err := core.SelectUser(utils.ToInt(vars["id"])) if err != nil { sendErrorJson(err, w, r) return @@ -109,7 +109,7 @@ func apiUserDeleteHandler(w http.ResponseWriter, r *http.Request) { } func apiAllUsersHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } @@ -123,7 +123,7 @@ func apiAllUsersHandler(w http.ResponseWriter, r *http.Request) { } func apiCreateUsersHandler(w http.ResponseWriter, r *http.Request) { - if !isAPIAuthorized(r) { + if !isAuthorized(r) { sendUnauthorizedJson(w, r) return } diff --git a/utils/utils.go b/utils/utils.go index 28b6a271..e947739c 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -43,10 +43,15 @@ func init() { } } -// StringInt converts a string to an int64 -func StringInt(s string) int64 { - num, _ := strconv.Atoi(s) - return int64(num) +// ToInt converts a int to a string +func ToInt(s interface{}) int64 { + switch v := s.(type) { + case string: + val, _ := strconv.Atoi(v) + return int64(val) + default: + return 0 + } } // ToString converts a int to a string @@ -55,14 +60,11 @@ func ToString(s interface{}) string { case int, int32, int64: return fmt.Sprintf("%v", v) case float32, float64: - return fmt.Sprintf("%v", v) + return fmt.Sprintf("%f", v) case []byte: return string(v) case bool: - if v { - return "true" - } - return "false" + return fmt.Sprintf("%t", v) default: return fmt.Sprintf("%v", v) } diff --git a/utils/utils_test.go b/utils/utils_test.go index 64cf28a1..bc0bc65b 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -106,19 +106,15 @@ func ExampleToString() { } func TestStringInt(t *testing.T) { - assert.Equal(t, int64(1), StringInt("1")) + assert.Equal(t, int64(1), ToString("1")) } func ExampleStringInt() { amount := "42" - fmt.Print(StringInt(amount)) + fmt.Print(ToString(amount)) // Output: 42 } -func TestDbTime(t *testing.T) { - -} - func TestTimezone(t *testing.T) { zone := float32(-4.0) loc, _ := time.LoadLocation("America/Los_Angeles")