-
Go to OAuth Consent Screen on Google Console to create a new OAuth application.
+
Go to Slack Apps and create a new Application.
Slack Client ID
@@ -128,10 +132,17 @@
+
@@ -188,11 +199,12 @@
gh_orgs: "",
google_client_id: "",
google_client_secret: "",
- oauth_domains: "",
+ google_users: "",
oauth_providers: "",
slack_client_id: "",
slack_client_secret: "",
- slack_team: ""
+ slack_team: "",
+ slack_users: ""
}
}
},
diff --git a/handlers/oauth.go b/handlers/oauth.go
index 3a7f7149..ba27d012 100644
--- a/handlers/oauth.go
+++ b/handlers/oauth.go
@@ -6,17 +6,14 @@ import (
"github.com/statping/statping/types/core"
"github.com/statping/statping/types/null"
"github.com/statping/statping/types/users"
+ "golang.org/x/oauth2"
"net/http"
)
type oAuth struct {
- ID string
- Email string
- Username string
- Token string
- RefreshToken string
- Valid bool
- Type string
+ Email string
+ Username string
+ *oauth2.Token
}
func oauthHandler(w http.ResponseWriter, r *http.Request) {
@@ -51,9 +48,7 @@ func oauthLogin(oauth *oAuth, w http.ResponseWriter, r *http.Request) {
Admin: null.NewNullBool(true),
}
log.Infoln(fmt.Sprintf("OAuth %s User %s logged in from IP %s", oauth.Type, oauth.Email, r.RemoteAddr))
-
setJwtToken(user, w)
- //returnJson(user, w, r)
http.Redirect(w, r, core.App.Domain+"/dashboard", http.StatusPermanentRedirect)
}
diff --git a/handlers/oauth_github.go b/handlers/oauth_github.go
index 9a9ac856..d35d3117 100644
--- a/handlers/oauth_github.go
+++ b/handlers/oauth_github.go
@@ -13,12 +13,12 @@ import (
)
func githubOAuth(r *http.Request) (*oAuth, error) {
- c := *core.App
+ auth := core.App.OAuth
code := r.URL.Query().Get("code")
config := &oauth2.Config{
- ClientID: c.OAuth.GithubClientID,
- ClientSecret: c.OAuth.GithubClientSecret,
+ ClientID: auth.GithubClientID,
+ ClientSecret: auth.GithubClientSecret,
Endpoint: github.Endpoint,
}
@@ -27,6 +27,10 @@ func githubOAuth(r *http.Request) (*oAuth, error) {
return nil, err
}
+ if !gg.Valid() {
+ return nil, errors.New("oauth token is not valid")
+ }
+
user, err := returnGithubUser(gg.AccessToken)
if err != nil {
return nil, err
@@ -37,17 +41,14 @@ func githubOAuth(r *http.Request) (*oAuth, error) {
return nil, err
}
- if allowed := validateGithub(user, orgs); !allowed {
+ if !validateGithub(user, orgs) {
return nil, errors.New("github user is not allowed to login")
}
return &oAuth{
- Token: gg.AccessToken,
- RefreshToken: gg.RefreshToken,
- Valid: gg.Valid(),
- Username: strings.ToLower(user.Name),
- Email: strings.ToLower(user.Email),
- Type: "github",
+ Token: gg,
+ Username: strings.ToLower(user.Name),
+ Email: strings.ToLower(user.Email),
}, nil
}
diff --git a/handlers/oauth_google.go b/handlers/oauth_google.go
index fb231716..0f866fcf 100644
--- a/handlers/oauth_google.go
+++ b/handlers/oauth_google.go
@@ -1,20 +1,26 @@
package handlers
import (
+ "encoding/json"
"github.com/statping/statping/types/core"
+ "github.com/statping/statping/types/errors"
+ "github.com/statping/statping/utils"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"net/http"
+ "strings"
+ "time"
)
func googleOAuth(r *http.Request) (*oAuth, error) {
- c := core.App
+ auth := core.App.OAuth
code := r.URL.Query().Get("code")
config := &oauth2.Config{
- ClientID: c.OAuth.GoogleClientID,
- ClientSecret: c.OAuth.GoogleClientSecret,
+ ClientID: auth.GoogleClientID,
+ ClientSecret: auth.GoogleClientSecret,
Endpoint: google.Endpoint,
+ RedirectURL: core.App.Domain + "/oauth/google",
}
gg, err := config.Exchange(r.Context(), code)
@@ -22,9 +28,69 @@ func googleOAuth(r *http.Request) (*oAuth, error) {
return nil, err
}
+ if !gg.Valid() {
+ return nil, errors.New("oauth token is not valid")
+ }
+
+ info, err := returnGoogleInfo(gg.AccessToken)
+ if err != nil {
+ return nil, err
+ }
+
+ if !validateGoogle(info) {
+ return nil, errors.New("google user is not allowed to login")
+ }
+
return &oAuth{
- Token: gg.AccessToken,
- RefreshToken: gg.RefreshToken,
- Valid: gg.Valid(),
+ Token: gg,
+ Username: info.Name,
+ Email: info.Email,
}, nil
}
+
+func validateGoogle(info googleUserInfo) bool {
+ auth := core.App.OAuth
+ if auth.GoogleUsers == "" {
+ return true
+ }
+
+ if auth.GoogleUsers != "" {
+ users := strings.Split(auth.GoogleUsers, ",")
+ for _, u := range users {
+ if strings.ToLower(info.Email) == strings.ToLower(u) {
+ return true
+ }
+ if strings.ToLower(info.Hd) == strings.ToLower(u) {
+ return true
+ }
+ }
+ }
+
+ return false
+}
+
+func returnGoogleInfo(token string) (googleUserInfo, error) {
+ resp, _, err := utils.HttpRequest("https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token="+token, "GET", nil, nil, nil, 10*time.Second, true, nil)
+ if err != nil {
+ return googleUserInfo{}, err
+ }
+ var user googleUserInfo
+ if err := json.Unmarshal(resp, &user); err != nil {
+ return googleUserInfo{}, err
+ }
+ return user, nil
+}
+
+type googleUserInfo struct {
+ ID string `json:"id"`
+ Email string `json:"email"`
+ VerifiedEmail bool `json:"verified_email"`
+ Name string `json:"name"`
+ GivenName string `json:"given_name"`
+ FamilyName string `json:"family_name"`
+ Link string `json:"link"`
+ Picture string `json:"picture"`
+ Gender string `json:"gender"`
+ Locale string `json:"locale"`
+ Hd string `json:"hd"`
+}
diff --git a/handlers/oauth_slack.go b/handlers/oauth_slack.go
index 857065bf..bb482f88 100644
--- a/handlers/oauth_slack.go
+++ b/handlers/oauth_slack.go
@@ -9,18 +9,19 @@ import (
"golang.org/x/oauth2"
"golang.org/x/oauth2/slack"
"net/http"
+ "strings"
"time"
)
func slackOAuth(r *http.Request) (*oAuth, error) {
- c := core.App
+ auth := core.App.OAuth
code := r.URL.Query().Get("code")
config := &oauth2.Config{
- ClientID: c.OAuth.SlackClientID,
- ClientSecret: c.OAuth.SlackClientSecret,
+ ClientID: auth.SlackClientID,
+ ClientSecret: auth.SlackClientSecret,
Endpoint: slack.Endpoint,
- RedirectURL: c.Domain + basePath + "oauth/slack",
+ RedirectURL: core.App.Domain + basePath + "oauth/slack",
Scopes: []string{"identity.basic"},
}
@@ -29,11 +30,8 @@ func slackOAuth(r *http.Request) (*oAuth, error) {
return nil, err
}
- oauther := &oAuth{
- Token: gg.AccessToken,
- RefreshToken: gg.RefreshToken,
- Valid: gg.Valid(),
- Type: gg.Type(),
+ if !gg.Valid() {
+ return nil, errors.New("oauth token is not valid")
}
identity, err := returnSlackIdentity(gg.AccessToken)
@@ -45,10 +43,36 @@ func slackOAuth(r *http.Request) (*oAuth, error) {
return nil, errors.New("slack identity is invalid")
}
- oauther.Username = identity.User.Name
- oauther.Email = identity.User.Email
+ if !validateSlack(identity) {
+ return nil, errors.New("slack user is not whitelisted")
+ }
- return oauther, nil
+ return &oAuth{
+ Token: gg,
+ Username: strings.ToLower(identity.User.Name),
+ Email: strings.ToLower(identity.User.Email),
+ }, nil
+}
+
+func validateSlack(id slackIdentity) bool {
+ auth := core.App.OAuth
+ if auth.SlackUsers == "" {
+ return true
+ }
+
+ if auth.SlackUsers != "" {
+ users := strings.Split(auth.SlackUsers, ",")
+ for _, u := range users {
+ if strings.ToLower(u) == strings.ToLower(id.User.Email) {
+ return true
+ }
+ if strings.ToLower(u) == strings.ToLower(id.User.Name) {
+ return true
+ }
+ }
+ }
+
+ return false
}
// slackIdentity will query the Slack API to fetch the users ID, username, and email address.
diff --git a/notifiers/command.go b/notifiers/command.go
index 6e1e5c68..47a6ee4f 100644
--- a/notifiers/command.go
+++ b/notifiers/command.go
@@ -49,14 +49,14 @@ func runCommand(app string, cmd ...string) (string, string, error) {
}
// OnSuccess for commandLine will trigger successful service
-func (c *commandLine) OnSuccess(s *services.Service) (string, error) {
- tmpl := ReplaceVars(c.SuccessData, s, nil)
+func (c *commandLine) OnSuccess(s services.Service) (string, error) {
+ tmpl := ReplaceVars(c.SuccessData, s, failures.Failure{})
out, _, err := runCommand(c.Host, tmpl)
return out, err
}
// OnFailure for commandLine will trigger failing service
-func (c *commandLine) OnFailure(s *services.Service, f *failures.Failure) (string, error) {
+func (c *commandLine) OnFailure(s services.Service, f failures.Failure) (string, error) {
tmpl := ReplaceVars(c.FailureData, s, f)
_, ouerr, err := runCommand(c.Host, tmpl)
return ouerr, err
diff --git a/notifiers/command_test.go b/notifiers/command_test.go
index 4827e73f..b424fb65 100644
--- a/notifiers/command_test.go
+++ b/notifiers/command_test.go
@@ -2,6 +2,7 @@ package notifiers
import (
"github.com/statping/statping/database"
+ "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
@@ -21,6 +22,7 @@ func TestCommandNotifier(t *testing.T) {
require.Nil(t, err)
db.AutoMigrate(¬ifications.Notification{})
notifications.SetDB(db)
+ core.Example()
t.Run("Load Command", func(t *testing.T) {
Command.Host = "/bin/echo"
@@ -40,6 +42,11 @@ func TestCommandNotifier(t *testing.T) {
assert.True(t, Command.CanSend())
})
+ t.Run("Command OnSave", func(t *testing.T) {
+ _, err := Command.OnSave()
+ assert.Nil(t, err)
+ })
+
t.Run("Command OnFailure", func(t *testing.T) {
_, err := Command.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err)
diff --git a/notifiers/discord.go b/notifiers/discord.go
index 1e6b37f5..416ab57d 100644
--- a/notifiers/discord.go
+++ b/notifiers/discord.go
@@ -51,14 +51,14 @@ func (d *discord) Select() *notifications.Notification {
}
// 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, s, f))
return out, err
}
// OnSuccess will trigger successful service
-func (d *discord) OnSuccess(s *services.Service) (string, error) {
- out, err := d.sendRequest(ReplaceVars(d.SuccessData, s, nil))
+func (d *discord) OnSuccess(s services.Service) (string, error) {
+ out, err := d.sendRequest(ReplaceVars(d.SuccessData, s, failures.Failure{}))
return out, err
}
diff --git a/notifiers/discord_test.go b/notifiers/discord_test.go
index e1648ddc..7d33b3b1 100644
--- a/notifiers/discord_test.go
+++ b/notifiers/discord_test.go
@@ -2,6 +2,7 @@ package notifiers
import (
"github.com/statping/statping/database"
+ "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
@@ -26,6 +27,7 @@ func TestDiscordNotifier(t *testing.T) {
require.Nil(t, err)
db.AutoMigrate(¬ifications.Notification{})
notifications.SetDB(db)
+ core.Example()
if DISCORD_URL == "" {
t.Log("discord notifier testing skipped, missing DISCORD_URL environment variable")
@@ -47,6 +49,11 @@ func TestDiscordNotifier(t *testing.T) {
assert.True(t, Discorder.CanSend())
})
+ t.Run("discord Notifier Tester OnSave", func(t *testing.T) {
+ _, err := Discorder.OnSave()
+ assert.Nil(t, err)
+ })
+
t.Run("discord OnFailure", func(t *testing.T) {
_, err := Discorder.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err)
diff --git a/notifiers/email.go b/notifiers/email.go
index 37c1a291..d3ec0461 100644
--- a/notifiers/email.go
+++ b/notifiers/email.go
@@ -86,7 +86,7 @@ type emailOutgoing struct {
}
// OnFailure will trigger failing service
-func (e *emailer) OnFailure(s *services.Service, f *failures.Failure) (string, error) {
+func (e *emailer) OnFailure(s services.Service, f failures.Failure) (string, error) {
subject := fmt.Sprintf("Service %s is Offline", s.Name)
tmpl := renderEmail(s, f)
email := &emailOutgoing{
@@ -99,9 +99,9 @@ func (e *emailer) OnFailure(s *services.Service, f *failures.Failure) (string, e
}
// OnSuccess will trigger successful service
-func (e *emailer) OnSuccess(s *services.Service) (string, error) {
+func (e *emailer) OnSuccess(s services.Service) (string, error) {
subject := fmt.Sprintf("Service %s is Back Online", s.Name)
- tmpl := renderEmail(s, nil)
+ tmpl := renderEmail(s, failures.Failure{})
email := &emailOutgoing{
To: e.Var2,
Subject: subject,
@@ -111,7 +111,7 @@ func (e *emailer) OnSuccess(s *services.Service) (string, error) {
return tmpl, e.dialSend(email)
}
-func renderEmail(s *services.Service, f *failures.Failure) string {
+func renderEmail(s services.Service, f failures.Failure) string {
wr := bytes.NewBuffer(nil)
tmpl := template.New("email")
tmpl, err := tmpl.Parse(emailBase)
@@ -121,7 +121,7 @@ func renderEmail(s *services.Service, f *failures.Failure) string {
}
data := replacer{
- Core: core.App,
+ Core: *core.App,
Service: s,
Failure: f,
Custom: nil,
diff --git a/notifiers/email_test.go b/notifiers/email_test.go
index 8c00cd3d..cbcec63e 100644
--- a/notifiers/email_test.go
+++ b/notifiers/email_test.go
@@ -2,6 +2,7 @@ package notifiers
import (
"github.com/statping/statping/database"
+ "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
@@ -37,6 +38,7 @@ func TestEmailNotifier(t *testing.T) {
require.Nil(t, err)
db.AutoMigrate(¬ifications.Notification{})
notifications.SetDB(db)
+ core.Example()
if EMAIL_HOST == "" || EMAIL_USER == "" || EMAIL_PASS == "" {
t.Log("email notifier testing skipped, missing EMAIL_ environment variables")
@@ -63,6 +65,11 @@ func TestEmailNotifier(t *testing.T) {
assert.True(t, ok)
})
+ t.Run("email OnSave", func(t *testing.T) {
+ _, err := email.OnSave()
+ assert.Nil(t, err)
+ })
+
t.Run("email OnFailure", func(t *testing.T) {
_, err := email.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err)
diff --git a/notifiers/line_notify.go b/notifiers/line_notify.go
index b432517d..37d0908d 100644
--- a/notifiers/line_notify.go
+++ b/notifiers/line_notify.go
@@ -52,14 +52,14 @@ func (l *lineNotifier) sendMessage(message string) (string, error) {
}
// OnFailure will trigger failing service
-func (l *lineNotifier) OnFailure(s *services.Service, f *failures.Failure) (string, error) {
- msg := fmt.Sprintf("Your service '%v' is currently offline!", s.Name)
+func (l *lineNotifier) OnFailure(s services.Service, f failures.Failure) (string, error) {
+ msg := fmt.Sprintf("Your service '%v' is currently offline! %s", s.Name, f.Issue)
out, err := l.sendMessage(msg)
return out, err
}
// OnSuccess will trigger successful service
-func (l *lineNotifier) OnSuccess(s *services.Service) (string, error) {
+func (l *lineNotifier) OnSuccess(s services.Service) (string, error) {
msg := fmt.Sprintf("Service %s is online!", s.Name)
out, err := l.sendMessage(msg)
return out, err
diff --git a/notifiers/mobile.go b/notifiers/mobile.go
index ab05d80f..d3664642 100644
--- a/notifiers/mobile.go
+++ b/notifiers/mobile.go
@@ -47,19 +47,14 @@ var Mobile = &mobilePush{¬ifications.Notification{
}}},
}
-func dataJson(s *services.Service, f *failures.Failure) map[string]interface{} {
+func dataJson(s services.Service, f failures.Failure) map[string]interface{} {
serviceId := "0"
- if s != nil {
- serviceId = utils.ToString(s.Id)
- }
+ serviceId = utils.ToString(s.Id)
online := "online"
if !s.Online {
online = "offline"
}
- issue := ""
- if f != nil {
- issue = f.Issue
- }
+ issue := f.Issue
link := fmt.Sprintf("statping://service?id=%v", serviceId)
out := map[string]interface{}{
"status": online,
@@ -71,7 +66,7 @@ func dataJson(s *services.Service, f *failures.Failure) map[string]interface{} {
}
// OnFailure will trigger failing service
-func (m *mobilePush) OnFailure(s *services.Service, f *failures.Failure) (string, error) {
+func (m *mobilePush) OnFailure(s services.Service, f failures.Failure) (string, error) {
data := dataJson(s, f)
msg := &pushArray{
Message: fmt.Sprintf("Your service '%v' is currently failing! Reason: %v", s.Name, f.Issue),
@@ -82,8 +77,8 @@ func (m *mobilePush) OnFailure(s *services.Service, f *failures.Failure) (string
}
// OnSuccess will trigger successful service
-func (m *mobilePush) OnSuccess(s *services.Service) (string, error) {
- data := dataJson(s, nil)
+func (m *mobilePush) OnSuccess(s services.Service) (string, error) {
+ data := dataJson(s, failures.Failure{})
msg := &pushArray{
Message: "Service is Online!",
Title: "Service Online",
diff --git a/notifiers/mobile_test.go b/notifiers/mobile_test.go
index ac358327..5268e1e9 100644
--- a/notifiers/mobile_test.go
+++ b/notifiers/mobile_test.go
@@ -2,6 +2,7 @@ package notifiers
import (
"github.com/statping/statping/database"
+ "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
@@ -29,6 +30,7 @@ func TestMobileNotifier(t *testing.T) {
require.Nil(t, err)
db.AutoMigrate(¬ifications.Notification{})
notifications.SetDB(db)
+ core.Example()
Mobile.Var1 = mobileToken
if mobileToken == "" {
@@ -52,6 +54,11 @@ func TestMobileNotifier(t *testing.T) {
assert.True(t, Mobile.CanSend())
})
+ t.Run("Mobile OnSave", func(t *testing.T) {
+ _, err := Mobile.OnSave()
+ assert.Nil(t, err)
+ })
+
t.Run("Mobile OnFailure", func(t *testing.T) {
_, err := Mobile.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err)
diff --git a/notifiers/notifiers.go b/notifiers/notifiers.go
index 4ba59fb2..d1a74a26 100644
--- a/notifiers/notifiers.go
+++ b/notifiers/notifiers.go
@@ -13,9 +13,9 @@ import (
var log = utils.Log.WithField("type", "notifier")
type replacer struct {
- Core *core.Core
- Service *services.Service
- Failure *failures.Failure
+ Core core.Core
+ Service services.Service
+ Failure failures.Failure
Custom map[string]string
}
@@ -59,8 +59,8 @@ func Add(notifs ...services.ServiceNotifier) {
}
}
-func ReplaceVars(input string, s *services.Service, f *failures.Failure) string {
- return ReplaceTemplate(input, replacer{Service: s, Failure: f, Core: core.App})
+func ReplaceVars(input string, s services.Service, f failures.Failure) string {
+ return ReplaceTemplate(input, replacer{Service: s, Failure: f, Core: *core.App})
}
var exampleFailure = &failures.Failure{
diff --git a/notifiers/pushover.go b/notifiers/pushover.go
index 1f295e13..623eb0fd 100644
--- a/notifiers/pushover.go
+++ b/notifiers/pushover.go
@@ -81,7 +81,7 @@ func priority(val string) string {
case "emergency":
return "2"
default:
- return "1"
+ return "0"
}
}
@@ -105,15 +105,15 @@ func (t *pushover) sendMessage(message string) (string, error) {
}
// OnFailure will trigger failing service
-func (t *pushover) OnFailure(s *services.Service, f *failures.Failure) (string, error) {
+func (t *pushover) OnFailure(s services.Service, f failures.Failure) (string, error) {
message := ReplaceVars(t.FailureData, s, f)
out, err := t.sendMessage(message)
return out, err
}
// OnSuccess will trigger successful service
-func (t *pushover) OnSuccess(s *services.Service) (string, error) {
- message := ReplaceVars(t.SuccessData, s, nil)
+func (t *pushover) OnSuccess(s services.Service) (string, error) {
+ message := ReplaceVars(t.SuccessData, s, failures.Failure{})
out, err := t.sendMessage(message)
return out, err
}
diff --git a/notifiers/pushover_test.go b/notifiers/pushover_test.go
index 58a52ddd..aea799c0 100644
--- a/notifiers/pushover_test.go
+++ b/notifiers/pushover_test.go
@@ -2,6 +2,7 @@ package notifiers
import (
"github.com/statping/statping/database"
+ "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
@@ -28,6 +29,7 @@ func TestPushoverNotifier(t *testing.T) {
require.Nil(t, err)
db.AutoMigrate(¬ifications.Notification{})
notifications.SetDB(db)
+ core.Example()
if PUSHOVER_TOKEN == "" || PUSHOVER_API == "" {
t.Log("Pushover notifier testing skipped, missing PUSHOVER_TOKEN and PUSHOVER_API environment variable")
@@ -37,6 +39,8 @@ func TestPushoverNotifier(t *testing.T) {
t.Run("Load Pushover", func(t *testing.T) {
Pushover.ApiKey = PUSHOVER_TOKEN
Pushover.ApiSecret = PUSHOVER_API
+ Pushover.Var1 = "Normal"
+ Pushover.Var2 = "vibrate"
Pushover.Enabled = null.NewNullBool(true)
Add(Pushover)
@@ -50,6 +54,11 @@ func TestPushoverNotifier(t *testing.T) {
assert.True(t, Pushover.CanSend())
})
+ t.Run("Pushover OnSave", func(t *testing.T) {
+ _, err := Pushover.OnSave()
+ assert.Nil(t, err)
+ })
+
t.Run("Pushover OnFailure", func(t *testing.T) {
_, err := Pushover.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err)
diff --git a/notifiers/slack.go b/notifiers/slack.go
index 3c9eae3a..8b1bfdd7 100644
--- a/notifiers/slack.go
+++ b/notifiers/slack.go
@@ -61,7 +61,7 @@ func (s *slack) sendSlack(msg string) (string, error) {
func (s *slack) OnTest() (string, error) {
example := services.Example(true)
- testMsg := ReplaceVars(s.SuccessData, example, nil)
+ testMsg := ReplaceVars(s.SuccessData, example, failures.Failure{})
contents, resp, err := utils.HttpRequest(s.Host, "POST", "application/json", nil, bytes.NewBuffer([]byte(testMsg)), time.Duration(10*time.Second), true, nil)
if err != nil {
return "", err
@@ -74,15 +74,15 @@ func (s *slack) OnTest() (string, error) {
}
// OnFailure will trigger failing service
-func (s *slack) OnFailure(srv *services.Service, f *failures.Failure) (string, error) {
+func (s *slack) OnFailure(srv services.Service, f failures.Failure) (string, error) {
msg := ReplaceVars(s.FailureData, srv, f)
out, err := s.sendSlack(msg)
return out, err
}
// OnSuccess will trigger successful service
-func (s *slack) OnSuccess(srv *services.Service) (string, error) {
- msg := ReplaceVars(s.SuccessData, srv, nil)
+func (s *slack) OnSuccess(srv services.Service) (string, error) {
+ msg := ReplaceVars(s.SuccessData, srv, failures.Failure{})
out, err := s.sendSlack(msg)
return out, err
}
diff --git a/notifiers/slack_test.go b/notifiers/slack_test.go
index ea21a093..cc05def5 100644
--- a/notifiers/slack_test.go
+++ b/notifiers/slack_test.go
@@ -2,6 +2,7 @@ package notifiers
import (
"github.com/statping/statping/database"
+ "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
@@ -24,6 +25,7 @@ func TestSlackNotifier(t *testing.T) {
require.Nil(t, err)
db.AutoMigrate(¬ifications.Notification{})
notifications.SetDB(db)
+ core.Example()
SLACK_URL = utils.Params.GetString("SLACK_URL")
slacker.Host = SLACK_URL
@@ -48,6 +50,11 @@ func TestSlackNotifier(t *testing.T) {
assert.True(t, ok)
})
+ t.Run("slack OnSave", func(t *testing.T) {
+ _, err := slacker.OnSave()
+ assert.Nil(t, err)
+ })
+
t.Run("slack OnFailure", func(t *testing.T) {
_, err := slacker.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err)
diff --git a/notifiers/statping_emailer.go b/notifiers/statping_emailer.go
index 444ee92c..81208f20 100644
--- a/notifiers/statping_emailer.go
+++ b/notifiers/statping_emailer.go
@@ -60,17 +60,17 @@ func (s *statpingEmailer) OnTest() (string, error) {
}
type statpingMail struct {
- Email string `json:"email"`
- Core *core.Core `json:"core,omitempty"`
- Service *services.Service `json:"service,omitempty"`
- Failure *failures.Failure `json:"failure,omitempty"`
+ Email string `json:"email"`
+ Core core.Core `json:"core,omitempty"`
+ Service services.Service `json:"service,omitempty"`
+ Failure failures.Failure `json:"failure,omitempty"`
}
// OnFailure will trigger failing service
-func (s *statpingEmailer) OnFailure(srv *services.Service, f *failures.Failure) (string, error) {
+func (s *statpingEmailer) OnFailure(srv services.Service, f failures.Failure) (string, error) {
ee := statpingMail{
Email: s.Host,
- Core: core.App,
+ Core: *core.App,
Service: srv,
Failure: f,
}
@@ -78,12 +78,12 @@ func (s *statpingEmailer) OnFailure(srv *services.Service, f *failures.Failure)
}
// OnSuccess will trigger successful service
-func (s *statpingEmailer) OnSuccess(srv *services.Service) (string, error) {
+func (s *statpingEmailer) OnSuccess(srv services.Service) (string, error) {
ee := statpingMail{
Email: s.Host,
- Core: core.App,
+ Core: *core.App,
Service: srv,
- Failure: nil,
+ Failure: failures.Failure{},
}
return s.sendStatpingEmail(ee)
}
@@ -92,9 +92,9 @@ func (s *statpingEmailer) OnSuccess(srv *services.Service) (string, error) {
func (s *statpingEmailer) OnSave() (string, error) {
ee := statpingMail{
Email: s.Host,
- Core: core.App,
- Service: nil,
- Failure: nil,
+ Core: *core.App,
+ Service: services.Service{},
+ Failure: failures.Failure{},
}
out, err := s.sendStatpingEmail(ee)
log.Println("statping emailer response", out)
diff --git a/notifiers/statping_emailer_test.go b/notifiers/statping_emailer_test.go
index 7155cf24..76ebf05f 100644
--- a/notifiers/statping_emailer_test.go
+++ b/notifiers/statping_emailer_test.go
@@ -2,6 +2,7 @@ package notifiers
import (
"github.com/statping/statping/database"
+ "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
@@ -24,6 +25,7 @@ func TestStatpingEmailerNotifier(t *testing.T) {
require.Nil(t, err)
db.AutoMigrate(¬ifications.Notification{})
notifications.SetDB(db)
+ core.Example()
testEmail = utils.Params.GetString("TEST_EMAIL")
statpingMailer.Host = testEmail
@@ -48,6 +50,11 @@ func TestStatpingEmailerNotifier(t *testing.T) {
assert.True(t, ok)
})
+ t.Run("statping emailer OnSave", func(t *testing.T) {
+ _, err := statpingMailer.OnSave()
+ assert.Nil(t, err)
+ })
+
t.Run("statping emailer OnFailure", func(t *testing.T) {
_, err := statpingMailer.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err)
diff --git a/notifiers/telegram.go b/notifiers/telegram.go
index bd53cb29..e7ce4c0d 100644
--- a/notifiers/telegram.go
+++ b/notifiers/telegram.go
@@ -74,15 +74,15 @@ func (t *telegram) sendMessage(message string) (string, error) {
}
// OnFailure will trigger failing service
-func (t *telegram) OnFailure(s *services.Service, f *failures.Failure) (string, error) {
+func (t *telegram) OnFailure(s services.Service, f failures.Failure) (string, error) {
msg := ReplaceVars(t.FailureData, s, f)
out, err := t.sendMessage(msg)
return out, err
}
// OnSuccess will trigger successful service
-func (t *telegram) OnSuccess(s *services.Service) (string, error) {
- msg := ReplaceVars(t.SuccessData, s, nil)
+func (t *telegram) OnSuccess(s services.Service) (string, error) {
+ msg := ReplaceVars(t.SuccessData, s, failures.Failure{})
out, err := t.sendMessage(msg)
return out, err
}
diff --git a/notifiers/telegram_test.go b/notifiers/telegram_test.go
index 571dbd0b..b7895975 100644
--- a/notifiers/telegram_test.go
+++ b/notifiers/telegram_test.go
@@ -2,6 +2,7 @@ package notifiers
import (
"github.com/statping/statping/database"
+ "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
@@ -31,6 +32,7 @@ func TestTelegramNotifier(t *testing.T) {
require.Nil(t, err)
db.AutoMigrate(¬ifications.Notification{})
notifications.SetDB(db)
+ core.Example()
if telegramToken == "" || telegramChannel == "" {
t.Log("Telegram notifier testing skipped, missing TELEGRAM_TOKEN and TELEGRAM_CHANNEL environment variable")
@@ -54,6 +56,11 @@ func TestTelegramNotifier(t *testing.T) {
assert.True(t, Telegram.CanSend())
})
+ t.Run("Telegram OnSave", func(t *testing.T) {
+ _, err := Telegram.OnSave()
+ assert.Nil(t, err)
+ })
+
t.Run("Telegram OnFailure", func(t *testing.T) {
_, err := Telegram.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err)
diff --git a/notifiers/twilio.go b/notifiers/twilio.go
index 2892fd1b..ec46d21a 100644
--- a/notifiers/twilio.go
+++ b/notifiers/twilio.go
@@ -90,14 +90,14 @@ func (t *twilio) sendMessage(message string) (string, error) {
}
// OnFailure will trigger failing service
-func (t *twilio) OnFailure(s *services.Service, f *failures.Failure) (string, error) {
+func (t *twilio) OnFailure(s services.Service, f failures.Failure) (string, error) {
msg := ReplaceVars(t.FailureData, s, f)
return t.sendMessage(msg)
}
// OnSuccess will trigger successful service
-func (t *twilio) OnSuccess(s *services.Service) (string, error) {
- msg := ReplaceVars(t.SuccessData, s, nil)
+func (t *twilio) OnSuccess(s services.Service) (string, error) {
+ msg := ReplaceVars(t.SuccessData, s, failures.Failure{})
return t.sendMessage(msg)
}
diff --git a/notifiers/twilio_test.go b/notifiers/twilio_test.go
index d12a8bfe..f7195811 100644
--- a/notifiers/twilio_test.go
+++ b/notifiers/twilio_test.go
@@ -2,6 +2,7 @@ package notifiers
import (
"github.com/statping/statping/database"
+ "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
@@ -29,6 +30,7 @@ func TestTwilioNotifier(t *testing.T) {
require.Nil(t, err)
db.AutoMigrate(¬ifications.Notification{})
notifications.SetDB(db)
+ core.Example()
if TWILIO_SID == "" || TWILIO_SECRET == "" {
t.Log("twilio notifier testing skipped, missing TWILIO_SID and TWILIO_SECRET environment variable")
@@ -54,6 +56,11 @@ func TestTwilioNotifier(t *testing.T) {
assert.True(t, Twilio.CanSend())
})
+ t.Run("Twilio OnSave", func(t *testing.T) {
+ _, err := Twilio.OnSave()
+ assert.Nil(t, err)
+ })
+
t.Run("Twilio OnFailure", func(t *testing.T) {
_, err := Twilio.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err)
diff --git a/notifiers/webhook.go b/notifiers/webhook.go
index b1ff300d..8f3d520c 100644
--- a/notifiers/webhook.go
+++ b/notifiers/webhook.go
@@ -127,7 +127,7 @@ func (w *webhooker) OnTest() (string, error) {
}
// OnFailure will trigger failing service
-func (w *webhooker) OnFailure(s *services.Service, f *failures.Failure) (string, error) {
+func (w *webhooker) OnFailure(s services.Service, f failures.Failure) (string, error) {
msg := ReplaceVars(w.FailureData, s, f)
resp, err := w.sendHttpWebhook(msg)
if err != nil {
@@ -139,8 +139,8 @@ func (w *webhooker) OnFailure(s *services.Service, f *failures.Failure) (string,
}
// OnSuccess will trigger successful service
-func (w *webhooker) OnSuccess(s *services.Service) (string, error) {
- msg := ReplaceVars(w.SuccessData, s, nil)
+func (w *webhooker) OnSuccess(s services.Service) (string, error) {
+ msg := ReplaceVars(w.SuccessData, s, failures.Failure{})
resp, err := w.sendHttpWebhook(msg)
if err != nil {
return "", err
diff --git a/notifiers/webhook_test.go b/notifiers/webhook_test.go
index eb5fcbfa..bb70d8bc 100644
--- a/notifiers/webhook_test.go
+++ b/notifiers/webhook_test.go
@@ -2,6 +2,7 @@ package notifiers
import (
"github.com/statping/statping/database"
+ "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
@@ -27,6 +28,7 @@ func TestWebhookNotifier(t *testing.T) {
require.Nil(t, err)
db.AutoMigrate(¬ifications.Notification{})
notifications.SetDB(db)
+ core.Example()
t.Run("Load webhooker", func(t *testing.T) {
Webhook.Host = webhookTestUrl
@@ -46,6 +48,11 @@ func TestWebhookNotifier(t *testing.T) {
assert.True(t, Webhook.CanSend())
})
+ t.Run("webhooker OnSave", func(t *testing.T) {
+ _, err := Webhook.OnSave()
+ assert.Nil(t, err)
+ })
+
t.Run("webhooker OnFailure", func(t *testing.T) {
_, err := Webhook.OnFailure(services.Example(false), failures.Example())
assert.Nil(t, err)
diff --git a/types/core/samples.go b/types/core/samples.go
index f11cb798..700cc848 100644
--- a/types/core/samples.go
+++ b/types/core/samples.go
@@ -5,6 +5,22 @@ import (
"github.com/statping/statping/utils"
)
+func Example() *Core {
+ core := &Core{
+ Name: "Statping Testing",
+ Description: "This is a instance that runs for tests",
+ ApiSecret: "exampleapisecret",
+ Domain: "http://localhost:8080",
+ CreatedAt: utils.Now(),
+ UseCdn: null.NewNullBool(false),
+ Footer: null.NewNullString(""),
+ MigrationId: utils.Now().Unix(),
+ Language: "en",
+ }
+ App = core
+ return App
+}
+
func Samples() error {
apiSecret := utils.Params.GetString("API_SECRET")
diff --git a/types/core/struct.go b/types/core/struct.go
index 88d51a13..fdcc6c50 100644
--- a/types/core/struct.go
+++ b/types/core/struct.go
@@ -43,7 +43,6 @@ type Core struct {
}
type OAuth struct {
- Domains string `gorm:"column:oauth_domains" json:"oauth_domains" scope:"admin"`
Providers string `gorm:"column:oauth_providers;" json:"oauth_providers"`
GithubClientID string `gorm:"column:gh_client_id" json:"gh_client_id"`
GithubClientSecret string `gorm:"column:gh_client_secret" json:"gh_client_secret" scope:"admin"`
@@ -55,6 +54,7 @@ type OAuth struct {
SlackClientID string `gorm:"column:slack_client_id" json:"slack_client_id"`
SlackClientSecret string `gorm:"column:slack_client_secret" json:"slack_client_secret" scope:"admin"`
SlackTeam string `gorm:"column:slack_team" json:"slack_team" scope:"admin"`
+ SlackUsers string `gorm:"column:slack_users" json:"slack_users" scope:"admin"`
}
// AllNotifiers contains all the Notifiers loaded
diff --git a/types/failures/samples.go b/types/failures/samples.go
index 57fa4737..cd03f296 100644
--- a/types/failures/samples.go
+++ b/types/failures/samples.go
@@ -12,8 +12,8 @@ var (
log = utils.Log.WithField("type", "failure")
)
-func Example() *Failure {
- return &Failure{
+func Example() Failure {
+ return Failure{
Id: 48533,
Issue: "Response did not response a 200 status code",
Method: "",
diff --git a/types/notifications/methods.go b/types/notifications/methods.go
index 71c82337..b17b12ea 100644
--- a/types/notifications/methods.go
+++ b/types/notifications/methods.go
@@ -7,16 +7,15 @@ import (
"time"
)
-func (n *Notification) Name() string {
+func (n Notification) Name() string {
newName := strings.ToLower(n.Method)
newName = strings.ReplaceAll(newName, " ", "_")
return newName
}
// LastSent returns a time.Duration of the last sent notification for the notifier
-func (n *Notification) LastSent() time.Duration {
- since := time.Since(n.lastSent)
- return since
+func (n Notification) LastSent() time.Duration {
+ return time.Since(n.lastSent)
}
func (n *Notification) CanSend() bool {
diff --git a/types/notifier/interface.go b/types/notifier/interface.go
index 405bb927..2f84d2d0 100644
--- a/types/notifier/interface.go
+++ b/types/notifier/interface.go
@@ -7,8 +7,8 @@ import (
// Notifier interface is required to create a new Notifier
type Notifier interface {
- OnSuccess(*services.Service) (string, error) // OnSuccess is triggered when a service is successful
- OnFailure(*services.Service, *failures.Failure) (string, error) // OnFailure is triggered when a service is failing
- OnTest() (string, error) // OnTest is triggered for testing
- OnSave() (string, error) // OnSave is triggered for when saved
+ OnSuccess(services.Service) (string, error) // OnSuccess is triggered when a service is successful
+ OnFailure(services.Service, failures.Failure) (string, error) // OnFailure is triggered when a service is failing
+ OnTest() (string, error) // OnTest is triggered for testing
+ OnSave() (string, error) // OnSave is triggered for when saved
}
diff --git a/types/services/failures.go b/types/services/failures.go
index d670f58a..36027249 100644
--- a/types/services/failures.go
+++ b/types/services/failures.go
@@ -20,15 +20,14 @@ func (s *Service) FailuresSince(t time.Time) failures.Failurer {
return failures.Since(t, s)
}
-func (s *Service) DowntimeAgo() string {
- last := s.LastOnline
- if last.IsZero() {
+func (s Service) DowntimeAgo() string {
+ if s.LastOnline.IsZero() {
return "Never been online"
}
- return humanize.Time(last)
+ return humanize.Time(s.LastOnline)
}
-func (s *Service) DowntimeText() string {
+func (s Service) DowntimeText() string {
last := s.AllFailures().Last()
if last == nil {
return ""
diff --git a/types/services/methods.go b/types/services/methods.go
index 60132b72..54ee3bff 100644
--- a/types/services/methods.go
+++ b/types/services/methods.go
@@ -61,12 +61,12 @@ func (s *Service) LoadTLSCert() (*tls.Config, error) {
return config, nil
}
-func (s *Service) Duration() time.Duration {
+func (s Service) Duration() time.Duration {
return time.Duration(s.Interval) * time.Second
}
// Start will create a channel for the service checking go routine
-func (s *Service) UptimeData(hits []*hits.Hit, fails []*failures.Failure) (*UptimeSeries, error) {
+func (s Service) UptimeData(hits []*hits.Hit, fails []*failures.Failure) (*UptimeSeries, error) {
if len(hits) == 0 {
return nil, errors.New("service does not have any successful hits")
}
@@ -291,12 +291,12 @@ func (s *Service) UpdateStats() *Service {
}
// AvgTime will return the average amount of time for a service to response back successfully
-func (s *Service) AvgTime() int64 {
+func (s Service) AvgTime() int64 {
return s.AllHits().Avg()
}
// OnlineDaysPercent returns the service's uptime percent within last 24 hours
-func (s *Service) OnlineDaysPercent(days int) float32 {
+func (s Service) OnlineDaysPercent(days int) float32 {
ago := utils.Now().Add(-time.Duration(days) * types.Day)
return s.OnlineSince(ago)
}
@@ -326,12 +326,12 @@ func (s *Service) OnlineSince(ago time.Time) float32 {
return s.Online24Hours
}
-func (s *Service) Uptime() utils.Duration {
+func (s Service) Uptime() utils.Duration {
return utils.Duration{Duration: utils.Now().Sub(s.LastOffline)}
}
// Downtime returns the amount of time of a offline service
-func (s *Service) Downtime() utils.Duration {
+func (s Service) Downtime() utils.Duration {
return utils.Duration{Duration: utils.Now().Sub(s.LastOnline)}
}
diff --git a/types/services/notifier.go b/types/services/notifier.go
index 5a822078..a51b9a62 100644
--- a/types/services/notifier.go
+++ b/types/services/notifier.go
@@ -26,9 +26,9 @@ func FindNotifier(method string) *notifications.Notification {
}
type ServiceNotifier interface {
- OnSuccess(*Service) (string, error) // OnSuccess is triggered when a service is successful
- OnFailure(*Service, *failures.Failure) (string, error) // OnFailure is triggered when a service is failing
- OnTest() (string, error) // OnTest is triggered for testing
- OnSave() (string, error) // OnSave is triggered for testing
- Select() *notifications.Notification // OnTest is triggered for testing
+ OnSuccess(Service) (string, error) // OnSuccess is triggered when a service is successful
+ OnFailure(Service, failures.Failure) (string, error) // OnFailure is triggered when a service is failing
+ OnTest() (string, error) // OnTest is triggered for testing
+ OnSave() (string, error) // OnSave is triggered for testing
+ Select() *notifications.Notification // OnTest is triggered for testing
}
diff --git a/types/services/routine.go b/types/services/routine.go
index 30eb2b8d..db70dea0 100644
--- a/types/services/routine.go
+++ b/types/services/routine.go
@@ -353,7 +353,7 @@ func sendSuccess(s *Service) {
notif := n.Select()
if notif.CanSend() {
log.Infof("Sending notification to: %s!", notif.Method)
- if _, err := n.OnSuccess(s); err != nil {
+ if _, err := n.OnSuccess(*s); err != nil {
notif.Logger().Errorln(err)
}
s.UserNotified = true
@@ -405,7 +405,7 @@ func sendFailure(s *Service, f *failures.Failure) {
notif := n.Select()
if notif.CanSend() {
log.Infof("Sending Failure notification to: %s!", notif.Method)
- if _, err := n.OnFailure(s, f); err != nil {
+ if _, err := n.OnFailure(*s, *f); err != nil {
notif.Logger().WithField("failure", f.Issue).Errorln(err)
}
s.UserNotified = true
diff --git a/types/services/samples.go b/types/services/samples.go
index aaed0904..c979ac8c 100644
--- a/types/services/samples.go
+++ b/types/services/samples.go
@@ -6,8 +6,8 @@ import (
"time"
)
-func Example(online bool) *Service {
- return &Service{
+func Example(online bool) Service {
+ return Service{
Id: 6283,
Name: "Statping Example",
Domain: "https://statping.com",