diff --git a/cmd/cli.go b/cmd/cli.go index e3f49c55..7fd46a27 100644 --- a/cmd/cli.go +++ b/cmd/cli.go @@ -27,9 +27,9 @@ func CatchCLI(args []string) { fmt.Printf("Statup v%v\n", VERSION) case "assets": core.RenderBoxes() - core.CreateAllAssets() + core.CreateAllAssets(".") case "sass": - core.CompileSASS() + core.CompileSASS(".") case "update": gitCurrent, err := CheckGithubUpdates() if err != nil { @@ -93,7 +93,7 @@ func RunOnce() { if err != nil { utils.Log(4, "config.yml file not found") } - err = core.DbConnection(core.Configs.Connection, false, "") + err = core.DbConnection(core.Configs.Connection, false, ".") if err != nil { utils.Log(4, err) } diff --git a/cmd/main.go b/cmd/main.go index c3f8ded5..aba0fa47 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -15,8 +15,9 @@ import ( ) var ( - VERSION string - usingEnv bool + VERSION string + usingEnv bool + directory string ) func init() { @@ -33,7 +34,7 @@ func main() { } utils.Log(1, fmt.Sprintf("Starting Statup v%v", VERSION)) core.RenderBoxes() - core.HasAssets() + core.HasAssets(directory) core.Configs, err = core.LoadConfig() if err != nil { @@ -55,7 +56,7 @@ func LoadDotEnvs() error { func mainProcess() { var err error - err = core.DbConnection(core.Configs.Connection, false, "") + err = core.DbConnection(core.Configs.Connection, false, ".") if err != nil { utils.Log(4, fmt.Sprintf("could not connect to database: %v", err)) } diff --git a/cmd/main_test.go b/cmd/main_test.go index ec9d7ce4..07ac8dec 100644 --- a/cmd/main_test.go +++ b/cmd/main_test.go @@ -7,6 +7,7 @@ import ( "github.com/hunterlong/statup/handlers" "github.com/hunterlong/statup/notifiers" "github.com/hunterlong/statup/types" + "github.com/hunterlong/statup/utils" "github.com/rendon/testcli" "github.com/stretchr/testify/assert" "net/http" @@ -25,14 +26,14 @@ var ( func init() { gopath := os.Getenv("GOPATH") - gopath += "/src/github.com/hunterlong/statup/" + gopath += "/src/github.com/hunterlong/statup" } func RunInit(t *testing.T) { core.RenderBoxes() - os.Remove(gopath + "statup.db") - os.Remove(gopath + "cmd/config.yml") - os.Remove(gopath + "cmd/index.html") + os.Remove(gopath + "/statup.db") + os.Remove(gopath + "/cmd/config.yml") + os.Remove(gopath + "/cmd/index.html") route = handlers.Router() LoadDotEnvs() core.CoreApp = core.NewCore() @@ -157,9 +158,9 @@ func TestRunAll(t *testing.T) { t.Run(dbt+" HTTP /settings", func(t *testing.T) { RunSettingsHandler(t) }) - t.Run(dbt+" Cleanup", func(t *testing.T) { - Cleanup(t) - }) + //t.Run(dbt+" Cleanup", func(t *testing.T) { + // Cleanup(t) + //}) } @@ -185,7 +186,7 @@ func TestExportCommand(t *testing.T) { c.Run() t.Log(c.Stdout()) assert.True(t, c.StdoutContains("Exporting Static 'index.html' page")) - assert.True(t, fileExists(gopath+"cmd/index.html")) + assert.True(t, fileExists(gopath+"/cmd/index.html")) } func TestAssetsCommand(t *testing.T) { @@ -199,6 +200,7 @@ func TestAssetsCommand(t *testing.T) { } func RunMakeDatabaseConfig(t *testing.T, db string) { + dir := utils.Dir() port := 5432 if db == "mysql" { port = 3306 @@ -217,7 +219,7 @@ func RunMakeDatabaseConfig(t *testing.T, db string) { "admin", "", nil, - gopath, + dir, } err := config.Save() assert.Nil(t, err) @@ -226,7 +228,7 @@ func RunMakeDatabaseConfig(t *testing.T, db string) { assert.Nil(t, err) assert.Equal(t, db, core.Configs.Connection) - err = core.DbConnection(core.Configs.Connection, false, "") + err = core.DbConnection(core.Configs.Connection, false, dir) assert.Nil(t, err) } @@ -559,10 +561,10 @@ func RunSettingsHandler(t *testing.T) { } func Cleanup(t *testing.T) { - os.Remove(gopath + "cmd/statup.db") - //os.Remove(gopath+"cmd/config.yml") - os.RemoveAll(gopath + "cmd/assets") - os.RemoveAll(gopath + "cmd/logs") + os.Remove(gopath + "/cmd/statup.db") + //os.Remove(gopath+"/cmd/config.yml") + os.RemoveAll(gopath + "/cmd/assets") + os.RemoveAll(gopath + "/cmd/logs") } func fileExists(file string) bool { diff --git a/core/assets.go b/core/assets.go index d05c76ae..6fa85de9 100644 --- a/core/assets.go +++ b/core/assets.go @@ -18,10 +18,7 @@ func RenderBoxes() { } func CopyToPublic(box *rice.Box, folder, file string) { - assetFolder := fmt.Sprintf("assets/%v/%v", folder, file) - if folder == "" { - assetFolder = fmt.Sprintf("assets/%v", file) - } + assetFolder := fmt.Sprintf("%v/%v", folder, file) utils.Log(1, fmt.Sprintf("Copying %v to %v", file, assetFolder)) base, err := box.String(file) if err != nil { @@ -43,24 +40,28 @@ func MakePublicFolder(folder string) { } } -func CompileSASS() error { +func CompileSASS(folder string) error { sassBin := os.Getenv("SASS") shell := os.Getenv("CMD_FILE") - utils.Log(1, fmt.Sprintf("Compiling SASS into /css/base.css...")) - command := fmt.Sprintf("%v %v %v", sassBin, "assets/scss/base.scss", "assets/css/base.css") + + scssFile := fmt.Sprintf("%v/%v", folder, "assets/scss/base.scss") + baseFile := fmt.Sprintf("%v/%v", folder, "assets/css/base.css") + + utils.Log(1, fmt.Sprintf("Compiling SASS %v into %v", scssFile, baseFile)) + command := fmt.Sprintf("%v %v %v", sassBin, scssFile, baseFile) testCmd := exec.Command(shell, command) _, err := testCmd.Output() if err != nil { utils.Log(3, fmt.Sprintf("Failed to compile assets with SASS %v", err)) - utils.Log(3, fmt.Sprintf("SASS: %v | CMD_FILE:%v", sassBin, shell)) + utils.Log(3, fmt.Sprintf("%v %v %v", sassBin, scssFile, baseFile)) return err } utils.Log(1, "SASS Compiling is complete!") return err } -func HasAssets() bool { - if _, err := os.Stat("assets"); err == nil { +func HasAssets(folder string) bool { + if _, err := os.Stat(folder + "/assets"); err == nil { utils.Log(1, "Assets folder was found!") UsingAssets = true return true @@ -68,7 +69,13 @@ func HasAssets() bool { assetEnv := os.Getenv("USE_ASSETS") if assetEnv == "true" { utils.Log(1, "Environment variable USE_ASSETS was found.") - CreateAllAssets() + CreateAllAssets(folder) + err := CompileSASS(folder) + if err != nil { + CopyToPublic(CssBox, folder+"/css", "base.css") + utils.Log(2, "Default 'base.css' was insert because SASS did not work.") + return true + } UsingAssets = true return true } @@ -76,16 +83,16 @@ func HasAssets() bool { return false } -func SaveAsset(data, file string) { - utils.Log(1, fmt.Sprintf("Saving %v into assets folder", file)) - err := ioutil.WriteFile("assets/"+file, []byte(data), 0644) +func SaveAsset(data, folder, file string) { + utils.Log(1, fmt.Sprintf("Saving %v/%v into assets folder", folder, file)) + err := ioutil.WriteFile(folder+"/assets/"+file, []byte(data), 0644) if err != nil { - utils.Log(3, fmt.Sprintf("Failed to save %v, %v", file, err)) + utils.Log(3, fmt.Sprintf("Failed to save %v/%v, %v", folder, file, err)) } } -func OpenAsset(file string) string { - dat, err := ioutil.ReadFile("assets/" + file) +func OpenAsset(folder, file string) string { + dat, err := ioutil.ReadFile(folder + "/assets/" + file) if err != nil { utils.Log(3, fmt.Sprintf("Failed to open %v, %v", file, err)) return "" @@ -93,37 +100,31 @@ func OpenAsset(file string) string { return string(dat) } -func CreateAllAssets() error { - utils.Log(1, "Dump Statup assets into current directory...") - MakePublicFolder("assets") - MakePublicFolder("assets/js") - MakePublicFolder("assets/css") - MakePublicFolder("assets/scss") - MakePublicFolder("assets/emails") +func CreateAllAssets(folder string) error { + utils.Log(1, fmt.Sprintf("Dump Statup assets into %v/assets", folder)) + MakePublicFolder(folder + "/assets") + MakePublicFolder(folder + "/assets/js") + MakePublicFolder(folder + "/assets/css") + MakePublicFolder(folder + "/assets/scss") + MakePublicFolder(folder + "/assets/emails") utils.Log(1, "Inserting scss, css, emails, and javascript files into assets..") - CopyToPublic(ScssBox, "scss", "base.scss") - CopyToPublic(ScssBox, "scss", "variables.scss") - CopyToPublic(CssBox, "css", "bootstrap.min.css") - CopyToPublic(JsBox, "js", "bootstrap.min.js") - CopyToPublic(JsBox, "js", "Chart.bundle.min.js") - CopyToPublic(JsBox, "js", "jquery-3.3.1.slim.min.js") - CopyToPublic(JsBox, "js", "main.js") - CopyToPublic(JsBox, "js", "setup.js") - CopyToPublic(TmplBox, "", "robots.txt") - CopyToPublic(TmplBox, "", "favicon.ico") + CopyToPublic(ScssBox, folder+"/assets/scss", "base.scss") + CopyToPublic(ScssBox, folder+"/assets/scss", "variables.scss") + CopyToPublic(CssBox, folder+"/assets/css", "bootstrap.min.css") + CopyToPublic(JsBox, folder+"/assets/js", "bootstrap.min.js") + CopyToPublic(JsBox, folder+"/assets/js", "Chart.bundle.min.js") + CopyToPublic(JsBox, folder+"/assets/js", "jquery-3.3.1.slim.min.js") + CopyToPublic(JsBox, folder+"/assets/js", "main.js") + CopyToPublic(JsBox, folder+"/assets/js", "setup.js") + CopyToPublic(TmplBox, folder+"/assets/", "robots.txt") + CopyToPublic(TmplBox, folder+"/assets/", "favicon.ico") utils.Log(1, "Compiling CSS from SCSS style...") - err := CompileSASS() - if err != nil { - CopyToPublic(CssBox, "css", "base.css") - utils.Log(2, "Default 'base.css' was insert because SASS did not work.") - return err - } - utils.Log(1, "Statup assets have been inserted") + err := utils.Log(1, "Statup assets have been inserted") return err } -func DeleteAllAssets() error { - err := os.RemoveAll("assets") +func DeleteAllAssets(folder string) error { + err := os.RemoveAll(folder + "/assets") if err != nil { utils.Log(1, fmt.Sprintf("There was an issue deleting Statup Assets, %v", err)) return err diff --git a/core/configs.go b/core/configs.go index 6426ea99..9829e98b 100644 --- a/core/configs.go +++ b/core/configs.go @@ -22,6 +22,9 @@ func LoadConfig() (*types.Config, error) { return nil, errors.New("config.yml file not found - starting in setup mode") } err = yaml.Unmarshal(file, &Configs) + if err != nil { + return nil, err + } CoreApp.DbConnection = Configs.Connection return Configs, err } @@ -71,7 +74,7 @@ func LoadUsingEnv() (*types.Config, error) { Email: "info@localhost.com", } - err := DbConnection(dbConfig.DbConn, true, "") + err := DbConnection(dbConfig.DbConn, true, ".") if err != nil { utils.Log(4, err) return nil, err diff --git a/core/core.go b/core/core.go index d5f5040a..1f810cb3 100644 --- a/core/core.go +++ b/core/core.go @@ -62,7 +62,7 @@ func InitApp() { func InsertNotifierDB() error { if DbSession == nil { - err := DbConnection(CoreApp.DbConnection, false, "") + err := DbConnection(CoreApp.DbConnection, false, ".") if err != nil { return errors.New("database connection has not been created") } @@ -85,21 +85,21 @@ func (c Core) SassVars() string { if !UsingAssets { return "" } - return OpenAsset("scss/variables.scss") + return OpenAsset(".", "scss/variables.scss") } func (c Core) BaseSASS() string { if !UsingAssets { return "" } - return OpenAsset("scss/base.scss") + return OpenAsset(".", "scss/base.scss") } func (c Core) MobileSASS() string { if !UsingAssets { return "" } - return OpenAsset("scss/mobile.scss") + return OpenAsset(".", "scss/mobile.scss") } func (c Core) AllOnline() bool { diff --git a/core/core_test.go b/core/core_test.go index 8c783d87..d2792f51 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -8,14 +8,14 @@ import ( ) var ( - testCore *Core - testConfig *DbConfig - testDatabase string + testCore *Core + testConfig *DbConfig + gopath string ) func init() { - testDatabase = os.Getenv("GOPATH") - testDatabase += "/src/github.com/hunterlong/statup/" + gopath = os.Getenv("GOPATH") + gopath += "/src/github.com/hunterlong/statup" utils.InitLogs() RenderBoxes() @@ -31,14 +31,14 @@ func TestDbConfig_Save(t *testing.T) { testConfig = &DbConfig{ DbConn: "sqlite", Project: "Tester", - Location: testDatabase, + Location: gopath, } err := testConfig.Save() assert.Nil(t, err) } func TestDbConnection(t *testing.T) { - err := DbConnection(testConfig.DbConn, false, testDatabase) + err := DbConnection(testConfig.DbConn, false, gopath) assert.Nil(t, err) } @@ -74,7 +74,25 @@ func TestCore_UsingAssets(t *testing.T) { } func TestHasAssets(t *testing.T) { - assert.False(t, HasAssets()) + assert.False(t, HasAssets(gopath)) +} + +func TestCreateAssets(t *testing.T) { + assert.Nil(t, CreateAllAssets(gopath)) + assert.True(t, HasAssets(gopath)) +} + +func TestCompileSASS(t *testing.T) { + t.SkipNow() + os.Setenv("SASS", "sass") + os.Setenv("CMD_FILE", gopath+"/cmd.sh") + assert.Nil(t, CompileSASS(gopath)) + assert.True(t, HasAssets(gopath)) +} + +func TestDeleteAssets(t *testing.T) { + assert.Nil(t, DeleteAllAssets(gopath)) + assert.False(t, HasAssets(gopath)) } func TestInsertNotifierDB(t *testing.T) { diff --git a/core/database.go b/core/database.go index a5d0edfc..a067ee44 100644 --- a/core/database.go +++ b/core/database.go @@ -29,7 +29,7 @@ func DbConnection(dbType string, retry bool, location string) error { var err error if dbType == "sqlite" { sqliteSettings = sqlite.ConnectionURL{ - Database: location + "statup.db", + Database: location + "/statup.db", } DbSession, err = sqlite.Open(sqliteSettings) if err != nil { @@ -86,7 +86,7 @@ func DbConnection(dbType string, retry bool, location string) error { func waitForDb(dbType string) error { time.Sleep(5 * time.Second) - return DbConnection(dbType, true, "") + return DbConnection(dbType, true, ".") } func DatabaseMaintence() { diff --git a/core/services_test.go b/core/services_test.go index 6b5d4fe4..e974a562 100644 --- a/core/services_test.go +++ b/core/services_test.go @@ -16,9 +16,16 @@ func TestSelectAllServices(t *testing.T) { assert.Equal(t, 5, len(services)) } -func TestSelectService(t *testing.T) { +func TestSelectHTTPService(t *testing.T) { service := SelectService(1) assert.Equal(t, "Google", service.ToService().Name) + assert.Equal(t, "http", service.ToService().Type) +} + +func TestSelectTCPService(t *testing.T) { + service := SelectService(5) + assert.Equal(t, "Postgres TCP Check", service.ToService().Name) + assert.Equal(t, "tcp", service.ToService().Type) } func TestUpdateService(t *testing.T) { @@ -32,12 +39,12 @@ func TestUpdateService(t *testing.T) { func TestServiceHTTPCheck(t *testing.T) { service := SelectService(1) - checked := ServiceHTTPCheck(service.ToService()) + checked := ServiceCheck(service.ToService()) assert.Equal(t, "Updated Google", checked.Name) assert.True(t, checked.Online) } -func TestCheckService(t *testing.T) { +func TestCheckHTTPService(t *testing.T) { service := SelectService(1).ToService() assert.Equal(t, "Updated Google", service.Name) assert.True(t, service.Online) @@ -45,6 +52,20 @@ func TestCheckService(t *testing.T) { assert.NotZero(t, service.Latency) } +func TestServiceTCPCheck(t *testing.T) { + service := SelectService(5) + checked := ServiceCheck(service.ToService()) + assert.Equal(t, "Postgres TCP Check", checked.Name) + assert.True(t, checked.Online) +} + +func TestCheckTCPService(t *testing.T) { + service := SelectService(5).ToService() + assert.Equal(t, "Postgres TCP Check", service.Name) + assert.True(t, service.Online) + assert.NotZero(t, service.Latency) +} + func TestCreateService(t *testing.T) { s := &types.Service{ Name: "Interpol - All The Rage Back Home", @@ -63,17 +84,78 @@ func TestCreateService(t *testing.T) { assert.Equal(t, "Interpol - All The Rage Back Home", newService.Name) } +func TestCreateFailingHTTPService(t *testing.T) { + s := &types.Service{ + Name: "Bad URL", + Domain: "http://localhost/iamnothere", + ExpectedStatus: 200, + Interval: 30, + Type: "http", + Method: "GET", + Timeout: 5, + } + var err error + newServiceId, err = CreateService(s) + assert.Nil(t, err) + assert.NotZero(t, newServiceId) + newService := SelectService(newServiceId).ToService() + assert.Equal(t, "Bad URL", newService.Name) +} + +func TestServiceFailedCheck(t *testing.T) { + service := SelectService(7) + checked := ServiceCheck(service.ToService()) + assert.Equal(t, "Bad URL", checked.Name) + assert.False(t, checked.Online) +} + +func TestCreateFailingTCPService(t *testing.T) { + s := &types.Service{ + Name: "Bad TCP", + Domain: "localhost", + Port: 5050, + Interval: 30, + Type: "tcp", + Timeout: 5, + } + var err error + newServiceId, err = CreateService(s) + assert.Nil(t, err) + assert.NotZero(t, newServiceId) + newService := SelectService(newServiceId).ToService() + assert.Equal(t, "Bad TCP", newService.Name) +} + +func TestServiceFailedTCPCheck(t *testing.T) { + service := SelectService(8) + checked := ServiceCheck(service.ToService()) + assert.Equal(t, "Bad TCP", checked.Name) + assert.False(t, checked.Online) +} + +func TestCreateServiceFailure(t *testing.T) { + + fail := FailureData{ + Issue: "This is not an issue, but it would container HTTP response errors.", + } + service := SelectService(8) + + id, err := CreateServiceFailure(service.ToService(), fail) + assert.Nil(t, err) + assert.NotZero(t, id) +} + func TestDeleteService(t *testing.T) { service := SelectService(newServiceId).ToService() count, err := SelectAllServices() assert.Nil(t, err) - assert.Equal(t, 6, len(count)) + assert.Equal(t, 8, len(count)) err = DeleteService(service) assert.Nil(t, err) count, err = SelectAllServices() assert.Nil(t, err) - assert.Equal(t, 5, len(count)) + assert.Equal(t, 7, len(count)) } diff --git a/handlers/dashboard.go b/handlers/dashboard.go index 6396426e..7def14f7 100644 --- a/handlers/dashboard.go +++ b/handlers/dashboard.go @@ -1,10 +1,7 @@ package handlers import ( - "encoding/json" - "fmt" "github.com/hunterlong/statup/core" - "github.com/hunterlong/statup/types" "github.com/hunterlong/statup/utils" "net/http" ) @@ -82,27 +79,3 @@ func LogsLineHandler(w http.ResponseWriter, r *http.Request) { w.Write(v) } } - -type backups struct { - Core types.Core `json:"core"` -} - -func BackupCreateHandler(w http.ResponseWriter, r *http.Request) { - //if !IsAuthenticated(r) { - // http.Redirect(w, r, "/", http.StatusSeeOther) - // return - //} - - backup := backups{ - Core: *core.CoreApp.ToCore(), - } - - out, err := json.Marshal(backup) - if err != nil { - panic(err) - } - fmt.Println(out) - - json.NewEncoder(w).Encode(backup) - -} diff --git a/handlers/handlers_test.go b/handlers/handlers_test.go index b7ee0aa4..15dc0478 100644 --- a/handlers/handlers_test.go +++ b/handlers/handlers_test.go @@ -57,6 +57,14 @@ func TestProcessSetupHandler(t *testing.T) { assert.Equal(t, 303, rr.Code) } +func TestCheckSetupHandler(t *testing.T) { + req, err := http.NewRequest("GET", "/setup", nil) + assert.Nil(t, err) + rr := httptest.NewRecorder() + Router().ServeHTTP(rr, req) + assert.Equal(t, 303, rr.Code) +} + func TestCheckIndexHandler(t *testing.T) { req, err := http.NewRequest("GET", "/", nil) assert.Nil(t, err) @@ -76,6 +84,19 @@ func TestServicesViewHandler(t *testing.T) { assert.Contains(t, body, "Statup made with ❤️") } +func TestServiceChartHandler(t *testing.T) { + req, err := http.NewRequest("GET", "/charts.js", nil) + assert.Nil(t, err) + rr := httptest.NewRecorder() + Router().ServeHTTP(rr, req) + body := rr.Body.String() + assert.Equal(t, 200, rr.Code) + assert.Contains(t, body, "var ctx_1") + assert.Contains(t, body, "var ctx_2") + assert.Contains(t, body, "var ctx_3") + assert.Contains(t, body, "var ctx_4") +} + func TestDashboardHandler(t *testing.T) { req, err := http.NewRequest("GET", "/dashboard", nil) assert.Nil(t, err) @@ -99,6 +120,20 @@ func TestLoginHandler(t *testing.T) { assert.Equal(t, 303, rr.Code) } +func TestBadLoginHandler(t *testing.T) { + form := url.Values{} + form.Add("username", "admin") + form.Add("password", "wrongpassword") + req, err := http.NewRequest("POST", "/dashboard", strings.NewReader(form.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + assert.Nil(t, err) + rr := httptest.NewRecorder() + Router().ServeHTTP(rr, req) + body := rr.Body.String() + assert.Contains(t, body, "Incorrect login information submitted, try again.") + assert.Equal(t, 200, rr.Code) +} + func TestServicesHandler(t *testing.T) { req, err := http.NewRequest("GET", "/services", nil) assert.Nil(t, err) @@ -124,6 +159,31 @@ func TestCreateUserHandler(t *testing.T) { assert.Equal(t, 303, rr.Code) } +func TestEditUserHandler(t *testing.T) { + form := url.Values{} + form.Add("username", "changedusername") + form.Add("password", "##########") + form.Add("email", "info@okokk.com") + form.Add("admin", "on") + req, err := http.NewRequest("POST", "/user/2", strings.NewReader(form.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + assert.Nil(t, err) + rr := httptest.NewRecorder() + Router().ServeHTTP(rr, req) + body := rr.Body.String() + assert.Contains(t, body, "admin") + assert.Contains(t, body, "changedusername") + assert.Equal(t, 200, rr.Code) +} + +func TestDeleteUserHandler(t *testing.T) { + req, err := http.NewRequest("GET", "/user/2/delete", nil) + assert.Nil(t, err) + rr := httptest.NewRecorder() + Router().ServeHTTP(rr, req) + assert.Equal(t, 303, rr.Code) +} + func TestUsersHandler(t *testing.T) { req, err := http.NewRequest("GET", "/users", nil) assert.Nil(t, err) @@ -133,7 +193,21 @@ func TestUsersHandler(t *testing.T) { assert.Equal(t, 200, rr.Code) assert.Contains(t, body, "Statup | Users") assert.Contains(t, body, "admin") - assert.Contains(t, body, "newuser") + assert.NotContains(t, body, "changedusername") + assert.Contains(t, body, "Statup made with ❤️") +} + +func TestUsersEditHandler(t *testing.T) { + req, err := http.NewRequest("GET", "/user/1", nil) + assert.Nil(t, err) + rr := httptest.NewRecorder() + Router().ServeHTTP(rr, req) + body := rr.Body.String() + assert.Equal(t, 200, rr.Code) + assert.Contains(t, body, "Statup | Users") + assert.Contains(t, body, "

User admin

") + assert.Contains(t, body, "value=\"info@statup.io\"") + assert.Contains(t, body, "value=\"##########\"") assert.Contains(t, body, "Statup made with ❤️") } @@ -256,6 +330,14 @@ func TestServicesUpdateHandler(t *testing.T) { assert.Contains(t, body, "Statup made with ❤️") } +func TestDeleteServiceHandler(t *testing.T) { + req, err := http.NewRequest("POST", "/service/7/delete", nil) + assert.Nil(t, err) + rr := httptest.NewRecorder() + Router().ServeHTTP(rr, req) + assert.Equal(t, 303, rr.Code) +} + func TestLogsHandler(t *testing.T) { t.SkipNow() req, err := http.NewRequest("GET", "/logs", nil) @@ -312,7 +394,7 @@ func TestPrometheusHandler(t *testing.T) { Router().ServeHTTP(rr, req) body := rr.Body.String() assert.Equal(t, 200, rr.Code) - assert.Contains(t, body, "statup_total_services 7") + assert.Contains(t, body, "statup_total_services 6") } func TestLogoutHandler(t *testing.T) { @@ -321,4 +403,4 @@ func TestLogoutHandler(t *testing.T) { rr := httptest.NewRecorder() Router().ServeHTTP(rr, req) assert.Equal(t, 303, rr.Code) -} \ No newline at end of file +} diff --git a/handlers/routes.go b/handlers/routes.go index 74f3eb72..7a5c74e2 100644 --- a/handlers/routes.go +++ b/handlers/routes.go @@ -30,7 +30,6 @@ func Router() *mux.Router { r.Handle("/service/{id}", http.HandlerFunc(ServicesUpdateHandler)).Methods("POST") r.Handle("/service/{id}/edit", http.HandlerFunc(ServicesViewHandler)) r.Handle("/service/{id}/delete", http.HandlerFunc(ServicesDeleteHandler)) - r.Handle("/service/{id}/badge.svg", http.HandlerFunc(ServicesBadgeHandler)) r.Handle("/service/{id}/delete_failures", http.HandlerFunc(ServicesDeleteFailuresHandler)).Methods("GET") r.Handle("/service/{id}/checkin", http.HandlerFunc(CheckinCreateUpdateHandler)).Methods("POST") r.Handle("/users", http.HandlerFunc(UsersHandler)).Methods("GET") diff --git a/handlers/services.go b/handlers/services.go index 2c1db5a1..39c2620a 100644 --- a/handlers/services.go +++ b/handlers/services.go @@ -83,22 +83,6 @@ func ServicesViewHandler(w http.ResponseWriter, r *http.Request) { ExecuteResponse(w, r, "service.html", serv) } -func ServicesBadgeHandler(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - serv := core.SelectService(utils.StringInt(vars["id"])) - service := serv.ToService() - var badge []byte - if service.Online { - badge = []byte(`` + service.Name + `` + service.Name + `onlineonline`) - } else { - badge = []byte(`` + service.Name + `` + service.Name + `offlineoffline`) - } - - w.Header().Set("Content-Type", "image/svg+xml") - w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") - w.Write(badge) -} - func ServicesUpdateHandler(w http.ResponseWriter, r *http.Request) { if !IsAuthenticated(r) { http.Redirect(w, r, "/", http.StatusSeeOther) diff --git a/handlers/settings.go b/handlers/settings.go index a93c9b9f..af3ef8b3 100644 --- a/handlers/settings.go +++ b/handlers/settings.go @@ -57,9 +57,9 @@ func SaveSASSHandler(w http.ResponseWriter, r *http.Request) { r.ParseForm() theme := r.PostForm.Get("theme") variables := r.PostForm.Get("variables") - core.SaveAsset(theme, "scss/base.scss") - core.SaveAsset(variables, "scss/variables.scss") - core.CompileSASS() + core.SaveAsset(theme, ".", "scss/base.scss") + core.SaveAsset(variables, ".", "scss/variables.scss") + core.CompileSASS(".") http.Redirect(w, r, "/settings", http.StatusSeeOther) } @@ -68,7 +68,12 @@ func SaveAssetsHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/", http.StatusSeeOther) return } - core.CreateAllAssets() + core.CreateAllAssets(".") + err := core.CompileSASS(".") + if err != nil { + core.CopyToPublic(core.CssBox, "css", "base.css") + utils.Log(2, "Default 'base.css' was insert because SASS did not work.") + } core.UsingAssets = true http.Redirect(w, r, "/settings", http.StatusSeeOther) } @@ -78,7 +83,7 @@ func DeleteAssetsHandler(w http.ResponseWriter, req *http.Request) { http.Redirect(w, req, "/", http.StatusSeeOther) return } - core.DeleteAllAssets() + core.DeleteAllAssets(".") core.UsingAssets = false LocalizedAssets(r) http.Redirect(w, req, "/settings", http.StatusSeeOther) diff --git a/handlers/setup.go b/handlers/setup.go index 3903fd6c..be3f4c69 100644 --- a/handlers/setup.go +++ b/handlers/setup.go @@ -74,7 +74,7 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) { password, email, nil, - "", + ".", } err := config.Save() if err != nil { @@ -96,7 +96,7 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) { return } - err = core.DbConnection(core.Configs.Connection, false, "") + err = core.DbConnection(core.Configs.Connection, false, ".") if err != nil { utils.Log(3, err) core.DeleteConfig() diff --git a/handlers/users.go b/handlers/users.go index 61a8af26..d74e2ddd 100644 --- a/handlers/users.go +++ b/handlers/users.go @@ -105,6 +105,7 @@ func UsersDeleteHandler(w http.ResponseWriter, r *http.Request) { users, _ := core.SelectAllUsers() if len(users) == 1 { + utils.Log(2, "cannot delete the only user in the system") http.Redirect(w, r, "/users", http.StatusSeeOther) return } diff --git a/notifiers/notifiers_test.go b/notifiers/notifiers_test.go index 4aa04d71..a1b60460 100644 --- a/notifiers/notifiers_test.go +++ b/notifiers/notifiers_test.go @@ -49,14 +49,14 @@ func (n *Tester) Test() error { func init() { testDatabase = os.Getenv("GOPATH") - testDatabase += "/src/github.com/hunterlong/statup/" + testDatabase += "/src/github.com/hunterlong/statup" utils.InitLogs() } func injectDatabase() { sqliteDb := sqlite.ConnectionURL{ - Database: testDatabase + "statup.db", + Database: testDatabase + "/statup.db", } dbSession, _ := sqlite.Open(sqliteDb) Collections = dbSession.Collection("communication") diff --git a/source/tmpl/user.html b/source/tmpl/user.html index 8a102be2..9734123f 100644 --- a/source/tmpl/user.html +++ b/source/tmpl/user.html @@ -56,7 +56,6 @@
-
diff --git a/utils/log.go b/utils/log.go index e23c4340..c54206e5 100644 --- a/utils/log.go +++ b/utils/log.go @@ -2,7 +2,6 @@ package utils import ( "fmt" - "github.com/fatih/color" "gopkg.in/natefinch/lumberjack.v2" "log" "net/http" @@ -13,7 +12,6 @@ import ( var ( logFile *os.File - logLevel int fmtLogs *log.Logger ljLogger *lumberjack.Logger LastLine interface{} @@ -44,23 +42,8 @@ func InitLogs() error { MaxAge: 28, } fmtLogs = log.New(logFile, "", log.Ldate|log.Ltime) - log.SetOutput(ljLogger) - - logEnv := os.Getenv("LOG") - - if logEnv == "fatal" { - logLevel = 3 - } else if logEnv == "debug" { - logLevel = 2 - } else if logEnv == "info" { - logLevel = 1 - } else { - logLevel = 0 - } - rotate() - return err } @@ -75,39 +58,42 @@ func rotate() { }() } -func Log(level int, err interface{}) { +func Log(level int, err interface{}) error { LastLine = err + var outErr error switch level { case 5: - fmt.Printf("PANIC: %v\n", err) - fmtLogs.Fatalf("PANIC: %v\n", err) + _, outErr = fmt.Printf("PANIC: %v\n", err) + fmtLogs.Printf("PANIC: %v\n", err) case 4: - fmt.Printf("FATAL: %v\n", err) + _, outErr = fmt.Printf("FATAL: %v\n", err) fmtLogs.Printf("FATAL: %v\n", err) //color.Red("ERROR: %v\n", err) //os.Exit(2) case 3: - fmt.Printf("ERROR: %v\n", err) + _, outErr = fmt.Printf("ERROR: %v\n", err) fmtLogs.Printf("ERROR: %v\n", err) //color.Red("ERROR: %v\n", err) case 2: - fmt.Printf("WARNING: %v\n", err) + _, outErr = fmt.Printf("WARNING: %v\n", err) fmtLogs.Printf("WARNING: %v\n", err) //color.Yellow("WARNING: %v\n", err) case 1: - fmt.Printf("INFO: %v\n", err) + _, outErr = fmt.Printf("INFO: %v\n", err) fmtLogs.Printf("INFO: %v\n", err) //color.Blue("INFO: %v\n", err) case 0: - fmt.Printf("%v\n", err) + _, outErr = fmt.Printf("%v\n", err) fmtLogs.Printf("%v\n", err) - color.White("%v\n", err) + //color.White("%v\n", err) } + return outErr } -func Http(r *http.Request) { +func Http(r *http.Request) string { msg := fmt.Sprintf("%v (%v) | IP: %v", r.RequestURI, r.Method, r.Host) fmtLogs.Printf("WEB: %v\n", msg) fmt.Printf("WEB: %v\n", msg) LastLine = msg + return msg } diff --git a/utils/utils.go b/utils/utils.go index 1f457785..59638793 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -18,6 +18,14 @@ func IntString(s int) string { return strconv.Itoa(s) } +func Dir() string { + dir, err := os.Getwd() + if err != nil { + return "." + } + return dir +} + type Timestamp time.Time type Timestamper interface { diff --git a/utils/utils_test.go b/utils/utils_test.go index c0f3d5bd..4c0e4a72 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -1,7 +1,9 @@ package utils import ( + "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "net/http" "testing" "time" ) @@ -10,6 +12,25 @@ func TestInitLogs(t *testing.T) { assert.Nil(t, InitLogs()) } +func TestDir(t *testing.T) { + assert.Contains(t, Dir(), "github.com/hunterlong/statup") +} + +func TestLog(t *testing.T) { + assert.Nil(t, Log(0, errors.New("this is a 0 level error"))) + assert.Nil(t, Log(1, errors.New("this is a 1 level error"))) + assert.Nil(t, Log(2, errors.New("this is a 2 level error"))) + assert.Nil(t, Log(3, errors.New("this is a 3 level error"))) + assert.Nil(t, Log(4, errors.New("this is a 4 level error"))) + assert.Nil(t, Log(5, errors.New("this is a 5 level error"))) +} + +func TestLogHTTP(t *testing.T) { + req, err := http.NewRequest("GET", "/", nil) + assert.Nil(t, err) + assert.NotEmpty(t, Http(req)) +} + func TestIntString(t *testing.T) { assert.Equal(t, "1", IntString(1)) }