From a49397c6be59b3f562d6fe20a35b85711de37661 Mon Sep 17 00:00:00 2001 From: Hunter Long Date: Wed, 15 Aug 2018 19:22:10 -0700 Subject: [PATCH] testing - dockerfile version --- cmd/Dockerfile | 2 +- cmd/cli_test.go | 4 --- cmd/main.go | 4 +-- cmd/main_test.go | 11 +++++++- core/core.go | 7 +++--- handlers/handlers.go | 20 ++++++++------- handlers/handlers_test.go | 53 +++++++++++++++++++++++++++++++++------ handlers/misc.go | 10 -------- handlers/prometheus.go | 2 +- handlers/settings.go | 14 +++++++---- source/source.go | 17 ++++++++----- source/source_test.go | 21 +++++++++++++--- utils/log.go | 18 ++++++++----- utils/utils.go | 16 ++++-------- utils/utils_test.go | 16 ++++++++---- 15 files changed, 140 insertions(+), 75 deletions(-) delete mode 100644 handlers/misc.go diff --git a/cmd/Dockerfile b/cmd/Dockerfile index 145d1991..c0a23d45 100644 --- a/cmd/Dockerfile +++ b/cmd/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:latest -ENV VERSION=v0.4 +ENV VERSION=v0.41 RUN apk --no-cache add libstdc++ ca-certificates RUN wget -q https://github.com/hunterlong/statup/releases/download/$VERSION/statup-linux-alpine.tar.gz && \ diff --git a/cmd/cli_test.go b/cmd/cli_test.go index 0af5ee34..0a94d144 100644 --- a/cmd/cli_test.go +++ b/cmd/cli_test.go @@ -3,7 +3,6 @@ package main import ( "github.com/rendon/testcli" "github.com/stretchr/testify/assert" - "os" "testing" ) @@ -52,9 +51,6 @@ func TestAssetsCLI(t *testing.T) { } func TestSassCLI(t *testing.T) { - if os.Getenv("IS_DOCKER") == "true" { - os.Setenv("SASS", "/usr/local/bin/sass") - } run := CatchCLI([]string{"statup", "sass"}) assert.Nil(t, run) assert.FileExists(t, dir+"/assets/css/base.css") diff --git a/cmd/main.go b/cmd/main.go index b064079e..906e7513 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -45,7 +45,7 @@ func main() { if err != nil { utils.Log(3, err) core.SetupMode = true - handlers.RunHTTPServer() + handlers.RunHTTPServer("localhost", 8080) } mainProcess() } @@ -71,7 +71,7 @@ func mainProcess() { if !core.SetupMode { LoadPlugins(false) - handlers.RunHTTPServer() + handlers.RunHTTPServer("localhost", 8080) } } diff --git a/cmd/main_test.go b/cmd/main_test.go index 301defcb..ffe7aff2 100644 --- a/cmd/main_test.go +++ b/cmd/main_test.go @@ -454,6 +454,7 @@ func RunPrometheusHandler(t *testing.T) { route.ServeHTTP(rr, req) t.Log(rr.Body.String()) assert.True(t, strings.Contains(rr.Body.String(), "statup_total_services 6")) + assert.True(t, handlers.IsAuthenticated(req)) } func RunFailingPrometheusHandler(t *testing.T) { @@ -461,7 +462,8 @@ func RunFailingPrometheusHandler(t *testing.T) { assert.Nil(t, err) rr := httptest.NewRecorder() route.ServeHTTP(rr, req) - assert.Equal(t, 401, rr.Result().StatusCode) + assert.Equal(t, 303, rr.Result().StatusCode) + assert.True(t, handlers.IsAuthenticated(req)) } func RunLoginHandler(t *testing.T) { @@ -474,6 +476,7 @@ func RunLoginHandler(t *testing.T) { rr := httptest.NewRecorder() route.ServeHTTP(rr, req) assert.Equal(t, 303, rr.Result().StatusCode) + assert.True(t, handlers.IsAuthenticated(req)) } func RunDashboardHandler(t *testing.T) { @@ -483,6 +486,7 @@ func RunDashboardHandler(t *testing.T) { route.ServeHTTP(rr, req) assert.True(t, strings.Contains(rr.Body.String(), "Statup | Dashboard")) assert.True(t, strings.Contains(rr.Body.String(), "footer")) + assert.True(t, handlers.IsAuthenticated(req)) } func RunUsersHandler(t *testing.T) { @@ -492,6 +496,7 @@ func RunUsersHandler(t *testing.T) { route.ServeHTTP(rr, req) assert.True(t, strings.Contains(rr.Body.String(), "Statup | Users")) assert.True(t, strings.Contains(rr.Body.String(), "footer")) + assert.True(t, handlers.IsAuthenticated(req)) } func RunUserViewHandler(t *testing.T) { @@ -501,6 +506,7 @@ func RunUserViewHandler(t *testing.T) { route.ServeHTTP(rr, req) assert.True(t, strings.Contains(rr.Body.String(), "Statup | Users")) assert.True(t, strings.Contains(rr.Body.String(), "footer")) + assert.True(t, handlers.IsAuthenticated(req)) } func RunServicesHandler(t *testing.T) { @@ -510,6 +516,7 @@ func RunServicesHandler(t *testing.T) { route.ServeHTTP(rr, req) assert.True(t, strings.Contains(rr.Body.String(), "Statup | Services")) assert.True(t, strings.Contains(rr.Body.String(), "footer")) + assert.True(t, handlers.IsAuthenticated(req)) } func RunHelpHandler(t *testing.T) { @@ -519,6 +526,7 @@ func RunHelpHandler(t *testing.T) { route.ServeHTTP(rr, req) assert.True(t, strings.Contains(rr.Body.String(), "Statup | Help")) assert.True(t, strings.Contains(rr.Body.String(), "footer")) + assert.True(t, handlers.IsAuthenticated(req)) } func RunSettingsHandler(t *testing.T) { @@ -529,6 +537,7 @@ func RunSettingsHandler(t *testing.T) { assert.True(t, strings.Contains(rr.Body.String(), "Statup | Settings")) assert.True(t, strings.Contains(rr.Body.String(), "Theme Editor")) assert.True(t, strings.Contains(rr.Body.String(), "footer")) + assert.True(t, handlers.IsAuthenticated(req)) } func fileExists(file string) bool { diff --git a/core/core.go b/core/core.go index accbdb73..cd96fa13 100644 --- a/core/core.go +++ b/core/core.go @@ -4,6 +4,7 @@ import ( "github.com/hunterlong/statup/notifiers" "github.com/hunterlong/statup/source" "github.com/hunterlong/statup/types" + "github.com/hunterlong/statup/utils" "github.com/pkg/errors" "os" "time" @@ -79,21 +80,21 @@ func (c Core) SassVars() string { if !source.UsingAssets { return "" } - return source.OpenAsset(".", "scss/variables.scss") + return source.OpenAsset(utils.Directory, "scss/variables.scss") } func (c Core) BaseSASS() string { if !source.UsingAssets { return "" } - return source.OpenAsset(".", "scss/base.scss") + return source.OpenAsset(utils.Directory, "scss/base.scss") } func (c Core) MobileSASS() string { if !source.UsingAssets { return "" } - return source.OpenAsset(".", "scss/mobile.scss") + return source.OpenAsset(utils.Directory, "scss/mobile.scss") } func (c Core) AllOnline() bool { diff --git a/handlers/handlers.go b/handlers/handlers.go index 98210279..a853ac3d 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -21,9 +21,9 @@ var ( Store *sessions.CookieStore ) -func RunHTTPServer() { - utils.Log(1, "Statup HTTP Server running on http://localhost:8080") - r := Router() +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() { @@ -33,16 +33,13 @@ func RunHTTPServer() { } } srv := &http.Server{ - Addr: "0.0.0.0:8080", + Addr: host, WriteTimeout: time.Second * 15, ReadTimeout: time.Second * 15, IdleTimeout: time.Second * 60, - Handler: r, - } - err := srv.ListenAndServe() - if err != nil { - utils.Log(4, err) + Handler: Router(), } + return srv.ListenAndServe() } func IsAuthenticated(r *http.Request) bool { @@ -118,4 +115,9 @@ func ExecuteJSResponse(w http.ResponseWriter, r *http.Request, file string, data t.Execute(w, data) } +func Error404Handler(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotFound) + ExecuteResponse(w, r, "error_404.html", nil) +} + type DbConfig types.DbConfig diff --git a/handlers/handlers_test.go b/handlers/handlers_test.go index 08af9b3a..01a076e2 100644 --- a/handlers/handlers_test.go +++ b/handlers/handlers_test.go @@ -1,7 +1,6 @@ package handlers import ( - "fmt" "github.com/hunterlong/statup/core" "github.com/hunterlong/statup/source" "github.com/hunterlong/statup/utils" @@ -21,16 +20,11 @@ func init() { func IsRouteAuthenticated(req *http.Request) bool { os.Setenv("GO_ENV", "production") - req, err := http.NewRequest(req.Method, req.URL.String(), req.Body) - if err != nil { - os.Setenv("GO_ENV", "test") - return false - } rr := httptest.NewRecorder() + req.Header.Set("Authorization", "badkey") Router().ServeHTTP(rr, req) - fmt.Println(req.URL.String(), rr.Code) code := rr.Code - if code != 303 { + if code == 200 { os.Setenv("GO_ENV", "test") return false } @@ -38,6 +32,11 @@ func IsRouteAuthenticated(req *http.Request) bool { return true } +func TestFailedHTTPServer(t *testing.T) { + err := RunHTTPServer("missinghost", 0) + assert.Error(t, err) +} + func TestIndexHandler(t *testing.T) { req, err := http.NewRequest("GET", "/", nil) assert.Nil(t, err) @@ -386,6 +385,7 @@ func TestDeleteServiceHandler(t *testing.T) { rr := httptest.NewRecorder() Router().ServeHTTP(rr, req) assert.Equal(t, 200, rr.Code) + assert.True(t, IsRouteAuthenticated(req)) } func TestLogsHandler(t *testing.T) { @@ -397,6 +397,7 @@ func TestLogsHandler(t *testing.T) { assert.Equal(t, 200, rr.Code) assert.Contains(t, body, "Statup | Logs") assert.Contains(t, body, "Statup made with ❤️") + assert.True(t, IsRouteAuthenticated(req)) } func TestLogsLineHandler(t *testing.T) { @@ -408,6 +409,7 @@ func TestLogsLineHandler(t *testing.T) { assert.Equal(t, 200, rr.Code) t.Log(body) assert.NotEmpty(t, body) + assert.True(t, IsRouteAuthenticated(req)) } func TestSaveSettingsHandler(t *testing.T) { @@ -420,6 +422,7 @@ func TestSaveSettingsHandler(t *testing.T) { rr := httptest.NewRecorder() Router().ServeHTTP(rr, req) assert.Equal(t, 200, rr.Code) + assert.True(t, IsRouteAuthenticated(req)) } func TestViewSettingsHandler(t *testing.T) { @@ -445,6 +448,7 @@ func TestSaveAssetsHandler(t *testing.T) { assert.FileExists(t, utils.Directory+"/assets/js/main.js") assert.DirExists(t, utils.Directory+"/assets") assert.True(t, source.UsingAssets) + assert.True(t, IsRouteAuthenticated(req)) } func TestDeleteAssetsHandler(t *testing.T) { @@ -454,6 +458,7 @@ func TestDeleteAssetsHandler(t *testing.T) { Router().ServeHTTP(rr, req) assert.Equal(t, 200, rr.Code) assert.False(t, source.UsingAssets) + assert.True(t, IsRouteAuthenticated(req)) } func TestPrometheusHandler(t *testing.T) { @@ -465,6 +470,7 @@ func TestPrometheusHandler(t *testing.T) { body := rr.Body.String() assert.Equal(t, 200, rr.Code) assert.Contains(t, body, "statup_total_services 6") + assert.True(t, IsRouteAuthenticated(req)) } func TestSaveNotificationHandler(t *testing.T) { @@ -485,6 +491,7 @@ func TestSaveNotificationHandler(t *testing.T) { rr := httptest.NewRecorder() Router().ServeHTTP(rr, req) assert.Equal(t, 200, rr.Code) + assert.True(t, IsRouteAuthenticated(req)) } func TestViewNotificationSettingsHandler(t *testing.T) { @@ -515,6 +522,7 @@ func TestSaveFooterHandler(t *testing.T) { rr := httptest.NewRecorder() Router().ServeHTTP(rr, req) assert.Equal(t, 200, rr.Code) + assert.True(t, IsRouteAuthenticated(req)) req, err = http.NewRequest("GET", "/", nil) assert.Nil(t, err) @@ -540,3 +548,32 @@ func TestLogoutHandler(t *testing.T) { Router().ServeHTTP(rr, req) assert.Equal(t, 303, rr.Code) } + +func TestBuildAssetsHandler(t *testing.T) { + req, err := http.NewRequest("GET", "/settings/build", nil) + assert.Nil(t, err) + rr := httptest.NewRecorder() + Router().ServeHTTP(rr, req) + assert.Equal(t, 200, rr.Code) + assert.True(t, IsRouteAuthenticated(req)) + assert.FileExists(t, "../assets/scss/base.scss") +} + +func TestSaveSassHandler(t *testing.T) { + base := source.OpenAsset(utils.Directory, "scss/base.scss") + vars := source.OpenAsset(utils.Directory, "scss/variables.scss") + + form := url.Values{} + form.Add("theme", base+"\n .test_design { color: $test-design; }") + form.Add("variables", vars+"\n $test-design: #ffffff; ") + req, err := http.NewRequest("POST", "/settings/css", 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) + assert.Equal(t, 200, rr.Code) + assert.True(t, IsRouteAuthenticated(req)) + + newBase := source.OpenAsset(utils.Directory, "css/base.css") + assert.Contains(t, newBase, ".test_design {") +} diff --git a/handlers/misc.go b/handlers/misc.go deleted file mode 100644 index 03ec423c..00000000 --- a/handlers/misc.go +++ /dev/null @@ -1,10 +0,0 @@ -package handlers - -import ( - "net/http" -) - -func Error404Handler(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotFound) - ExecuteResponse(w, r, "error_404.html", nil) -} diff --git a/handlers/prometheus.go b/handlers/prometheus.go index efdace07..c365934f 100644 --- a/handlers/prometheus.go +++ b/handlers/prometheus.go @@ -21,7 +21,7 @@ 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.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) + http.Redirect(w, r, "/", http.StatusSeeOther) return } metrics := []string{} diff --git a/handlers/settings.go b/handlers/settings.go index 0b8fffce..df85f02e 100644 --- a/handlers/settings.go +++ b/handlers/settings.go @@ -58,9 +58,9 @@ func SaveSASSHandler(w http.ResponseWriter, r *http.Request) { r.ParseForm() theme := r.PostForm.Get("theme") variables := r.PostForm.Get("variables") - source.SaveAsset(theme, ".", "scss/base.scss") - source.SaveAsset(variables, ".", "scss/variables.scss") - source.CompileSASS(".") + source.SaveAsset([]byte(theme), utils.Directory, "scss/base.scss") + source.SaveAsset([]byte(variables), utils.Directory, "scss/variables.scss") + source.CompileSASS(utils.Directory) ExecuteResponse(w, r, "settings.html", core.CoreApp) } @@ -70,8 +70,12 @@ func SaveAssetsHandler(w http.ResponseWriter, r *http.Request) { return } dir := utils.Directory - source.CreateAllAssets(dir) - err := source.CompileSASS(dir) + err := source.CreateAllAssets(dir) + if err != nil { + utils.Log(3, err) + return + } + err = source.CompileSASS(dir) if err != nil { source.CopyToPublic(source.CssBox, dir+"/assets/css", "base.css") utils.Log(2, "Default 'base.css' was insert because SASS did not work.") diff --git a/source/source.go b/source/source.go index a14eda72..5a29bf4a 100644 --- a/source/source.go +++ b/source/source.go @@ -104,12 +104,14 @@ func HasAssets(folder string) bool { return false } -func SaveAsset(data, folder, file string) { +func SaveAsset(data []byte, folder, file string) error { utils.Log(1, fmt.Sprintf("Saving %v/%v into assets folder", folder, file)) - err := ioutil.WriteFile(folder+"/assets/"+file, []byte(data), 0644) + err := ioutil.WriteFile(folder+"/assets/"+file, data, 0644) if err != nil { utils.Log(3, fmt.Sprintf("Failed to save %v/%v, %v", folder, file, err)) + return err } + return nil } func OpenAsset(folder, file string) string { @@ -155,27 +157,32 @@ func DeleteAllAssets(folder string) error { return err } -func CopyToPublic(box *rice.Box, folder, file string) { +func CopyToPublic(box *rice.Box, folder, file string) error { 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 { utils.Log(3, fmt.Sprintf("Failed to copy %v to %v, %v.", file, assetFolder, err)) + return err } err = ioutil.WriteFile(assetFolder, []byte(base), 0644) if err != nil { utils.Log(3, fmt.Sprintf("Failed to write file %v to %v, %v.", file, assetFolder, err)) + return err } + return nil } -func MakePublicFolder(folder string) { +func MakePublicFolder(folder string) error { utils.Log(1, fmt.Sprintf("Creating folder '%v'", folder)) if _, err := os.Stat(folder); os.IsNotExist(err) { err = os.MkdirAll(folder, 0755) if err != nil { utils.Log(3, fmt.Sprintf("Failed to created %v directory, %v", folder, err)) + return err } } + return nil } func copyAndCapture(w io.Writer, r io.Reader) ([]byte, error) { @@ -199,7 +206,5 @@ func copyAndCapture(w io.Writer, r io.Reader) ([]byte, error) { return out, err } } - // never reached - panic(true) return nil, nil } diff --git a/source/source_test.go b/source/source_test.go index 07c56d82..2434e343 100644 --- a/source/source_test.go +++ b/source/source_test.go @@ -30,14 +30,29 @@ func TestCreateAssets(t *testing.T) { } func TestCompileSASS(t *testing.T) { - if os.Getenv("IS_DOCKER") == "true" { - os.Setenv("SASS", "/usr/local/bin/sass") - } assert.Nil(t, CompileSASS(dir)) assert.True(t, HasAssets(dir)) } +func TestSaveAsset(t *testing.T) { + data := []byte("BODY { color: black; }") + asset := SaveAsset(data, dir, "scss/theme.scss") + assert.Nil(t, asset) + assert.FileExists(t, dir+"/assets/scss/theme.scss") +} + +func TestOpenAsset(t *testing.T) { + asset := OpenAsset(dir, "scss/theme.scss") + assert.NotEmpty(t, asset) +} + func TestDeleteAssets(t *testing.T) { assert.Nil(t, DeleteAllAssets(dir)) assert.False(t, HasAssets(dir)) } + +func TestCopyToPluginFailed(t *testing.T) { + + assert.Nil(t, DeleteAllAssets(dir)) + assert.False(t, HasAssets(dir)) +} diff --git a/utils/log.go b/utils/log.go index 2c81a163..d3aa2c74 100644 --- a/utils/log.go +++ b/utils/log.go @@ -17,23 +17,29 @@ var ( LastLine interface{} ) -func InitLogs() error { +func createLog(dir string) error { var err error - _, err = os.Stat(Directory + "/logs") + _, err = os.Stat(dir + "/logs") if err != nil { if os.IsNotExist(err) { - os.Mkdir(Directory+"/logs", 0777) + os.Mkdir(dir+"/logs", 0777) } else { - fmt.Println(err) + return err } } - - file, err := os.Create(Directory + "/logs/statup.log") + file, err := os.Create(dir + "/logs/statup.log") if err != nil { return err } defer file.Close() + return err +} +func InitLogs() error { + err := createLog(Directory) + if err != nil { + return err + } logFile, err = os.OpenFile(Directory+"/logs/statup.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0755) if err != nil { log.Printf("ERROR opening file: %v", err) diff --git a/utils/utils.go b/utils/utils.go index c1f65a83..8db42553 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -72,20 +72,14 @@ func UnderScoreString(str string) string { return newStr } -func DeleteFile(file string) bool { +func DeleteFile(file string) error { err := os.Remove(file) if err != nil { - Log(3, err) - return false + return err } - return true + return nil } -func DeleteDirectory(directory string) bool { - err := os.RemoveAll(directory) - if err != nil { - Log(3, err) - return false - } - return true +func DeleteDirectory(directory string) error { + return os.RemoveAll(directory) } diff --git a/utils/utils_test.go b/utils/utils_test.go index 43e5b7af..3d655591 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -8,8 +8,14 @@ import ( "time" ) +func TestCreateLog(t *testing.T) { + err := createLog(Directory) + assert.Nil(t, err) +} + func TestInitLogs(t *testing.T) { assert.Nil(t, InitLogs()) + assert.FileExists(t, "../logs/statup.log") } func TestDir(t *testing.T) { @@ -25,12 +31,12 @@ func TestLog(t *testing.T) { assert.Nil(t, Log(5, errors.New("this is a 5 level error"))) } -func TestLogFileCreation(t *testing.T) { - assert.FileExists(t, "../logs/statup.log") +func TestDeleteFile(t *testing.T) { + assert.Nil(t, DeleteFile(Directory+"/logs/statup.log")) } -func TestDeleteFile(t *testing.T) { - assert.True(t, DeleteFile(Directory+"/logs/statup.log")) +func TestFailedDeleteFile(t *testing.T) { + assert.Error(t, DeleteFile(Directory+"/missingfilehere.txt")) } func TestLogHTTP(t *testing.T) { @@ -73,5 +79,5 @@ func TestSha256(t *testing.T) { } func TestDeleteDirectory(t *testing.T) { - assert.True(t, DeleteDirectory(Directory+"/logs")) + assert.Nil(t, DeleteDirectory(Directory+"/logs")) }