not finalized, notifications works, additional testing

pull/773/head
hunterlong 2020-08-02 22:48:35 -07:00
parent c92fe8a329
commit 1cfc5b4bda
22 changed files with 114 additions and 28 deletions

View File

@ -20,6 +20,8 @@
<h6 class="mt-4 text-muted">Notifiers</h6> <h6 class="mt-4 text-muted">Notifiers</h6>
{{notifiers}}
<div id="notifiers_tabs"> <div id="notifiers_tabs">
<a v-for="(notifier, index) in notifiers" v-bind:key="`${notifier.method}`" @click.prevent="changeTab" class="nav-link text-capitalize" v-bind:class="{active: liClass(`v-pills-${notifier.method.toLowerCase()}-tab`)}" v-bind:id="`v-pills-${notifier.method.toLowerCase()}-tab`" data-toggle="pill" v-bind:href="`#v-pills-${notifier.method.toLowerCase()}`" role="tab" v-bind:aria-controls="`v-pills-${notifier.method.toLowerCase()}`" aria-selected="false"> <a v-for="(notifier, index) in notifiers" v-bind:key="`${notifier.method}`" @click.prevent="changeTab" class="nav-link text-capitalize" v-bind:class="{active: liClass(`v-pills-${notifier.method.toLowerCase()}-tab`)}" v-bind:id="`v-pills-${notifier.method.toLowerCase()}-tab`" data-toggle="pill" v-bind:href="`#v-pills-${notifier.method.toLowerCase()}`" role="tab" v-bind:aria-controls="`v-pills-${notifier.method.toLowerCase()}`" aria-selected="false">
<font-awesome-icon :icon="iconName(notifier.icon)" class="mr-2"/> {{notifier.title}} <font-awesome-icon :icon="iconName(notifier.icon)" class="mr-2"/> {{notifier.title}}
@ -152,10 +154,10 @@
} }
}, },
mounted() { mounted() {
this.update()
}, },
created() { created() {
this.update() this.update()
}, },
methods: { methods: {
async update() { async update() {

View File

@ -12,12 +12,10 @@ import (
func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) { func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) {
var notifs []notifications.Notification var notifs []notifications.Notification
notifiers := services.AllNotifiers() for _, n := range services.AllNotifiers() {
for _, n := range notifiers { no := n.Select()
notif := n.Select() notif, _ := notifications.Find(no.Method)
notifer, _ := notifications.Find(notif.Method) notifs = append(notifs, *no.UpdateFields(notif))
notif.UpdateFields(notifer)
notifs = append(notifs, *notif)
} }
sort.Sort(notifications.NotificationOrder(notifs)) sort.Sort(notifications.NotificationOrder(notifs))
returnJson(notifs, w, r) returnJson(notifs, w, r)
@ -25,12 +23,12 @@ func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) {
func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) { func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
notif := services.FindNotifier(vars["notifier"]) notifer := services.FindNotifier(vars["notifier"])
if notif == nil { if notifer == nil {
sendErrorJson(errors.New("could not find notifier"), w, r) sendErrorJson(errors.New("could not find notifier"), w, r)
return return
} }
returnJson(notif, w, r) returnJson(notifer, w, r)
} }
func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) { func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) {
@ -48,8 +46,7 @@ func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) {
log.Infof("Updating %s Notifier", notifer.Title) log.Infof("Updating %s Notifier", notifer.Title)
err = notifer.Update() if err := notifer.Update(); err != nil {
if err != nil {
sendErrorJson(err, w, r) sendErrorJson(err, w, r)
return return
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing" "testing"
) )
@ -12,7 +13,7 @@ func TestAttachment(t *testing.T) {
notifiers.InitNotifiers() notifiers.InitNotifiers()
} }
func TestUnAuthenticatedNotifierRoutes(t *testing.T) { func TestAuthenticatedNotifierRoutes(t *testing.T) {
slackWebhookUrl := utils.Params.GetString("SLACK_URL") slackWebhookUrl := utils.Params.GetString("SLACK_URL")
tests := []HTTPTest{ tests := []HTTPTest{
@ -42,7 +43,12 @@ func TestUnAuthenticatedNotifierRoutes(t *testing.T) {
URL: "/api/notifier/slack", URL: "/api/notifier/slack",
Method: "GET", Method: "GET",
ExpectedStatus: 200, ExpectedStatus: 200,
BeforeTest: SetTestENV, BeforeTest: func(t *testing.T) error {
notif := services.FindNotifier("slack")
require.NotNil(t, notif)
assert.Equal(t, "slack", notif.Method)
return SetTestENV(t)
},
}, },
{ {
Name: "No Authentication - Update Notifier", Name: "No Authentication - Update Notifier",
@ -68,7 +74,20 @@ func TestUnAuthenticatedNotifierRoutes(t *testing.T) {
"limits": 55 "limits": 55
}`, }`,
ExpectedStatus: 200, ExpectedStatus: 200,
BeforeTest: SetTestENV, BeforeTest: func(t *testing.T) error {
notif := services.FindNotifier("slack")
require.NotNil(t, notif)
assert.Equal(t, "slack", notif.Method)
assert.False(t, notif.Enabled.Bool)
return SetTestENV(t)
},
AfterTest: func(t *testing.T) error {
notif := services.FindNotifier("slack")
require.NotNil(t, notif)
assert.Equal(t, "slack", notif.Method)
assert.True(t, notif.Enabled.Bool)
return UnsetTestENV(t)
},
}, },
{ {
Name: "Test Notifier (OnSuccess)", Name: "Test Notifier (OnSuccess)",
@ -154,7 +173,7 @@ func TestApiNotifiersRoutes(t *testing.T) {
URL: "/api/notifier/slack", URL: "/api/notifier/slack",
Method: "GET", Method: "GET",
ExpectedStatus: 200, ExpectedStatus: 200,
ExpectedContains: []string{`"method":"slack"`}, ExpectedContains: []string{`"method":"slack"`, `"host":"https://slack.api/example/12345"`},
BeforeTest: SetTestENV, BeforeTest: SetTestENV,
SecureRoute: true, SecureRoute: true,
}, },

View File

@ -22,6 +22,10 @@ func (c *commandLine) Select() *notifications.Notification {
return c.Notification return c.Notification
} }
func (c *commandLine) Valid(values notifications.Values) error {
return nil
}
var Command = &commandLine{&notifications.Notification{ var Command = &commandLine{&notifications.Notification{
Method: "command", Method: "command",
Title: "Command", Title: "Command",

View File

@ -51,6 +51,10 @@ func (d *discord) Select() *notifications.Notification {
return d.Notification return d.Notification
} }
func (d *discord) Valid(values notifications.Values) error {
return nil
}
// OnFailure will trigger failing service // OnFailure will trigger failing service
func (d *discord) OnFailure(s services.Service, f failures.Failure) (string, error) { func (d *discord) OnFailure(s services.Service, f failures.Failure) (string, error) {
out, err := d.sendRequest(ReplaceVars(d.FailureData.String, s, f)) out, err := d.sendRequest(ReplaceVars(d.FailureData.String, s, f))

View File

@ -28,6 +28,10 @@ func (e *emailer) Select() *notifications.Notification {
return e.Notification return e.Notification
} }
func (e *emailer) Valid(values notifications.Values) error {
return nil
}
var email = &emailer{&notifications.Notification{ var email = &emailer{&notifications.Notification{
Method: "email", Method: "email",
Title: "SMTP Mail", Title: "SMTP Mail",

View File

@ -22,6 +22,10 @@ func (g *gotify) Select() *notifications.Notification {
return g.Notification return g.Notification
} }
func (g *gotify) Valid(values notifications.Values) error {
return nil
}
var Gotify = &gotify{&notifications.Notification{ var Gotify = &gotify{&notifications.Notification{
Method: "gotify", Method: "gotify",
Title: "Gotify", Title: "Gotify",

View File

@ -26,6 +26,10 @@ func (l *lineNotifier) Select() *notifications.Notification {
return l.Notification return l.Notification
} }
func (l *lineNotifier) Valid(values notifications.Values) error {
return nil
}
var LineNotify = &lineNotifier{&notifications.Notification{ var LineNotify = &lineNotifier{&notifications.Notification{
Method: lineNotifyMethod, Method: lineNotifyMethod,
Title: "LINE Notify", Title: "LINE Notify",

View File

@ -22,6 +22,10 @@ func (m *mobilePush) Select() *notifications.Notification {
return m.Notification return m.Notification
} }
func (m *mobilePush) Valid(values notifications.Values) error {
return nil
}
var Mobile = &mobilePush{&notifications.Notification{ var Mobile = &mobilePush{&notifications.Notification{
Method: "mobile", Method: "mobile",
Title: "Mobile", Title: "Mobile",

View File

@ -27,6 +27,10 @@ func (t *pushover) Select() *notifications.Notification {
return t.Notification return t.Notification
} }
func (t *pushover) Valid(values notifications.Values) error {
return nil
}
var Pushover = &pushover{&notifications.Notification{ var Pushover = &pushover{&notifications.Notification{
Method: "pushover", Method: "pushover",
Title: "Pushover", Title: "Pushover",

View File

@ -91,3 +91,7 @@ func (s *slack) OnSuccess(srv services.Service) (string, error) {
func (s *slack) OnSave() (string, error) { func (s *slack) OnSave() (string, error) {
return "", nil return "", nil
} }
func (s *slack) Valid(values notifications.Values) error {
return nil
}

View File

@ -27,6 +27,10 @@ func (s *statpingEmailer) Select() *notifications.Notification {
return s.Notification return s.Notification
} }
func (s *statpingEmailer) Valid(values notifications.Values) error {
return nil
}
var statpingMailer = &statpingEmailer{&notifications.Notification{ var statpingMailer = &statpingEmailer{&notifications.Notification{
Method: statpingEmailerName, Method: statpingEmailerName,
Title: "Email", Title: "Email",

View File

@ -25,6 +25,10 @@ func (t *telegram) Select() *notifications.Notification {
return t.Notification return t.Notification
} }
func (t *telegram) Valid(values notifications.Values) error {
return nil
}
var Telegram = &telegram{&notifications.Notification{ var Telegram = &telegram{&notifications.Notification{
Method: "telegram", Method: "telegram",
Title: "Telegram", Title: "Telegram",

View File

@ -26,6 +26,10 @@ func (t *twilio) Select() *notifications.Notification {
return t.Notification return t.Notification
} }
func (t *twilio) Valid(values notifications.Values) error {
return nil
}
var Twilio = &twilio{&notifications.Notification{ var Twilio = &twilio{&notifications.Notification{
Method: "twilio", Method: "twilio",
Title: "Twilio", Title: "Twilio",

View File

@ -80,6 +80,10 @@ func (w *webhooker) Select() *notifications.Notification {
return w.Notification return w.Notification
} }
func (w *webhooker) Valid(values notifications.Values) error {
return nil
}
func (w *webhooker) sendHttpWebhook(body string) (*http.Response, error) { func (w *webhooker) sendHttpWebhook(body string) (*http.Response, error) {
utils.Log.Infoln(fmt.Sprintf("sending body: '%v' to %v as a %v request", body, w.Host.String, w.Var1.String)) utils.Log.Infoln(fmt.Sprintf("sending body: '%v' to %v as a %v request", body, w.Host.String, w.Var1.String))
client := new(http.Client) client := new(http.Client)

View File

@ -48,6 +48,10 @@ func Select() (*Core, error) {
func (c *Core) Create() error { func (c *Core) Create() error {
if c.ApiSecret == "" { if c.ApiSecret == "" {
c.ApiSecret = utils.RandomString(16) c.ApiSecret = utils.RandomString(16)
apiEnv := utils.Params.GetString("API_SECRET")
if apiEnv != "" {
c.ApiSecret = apiEnv
}
} }
q := db.Create(c) q := db.Create(c)
utils.Log.Infof("API Key created: %s", c.ApiSecret) utils.Log.Infof("API Key created: %s", c.ApiSecret)

View File

@ -1,7 +1,6 @@
package notifications package notifications
import ( import (
"errors"
"github.com/statping/statping/database" "github.com/statping/statping/database"
) )
@ -16,11 +15,10 @@ func SetDB(database database.Database) {
func Find(method string) (*Notification, error) { func Find(method string) (*Notification, error) {
var n Notification var n Notification
q := db.Where("method = ?", method).Find(&n) q := db.Where("method = ?", method).Find(&n)
if &n == nil { if q.Error() != nil {
return nil, errors.New("cannot find notifier") return nil, q.Error()
} }
n.UpdateFields(&n) return &n, nil
return &n, q.Error()
} }
func (n *Notification) Create() error { func (n *Notification) Create() error {
@ -45,6 +43,7 @@ func (n *Notification) Create() error {
} }
func (n *Notification) UpdateFields(notif *Notification) *Notification { func (n *Notification) UpdateFields(notif *Notification) *Notification {
n.Id = notif.Id
n.Limits = notif.Limits n.Limits = notif.Limits
n.Enabled = notif.Enabled n.Enabled = notif.Enabled
n.Host = notif.Host n.Host = notif.Host

View File

@ -2,13 +2,9 @@ package notifications
import ( import (
"github.com/statping/statping/types/metrics" "github.com/statping/statping/types/metrics"
"github.com/statping/statping/utils"
) )
// AfterFind for Notification will set the timezone
func (n *Notification) AfterFind() (err error) { func (n *Notification) AfterFind() (err error) {
n.CreatedAt = utils.Now()
n.UpdatedAt = utils.Now()
metrics.Query("notifier", "find") metrics.Query("notifier", "find")
return return
} }

View File

@ -61,6 +61,17 @@ func (n *Notification) Logger() *logrus.Logger {
type RunFunc func(interface{}) error type RunFunc func(interface{}) error
type Values struct {
Host string
Port int64
Username string
Password string
Var1 string
Var2 string
ApiKey string
ApiSecret string
}
// NotificationForm contains the HTML fields for each variable/input you want the notifier to accept. // NotificationForm contains the HTML fields for each variable/input you want the notifier to accept.
type NotificationForm struct { type NotificationForm struct {
Type string `json:"type"` // the html input type (text, password, email) Type string `json:"type"` // the html input type (text, password, email)

View File

@ -20,7 +20,9 @@ func ReturnNotifier(method string) ServiceNotifier {
func FindNotifier(method string) *notifications.Notification { func FindNotifier(method string) *notifications.Notification {
n := allNotifiers[method] n := allNotifiers[method]
if n != nil { if n != nil {
return n.Select() notif := n.Select()
no, _ := notifications.Find(notif.Method)
return notif.UpdateFields(no)
} }
return nil return nil
} }
@ -31,4 +33,5 @@ type ServiceNotifier interface {
OnTest() (string, error) // OnTest is triggered for testing OnTest() (string, error) // OnTest is triggered for testing
OnSave() (string, error) // OnSave is triggered for testing OnSave() (string, error) // OnSave is triggered for testing
Select() *notifications.Notification // OnTest is triggered for testing Select() *notifications.Notification // OnTest is triggered for testing
Valid(notifications.Values) error // Valid checks your form values
} }

View File

@ -10,6 +10,7 @@ import (
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/hits" "github.com/statping/statping/types/hits"
"github.com/statping/statping/types/incidents" "github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -182,10 +183,11 @@ func startupDb(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
db, err := database.OpenTester() db, err := database.OpenTester()
require.Nil(t, err) require.Nil(t, err)
db.AutoMigrate(&Service{}, &hits.Hit{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &failures.Failure{}, &incidents.Incident{}, &incidents.IncidentUpdate{}) db.AutoMigrate(&Service{}, &notifications.Notification{}, &hits.Hit{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &failures.Failure{}, &incidents.Incident{}, &incidents.IncidentUpdate{})
checkins.SetDB(db) checkins.SetDB(db)
failures.SetDB(db) failures.SetDB(db)
incidents.SetDB(db) incidents.SetDB(db)
notifications.SetDB(db)
hits.SetDB(db) hits.SetDB(db)
SetDB(db) SetDB(db)
@ -198,6 +200,7 @@ func startupDb(t *testing.T) {
db.Create(&fail2) db.Create(&fail2)
db.Create(&incident1) db.Create(&incident1)
db.Create(&incidentUpdate1) db.Create(&incidentUpdate1)
db.Create(&incidentUpdate1)
} }
func TestServices(t *testing.T) { func TestServices(t *testing.T) {

View File

@ -322,3 +322,7 @@ func (e *exampleNotifier) OnTest() (string, error) {
e.tests++ e.tests++
return "", nil return "", nil
} }
func (e *exampleNotifier) Valid(form notifications.Values) error {
return nil
}