mirror of https://github.com/statping/statping
oauth Google fixes, google oauth restrict users based on domain and/or email address, notifiers no dereference pointer for services and failure
parent
ea23865494
commit
202695ba20
|
@ -7,6 +7,10 @@
|
||||||
- Added error if Theme Editor returns an error from API
|
- Added error if Theme Editor returns an error from API
|
||||||
- Added Pushover priority and sounds
|
- Added Pushover priority and sounds
|
||||||
- Added HTTP headers for outgoing requests (includes User-Agent=Statping and Statping-Version=0.90.55)
|
- Added HTTP headers for outgoing requests (includes User-Agent=Statping and Statping-Version=0.90.55)
|
||||||
|
- Fixed Google oAuth handling
|
||||||
|
- Added Google oAuth email/domain user restrictions
|
||||||
|
- Modified notifiers to use dereferenced services and failures
|
||||||
|
- Added core.Example() function for testing
|
||||||
|
|
||||||
# 0.90.55 (06-18-2020)
|
# 0.90.55 (06-18-2020)
|
||||||
- Added 404 page
|
- Added 404 page
|
||||||
|
|
|
@ -4,20 +4,15 @@
|
||||||
<div class="card-header">Internal Login</div>
|
<div class="card-header">Internal Login</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="switch-gh-oauth" class="col-sm-4 col-form-label">OAuth Login Settings</label>
|
<label for="switch-gh-oauth" class="col-sm-6 col-form-label">Statping Authentication</label>
|
||||||
<div class="col-md-8 col-xs-12 mt-1">
|
<div class="col-md-6 col-xs-12 mt-1">
|
||||||
<span @click="local_enabled = !!local_enabled" class="switch float-left">
|
<span @click="local_enabled = !!local_enabled" class="switch float-left">
|
||||||
<input v-model="local_enabled" type="checkbox" class="switch" id="switch-local-oauth" :checked="local_enabled">
|
<input v-model="local_enabled" type="checkbox" class="switch" id="switch-local-oauth" :checked="local_enabled">
|
||||||
<label for="switch-local-oauth">Use email/password Authentication</label>
|
<label for="switch-local-oauth"></label>
|
||||||
|
<span class="small d-block">Use email/password Authentication</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group row">
|
|
||||||
<label for="whitelist_domains" class="col-sm-4 col-form-label">Whitelist Domains</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input v-model="oauth.oauth_domains" type="text" class="form-control" placeholder="domain.com" id="whitelist_domains">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card text-black-50 bg-white mb-3">
|
<div class="card text-black-50 bg-white mb-3">
|
||||||
|
@ -37,6 +32,20 @@
|
||||||
<input v-model="oauth.gh_client_secret" type="text" class="form-control" id="github_secret" required>
|
<input v-model="oauth.gh_client_secret" type="text" class="form-control" id="github_secret" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="github_secret" class="col-sm-4 col-form-label">Restrict Users</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input v-model="oauth.gh_users" type="text" class="form-control" id="github_users" placeholder="octocat,hunterlong,jimbo123">
|
||||||
|
<small>Optional comma delimited list of usernames</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="github_secret" class="col-sm-4 col-form-label">Restrict Organizations</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input v-model="oauth.gh_orgs" type="text" class="form-control" id="github_orgs" placeholder="statping,github">
|
||||||
|
<small>Optional comma delimited list of Github Organizations</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="switch-gh-oauth" class="col-sm-4 col-form-label">Enable Github Login</label>
|
<label for="switch-gh-oauth" class="col-sm-4 col-form-label">Enable Github Login</label>
|
||||||
<div class="col-md-8 col-xs-12 mt-1">
|
<div class="col-md-8 col-xs-12 mt-1">
|
||||||
|
@ -46,18 +55,6 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group row">
|
|
||||||
<label for="github_secret" class="col-sm-4 col-form-label">Github Restrict Users</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input v-model="oauth.gh_users" type="text" class="form-control" id="github_users">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group row">
|
|
||||||
<label for="github_secret" class="col-sm-4 col-form-label">Github Restrict Organizations</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input v-model="oauth.gh_orgs" type="text" class="form-control" id="github_orgs">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="gh_callback" class="col-sm-4 col-form-label">Callback URL</label>
|
<label for="gh_callback" class="col-sm-4 col-form-label">Callback URL</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
|
@ -74,7 +71,7 @@
|
||||||
<div class="card text-black-50 bg-white mb-3">
|
<div class="card text-black-50 bg-white mb-3">
|
||||||
<div class="card-header">Google Settings</div>
|
<div class="card-header">Google Settings</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<span>Go to <a href="https://console.cloud.google.com/apis/credentials">OAuth Consent Screen</a> on Google Console to create a new OAuth application.</span>
|
<span>Go to <a href="https://console.cloud.google.com/apis/credentials">OAuth Consent Screen</a> on Google Console to create a new "Web Application" OAuth application. </span>
|
||||||
|
|
||||||
<div class="form-group row mt-3">
|
<div class="form-group row mt-3">
|
||||||
<label for="github_client" class="col-sm-4 col-form-label">Google Client ID</label>
|
<label for="github_client" class="col-sm-4 col-form-label">Google Client ID</label>
|
||||||
|
@ -88,6 +85,13 @@
|
||||||
<input v-model="oauth.google_client_secret" type="text" class="form-control" id="google_secret" required>
|
<input v-model="oauth.google_client_secret" type="text" class="form-control" id="google_secret" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="github_secret" class="col-sm-4 col-form-label">Restrict Users</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input v-model="oauth.google_users" type="text" class="form-control" id="google_users" placeholder="info@gmail.com,example.com">
|
||||||
|
<small>Optional comma delimited list of emails and/or domains</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="switch-google-oauth" class="col-sm-4 col-form-label">Enable Google Login</label>
|
<label for="switch-google-oauth" class="col-sm-4 col-form-label">Enable Google Login</label>
|
||||||
<div class="col-md-8 col-xs-12 mt-1">
|
<div class="col-md-8 col-xs-12 mt-1">
|
||||||
|
@ -113,7 +117,7 @@
|
||||||
<div class="card text-black-50 bg-white mb-3">
|
<div class="card text-black-50 bg-white mb-3">
|
||||||
<div class="card-header">Slack Settings</div>
|
<div class="card-header">Slack Settings</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<span>Go to <a href="https://console.cloud.google.com/apis/credentials">OAuth Consent Screen</a> on Google Console to create a new OAuth application.</span>
|
<span>Go to <a href="https://api.slack.com/apps">Slack Apps</a> and create a new Application.</span>
|
||||||
|
|
||||||
<div class="form-group row mt-3">
|
<div class="form-group row mt-3">
|
||||||
<label for="slack_client" class="col-sm-4 col-form-label">Slack Client ID</label>
|
<label for="slack_client" class="col-sm-4 col-form-label">Slack Client ID</label>
|
||||||
|
@ -128,10 +132,17 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="slack_secret" class="col-sm-4 col-form-label">Slack Team ID</label>
|
<label for="slack_secret" class="col-sm-4 col-form-label">Team ID</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<input v-model="oauth.slack_team" type="text" class="form-control" id="slack_team">
|
<input v-model="oauth.slack_team" type="text" class="form-control" id="slack_team">
|
||||||
<small>Optional</small>
|
<small>Optional Slack Team ID</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="slack_secret" class="col-sm-4 col-form-label">Restrict Users</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input v-model="oauth.slack_users" type="text" class="form-control" id="slack_users" placeholder="info@example.com,info@domain.net">
|
||||||
|
<small>Optional comma delimited list of email addresses</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
|
@ -188,11 +199,12 @@
|
||||||
gh_orgs: "",
|
gh_orgs: "",
|
||||||
google_client_id: "",
|
google_client_id: "",
|
||||||
google_client_secret: "",
|
google_client_secret: "",
|
||||||
oauth_domains: "",
|
google_users: "",
|
||||||
oauth_providers: "",
|
oauth_providers: "",
|
||||||
slack_client_id: "",
|
slack_client_id: "",
|
||||||
slack_client_secret: "",
|
slack_client_secret: "",
|
||||||
slack_team: ""
|
slack_team: "",
|
||||||
|
slack_users: ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,17 +6,14 @@ import (
|
||||||
"github.com/statping/statping/types/core"
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
"github.com/statping/statping/types/users"
|
"github.com/statping/statping/types/users"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type oAuth struct {
|
type oAuth struct {
|
||||||
ID string
|
Email string
|
||||||
Email string
|
Username string
|
||||||
Username string
|
*oauth2.Token
|
||||||
Token string
|
|
||||||
RefreshToken string
|
|
||||||
Valid bool
|
|
||||||
Type string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func oauthHandler(w http.ResponseWriter, r *http.Request) {
|
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),
|
Admin: null.NewNullBool(true),
|
||||||
}
|
}
|
||||||
log.Infoln(fmt.Sprintf("OAuth %s User %s logged in from IP %s", oauth.Type, oauth.Email, r.RemoteAddr))
|
log.Infoln(fmt.Sprintf("OAuth %s User %s logged in from IP %s", oauth.Type, oauth.Email, r.RemoteAddr))
|
||||||
|
|
||||||
setJwtToken(user, w)
|
setJwtToken(user, w)
|
||||||
|
|
||||||
//returnJson(user, w, r)
|
|
||||||
http.Redirect(w, r, core.App.Domain+"/dashboard", http.StatusPermanentRedirect)
|
http.Redirect(w, r, core.App.Domain+"/dashboard", http.StatusPermanentRedirect)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func githubOAuth(r *http.Request) (*oAuth, error) {
|
func githubOAuth(r *http.Request) (*oAuth, error) {
|
||||||
c := *core.App
|
auth := core.App.OAuth
|
||||||
code := r.URL.Query().Get("code")
|
code := r.URL.Query().Get("code")
|
||||||
|
|
||||||
config := &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
ClientID: c.OAuth.GithubClientID,
|
ClientID: auth.GithubClientID,
|
||||||
ClientSecret: c.OAuth.GithubClientSecret,
|
ClientSecret: auth.GithubClientSecret,
|
||||||
Endpoint: github.Endpoint,
|
Endpoint: github.Endpoint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,10 @@ func githubOAuth(r *http.Request) (*oAuth, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !gg.Valid() {
|
||||||
|
return nil, errors.New("oauth token is not valid")
|
||||||
|
}
|
||||||
|
|
||||||
user, err := returnGithubUser(gg.AccessToken)
|
user, err := returnGithubUser(gg.AccessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -37,17 +41,14 @@ func githubOAuth(r *http.Request) (*oAuth, error) {
|
||||||
return nil, err
|
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 nil, errors.New("github user is not allowed to login")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &oAuth{
|
return &oAuth{
|
||||||
Token: gg.AccessToken,
|
Token: gg,
|
||||||
RefreshToken: gg.RefreshToken,
|
Username: strings.ToLower(user.Name),
|
||||||
Valid: gg.Valid(),
|
Email: strings.ToLower(user.Email),
|
||||||
Username: strings.ToLower(user.Name),
|
|
||||||
Email: strings.ToLower(user.Email),
|
|
||||||
Type: "github",
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,26 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"github.com/statping/statping/types/core"
|
"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"
|
||||||
"golang.org/x/oauth2/google"
|
"golang.org/x/oauth2/google"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func googleOAuth(r *http.Request) (*oAuth, error) {
|
func googleOAuth(r *http.Request) (*oAuth, error) {
|
||||||
c := core.App
|
auth := core.App.OAuth
|
||||||
code := r.URL.Query().Get("code")
|
code := r.URL.Query().Get("code")
|
||||||
|
|
||||||
config := &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
ClientID: c.OAuth.GoogleClientID,
|
ClientID: auth.GoogleClientID,
|
||||||
ClientSecret: c.OAuth.GoogleClientSecret,
|
ClientSecret: auth.GoogleClientSecret,
|
||||||
Endpoint: google.Endpoint,
|
Endpoint: google.Endpoint,
|
||||||
|
RedirectURL: core.App.Domain + "/oauth/google",
|
||||||
}
|
}
|
||||||
|
|
||||||
gg, err := config.Exchange(r.Context(), code)
|
gg, err := config.Exchange(r.Context(), code)
|
||||||
|
@ -22,9 +28,69 @@ func googleOAuth(r *http.Request) (*oAuth, error) {
|
||||||
return nil, err
|
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{
|
return &oAuth{
|
||||||
Token: gg.AccessToken,
|
Token: gg,
|
||||||
RefreshToken: gg.RefreshToken,
|
Username: info.Name,
|
||||||
Valid: gg.Valid(),
|
Email: info.Email,
|
||||||
}, nil
|
}, 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"`
|
||||||
|
}
|
||||||
|
|
|
@ -9,18 +9,19 @@ import (
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
"golang.org/x/oauth2/slack"
|
"golang.org/x/oauth2/slack"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func slackOAuth(r *http.Request) (*oAuth, error) {
|
func slackOAuth(r *http.Request) (*oAuth, error) {
|
||||||
c := core.App
|
auth := core.App.OAuth
|
||||||
code := r.URL.Query().Get("code")
|
code := r.URL.Query().Get("code")
|
||||||
|
|
||||||
config := &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
ClientID: c.OAuth.SlackClientID,
|
ClientID: auth.SlackClientID,
|
||||||
ClientSecret: c.OAuth.SlackClientSecret,
|
ClientSecret: auth.SlackClientSecret,
|
||||||
Endpoint: slack.Endpoint,
|
Endpoint: slack.Endpoint,
|
||||||
RedirectURL: c.Domain + basePath + "oauth/slack",
|
RedirectURL: core.App.Domain + basePath + "oauth/slack",
|
||||||
Scopes: []string{"identity.basic"},
|
Scopes: []string{"identity.basic"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,11 +30,8 @@ func slackOAuth(r *http.Request) (*oAuth, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
oauther := &oAuth{
|
if !gg.Valid() {
|
||||||
Token: gg.AccessToken,
|
return nil, errors.New("oauth token is not valid")
|
||||||
RefreshToken: gg.RefreshToken,
|
|
||||||
Valid: gg.Valid(),
|
|
||||||
Type: gg.Type(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
identity, err := returnSlackIdentity(gg.AccessToken)
|
identity, err := returnSlackIdentity(gg.AccessToken)
|
||||||
|
@ -45,10 +43,36 @@ func slackOAuth(r *http.Request) (*oAuth, error) {
|
||||||
return nil, errors.New("slack identity is invalid")
|
return nil, errors.New("slack identity is invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
oauther.Username = identity.User.Name
|
if !validateSlack(identity) {
|
||||||
oauther.Email = identity.User.Email
|
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.
|
// slackIdentity will query the Slack API to fetch the users ID, username, and email address.
|
||||||
|
|
|
@ -49,14 +49,14 @@ func runCommand(app string, cmd ...string) (string, string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess for commandLine will trigger successful service
|
// OnSuccess for commandLine will trigger successful service
|
||||||
func (c *commandLine) OnSuccess(s *services.Service) (string, error) {
|
func (c *commandLine) OnSuccess(s services.Service) (string, error) {
|
||||||
tmpl := ReplaceVars(c.SuccessData, s, nil)
|
tmpl := ReplaceVars(c.SuccessData, s, failures.Failure{})
|
||||||
out, _, err := runCommand(c.Host, tmpl)
|
out, _, err := runCommand(c.Host, tmpl)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure for commandLine will trigger failing service
|
// 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)
|
tmpl := ReplaceVars(c.FailureData, s, f)
|
||||||
_, ouerr, err := runCommand(c.Host, tmpl)
|
_, ouerr, err := runCommand(c.Host, tmpl)
|
||||||
return ouerr, err
|
return ouerr, err
|
||||||
|
|
|
@ -2,6 +2,7 @@ package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/notifications"
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
|
@ -21,6 +22,7 @@ func TestCommandNotifier(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db.AutoMigrate(¬ifications.Notification{})
|
db.AutoMigrate(¬ifications.Notification{})
|
||||||
notifications.SetDB(db)
|
notifications.SetDB(db)
|
||||||
|
core.Example()
|
||||||
|
|
||||||
t.Run("Load Command", func(t *testing.T) {
|
t.Run("Load Command", func(t *testing.T) {
|
||||||
Command.Host = "/bin/echo"
|
Command.Host = "/bin/echo"
|
||||||
|
@ -40,6 +42,11 @@ func TestCommandNotifier(t *testing.T) {
|
||||||
assert.True(t, Command.CanSend())
|
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) {
|
t.Run("Command OnFailure", func(t *testing.T) {
|
||||||
_, err := Command.OnFailure(services.Example(false), failures.Example())
|
_, err := Command.OnFailure(services.Example(false), failures.Example())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -51,14 +51,14 @@ func (d *discord) Select() *notifications.Notification {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, s, f))
|
out, err := d.sendRequest(ReplaceVars(d.FailureData, s, f))
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (d *discord) OnSuccess(s *services.Service) (string, error) {
|
func (d *discord) OnSuccess(s services.Service) (string, error) {
|
||||||
out, err := d.sendRequest(ReplaceVars(d.SuccessData, s, nil))
|
out, err := d.sendRequest(ReplaceVars(d.SuccessData, s, failures.Failure{}))
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/notifications"
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
|
@ -26,6 +27,7 @@ func TestDiscordNotifier(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db.AutoMigrate(¬ifications.Notification{})
|
db.AutoMigrate(¬ifications.Notification{})
|
||||||
notifications.SetDB(db)
|
notifications.SetDB(db)
|
||||||
|
core.Example()
|
||||||
|
|
||||||
if DISCORD_URL == "" {
|
if DISCORD_URL == "" {
|
||||||
t.Log("discord notifier testing skipped, missing DISCORD_URL environment variable")
|
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())
|
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) {
|
t.Run("discord OnFailure", func(t *testing.T) {
|
||||||
_, err := Discorder.OnFailure(services.Example(false), failures.Example())
|
_, err := Discorder.OnFailure(services.Example(false), failures.Example())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -86,7 +86,7 @@ type emailOutgoing struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// 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)
|
subject := fmt.Sprintf("Service %s is Offline", s.Name)
|
||||||
tmpl := renderEmail(s, f)
|
tmpl := renderEmail(s, f)
|
||||||
email := &emailOutgoing{
|
email := &emailOutgoing{
|
||||||
|
@ -99,9 +99,9 @@ func (e *emailer) OnFailure(s *services.Service, f *failures.Failure) (string, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// 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)
|
subject := fmt.Sprintf("Service %s is Back Online", s.Name)
|
||||||
tmpl := renderEmail(s, nil)
|
tmpl := renderEmail(s, failures.Failure{})
|
||||||
email := &emailOutgoing{
|
email := &emailOutgoing{
|
||||||
To: e.Var2,
|
To: e.Var2,
|
||||||
Subject: subject,
|
Subject: subject,
|
||||||
|
@ -111,7 +111,7 @@ func (e *emailer) OnSuccess(s *services.Service) (string, error) {
|
||||||
return tmpl, e.dialSend(email)
|
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)
|
wr := bytes.NewBuffer(nil)
|
||||||
tmpl := template.New("email")
|
tmpl := template.New("email")
|
||||||
tmpl, err := tmpl.Parse(emailBase)
|
tmpl, err := tmpl.Parse(emailBase)
|
||||||
|
@ -121,7 +121,7 @@ func renderEmail(s *services.Service, f *failures.Failure) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
data := replacer{
|
data := replacer{
|
||||||
Core: core.App,
|
Core: *core.App,
|
||||||
Service: s,
|
Service: s,
|
||||||
Failure: f,
|
Failure: f,
|
||||||
Custom: nil,
|
Custom: nil,
|
||||||
|
|
|
@ -2,6 +2,7 @@ package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/notifications"
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
|
@ -37,6 +38,7 @@ func TestEmailNotifier(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db.AutoMigrate(¬ifications.Notification{})
|
db.AutoMigrate(¬ifications.Notification{})
|
||||||
notifications.SetDB(db)
|
notifications.SetDB(db)
|
||||||
|
core.Example()
|
||||||
|
|
||||||
if EMAIL_HOST == "" || EMAIL_USER == "" || EMAIL_PASS == "" {
|
if EMAIL_HOST == "" || EMAIL_USER == "" || EMAIL_PASS == "" {
|
||||||
t.Log("email notifier testing skipped, missing EMAIL_ environment variables")
|
t.Log("email notifier testing skipped, missing EMAIL_ environment variables")
|
||||||
|
@ -63,6 +65,11 @@ func TestEmailNotifier(t *testing.T) {
|
||||||
assert.True(t, ok)
|
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) {
|
t.Run("email OnFailure", func(t *testing.T) {
|
||||||
_, err := email.OnFailure(services.Example(false), failures.Example())
|
_, err := email.OnFailure(services.Example(false), failures.Example())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -52,14 +52,14 @@ func (l *lineNotifier) sendMessage(message string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// OnFailure will trigger failing service
|
||||||
func (l *lineNotifier) OnFailure(s *services.Service, f *failures.Failure) (string, error) {
|
func (l *lineNotifier) OnFailure(s services.Service, f failures.Failure) (string, error) {
|
||||||
msg := fmt.Sprintf("Your service '%v' is currently offline!", s.Name)
|
msg := fmt.Sprintf("Your service '%v' is currently offline! %s", s.Name, f.Issue)
|
||||||
out, err := l.sendMessage(msg)
|
out, err := l.sendMessage(msg)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// 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)
|
msg := fmt.Sprintf("Service %s is online!", s.Name)
|
||||||
out, err := l.sendMessage(msg)
|
out, err := l.sendMessage(msg)
|
||||||
return out, err
|
return out, err
|
||||||
|
|
|
@ -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"
|
serviceId := "0"
|
||||||
if s != nil {
|
serviceId = utils.ToString(s.Id)
|
||||||
serviceId = utils.ToString(s.Id)
|
|
||||||
}
|
|
||||||
online := "online"
|
online := "online"
|
||||||
if !s.Online {
|
if !s.Online {
|
||||||
online = "offline"
|
online = "offline"
|
||||||
}
|
}
|
||||||
issue := ""
|
issue := f.Issue
|
||||||
if f != nil {
|
|
||||||
issue = f.Issue
|
|
||||||
}
|
|
||||||
link := fmt.Sprintf("statping://service?id=%v", serviceId)
|
link := fmt.Sprintf("statping://service?id=%v", serviceId)
|
||||||
out := map[string]interface{}{
|
out := map[string]interface{}{
|
||||||
"status": online,
|
"status": online,
|
||||||
|
@ -71,7 +66,7 @@ func dataJson(s *services.Service, f *failures.Failure) map[string]interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// 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)
|
data := dataJson(s, f)
|
||||||
msg := &pushArray{
|
msg := &pushArray{
|
||||||
Message: fmt.Sprintf("Your service '%v' is currently failing! Reason: %v", s.Name, f.Issue),
|
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
|
// OnSuccess will trigger successful service
|
||||||
func (m *mobilePush) OnSuccess(s *services.Service) (string, error) {
|
func (m *mobilePush) OnSuccess(s services.Service) (string, error) {
|
||||||
data := dataJson(s, nil)
|
data := dataJson(s, failures.Failure{})
|
||||||
msg := &pushArray{
|
msg := &pushArray{
|
||||||
Message: "Service is Online!",
|
Message: "Service is Online!",
|
||||||
Title: "Service Online",
|
Title: "Service Online",
|
||||||
|
|
|
@ -2,6 +2,7 @@ package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/notifications"
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
|
@ -29,6 +30,7 @@ func TestMobileNotifier(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db.AutoMigrate(¬ifications.Notification{})
|
db.AutoMigrate(¬ifications.Notification{})
|
||||||
notifications.SetDB(db)
|
notifications.SetDB(db)
|
||||||
|
core.Example()
|
||||||
|
|
||||||
Mobile.Var1 = mobileToken
|
Mobile.Var1 = mobileToken
|
||||||
if mobileToken == "" {
|
if mobileToken == "" {
|
||||||
|
@ -52,6 +54,11 @@ func TestMobileNotifier(t *testing.T) {
|
||||||
assert.True(t, Mobile.CanSend())
|
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) {
|
t.Run("Mobile OnFailure", func(t *testing.T) {
|
||||||
_, err := Mobile.OnFailure(services.Example(false), failures.Example())
|
_, err := Mobile.OnFailure(services.Example(false), failures.Example())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -13,9 +13,9 @@ import (
|
||||||
var log = utils.Log.WithField("type", "notifier")
|
var log = utils.Log.WithField("type", "notifier")
|
||||||
|
|
||||||
type replacer struct {
|
type replacer struct {
|
||||||
Core *core.Core
|
Core core.Core
|
||||||
Service *services.Service
|
Service services.Service
|
||||||
Failure *failures.Failure
|
Failure failures.Failure
|
||||||
Custom map[string]string
|
Custom map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +59,8 @@ func Add(notifs ...services.ServiceNotifier) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReplaceVars(input string, s *services.Service, f *failures.Failure) string {
|
func ReplaceVars(input string, s services.Service, f failures.Failure) string {
|
||||||
return ReplaceTemplate(input, replacer{Service: s, Failure: f, Core: core.App})
|
return ReplaceTemplate(input, replacer{Service: s, Failure: f, Core: *core.App})
|
||||||
}
|
}
|
||||||
|
|
||||||
var exampleFailure = &failures.Failure{
|
var exampleFailure = &failures.Failure{
|
||||||
|
|
|
@ -81,7 +81,7 @@ func priority(val string) string {
|
||||||
case "emergency":
|
case "emergency":
|
||||||
return "2"
|
return "2"
|
||||||
default:
|
default:
|
||||||
return "1"
|
return "0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,15 +105,15 @@ func (t *pushover) sendMessage(message string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// 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)
|
message := ReplaceVars(t.FailureData, s, f)
|
||||||
out, err := t.sendMessage(message)
|
out, err := t.sendMessage(message)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (t *pushover) OnSuccess(s *services.Service) (string, error) {
|
func (t *pushover) OnSuccess(s services.Service) (string, error) {
|
||||||
message := ReplaceVars(t.SuccessData, s, nil)
|
message := ReplaceVars(t.SuccessData, s, failures.Failure{})
|
||||||
out, err := t.sendMessage(message)
|
out, err := t.sendMessage(message)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/notifications"
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
|
@ -28,6 +29,7 @@ func TestPushoverNotifier(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db.AutoMigrate(¬ifications.Notification{})
|
db.AutoMigrate(¬ifications.Notification{})
|
||||||
notifications.SetDB(db)
|
notifications.SetDB(db)
|
||||||
|
core.Example()
|
||||||
|
|
||||||
if PUSHOVER_TOKEN == "" || PUSHOVER_API == "" {
|
if PUSHOVER_TOKEN == "" || PUSHOVER_API == "" {
|
||||||
t.Log("Pushover notifier testing skipped, missing PUSHOVER_TOKEN and PUSHOVER_API environment variable")
|
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) {
|
t.Run("Load Pushover", func(t *testing.T) {
|
||||||
Pushover.ApiKey = PUSHOVER_TOKEN
|
Pushover.ApiKey = PUSHOVER_TOKEN
|
||||||
Pushover.ApiSecret = PUSHOVER_API
|
Pushover.ApiSecret = PUSHOVER_API
|
||||||
|
Pushover.Var1 = "Normal"
|
||||||
|
Pushover.Var2 = "vibrate"
|
||||||
Pushover.Enabled = null.NewNullBool(true)
|
Pushover.Enabled = null.NewNullBool(true)
|
||||||
|
|
||||||
Add(Pushover)
|
Add(Pushover)
|
||||||
|
@ -50,6 +54,11 @@ func TestPushoverNotifier(t *testing.T) {
|
||||||
assert.True(t, Pushover.CanSend())
|
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) {
|
t.Run("Pushover OnFailure", func(t *testing.T) {
|
||||||
_, err := Pushover.OnFailure(services.Example(false), failures.Example())
|
_, err := Pushover.OnFailure(services.Example(false), failures.Example())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -61,7 +61,7 @@ func (s *slack) sendSlack(msg string) (string, error) {
|
||||||
|
|
||||||
func (s *slack) OnTest() (string, error) {
|
func (s *slack) OnTest() (string, error) {
|
||||||
example := services.Example(true)
|
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)
|
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 {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -74,15 +74,15 @@ func (s *slack) OnTest() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// 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)
|
msg := ReplaceVars(s.FailureData, srv, f)
|
||||||
out, err := s.sendSlack(msg)
|
out, err := s.sendSlack(msg)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (s *slack) OnSuccess(srv *services.Service) (string, error) {
|
func (s *slack) OnSuccess(srv services.Service) (string, error) {
|
||||||
msg := ReplaceVars(s.SuccessData, srv, nil)
|
msg := ReplaceVars(s.SuccessData, srv, failures.Failure{})
|
||||||
out, err := s.sendSlack(msg)
|
out, err := s.sendSlack(msg)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/notifications"
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
|
@ -24,6 +25,7 @@ func TestSlackNotifier(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db.AutoMigrate(¬ifications.Notification{})
|
db.AutoMigrate(¬ifications.Notification{})
|
||||||
notifications.SetDB(db)
|
notifications.SetDB(db)
|
||||||
|
core.Example()
|
||||||
|
|
||||||
SLACK_URL = utils.Params.GetString("SLACK_URL")
|
SLACK_URL = utils.Params.GetString("SLACK_URL")
|
||||||
slacker.Host = SLACK_URL
|
slacker.Host = SLACK_URL
|
||||||
|
@ -48,6 +50,11 @@ func TestSlackNotifier(t *testing.T) {
|
||||||
assert.True(t, ok)
|
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) {
|
t.Run("slack OnFailure", func(t *testing.T) {
|
||||||
_, err := slacker.OnFailure(services.Example(false), failures.Example())
|
_, err := slacker.OnFailure(services.Example(false), failures.Example())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -60,17 +60,17 @@ func (s *statpingEmailer) OnTest() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type statpingMail struct {
|
type statpingMail struct {
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Core *core.Core `json:"core,omitempty"`
|
Core core.Core `json:"core,omitempty"`
|
||||||
Service *services.Service `json:"service,omitempty"`
|
Service services.Service `json:"service,omitempty"`
|
||||||
Failure *failures.Failure `json:"failure,omitempty"`
|
Failure failures.Failure `json:"failure,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// 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{
|
ee := statpingMail{
|
||||||
Email: s.Host,
|
Email: s.Host,
|
||||||
Core: core.App,
|
Core: *core.App,
|
||||||
Service: srv,
|
Service: srv,
|
||||||
Failure: f,
|
Failure: f,
|
||||||
}
|
}
|
||||||
|
@ -78,12 +78,12 @@ func (s *statpingEmailer) OnFailure(srv *services.Service, f *failures.Failure)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// 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{
|
ee := statpingMail{
|
||||||
Email: s.Host,
|
Email: s.Host,
|
||||||
Core: core.App,
|
Core: *core.App,
|
||||||
Service: srv,
|
Service: srv,
|
||||||
Failure: nil,
|
Failure: failures.Failure{},
|
||||||
}
|
}
|
||||||
return s.sendStatpingEmail(ee)
|
return s.sendStatpingEmail(ee)
|
||||||
}
|
}
|
||||||
|
@ -92,9 +92,9 @@ func (s *statpingEmailer) OnSuccess(srv *services.Service) (string, error) {
|
||||||
func (s *statpingEmailer) OnSave() (string, error) {
|
func (s *statpingEmailer) OnSave() (string, error) {
|
||||||
ee := statpingMail{
|
ee := statpingMail{
|
||||||
Email: s.Host,
|
Email: s.Host,
|
||||||
Core: core.App,
|
Core: *core.App,
|
||||||
Service: nil,
|
Service: services.Service{},
|
||||||
Failure: nil,
|
Failure: failures.Failure{},
|
||||||
}
|
}
|
||||||
out, err := s.sendStatpingEmail(ee)
|
out, err := s.sendStatpingEmail(ee)
|
||||||
log.Println("statping emailer response", out)
|
log.Println("statping emailer response", out)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/notifications"
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
|
@ -24,6 +25,7 @@ func TestStatpingEmailerNotifier(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db.AutoMigrate(¬ifications.Notification{})
|
db.AutoMigrate(¬ifications.Notification{})
|
||||||
notifications.SetDB(db)
|
notifications.SetDB(db)
|
||||||
|
core.Example()
|
||||||
|
|
||||||
testEmail = utils.Params.GetString("TEST_EMAIL")
|
testEmail = utils.Params.GetString("TEST_EMAIL")
|
||||||
statpingMailer.Host = testEmail
|
statpingMailer.Host = testEmail
|
||||||
|
@ -48,6 +50,11 @@ func TestStatpingEmailerNotifier(t *testing.T) {
|
||||||
assert.True(t, ok)
|
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) {
|
t.Run("statping emailer OnFailure", func(t *testing.T) {
|
||||||
_, err := statpingMailer.OnFailure(services.Example(false), failures.Example())
|
_, err := statpingMailer.OnFailure(services.Example(false), failures.Example())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -74,15 +74,15 @@ func (t *telegram) sendMessage(message string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// 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)
|
msg := ReplaceVars(t.FailureData, s, f)
|
||||||
out, err := t.sendMessage(msg)
|
out, err := t.sendMessage(msg)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (t *telegram) OnSuccess(s *services.Service) (string, error) {
|
func (t *telegram) OnSuccess(s services.Service) (string, error) {
|
||||||
msg := ReplaceVars(t.SuccessData, s, nil)
|
msg := ReplaceVars(t.SuccessData, s, failures.Failure{})
|
||||||
out, err := t.sendMessage(msg)
|
out, err := t.sendMessage(msg)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/notifications"
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
|
@ -31,6 +32,7 @@ func TestTelegramNotifier(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db.AutoMigrate(¬ifications.Notification{})
|
db.AutoMigrate(¬ifications.Notification{})
|
||||||
notifications.SetDB(db)
|
notifications.SetDB(db)
|
||||||
|
core.Example()
|
||||||
|
|
||||||
if telegramToken == "" || telegramChannel == "" {
|
if telegramToken == "" || telegramChannel == "" {
|
||||||
t.Log("Telegram notifier testing skipped, missing TELEGRAM_TOKEN and TELEGRAM_CHANNEL environment variable")
|
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())
|
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) {
|
t.Run("Telegram OnFailure", func(t *testing.T) {
|
||||||
_, err := Telegram.OnFailure(services.Example(false), failures.Example())
|
_, err := Telegram.OnFailure(services.Example(false), failures.Example())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -90,14 +90,14 @@ func (t *twilio) sendMessage(message string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// 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)
|
msg := ReplaceVars(t.FailureData, s, f)
|
||||||
return t.sendMessage(msg)
|
return t.sendMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (t *twilio) OnSuccess(s *services.Service) (string, error) {
|
func (t *twilio) OnSuccess(s services.Service) (string, error) {
|
||||||
msg := ReplaceVars(t.SuccessData, s, nil)
|
msg := ReplaceVars(t.SuccessData, s, failures.Failure{})
|
||||||
return t.sendMessage(msg)
|
return t.sendMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/notifications"
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
|
@ -29,6 +30,7 @@ func TestTwilioNotifier(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db.AutoMigrate(¬ifications.Notification{})
|
db.AutoMigrate(¬ifications.Notification{})
|
||||||
notifications.SetDB(db)
|
notifications.SetDB(db)
|
||||||
|
core.Example()
|
||||||
|
|
||||||
if TWILIO_SID == "" || TWILIO_SECRET == "" {
|
if TWILIO_SID == "" || TWILIO_SECRET == "" {
|
||||||
t.Log("twilio notifier testing skipped, missing TWILIO_SID and TWILIO_SECRET environment variable")
|
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())
|
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) {
|
t.Run("Twilio OnFailure", func(t *testing.T) {
|
||||||
_, err := Twilio.OnFailure(services.Example(false), failures.Example())
|
_, err := Twilio.OnFailure(services.Example(false), failures.Example())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -127,7 +127,7 @@ func (w *webhooker) OnTest() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// 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)
|
msg := ReplaceVars(w.FailureData, s, f)
|
||||||
resp, err := w.sendHttpWebhook(msg)
|
resp, err := w.sendHttpWebhook(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -139,8 +139,8 @@ func (w *webhooker) OnFailure(s *services.Service, f *failures.Failure) (string,
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (w *webhooker) OnSuccess(s *services.Service) (string, error) {
|
func (w *webhooker) OnSuccess(s services.Service) (string, error) {
|
||||||
msg := ReplaceVars(w.SuccessData, s, nil)
|
msg := ReplaceVars(w.SuccessData, s, failures.Failure{})
|
||||||
resp, err := w.sendHttpWebhook(msg)
|
resp, err := w.sendHttpWebhook(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
|
@ -2,6 +2,7 @@ package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/notifications"
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
|
@ -27,6 +28,7 @@ func TestWebhookNotifier(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
db.AutoMigrate(¬ifications.Notification{})
|
db.AutoMigrate(¬ifications.Notification{})
|
||||||
notifications.SetDB(db)
|
notifications.SetDB(db)
|
||||||
|
core.Example()
|
||||||
|
|
||||||
t.Run("Load webhooker", func(t *testing.T) {
|
t.Run("Load webhooker", func(t *testing.T) {
|
||||||
Webhook.Host = webhookTestUrl
|
Webhook.Host = webhookTestUrl
|
||||||
|
@ -46,6 +48,11 @@ func TestWebhookNotifier(t *testing.T) {
|
||||||
assert.True(t, Webhook.CanSend())
|
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) {
|
t.Run("webhooker OnFailure", func(t *testing.T) {
|
||||||
_, err := Webhook.OnFailure(services.Example(false), failures.Example())
|
_, err := Webhook.OnFailure(services.Example(false), failures.Example())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -5,6 +5,22 @@ import (
|
||||||
"github.com/statping/statping/utils"
|
"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 {
|
func Samples() error {
|
||||||
apiSecret := utils.Params.GetString("API_SECRET")
|
apiSecret := utils.Params.GetString("API_SECRET")
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,6 @@ type Core struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type OAuth struct {
|
type OAuth struct {
|
||||||
Domains string `gorm:"column:oauth_domains" json:"oauth_domains" scope:"admin"`
|
|
||||||
Providers string `gorm:"column:oauth_providers;" json:"oauth_providers"`
|
Providers string `gorm:"column:oauth_providers;" json:"oauth_providers"`
|
||||||
GithubClientID string `gorm:"column:gh_client_id" json:"gh_client_id"`
|
GithubClientID string `gorm:"column:gh_client_id" json:"gh_client_id"`
|
||||||
GithubClientSecret string `gorm:"column:gh_client_secret" json:"gh_client_secret" scope:"admin"`
|
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"`
|
SlackClientID string `gorm:"column:slack_client_id" json:"slack_client_id"`
|
||||||
SlackClientSecret string `gorm:"column:slack_client_secret" json:"slack_client_secret" scope:"admin"`
|
SlackClientSecret string `gorm:"column:slack_client_secret" json:"slack_client_secret" scope:"admin"`
|
||||||
SlackTeam string `gorm:"column:slack_team" json:"slack_team" 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
|
// AllNotifiers contains all the Notifiers loaded
|
||||||
|
|
|
@ -12,8 +12,8 @@ var (
|
||||||
log = utils.Log.WithField("type", "failure")
|
log = utils.Log.WithField("type", "failure")
|
||||||
)
|
)
|
||||||
|
|
||||||
func Example() *Failure {
|
func Example() Failure {
|
||||||
return &Failure{
|
return Failure{
|
||||||
Id: 48533,
|
Id: 48533,
|
||||||
Issue: "Response did not response a 200 status code",
|
Issue: "Response did not response a 200 status code",
|
||||||
Method: "",
|
Method: "",
|
||||||
|
|
|
@ -7,16 +7,15 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (n *Notification) Name() string {
|
func (n Notification) Name() string {
|
||||||
newName := strings.ToLower(n.Method)
|
newName := strings.ToLower(n.Method)
|
||||||
newName = strings.ReplaceAll(newName, " ", "_")
|
newName = strings.ReplaceAll(newName, " ", "_")
|
||||||
return newName
|
return newName
|
||||||
}
|
}
|
||||||
|
|
||||||
// LastSent returns a time.Duration of the last sent notification for the notifier
|
// LastSent returns a time.Duration of the last sent notification for the notifier
|
||||||
func (n *Notification) LastSent() time.Duration {
|
func (n Notification) LastSent() time.Duration {
|
||||||
since := time.Since(n.lastSent)
|
return time.Since(n.lastSent)
|
||||||
return since
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Notification) CanSend() bool {
|
func (n *Notification) CanSend() bool {
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
|
|
||||||
// Notifier interface is required to create a new Notifier
|
// Notifier interface is required to create a new Notifier
|
||||||
type Notifier interface {
|
type Notifier interface {
|
||||||
OnSuccess(*services.Service) (string, error) // OnSuccess is triggered when a service is successful
|
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
|
OnFailure(services.Service, failures.Failure) (string, error) // OnFailure is triggered when a service is failing
|
||||||
OnTest() (string, error) // OnTest is triggered for testing
|
OnTest() (string, error) // OnTest is triggered for testing
|
||||||
OnSave() (string, error) // OnSave is triggered for when saved
|
OnSave() (string, error) // OnSave is triggered for when saved
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,15 +20,14 @@ func (s *Service) FailuresSince(t time.Time) failures.Failurer {
|
||||||
return failures.Since(t, s)
|
return failures.Since(t, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) DowntimeAgo() string {
|
func (s Service) DowntimeAgo() string {
|
||||||
last := s.LastOnline
|
if s.LastOnline.IsZero() {
|
||||||
if last.IsZero() {
|
|
||||||
return "Never been online"
|
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()
|
last := s.AllFailures().Last()
|
||||||
if last == nil {
|
if last == nil {
|
||||||
return ""
|
return ""
|
||||||
|
|
|
@ -61,12 +61,12 @@ func (s *Service) LoadTLSCert() (*tls.Config, error) {
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Duration() time.Duration {
|
func (s Service) Duration() time.Duration {
|
||||||
return time.Duration(s.Interval) * time.Second
|
return time.Duration(s.Interval) * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start will create a channel for the service checking go routine
|
// 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 {
|
if len(hits) == 0 {
|
||||||
return nil, errors.New("service does not have any successful hits")
|
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
|
// 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()
|
return s.AllHits().Avg()
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnlineDaysPercent returns the service's uptime percent within last 24 hours
|
// 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)
|
ago := utils.Now().Add(-time.Duration(days) * types.Day)
|
||||||
return s.OnlineSince(ago)
|
return s.OnlineSince(ago)
|
||||||
}
|
}
|
||||||
|
@ -326,12 +326,12 @@ func (s *Service) OnlineSince(ago time.Time) float32 {
|
||||||
return s.Online24Hours
|
return s.Online24Hours
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Uptime() utils.Duration {
|
func (s Service) Uptime() utils.Duration {
|
||||||
return utils.Duration{Duration: utils.Now().Sub(s.LastOffline)}
|
return utils.Duration{Duration: utils.Now().Sub(s.LastOffline)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Downtime returns the amount of time of a offline service
|
// 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)}
|
return utils.Duration{Duration: utils.Now().Sub(s.LastOnline)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,9 @@ func FindNotifier(method string) *notifications.Notification {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServiceNotifier interface {
|
type ServiceNotifier interface {
|
||||||
OnSuccess(*Service) (string, error) // OnSuccess is triggered when a service is successful
|
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
|
OnFailure(Service, failures.Failure) (string, error) // OnFailure is triggered when a service is failing
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -353,7 +353,7 @@ func sendSuccess(s *Service) {
|
||||||
notif := n.Select()
|
notif := n.Select()
|
||||||
if notif.CanSend() {
|
if notif.CanSend() {
|
||||||
log.Infof("Sending notification to: %s!", notif.Method)
|
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)
|
notif.Logger().Errorln(err)
|
||||||
}
|
}
|
||||||
s.UserNotified = true
|
s.UserNotified = true
|
||||||
|
@ -405,7 +405,7 @@ func sendFailure(s *Service, f *failures.Failure) {
|
||||||
notif := n.Select()
|
notif := n.Select()
|
||||||
if notif.CanSend() {
|
if notif.CanSend() {
|
||||||
log.Infof("Sending Failure notification to: %s!", notif.Method)
|
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)
|
notif.Logger().WithField("failure", f.Issue).Errorln(err)
|
||||||
}
|
}
|
||||||
s.UserNotified = true
|
s.UserNotified = true
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Example(online bool) *Service {
|
func Example(online bool) Service {
|
||||||
return &Service{
|
return Service{
|
||||||
Id: 6283,
|
Id: 6283,
|
||||||
Name: "Statping Example",
|
Name: "Statping Example",
|
||||||
Domain: "https://statping.com",
|
Domain: "https://statping.com",
|
||||||
|
|
Loading…
Reference in New Issue