-
diff --git a/frontend/src/store.js b/frontend/src/store.js
index c06a4f56..17c79957 100644
--- a/frontend/src/store.js
+++ b/frontend/src/store.js
@@ -26,6 +26,7 @@ export default new Vuex.Store({
messages: [],
users: [],
notifiers: [],
+ checkins: [],
admin: false
},
getters: {
@@ -39,6 +40,7 @@ export default new Vuex.Store({
incidents: state => state.incidents,
users: state => state.users,
notifiers: state => state.notifiers,
+ checkins: state => state.checkins,
isAdmin: state => state.admin,
@@ -48,6 +50,9 @@ export default new Vuex.Store({
groupsClean: state => state.groups.filter(g => g.name !== '').sort((a, b) => a.order_id - b.order_id),
groupsCleanInOrder: state => state.groups.filter(g => g.name !== '').sort((a, b) => a.order_id - b.order_id).sort((a, b) => a.order_id - b.order_id),
+ serviceCheckins: (state) => (id) => {
+ return state.checkins.filter(c => c.service_id === id)
+ },
serviceByAll: (state) => (element) => {
if (element % 1 === 0) {
return state.services.find(s => s.id == element)
@@ -99,6 +104,9 @@ export default new Vuex.Store({
setServices (state, services) {
state.services = services
},
+ setCheckins (state, checkins) {
+ state.checkins = checkins
+ },
setGroups (state, groups) {
state.groups = groups
},
@@ -147,6 +155,8 @@ export default new Vuex.Store({
context.commit("setGroups", groups);
const services = await Api.services()
context.commit("setServices", services);
+ const checkins = await Api.checkins()
+ context.commit("setCheckins", checkins);
const messages = await Api.messages()
context.commit("setMessages", messages)
context.commit("setHasPublicData", true)
diff --git a/handlers/checkin.go b/handlers/checkin.go
index db61edb7..c0d6eec3 100644
--- a/handlers/checkin.go
+++ b/handlers/checkin.go
@@ -40,8 +40,7 @@ func checkinCreateHandler(w http.ResponseWriter, r *http.Request) {
return
}
checkin.ServiceId = service.Id
- err = checkin.Create()
- if err != nil {
+ if err := checkin.Create(); err != nil {
sendErrorJson(err, w, r)
return
}
@@ -52,7 +51,7 @@ func checkinHitHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
checkin, err := checkins.FindByAPI(vars["api"])
if err != nil {
- sendErrorJson(fmt.Errorf("checkin %v was not found", vars["api"]), w, r)
+ sendErrorJson(fmt.Errorf("checkin %s was not found", vars["api"]), w, r)
return
}
ip, _, _ := net.SplitHostPort(r.RemoteAddr)
@@ -60,15 +59,17 @@ func checkinHitHandler(w http.ResponseWriter, r *http.Request) {
hit := &checkins.CheckinHit{
Checkin: checkin.Id,
From: ip,
- CreatedAt: utils.Now().UTC(),
+ CreatedAt: utils.Now(),
}
+ log.Infof("Checking %s was requested", checkin.Name)
+
err = hit.Create()
if err != nil {
sendErrorJson(fmt.Errorf("checkin %v was not found", vars["api"]), w, r)
return
}
checkin.Failing = false
- checkin.LastHitTime = utils.Now().UTC()
+ checkin.LastHitTime = utils.Now()
sendJsonAction(hit.Id, "update", w, r)
}
diff --git a/handlers/incident.go b/handlers/incident.go
index dfa34171..2592dfa2 100644
--- a/handlers/incident.go
+++ b/handlers/incident.go
@@ -8,11 +8,6 @@ import (
"net/http"
)
-func apiAllIncidentsHandler(w http.ResponseWriter, r *http.Request) {
- inc := incidents.All()
- returnJson(inc, w, r)
-}
-
func apiServiceIncidentsHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
incids := incidents.FindByService(utils.ToInt(vars["id"]))
diff --git a/handlers/routes.go b/handlers/routes.go
index ff0ad564..fa8b357d 100644
--- a/handlers/routes.go
+++ b/handlers/routes.go
@@ -146,9 +146,9 @@ func Router() *mux.Router {
// API CHECKIN Routes
api.Handle("/api/checkins", authenticated(apiAllCheckinsHandler, false)).Methods("GET")
- api.Handle("/api/checkin/{api}", authenticated(apiCheckinHandler, false)).Methods("GET")
- api.Handle("/api/checkin", authenticated(checkinCreateHandler, false)).Methods("POST")
- api.Handle("/api/checkin/{api}", authenticated(checkinDeleteHandler, false)).Methods("DELETE")
+ api.Handle("/api/checkins", authenticated(checkinCreateHandler, false)).Methods("POST")
+ api.Handle("/api/checkins/{api}", authenticated(apiCheckinHandler, false)).Methods("GET")
+ api.Handle("/api/checkins/{api}", authenticated(checkinDeleteHandler, false)).Methods("DELETE")
r.Handle("/checkin/{api}", http.HandlerFunc(checkinHitHandler))
// Static Files Routes
diff --git a/notifiers/notifiers.go b/notifiers/notifiers.go
index ab9bb746..3f69ffcf 100644
--- a/notifiers/notifiers.go
+++ b/notifiers/notifiers.go
@@ -20,6 +20,7 @@ func InitNotifiers() {
Twilio,
Webhook,
Mobile,
+ Pushover,
)
}
diff --git a/notifiers/pushover.go b/notifiers/pushover.go
new file mode 100644
index 00000000..9ed7078d
--- /dev/null
+++ b/notifiers/pushover.go
@@ -0,0 +1,85 @@
+package notifiers
+
+import (
+ "fmt"
+ "github.com/statping/statping/types/failures"
+ "github.com/statping/statping/types/notifications"
+ "github.com/statping/statping/types/notifier"
+ "github.com/statping/statping/types/services"
+ "github.com/statping/statping/utils"
+ "net/url"
+ "strings"
+ "time"
+)
+
+const (
+ pushoverUrl = "https://api.pushover.net/1/messages.json"
+)
+
+var _ notifier.Notifier = (*pushover)(nil)
+
+type pushover struct {
+ *notifications.Notification
+}
+
+func (t *pushover) Select() *notifications.Notification {
+ return t.Notification
+}
+
+var Pushover = &pushover{¬ifications.Notification{
+ Method: "pushover",
+ Title: "Pushover",
+ Description: "Use Pushover to receive push notifications. You will need to create a
New Application on Pushover before using this notifier.",
+ Author: "Hunter Long",
+ AuthorUrl: "https://github.com/hunterlong",
+ Icon: "fa dot-circle",
+ Delay: time.Duration(10 * time.Second),
+ Limits: 60,
+ Form: []notifications.NotificationForm{{
+ Type: "text",
+ Title: "User Token",
+ Placeholder: "Insert your device's Pushover Token",
+ DbField: "api_key",
+ Required: true,
+ }, {
+ Type: "text",
+ Title: "Application API Key",
+ Placeholder: "Create an Application and insert the API Key here",
+ DbField: "api_secret",
+ Required: true,
+ },
+ }},
+}
+
+// Send will send a HTTP Post to the Pushover API. It accepts type: string
+func (t *pushover) sendMessage(message string) error {
+ v := url.Values{}
+ v.Set("token", t.ApiSecret)
+ v.Set("user", t.ApiKey)
+ v.Set("message", message)
+ rb := strings.NewReader(v.Encode())
+
+ _, _, err := utils.HttpRequest(pushoverUrl, "POST", "application/x-www-form-urlencoded", nil, rb, time.Duration(10*time.Second), true)
+ if err != nil {
+ return err
+ }
+ return err
+}
+
+// OnFailure will trigger failing service
+func (t *pushover) OnFailure(s *services.Service, f *failures.Failure) error {
+ msg := fmt.Sprintf("Your service '%v' is currently offline!", s.Name)
+ return t.sendMessage(msg)
+}
+
+// OnSuccess will trigger successful service
+func (t *pushover) OnSuccess(s *services.Service) error {
+ msg := fmt.Sprintf("Your service '%v' is currently online!", s.Name)
+ return t.sendMessage(msg)
+}
+
+// OnTest will test the Pushover SMS messaging
+func (t *pushover) OnTest() error {
+ msg := fmt.Sprintf("Testing the Pushover Notifier")
+ return t.sendMessage(msg)
+}
diff --git a/notifiers/pushover_test.go b/notifiers/pushover_test.go
new file mode 100644
index 00000000..494bc19f
--- /dev/null
+++ b/notifiers/pushover_test.go
@@ -0,0 +1,60 @@
+package notifiers
+
+import (
+ "github.com/statping/statping/database"
+ "github.com/statping/statping/types/notifications"
+ "github.com/statping/statping/types/null"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "os"
+ "testing"
+)
+
+var (
+ PUSHOVER_TOKEN = os.Getenv("PUSHOVER_TOKEN")
+ PUSHOVER_API = os.Getenv("PUSHOVER_API")
+)
+
+func TestPushoverNotifier(t *testing.T) {
+ db, err := database.OpenTester()
+ require.Nil(t, err)
+ db.AutoMigrate(¬ifications.Notification{})
+ notifications.SetDB(db)
+
+ if PUSHOVER_TOKEN == "" || PUSHOVER_API == "" {
+ t.Log("Pushover notifier testing skipped, missing PUSHOVER_TOKEN and PUSHOVER_API environment variable")
+ t.SkipNow()
+ }
+
+ t.Run("Load Pushover", func(t *testing.T) {
+ Pushover.ApiKey = PUSHOVER_TOKEN
+ Pushover.ApiSecret = PUSHOVER_API
+ Pushover.Enabled = null.NewNullBool(true)
+
+ Add(Pushover)
+
+ assert.Nil(t, err)
+ assert.Equal(t, "Hunter Long", Pushover.Author)
+ assert.Equal(t, PUSHOVER_TOKEN, Pushover.ApiKey)
+ })
+
+ t.Run("Pushover Within Limits", func(t *testing.T) {
+ assert.True(t, Pushover.CanSend())
+ })
+
+ t.Run("Pushover OnFailure", func(t *testing.T) {
+ err := Pushover.OnFailure(exampleService, exampleFailure)
+ assert.Nil(t, err)
+ })
+
+ t.Run("Pushover OnSuccess", func(t *testing.T) {
+ err := Pushover.OnSuccess(exampleService)
+ assert.Nil(t, err)
+ })
+
+ t.Run("Pushover Test", func(t *testing.T) {
+ err := Pushover.OnTest()
+ assert.Nil(t, err)
+ })
+
+}
diff --git a/types/checkins/database.go b/types/checkins/database.go
index 6732be18..2de053df 100644
--- a/types/checkins/database.go
+++ b/types/checkins/database.go
@@ -32,7 +32,7 @@ func All() []*Checkin {
}
func (c *Checkin) Create() error {
- c.ApiKey = utils.RandomString(7)
+ c.ApiKey = utils.RandomString(32)
q := db.Create(c)
c.Start()
diff --git a/types/configs/connection.go b/types/configs/connection.go
index ea671e4e..29c5eaf4 100644
--- a/types/configs/connection.go
+++ b/types/configs/connection.go
@@ -57,7 +57,7 @@ func Connect(configs *DbConfig, retry bool) error {
if err != nil {
log.Debugln(fmt.Sprintf("Database connection error %s", err))
if retry {
- log.Errorln(fmt.Sprintf("Database %s connection to '%s' is not available, trying again in 5 seconds...", configs.DbConn, configs.DbHost))
+ log.Warnln(fmt.Sprintf("Database %s connection to '%s' is not available, trying again in 5 seconds...", configs.DbConn, configs.DbHost))
time.Sleep(5 * time.Second)
return Connect(configs, retry)
} else {