diff --git a/.travis.yml b/.travis.yml
index 67890916..5962ca4b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,7 +18,7 @@ services:
env:
global:
- - VERSION=0.29.4
+ - VERSION=0.29.5
- DB_HOST=localhost
- DB_USER=travis
- DB_PASS=
@@ -37,6 +37,7 @@ before_deploy:
deploy:
- provider: releases
api_key: $GH_TOKEN
+ if: branch = master
file:
- "build/statup-osx-x64.tar.gz"
- "build/statup-osx-x32.tar.gz"
diff --git a/.travis/deploy.sh b/.travis/deploy.sh
index bcda6064..2b4ebfc0 100755
--- a/.travis/deploy.sh
+++ b/.travis/deploy.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# update homebrew to newest version by building on travis
+# update homebrew and cypress testing to newest version by building on travis
body='{ "request": { "branch": "master", "config": { "env": { "VERSION": "'$VERSION'" } } } }'
curl -s -X POST \
@@ -11,10 +11,18 @@ curl -s -X POST \
-d "$body" \
https://api.travis-ci.com/repo/hunterlong%2Fstatup-testing/requests
-#git clone https://$GH_USER:$GH_TOKEN@github.com/hunterlong/homebrew-statup.git
-#cd homebrew-statup
-#
-#./build.sh
-#cd ../
+# notify Docker hub to built this branch
+if [ "$TRAVIS_BRANCH" == "master" ]
+then
+ curl -s -X POST \
+ -H "Content-Type: application/json" \
+ -H "Accept: application/json" \
+ -H "Travis-API-Version: 3" \
+ -H "Authorization: token $TRAVIS_API" \
+ -d "$body" \
+ https://api.travis-ci.com/repo/hunterlong%2Fhomebrew-statup/requests
-curl -H "Content-Type: application/json" --data '{"source_type": "Branch", "source_name": "'"$TRAVIS_BRANCH"'"}' -X POST $DOCKER > /dev/null
\ No newline at end of file
+ curl -H "Content-Type: application/json" --data '{"docker_tag": "latest"}' -X POST $DOCKER
+else
+ curl -H "Content-Type: application/json" --data '{"source_type": "Branch", "source_name": "'"$TRAVIS_BRANCH"'"}' -X POST $DOCKER > /dev/null
+fi
diff --git a/Dockerfile b/Dockerfile
index ea3bfbe2..c4055eda 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
FROM alpine:latest
-ENV VERSION=v0.29.4
+ENV VERSION=v0.29.5
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/README.md b/README.md
index d9494f4a..6a63488d 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ An easy to use Status Page for your websites and applications. Statup will autom
Statup strives to remain future-proof and remain intact if a failure is created. Your Statup service should not be running on the same instance you're trying to monitor. If your server crashes your Status Page should still remaining online to notify your users of downtime.
-
+
## Lightweight and Fast
@@ -27,14 +27,15 @@ Statup is built in Go Language so all you need is the precompile binary based on
Statup will allow you to completely customize your Status Page using SASS styling with easy to use variables. The Docker image actually contains a prebuilt SASS binary so you won't even need to setup anything!
-
+
## Mobile View is Gorgeous
Your status page will be optimized for mobile and desktop viewers. Statup has a full width edge to edge view, which you can also edit to meet your requirements.
-
+
+
## Run on Any Server
@@ -57,7 +58,7 @@ Plugin are created in Golang using the [statup/plugin](https://github.com/hunter
## Easy to use Dashboard
Having a straight forward dashboard makes Statup that much better. Monitor your websites and applications with a basic HTTP GET request, or add a POST request with your own JSON to post to the endpoint.
-
+
## Exporting Static HTML
diff --git a/cli.go b/cli.go
index 50c18864..039f5177 100644
--- a/cli.go
+++ b/cli.go
@@ -4,8 +4,10 @@ import (
"fmt"
"github.com/hunterlong/statup/core"
"github.com/hunterlong/statup/plugin"
+ "github.com/hunterlong/statup/types"
"github.com/hunterlong/statup/utils"
"github.com/joho/godotenv"
+ "math/rand"
"strings"
"time"
"upper.io/db.v3/sqlite"
@@ -111,9 +113,9 @@ func HelpEcho() {
}
func TestPlugin(plug plugin.PluginActions) {
- RenderBoxes()
defer utils.DeleteFile("./.plugin_test.db")
- core.CoreApp.AllPlugins = []plugin.PluginActions{plug}
+ RenderBoxes()
+
info := plug.GetInfo()
fmt.Printf("\n" + BRAKER + "\n")
fmt.Printf(" Plugin Name: %v\n", info.Name)
@@ -123,25 +125,91 @@ func TestPlugin(plug plugin.PluginActions) {
fmt.Printf(" - Route %v - (%v) /%v \n", k+1, r.Method, r.URL)
}
+ // Function to create a new Core with example services, hits, failures, users, and default communications
+ FakeSeed(plug)
+
+ fmt.Println("\n" + BRAKER)
+ fmt.Println(POINT + "Sending 'OnLoad(sqlbuilder.Database)'")
+ core.OnLoad(core.DbSession)
+ fmt.Println("\n" + BRAKER)
+ fmt.Println(POINT + "Sending 'OnSuccess(Service)'")
+ core.OnSuccess(core.SelectService(1))
+ fmt.Println("\n" + BRAKER)
+ fmt.Println(POINT + "Sending 'OnFailure(Service, FailureData)'")
+ fakeFailD := core.FailureData{
+ Issue: "No issue, just testing this plugin. This would include HTTP failure information though",
+ }
+ core.OnFailure(core.SelectService(1), fakeFailD)
+ fmt.Println("\n" + BRAKER)
+ fmt.Println(POINT + "Sending 'OnSettingsSaved(Core)'")
+ fmt.Println(BRAKER)
+ core.OnSettingsSaved(core.CoreApp)
+ fmt.Println("\n" + BRAKER)
+ fmt.Println(POINT + "Sending 'OnNewService(Service)'")
+ core.OnNewService(core.SelectService(2))
+ fmt.Println("\n" + BRAKER)
+ fmt.Println(POINT + "Sending 'OnNewUser(User)'")
+ user, _ := core.SelectUser(1)
+ core.OnNewUser(user)
+ fmt.Println("\n" + BRAKER)
+ fmt.Println(POINT + "Sending 'OnUpdateService(Service)'")
+ srv := core.SelectService(2)
+ srv.Type = "http"
+ srv.Domain = "https://yahoo.com"
+ core.OnUpdateService(srv)
+ fmt.Println("\n" + BRAKER)
+ fmt.Println(POINT + "Sending 'OnDeletedService(Service)'")
+ core.OnDeletedService(core.SelectService(1))
+ fmt.Println("\n" + BRAKER)
+}
+
+func FakeSeed(plug plugin.PluginActions) {
+ var err error
+ core.CoreApp = core.NewCore()
+
+ core.CoreApp.AllPlugins = []plugin.PluginActions{plug}
+
fmt.Printf("\n" + BRAKER)
+ fmt.Println("\nCreating a SQLite database for testing, will be deleted automatically...")
+ sqlFake := sqlite.ConnectionURL{
+ Database: "./.plugin_test.db",
+ }
+ core.DbSession, err = sqlite.Open(sqlFake)
+ if err != nil {
+ utils.Log(3, err)
+ }
+ up, _ := core.SqlBox.String("sqlite_up.sql")
+ requests := strings.Split(up, ";")
+ for _, request := range requests {
+ _, err := core.DbSession.Exec(request)
+ if err != nil {
+ utils.Log(2, err)
+ }
+ }
+
+ fmt.Println("Finished creating Test SQLite database")
+ fmt.Println("Inserting example services into test database...")
+
+ core.CoreApp.Name = "Plugin Test"
+ core.CoreApp.Description = "This is a fake Core for testing your plugin"
+ core.CoreApp.Domain = "http://localhost:8080"
+ core.CoreApp.ApiSecret = "0x0x0x0x0"
+ core.CoreApp.ApiKey = "abcdefg12345"
+
fakeSrv := &core.Service{
- Id: 56,
Name: "Test Plugin Service",
Domain: "https://google.com",
+ Method: "GET",
}
+ fakeSrv.Create()
- fakeFailD := core.FailureData{
- Issue: "No issue, just testing this plugin.",
- }
-
- fakeCore := &core.Core{
- Name: "Plugin Test",
- Description: "This is a fake Core for testing your plugin",
- ApiSecret: "0x0x0x0x0",
- ApiKey: "abcdefg12345",
- Services: []*core.Service{fakeSrv},
+ fakeSrv2 := &core.Service{
+ Name: "Awesome Plugin Service",
+ Domain: "https://netflix.com",
+ Method: "GET",
}
+ fakeSrv2.Create()
fakeUser := &core.User{
Id: 6334,
@@ -151,54 +219,49 @@ func TestPlugin(plug plugin.PluginActions) {
Admin: true,
CreatedAt: time.Now(),
}
+ fakeUser.Create()
- fmt.Println("\nCreating a SQLite database for testing, will be deleted automatically...")
- sqlFake := sqlite.ConnectionURL{
- Database: "./.plugin_test.db",
+ fakeUser = &core.User{
+ Id: 6335,
+ Username: "Billy",
+ Password: "$2a$14$NzT/fLdE3f9iB1Eux2C84O6ZoPhI4NfY0Ke32qllCFo8pMTkUPZzy",
+ Email: "info@awesome.com",
+ CreatedAt: time.Now(),
}
- fakeDb, err := sqlite.Open(sqlFake)
- if err != nil {
- utils.Log(3, err)
+ fakeUser.Create()
+
+ comm := &types.Communication{
+ Id: 1,
+ Method: "email",
}
- up, _ := core.SqlBox.String("sqlite_up.sql")
- requests := strings.Split(up, ";")
- for _, request := range requests {
- _, err := fakeDb.Exec(request)
- if err != nil {
- utils.Log(2, err)
+ core.Create(comm)
+
+ comm2 := &types.Communication{
+ Id: 2,
+ Method: "slack",
+ }
+ core.Create(comm2)
+
+ for i := 0; i <= 50; i++ {
+ dd := core.HitData{
+ Latency: rand.Float64(),
}
+ fakeSrv.CreateHit(dd)
+ dd = core.HitData{
+ Latency: rand.Float64(),
+ }
+ fakeSrv2.CreateHit(dd)
+ fail := core.FailureData{
+ Issue: "This is not an issue, but it would container HTTP response errors.",
+ }
+ fakeSrv.CreateFailure(fail)
+
+ fail = core.FailureData{
+ Issue: "HTTP Status Code 521 did not match 200",
+ }
+ fakeSrv2.CreateFailure(fail)
}
- fmt.Println("Finished creating Test SQLite database, sending events.")
- fmt.Println("\n" + BRAKER)
- fmt.Println(POINT + "Sending 'OnLoad(sqlbuilder.Database)'")
- core.OnLoad(fakeDb)
- fmt.Println("\n" + BRAKER)
- fmt.Println(POINT + "Sending 'OnSuccess(Service)'")
- core.OnSuccess(fakeSrv)
- fmt.Println("\n" + BRAKER)
- fmt.Println(POINT + "Sending 'OnFailure(Service, FailureData)'")
- core.OnFailure(fakeSrv, fakeFailD)
- fmt.Println("\n" + BRAKER)
- fmt.Println(POINT + "Sending 'OnSettingsSaved(Core)'")
- fmt.Println(BRAKER)
- core.OnSettingsSaved(fakeCore)
- fmt.Println("\n" + BRAKER)
- fmt.Println(POINT + "Sending 'OnNewService(Service)'")
- core.OnNewService(fakeSrv)
- fmt.Println("\n" + BRAKER)
- fmt.Println(POINT + "Sending 'OnNewUser(User)'")
- core.OnNewUser(fakeUser)
- fmt.Println("\n" + BRAKER)
- fmt.Println(POINT + "Sending 'OnUpdateService(Service)'")
- core.OnUpdateService(fakeSrv)
- fmt.Println("\n" + BRAKER)
- fmt.Println(POINT + "Sending 'OnDeletedService(Service)'")
- core.OnDeletedService(fakeSrv)
- fmt.Println("\n" + BRAKER)
-
-}
-
-func FakeSeed() {
+ fmt.Println("Seeding example data is complete, running Plugin Tests")
}
diff --git a/core/services.go b/core/services.go
index f2c660e3..815ed836 100644
--- a/core/services.go
+++ b/core/services.go
@@ -244,8 +244,6 @@ func (u *Service) Create() (int64, error) {
u.Id = uuid.(int64)
u.stopRoutine = make(chan struct{})
CoreApp.Services = append(CoreApp.Services, u)
- go u.CheckQueue()
- OnNewService(u)
return uuid.(int64), err
}
diff --git a/core/users.go b/core/users.go
index e8c019bb..9ab74707 100644
--- a/core/users.go
+++ b/core/users.go
@@ -43,7 +43,6 @@ func (u *User) Create() (int64, error) {
utils.Log(3, fmt.Sprintf("Failed to create user %v. %v", u.Username, err))
return 0, err
}
- OnNewUser(u)
return uuid.(int64), err
}
diff --git a/handlers/services.go b/handlers/services.go
index f01d3773..23e8b0b8 100644
--- a/handlers/services.go
+++ b/handlers/services.go
@@ -55,7 +55,10 @@ func CreateServiceHandler(w http.ResponseWriter, r *http.Request) {
if err != nil {
utils.Log(3, fmt.Sprintf("Error starting %v check routine. %v", service.Name, err))
}
+
go service.CheckQueue()
+ core.OnNewService(service)
+
http.Redirect(w, r, "/services", http.StatusSeeOther)
}
diff --git a/handlers/users.go b/handlers/users.go
index 806b5a90..39d8d768 100644
--- a/handlers/users.go
+++ b/handlers/users.go
@@ -54,6 +54,7 @@ func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
if err != nil {
utils.Log(2, err)
}
+ core.OnNewUser(user)
http.Redirect(w, r, "/users", http.StatusSeeOther)
}
diff --git a/main_test.go b/main_test.go
index 959bcc0f..cc0739b1 100644
--- a/main_test.go
+++ b/main_test.go
@@ -64,6 +64,10 @@ func TestRunAll(t *testing.T) {
t.Run(dbt+" Create Users", func(t *testing.T) {
RunUser_Create(t)
})
+ t.Run(dbt+" Create Non Unique Users", func(t *testing.T) {
+ t.SkipNow()
+ RunUser_NonUniqueCreate(t)
+ })
t.Run(dbt+" Select Users", func(t *testing.T) {
RunUser_SelectAll(t)
})
@@ -275,6 +279,16 @@ func RunUser_Create(t *testing.T) {
assert.Equal(t, int64(2), id)
}
+func RunUser_NonUniqueCreate(t *testing.T) {
+ user := &core.User{
+ Username: "admin",
+ Password: "admin",
+ Email: "info@testuser.com",
+ }
+ _, err := user.Create()
+ assert.NotNil(t, err)
+}
+
func RunUser_Delete(t *testing.T) {
user, err := core.SelectUser(2)
assert.Nil(t, err)
diff --git a/source/sql/mysql_up.sql b/source/sql/mysql_up.sql
index dd21ab07..7f5bdb79 100644
--- a/source/sql/mysql_up.sql
+++ b/source/sql/mysql_up.sql
@@ -13,12 +13,13 @@ CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50),
password text,
- email text,
+ email VARCHAR (50),
api_key VARCHAR(50),
api_secret VARCHAR(50),
administrator BOOL NOT NULL DEFAULT '0',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
- INDEX (id)
+ INDEX (id),
+ UNIQUE (username, email)
);
CREATE TABLE services (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
diff --git a/source/sql/postgres_up.sql b/source/sql/postgres_up.sql
index 006a4406..994dabd7 100644
--- a/source/sql/postgres_up.sql
+++ b/source/sql/postgres_up.sql
@@ -12,9 +12,9 @@ CREATE TABLE core (
CREATE TABLE users (
id SERIAL PRIMARY KEY,
- username text,
+ username VARCHAR (50) UNIQUE,
password text,
- email text,
+ email VARCHAR (50) UNIQUE,
api_key text,
api_secret text,
administrator bool,
diff --git a/source/sql/sqlite_up.sql b/source/sql/sqlite_up.sql
index 79791127..82104d73 100644
--- a/source/sql/sqlite_up.sql
+++ b/source/sql/sqlite_up.sql
@@ -18,7 +18,8 @@ CREATE TABLE users (
api_key text,
api_secret text,
administrator bool,
- created_at DATETIME
+ created_at DATETIME,
+ UNIQUE (username, email)
);
CREATE TABLE services (
diff --git a/source/tmpl/login.html b/source/tmpl/login.html
index 2d3d493e..84db7e13 100644
--- a/source/tmpl/login.html
+++ b/source/tmpl/login.html
@@ -13,7 +13,7 @@
-
+
{{ if .Error }}
@@ -35,9 +35,8 @@