From 8c0543a16198c0c91e3d4d4fe22749ce90676b70 Mon Sep 17 00:00:00 2001 From: hunterlong Date: Tue, 25 Aug 2020 13:38:47 -0700 Subject: [PATCH 01/27] notifier panic fix --- CHANGELOG.md | 3 +++ database/grouping.go | 22 +++++++++++----------- handlers/notifications.go | 10 ++++++++-- handlers/routes.go | 1 + handlers/services.go | 13 +++++++++++++ types/checkins/database_hits.go | 2 +- types/incidents/database.go | 2 +- version.txt | 2 +- 8 files changed, 39 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 588e4c255..3f9e14664 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 0.90.65 (08-24-2020) +- Fixed issue with dashboard not logging in (notifier panic) + # 0.90.64 (08-18-2020) - Modified max-width for container to 1012px, larger UI - Added failure sparklines in the Services list view diff --git a/database/grouping.go b/database/grouping.go index ff953e246..28bce658f 100644 --- a/database/grouping.go +++ b/database/grouping.go @@ -70,19 +70,19 @@ func (t *TimeVar) ToValues() ([]*TimeValue, error) { } // GraphData will return all hits or failures -func (g *GroupQuery) GraphData(by By) ([]*TimeValue, error) { - g.db = g.db.MultipleSelects( - g.db.SelectByTime(g.Group), +func (b *GroupQuery) GraphData(by By) ([]*TimeValue, error) { + b.db = b.db.MultipleSelects( + b.db.SelectByTime(b.Group), by.String(), ).Group("timeframe").Order("timeframe", true) - caller, err := g.ToTimeValue() + caller, err := b.ToTimeValue() if err != nil { return nil, err } - if g.FillEmpty { - return caller.FillMissing(g.Start, g.End) + if b.FillEmpty { + return caller.FillMissing(b.Start, b.End) } return caller.ToValues() } @@ -90,8 +90,8 @@ func (g *GroupQuery) GraphData(by By) ([]*TimeValue, error) { // ToTimeValue will format the SQL rows into a JSON format for the API. // [{"timestamp": "2006-01-02T15:04:05Z", "amount": 468293}] // TODO redo this entire function, use better SQL query to group by time -func (g *GroupQuery) ToTimeValue() (*TimeVar, error) { - rows, err := g.db.Rows() +func (b *GroupQuery) ToTimeValue() (*TimeVar, error) { + rows, err := b.db.Rows() if err != nil { return nil, err } @@ -102,8 +102,8 @@ func (g *GroupQuery) ToTimeValue() (*TimeVar, error) { if err := rows.Scan(&timeframe, &amount); err != nil { log.Error(err, timeframe) } - trueTime, _ := g.db.ParseTime(timeframe) - newTs := types.FixedTime(trueTime, g.Group) + trueTime, _ := b.db.ParseTime(timeframe) + newTs := types.FixedTime(trueTime, b.Group) tv := &TimeValue{ Timeframe: newTs, @@ -111,7 +111,7 @@ func (g *GroupQuery) ToTimeValue() (*TimeVar, error) { } data = append(data, tv) } - return &TimeVar{g, data}, nil + return &TimeVar{b, data}, nil } func (t *TimeVar) FillMissing(current, end time.Time) ([]*TimeValue, error) { diff --git a/handlers/notifications.go b/handlers/notifications.go index 5f2c3dd63..81ed915fd 100644 --- a/handlers/notifications.go +++ b/handlers/notifications.go @@ -14,8 +14,14 @@ func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) { var notifs []notifications.Notification for _, n := range services.AllNotifiers() { no := n.Select() - notif, _ := notifications.Find(no.Method) - notifs = append(notifs, *no.UpdateFields(notif)) + notif, err := notifications.Find(no.Method) + if err != nil { + log.Errorln(err) + sendErrorJson(err, w, r) + return + } + updated := no.UpdateFields(notif) + notifs = append(notifs, *updated) } sort.Sort(notifications.NotificationOrder(notifs)) returnJson(notifs, w, r) diff --git a/handlers/routes.go b/handlers/routes.go index 346583e1d..8254101f9 100644 --- a/handlers/routes.go +++ b/handlers/routes.go @@ -132,6 +132,7 @@ func Router() *mux.Router { api.Handle("/api/services/{id}/failures", scoped(apiServiceFailuresHandler)).Methods("GET") api.Handle("/api/services/{id}/failures", authenticated(servicesDeleteFailuresHandler, false)).Methods("DELETE") api.Handle("/api/services/{id}/hits", scoped(apiServiceHitsHandler)).Methods("GET") + api.Handle("/api/services/{id}/hits", authenticated(apiServiceHitsDeleteHandler, false)).Methods("DELETE") // API SERVICE CHART DATA Routes api.Handle("/api/services/{id}/hits_data", cached("30s", "application/json", apiServiceDataHandler)).Methods("GET") diff --git a/handlers/services.go b/handlers/services.go index 37bc682f8..135ddccfe 100644 --- a/handlers/services.go +++ b/handlers/services.go @@ -237,6 +237,19 @@ func apiServiceTimeDataHandler(w http.ResponseWriter, r *http.Request) { returnJson(uptimeData, w, r) } +func apiServiceHitsDeleteHandler(w http.ResponseWriter, r *http.Request) { + service, err := findService(r) + if err != nil { + sendErrorJson(err, w, r) + return + } + if err := service.AllHits().DeleteAll(); err != nil { + sendErrorJson(err, w, r) + return + } + sendJsonAction(service, "delete", w, r) +} + func apiServiceDeleteHandler(w http.ResponseWriter, r *http.Request) { service, err := findService(r) if err != nil { diff --git a/types/checkins/database_hits.go b/types/checkins/database_hits.go index bcea292c7..b97c926d3 100644 --- a/types/checkins/database_hits.go +++ b/types/checkins/database_hits.go @@ -8,7 +8,7 @@ func (c *Checkin) LastHit() *CheckinHit { func (c *Checkin) Hits() []*CheckinHit { var hits []*CheckinHit - dbHits.Where("checkin = ?", c.Id).Order("DESC").Find(&hits) + dbHits.Where("checkin = ?", c.Id).Order("id DESC").Find(&hits) c.AllHits = hits return hits } diff --git a/types/incidents/database.go b/types/incidents/database.go index 315ba06be..7260cb61e 100644 --- a/types/incidents/database.go +++ b/types/incidents/database.go @@ -34,7 +34,7 @@ func (i *Incident) BeforeCreate() error { } func (i *Incident) AfterFind() { - db.Model(i).Related(&i.Updates).Order("DESC") + db.Model(i).Related(&i.Updates).Order("id DESC") metrics.Query("incident", "find") } diff --git a/version.txt b/version.txt index e23d7df85..18dfe4ba5 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.90.64 +0.90.65 From 954e19bd402e9a1bf711e26140b95f25ed150322 Mon Sep 17 00:00:00 2001 From: hunterlong Date: Tue, 25 Aug 2020 14:35:49 -0700 Subject: [PATCH 02/27] portainer template --- dev/portainer.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 dev/portainer.json diff --git a/dev/portainer.json b/dev/portainer.json new file mode 100644 index 000000000..44535ddf1 --- /dev/null +++ b/dev/portainer.json @@ -0,0 +1,15 @@ +{ + "type": 1, + "title": "Statping", + "description": "Service monitoring with a easy to use status page and mobile app", + "logo": "https://assets.statping.com/icon.png", + "image": "statping/statping:latest", + "ports": [ + "8080:8080/tcp" + ], + "volumes": [ + { + "container": "/app" + } + ] +} From 13878e5a8f30e7d90076f2c41f7b2ef01ba1e0a3 Mon Sep 17 00:00:00 2001 From: hunterlong Date: Tue, 25 Aug 2020 15:43:05 -0700 Subject: [PATCH 03/27] remove default host from discord notifier --- dev/portainer.json | 36 +++++++++++++++++++++--------------- notifiers/discord.go | 7 +++---- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/dev/portainer.json b/dev/portainer.json index 44535ddf1..fe93ba18d 100644 --- a/dev/portainer.json +++ b/dev/portainer.json @@ -1,15 +1,21 @@ -{ - "type": 1, - "title": "Statping", - "description": "Service monitoring with a easy to use status page and mobile app", - "logo": "https://assets.statping.com/icon.png", - "image": "statping/statping:latest", - "ports": [ - "8080:8080/tcp" - ], - "volumes": [ - { - "container": "/app" - } - ] -} +[ + { + "type": 1, + "title": "Statping", + "restart_policy": "unless-stopped", + "description": "Service monitoring with an easy to use status page and mobile app", + "logo": "https://assets.statping.com/icon.png", + "image": "statping/statping:latest", + "platform": "linux", + "categories": ["monitoring"], + "administrator_only": false, + "ports": [ + "8080:8080/tcp" + ], + "volumes": [ + { + "container": "/app" + } + ] + } +] diff --git a/notifiers/discord.go b/notifiers/discord.go index acb6d49a6..3443a323d 100644 --- a/notifiers/discord.go +++ b/notifiers/discord.go @@ -27,16 +27,15 @@ var Discorder = &discord{¬ifications.Notification{ Author: "Hunter Long", AuthorUrl: "https://github.com/hunterlong", Delay: time.Duration(5 * time.Second), - Host: null.NewNullString("https://discordapp.com/api/webhooks/****/*****"), Icon: "fab fa-discord", - SuccessData: null.NewNullString(`{"content": "Your service '{{.Service.Name}}' is currently online!"}`), - FailureData: null.NewNullString(`{"content": "Your service '{{.Service.Name}}' is currently failing! Reason: {{.Failure.Issue}}"}`), + SuccessData: null.NewNullString(`{"content": "Your service '{{.Service.Name}}' is currently back online and was down for {{.Service.Downtime.Human}}."}`), + FailureData: null.NewNullString(`{"content": "Your service '{{.Service.Name}}' is has been failing for {{.Service.Downtime.Human}}! Reason: {{.Failure.Issue}}"}`), DataType: "json", Limits: 60, Form: []notifications.NotificationForm{{ Type: "text", Title: "discord webhooker URL", - Placeholder: "Insert your Webhook URL here", + Placeholder: "https://discordapp.com/api/webhooks/****/*****", DbField: "host", }}}, } From 136831e70dc0e3407c9bab5436e35ecd2a4a3470 Mon Sep 17 00:00:00 2001 From: hunterlong Date: Tue, 25 Aug 2020 15:44:40 -0700 Subject: [PATCH 04/27] fix for updating fields --- types/notifications/database.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/types/notifications/database.go b/types/notifications/database.go index c034b0762..f06d20d4f 100644 --- a/types/notifications/database.go +++ b/types/notifications/database.go @@ -56,6 +56,9 @@ func (n *Notification) Create() error { } func (n *Notification) UpdateFields(notif *Notification) *Notification { + if notif == nil { + return n + } n.Id = notif.Id n.Limits = notif.Limits n.Enabled = notif.Enabled From a43d7834b9b99dd880f8a263f690014482ff9f21 Mon Sep 17 00:00:00 2001 From: hunterlong Date: Wed, 26 Aug 2020 03:48:05 -0700 Subject: [PATCH 05/27] fix for updating fields --- CHANGELOG.md | 2 ++ cmd/main.go | 8 ++++---- go.mod | 1 + go.sum | 3 +++ handlers/api.go | 10 ++++++---- handlers/notifications.go | 2 ++ notifiers/amazon_sns.go | 2 +- notifiers/email.go | 22 ++++++---------------- notifiers/notifiers.go | 5 +++-- types/configs/configs_form.go | 30 +++++++++++++++--------------- types/configs/load.go | 4 ++-- types/configs/struct.go | 24 ++++++++++++++++++++++-- types/notifications/database.go | 16 ++++++++++++++++ types/notifications/struct.go | 4 ---- types/services/methods.go | 1 + utils/metrics.go | 5 ----- 16 files changed, 84 insertions(+), 55 deletions(-) delete mode 100644 utils/metrics.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f9e14664..3f04bbcbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # 0.90.65 (08-24-2020) - Fixed issue with dashboard not logging in (notifier panic) +- Modified static email templates to github.com/statping/emails +- Modified Regenerate API function to keep API_SECRET env # 0.90.64 (08-18-2020) - Modified max-width for container to 1012px, larger UI diff --git a/cmd/main.go b/cmd/main.go index 85bec4170..d3f7e0820 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -148,20 +148,20 @@ func InitApp() error { if _, err := core.Select(); err != nil { return err } + // init Sentry error monitoring (its useful) + utils.SentryInit(core.App.AllowReports.Bool) // init prometheus metrics metrics.InitMetrics() + // connect each notifier, added them into database if needed + notifiers.InitNotifiers() // select all services in database and store services in a mapping of Service pointers if _, err := services.SelectAllServices(true); err != nil { return err } // start routines for each service checking process services.CheckServices() - // connect each notifier, added them into database if needed - notifiers.InitNotifiers() // start routine to delete old records (failures, hits) go database.Maintenance() - // init Sentry error monitoring (its useful) - utils.SentryInit(core.App.AllowReports.Bool) core.App.Setup = true core.App.Started = utils.Now() return nil diff --git a/go.mod b/go.mod index b8240921b..0ec61c1f6 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.6.3 + github.com/statping/emails v1.0.0 github.com/stretchr/testify v1.5.1 github.com/t-tiger/gorm-bulk-insert/v2 v2.0.1 github.com/tdewolff/minify/v2 v2.8.0 // indirect diff --git a/go.sum b/go.sum index f350ca447..e377a002d 100755 --- a/go.sum +++ b/go.sum @@ -568,6 +568,9 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs= github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw= +github.com/statping/emails v1.0.0 h1:90hGweEhr8wIFiy34KCkiFqGJlkug2gAQLVR6oSCFNU= +github.com/statping/emails v1.0.0/go.mod h1:xFU85jXaiWQadqHqu/jDrGsAn6WPSk1WgKyTVuFm0TI= +github.com/statping/statping v0.90.64/go.mod h1:lbyNPB73IjWtnommV4wSejYfgUT1yLhhqelMjl1ZBb8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/handlers/api.go b/handlers/api.go index 58c486925..e1d2cf38e 100644 --- a/handlers/api.go +++ b/handlers/api.go @@ -31,10 +31,12 @@ func apiIndexHandler(r *http.Request) interface{} { } func apiRenewHandler(w http.ResponseWriter, r *http.Request) { - var err error - core.App.ApiSecret = utils.NewSHA256Hash() - err = core.App.Update() - if err != nil { + newApi := utils.Params.GetString("API_SECRET") + if newApi == "" { + newApi = utils.NewSHA256Hash() + } + core.App.ApiSecret = newApi + if err := core.App.Update(); err != nil { sendErrorJson(err, w, r) return } diff --git a/handlers/notifications.go b/handlers/notifications.go index 81ed915fd..c542a0dbe 100644 --- a/handlers/notifications.go +++ b/handlers/notifications.go @@ -13,7 +13,9 @@ import ( func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) { var notifs []notifications.Notification for _, n := range services.AllNotifiers() { + log.Warningln(n) no := n.Select() + log.Warningln(no.Method) notif, err := notifications.Find(no.Method) if err != nil { log.Errorln(err) diff --git a/notifiers/amazon_sns.go b/notifiers/amazon_sns.go index fb21f1b34..f1405a484 100644 --- a/notifiers/amazon_sns.go +++ b/notifiers/amazon_sns.go @@ -64,7 +64,7 @@ var AmazonSNS = &amazonSNS{¬ifications.Notification{ Type: "text", Title: "SNS Topic ARN", SmallText: "The ARN of the Topic", - DbField: "host", + DbField: "Host", Placeholder: "arn:aws:sns:us-west-2:123456789012:YourTopic", Required: true, }}}, diff --git a/notifiers/email.go b/notifiers/email.go index 81c23bf21..2980c7055 100644 --- a/notifiers/email.go +++ b/notifiers/email.go @@ -1,17 +1,16 @@ package notifiers import ( - "bytes" "crypto/tls" "fmt" "github.com/go-mail/mail" + "github.com/statping/emails" "github.com/statping/statping/types/core" "github.com/statping/statping/types/failures" "github.com/statping/statping/types/notifications" "github.com/statping/statping/types/notifier" "github.com/statping/statping/types/services" "github.com/statping/statping/utils" - "html/template" ) var _ notifier.Notifier = (*emailer)(nil) @@ -92,7 +91,7 @@ type emailOutgoing struct { // OnFailure will trigger failing service 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, emailFailure) + tmpl := renderEmail(s, f, emails.Failure) email := &emailOutgoing{ To: e.Var2.String, Subject: subject, @@ -105,7 +104,7 @@ func (e *emailer) OnFailure(s services.Service, f failures.Failure) (string, err // OnSuccess will trigger successful service func (e *emailer) OnSuccess(s services.Service) (string, error) { subject := fmt.Sprintf("Service %s is Back Online", s.Name) - tmpl := renderEmail(s, failures.Failure{}, emailSuccess) + tmpl := renderEmail(s, failures.Failure{}, emails.Success) email := &emailOutgoing{ To: e.Var2.String, Subject: subject, @@ -116,27 +115,18 @@ func (e *emailer) OnSuccess(s services.Service) (string, error) { } func renderEmail(s services.Service, f failures.Failure, emailData string) string { - wr := bytes.NewBuffer(nil) - tmpl := template.New("email") - tmpl, err := tmpl.Parse(emailData) - if err != nil { - log.Errorln(err) - return emailData - } - data := replacer{ Core: *core.App, Service: s, Failure: f, Custom: nil, } - - if err = tmpl.ExecuteTemplate(wr, "email", data); err != nil { + output, err := emails.Parse(emailData, data) + if err != nil { log.Errorln(err) return emailData } - - return wr.String() + return output } // OnTest triggers when this notifier has been saved diff --git a/notifiers/notifiers.go b/notifiers/notifiers.go index 4bed95f4c..78b82e932 100644 --- a/notifiers/notifiers.go +++ b/notifiers/notifiers.go @@ -56,10 +56,11 @@ func ReplaceTemplate(tmpl string, data replacer) string { func Add(notifs ...services.ServiceNotifier) { for _, n := range notifs { - services.AddNotifier(n) - if err := n.Select().Create(); err != nil { + notif := n.Select() + if err := notif.Create(); err != nil { log.Error(err) } + services.AddNotifier(n) } } diff --git a/types/configs/configs_form.go b/types/configs/configs_form.go index a2c9da12b..0f78e980c 100644 --- a/types/configs/configs_form.go +++ b/types/configs/configs_form.go @@ -48,21 +48,21 @@ func LoadConfigForm(r *http.Request) (*DbConfig, error) { p.Set("ADMIN_EMAIL", email) confg := &DbConfig{ - DbConn: dbConn, - DbHost: dbHost, - DbUser: dbUser, - DbPass: dbPass, - DbData: dbDatabase, - DbPort: int(dbPort), - Project: project, - Description: description, - Domain: domain, - Username: username, - Password: password, - Email: email, - Location: utils.Directory, - Language: language, - SendReports: reports, + DbConn: dbConn, + DbHost: dbHost, + DbUser: dbUser, + DbPass: dbPass, + DbData: dbDatabase, + DbPort: int(dbPort), + Project: project, + Description: description, + Domain: domain, + Username: username, + Password: password, + Email: email, + Location: utils.Directory, + Language: language, + AllowReports: reports, } return confg, nil diff --git a/types/configs/load.go b/types/configs/load.go index 0258c80c5..66e490645 100644 --- a/types/configs/load.go +++ b/types/configs/load.go @@ -59,7 +59,7 @@ func LoadConfigs(cfgFile string) (*DbConfig, error) { if db.Language != "" { p.Set("LANGUAGE", db.Language) } - if db.SendReports { + if db.AllowReports { p.Set("ALLOW_REPORTS", true) } if db.LetsEncryptEmail != "" { @@ -88,7 +88,7 @@ func LoadConfigs(cfgFile string) (*DbConfig, error) { Location: utils.Directory, SqlFile: p.GetString("SQL_FILE"), Language: p.GetString("LANGUAGE"), - SendReports: p.GetBool("ALLOW_REPORTS"), + AllowReports: p.GetBool("ALLOW_REPORTS"), LetsEncryptEnable: p.GetBool("LETSENCRYPT_ENABLE"), LetsEncryptHost: p.GetString("LETSENCRYPT_HOST"), LetsEncryptEmail: p.GetString("LETSENCRYPT_EMAIL"), diff --git a/types/configs/struct.go b/types/configs/struct.go index 166fd9869..e4df6a0fd 100644 --- a/types/configs/struct.go +++ b/types/configs/struct.go @@ -14,7 +14,7 @@ type DbConfig struct { DbPort int `yaml:"port" json:"-"` ApiSecret string `yaml:"api_secret" json:"-"` Language string `yaml:"language" json:"language"` - SendReports bool `yaml:"send_reports" json:"send_reports"` + AllowReports bool `yaml:"allow_reports" json:"allow_reports"` Project string `yaml:"-" json:"-"` Description string `yaml:"-" json:"-"` Domain string `yaml:"-" json:"-"` @@ -26,8 +26,28 @@ type DbConfig struct { SqlFile string `yaml:"sqlfile,omitempty" json:"-"` LetsEncryptHost string `yaml:"letsencrypt_host,omitempty" json:"letsencrypt_host"` LetsEncryptEmail string `yaml:"letsencrypt_email,omitempty" json:"letsencrypt_email"` - LetsEncryptEnable bool `yaml:"letsencrypt_enable" json:"letsencrypt_enable"` + LetsEncryptEnable bool `yaml:"letsencrypt_enable,omitempty" json:"letsencrypt_enable"` LocalIP string `yaml:"-" json:"-"` + DisableHTTP bool `yaml:"disable_http" json:"disable_http"` + DemoMode bool `yaml:"demo_mode" json:"demo_mode"` + DisableLogs bool `yaml:"disable_logs" json:"disable_logs"` + UseAssets bool `yaml:"use_assets" json:"use_assets"` + BasePath bool `yaml:"base_path" json:"base_path"` + + AdminUser string `yaml:"admin_user" json:"admin_user"` + AdminPassword string `yaml:"admin_password" json:"admin_password"` + AdminEmail string `yaml:"admin_email" json:"admin_email"` + + MaxOpenConnections int `yaml:"db_open_connections" json:"db_open_connections"` + MaxIdleConnections int `yaml:"db_idle_connections" json:"db_idle_connections"` + MaxLifeConnections int `yaml:"db_max_life_connections" json:"db_max_life_connections"` + + SampleData bool `yaml:"sample_data" json:"sample_data"` + UseCDN bool `yaml:"use_cdn" json:"use_cdn"` + DisableColors bool `yaml:"disable_colors" json:"disable_colors"` + + PostgresSSLMode string `yaml:"postgres_ssl" json:"postgres_ssl"` + Db database.Database `yaml:"-" json:"-"` } diff --git a/types/notifications/database.go b/types/notifications/database.go index f06d20d4f..c75fadad9 100644 --- a/types/notifications/database.go +++ b/types/notifications/database.go @@ -2,6 +2,7 @@ package notifications import ( "github.com/statping/statping/database" + "github.com/statping/statping/types/null" ) var ( @@ -34,10 +35,25 @@ func Find(method string) (*Notification, error) { return &n, nil } +// BeforeCreate is a NULL constraint fix for postgres +func (n *Notification) BeforeCreate() error { + n.Host = null.NewNullString("") + n.Port = null.NewNullInt64(0) + n.Username = null.NewNullString("") + n.Password = null.NewNullString("") + n.Var1 = null.NewNullString("") + n.Var2 = null.NewNullString("") + n.ApiKey = null.NewNullString("") + n.ApiSecret = null.NewNullString("") + return nil +} + func (n *Notification) Create() error { var p Notification q := db.Where("method = ?", n.Method).Find(&p) if q.RecordNotFound() { + log.Infof("Notifier %s was not found, adding into database...\n", n.Method) + log.Infoln(n.Method, n.Id, n.Title, n.Host.String) if err := db.Create(n).Error(); err != nil { return err } diff --git a/types/notifications/struct.go b/types/notifications/struct.go index b0f2f217b..c273155a3 100644 --- a/types/notifications/struct.go +++ b/types/notifications/struct.go @@ -38,12 +38,10 @@ type Notification struct { AuthorUrl string `gorm:"-" json:"author_url"` Icon string `gorm:"-" json:"icon"` Delay time.Duration `gorm:"-" json:"delay,string"` - Running chan bool `gorm:"-" json:"-"` Form []NotificationForm `gorm:"-" json:"form"` LastSent time.Time `gorm:"-" json:"-"` LastSentCount int `gorm:"-" json:"-"` - sentCount int `gorm:"-" json:"-"` Logs []*NotificationLog `gorm:"-" json:"logs,omitempty"` } @@ -59,8 +57,6 @@ func (n *Notification) Logger() *logrus.Logger { return log.WithField("notifier", n.Method).Logger } -type RunFunc func(interface{}) error - type Values struct { Host string Port int64 diff --git a/types/services/methods.go b/types/services/methods.go index 18a71e197..d564861a6 100644 --- a/types/services/methods.go +++ b/types/services/methods.go @@ -226,6 +226,7 @@ func SelectAllServices(start bool) (map[int64]*Service, error) { if len(allServices) > 0 { return allServices, nil } + log.Infof("Preparing to monitor %d services...\n", len(allServices)) for _, s := range all() { s.Failures = s.AllFailures().LastAmount(limitedFailures) s.prevOnline = true diff --git a/utils/metrics.go b/utils/metrics.go deleted file mode 100644 index 489c28085..000000000 --- a/utils/metrics.go +++ /dev/null @@ -1,5 +0,0 @@ -package utils - -var ( - StartTime = Now() -) From 3051206a7a843b97c92462a536f1c54ee92fbab8 Mon Sep 17 00:00:00 2001 From: hunterlong Date: Wed, 26 Aug 2020 16:02:17 -0700 Subject: [PATCH 06/27] fixed notifier panic --- types/configs/struct.go | 10 +++++----- types/notifications/database.go | 17 +---------------- types/null/marshal.go | 14 +++++++++++++- types/services/methods.go | 1 - 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/types/configs/struct.go b/types/configs/struct.go index e4df6a0fd..93ec5ef60 100644 --- a/types/configs/struct.go +++ b/types/configs/struct.go @@ -29,11 +29,11 @@ type DbConfig struct { LetsEncryptEnable bool `yaml:"letsencrypt_enable,omitempty" json:"letsencrypt_enable"` LocalIP string `yaml:"-" json:"-"` - DisableHTTP bool `yaml:"disable_http" json:"disable_http"` - DemoMode bool `yaml:"demo_mode" json:"demo_mode"` - DisableLogs bool `yaml:"disable_logs" json:"disable_logs"` - UseAssets bool `yaml:"use_assets" json:"use_assets"` - BasePath bool `yaml:"base_path" json:"base_path"` + DisableHTTP bool `yaml:"disable_http" json:"disable_http"` + DemoMode bool `yaml:"demo_mode" json:"demo_mode"` + DisableLogs bool `yaml:"disable_logs" json:"disable_logs"` + UseAssets bool `yaml:"use_assets" json:"use_assets"` + BasePath string `yaml:"base_path" json:"base_path"` AdminUser string `yaml:"admin_user" json:"admin_user"` AdminPassword string `yaml:"admin_password" json:"admin_password"` diff --git a/types/notifications/database.go b/types/notifications/database.go index c75fadad9..d4b1f40db 100644 --- a/types/notifications/database.go +++ b/types/notifications/database.go @@ -2,7 +2,6 @@ package notifications import ( "github.com/statping/statping/database" - "github.com/statping/statping/types/null" ) var ( @@ -35,25 +34,11 @@ func Find(method string) (*Notification, error) { return &n, nil } -// BeforeCreate is a NULL constraint fix for postgres -func (n *Notification) BeforeCreate() error { - n.Host = null.NewNullString("") - n.Port = null.NewNullInt64(0) - n.Username = null.NewNullString("") - n.Password = null.NewNullString("") - n.Var1 = null.NewNullString("") - n.Var2 = null.NewNullString("") - n.ApiKey = null.NewNullString("") - n.ApiSecret = null.NewNullString("") - return nil -} - func (n *Notification) Create() error { var p Notification q := db.Where("method = ?", n.Method).Find(&p) if q.RecordNotFound() { - log.Infof("Notifier %s was not found, adding into database...\n", n.Method) - log.Infoln(n.Method, n.Id, n.Title, n.Host.String) + log.Infof("Notifier '%s' was not found, adding into database...\n", n.Method) if err := db.Create(n).Error(); err != nil { return err } diff --git a/types/null/marshal.go b/types/null/marshal.go index dae3e551f..8cbc56717 100644 --- a/types/null/marshal.go +++ b/types/null/marshal.go @@ -1,10 +1,22 @@ package null import ( + "database/sql/driver" "encoding/json" "gopkg.in/yaml.v2" ) +func (s NullString) Scan(value interface{}) error { + if s.Valid { + s.String = value.(string) + } + return nil +} + +func (s NullString) Value() (driver.Value, error) { + return s.String, nil +} + // MarshalJSON for NullInt64 func (i NullInt64) MarshalJSON() ([]byte, error) { if !i.Valid { @@ -32,7 +44,7 @@ func (bb NullBool) MarshalJSON() ([]byte, error) { // MarshalJSON for NullString func (s NullString) MarshalJSON() ([]byte, error) { if !s.Valid { - return []byte("null"), nil + return json.Marshal(nil) } return json.Marshal(s.String) } diff --git a/types/services/methods.go b/types/services/methods.go index d564861a6..18a71e197 100644 --- a/types/services/methods.go +++ b/types/services/methods.go @@ -226,7 +226,6 @@ func SelectAllServices(start bool) (map[int64]*Service, error) { if len(allServices) > 0 { return allServices, nil } - log.Infof("Preparing to monitor %d services...\n", len(allServices)) for _, s := range all() { s.Failures = s.AllFailures().LastAmount(limitedFailures) s.prevOnline = true From ee52eaa96b20cfe3a4b8b9a392a1238aed4ae108 Mon Sep 17 00:00:00 2001 From: hunterlong Date: Sat, 29 Aug 2020 19:02:23 -0700 Subject: [PATCH 07/27] fixed notifier panic --- .gitignore | 1 + frontend/src/API.js | 4 ++-- frontend/src/pages/Help.vue | 2 +- handlers/notifications.go | 12 +----------- handlers/routes.go | 8 ++------ notifiers/notifiers.go | 2 ++ notifiers/slack.go | 6 ------ types/notifications/database.go | 9 +++++++++ types/null/marshal.go | 7 ------- types/services/notifications.go | 7 +++++++ 10 files changed, 25 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index d0b073133..ccdb9205a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ snap prime stage parts +assets_backup certs releases core/rice-box.go diff --git a/frontend/src/API.js b/frontend/src/API.js index 49ef994c9..82dbb00b9 100644 --- a/frontend/src/API.js +++ b/frontend/src/API.js @@ -7,8 +7,8 @@ const tokenKey = "statping_auth"; class Api { constructor() { - this.version = "0.90.64"; - this.commit = "130cc3ede7463ec9af8d62abb84992e2a0ef453c"; + this.version = "0.90.65"; + this.commit = "3051206a7a843b97c92462a536f1c54ee92fbab8"; } async oauth() { diff --git a/frontend/src/pages/Help.vue b/frontend/src/pages/Help.vue index 9c79c8342..62fae2347 100755 --- a/frontend/src/pages/Help.vue +++ b/frontend/src/pages/Help.vue @@ -2275,7 +2275,7 @@ OluFxewsEO0QNDrfFb+0gnjYlnGqOFcZjUMXbDdY5oLSPtXohynuTK1qyQ==
-Automatically generated from Statping's Wiki on 2020-08-22 21:27:09.3468 +0000 UTC +Automatically generated from Statping's Wiki on 2020-08-30 00:32:40.685063 +0000 UTC
diff --git a/handlers/notifications.go b/handlers/notifications.go index c542a0dbe..da4a2c1f0 100644 --- a/handlers/notifications.go +++ b/handlers/notifications.go @@ -13,17 +13,7 @@ import ( func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) { var notifs []notifications.Notification for _, n := range services.AllNotifiers() { - log.Warningln(n) - no := n.Select() - log.Warningln(no.Method) - notif, err := notifications.Find(no.Method) - if err != nil { - log.Errorln(err) - sendErrorJson(err, w, r) - return - } - updated := no.UpdateFields(notif) - notifs = append(notifs, *updated) + notifs = append(notifs, *n.Select()) } sort.Sort(notifications.NotificationOrder(notifs)) returnJson(notifs, w, r) diff --git a/handlers/routes.go b/handlers/routes.go index 8254101f9..576431aea 100644 --- a/handlers/routes.go +++ b/handlers/routes.go @@ -68,12 +68,8 @@ func Router() *mux.Router { } if source.UsingAssets(dir) { - indexHandler := http.FileServer(http.Dir(dir + "/assets/")) - - r.PathPrefix("/css/").Handler(http.StripPrefix(basePath, staticAssets("css"))) - r.PathPrefix("/favicon/").Handler(http.StripPrefix(basePath, staticAssets("favicon"))) - r.PathPrefix("/robots.txt").Handler(http.StripPrefix(basePath, indexHandler)) - r.PathPrefix("/banner.png").Handler(http.StripPrefix(basePath, indexHandler)) + prefixed := http.StripPrefix(basePath+"assets/", http.FileServer(http.Dir(dir+"/assets/"))) + r.PathPrefix("/assets/").Handler(prefixed) } else { tmplFileSrv := http.FileServer(source.TmplBox.HTTPBox()) tmplBoxHandler := http.StripPrefix(basePath, tmplFileSrv) diff --git a/notifiers/notifiers.go b/notifiers/notifiers.go index 78b82e932..ec23bd1e3 100644 --- a/notifiers/notifiers.go +++ b/notifiers/notifiers.go @@ -37,6 +37,8 @@ func InitNotifiers() { Gotify, AmazonSNS, ) + + services.UpdateNotifiers() } func ReplaceTemplate(tmpl string, data replacer) string { diff --git a/notifiers/slack.go b/notifiers/slack.go index 8566c6ddc..f476da66c 100644 --- a/notifiers/slack.go +++ b/notifiers/slack.go @@ -9,7 +9,6 @@ import ( "github.com/statping/statping/types/null" "github.com/statping/statping/types/services" "github.com/statping/statping/utils" - "regexp" "strings" "time" ) @@ -94,10 +93,5 @@ func (s *slack) OnSave() (string, error) { } func (s *slack) Valid(values notifications.Values) error { - regex := `https\:\/\/hooks\.slack\.com/services/[A-Z0-9]{7,11}/[A-Z0-9]{7,11}/[a-zA-Z0-9]{20,22}` - r := regexp.MustCompile(regex) - if !r.MatchString(values.Host) { - return errors.New("slack webhook does not match with expected regex " + regex) - } return nil } diff --git a/types/notifications/database.go b/types/notifications/database.go index d4b1f40db..37c5779a7 100644 --- a/types/notifications/database.go +++ b/types/notifications/database.go @@ -25,6 +25,15 @@ func (n *Notification) Values() Values { } } +func All() []*Notification { + var n []*Notification + q := db.Find(&n) + if q.Error() != nil { + return nil + } + return n +} + func Find(method string) (*Notification, error) { var n Notification q := db.Where("method = ?", method).Find(&n) diff --git a/types/null/marshal.go b/types/null/marshal.go index 8cbc56717..ac23d4362 100644 --- a/types/null/marshal.go +++ b/types/null/marshal.go @@ -6,13 +6,6 @@ import ( "gopkg.in/yaml.v2" ) -func (s NullString) Scan(value interface{}) error { - if s.Valid { - s.String = value.(string) - } - return nil -} - func (s NullString) Value() (driver.Value, error) { return s.String, nil } diff --git a/types/services/notifications.go b/types/services/notifications.go index 80b581822..352df55e2 100644 --- a/types/services/notifications.go +++ b/types/services/notifications.go @@ -11,6 +11,13 @@ func AddNotifier(n ServiceNotifier) { allNotifiers[notif.Method] = n } +func UpdateNotifiers() { + for _, n := range notifications.All() { + notifier := allNotifiers[n.Method] + notifier.Select().UpdateFields(n) + } +} + func sendSuccess(s *Service) { if !s.AllowNotifications.Bool { return From ba70a4c4794cdf9bcba5e8c56ea69d60eaa5dced Mon Sep 17 00:00:00 2001 From: hunterlong Date: Sat, 29 Aug 2020 19:23:01 -0700 Subject: [PATCH 08/27] test fix --- types/configs/load.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types/configs/load.go b/types/configs/load.go index 66e490645..798886e00 100644 --- a/types/configs/load.go +++ b/types/configs/load.go @@ -93,6 +93,7 @@ func LoadConfigs(cfgFile string) (*DbConfig, error) { LetsEncryptHost: p.GetString("LETSENCRYPT_HOST"), LetsEncryptEmail: p.GetString("LETSENCRYPT_EMAIL"), ApiSecret: p.GetString("API_SECRET"), + SampleData: p.GetBool("SAMPLE_DATA"), } log.WithFields(utils.ToFields(configs)).Debugln("read config file: " + cfgFile) From 7901aeea7caafa68b16ead851ca03fccb3962874 Mon Sep 17 00:00:00 2001 From: hunterlong Date: Sat, 29 Aug 2020 20:32:10 -0700 Subject: [PATCH 09/27] test fix --- .github/workflows/development.yml | 1 + .github/workflows/master.yml | 1 + utils/utils_test.go | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml index ea9feaad1..ed698db3c 100644 --- a/.github/workflows/development.yml +++ b/.github/workflows/development.yml @@ -257,6 +257,7 @@ jobs: API_SECRET: demopassword123 DISABLE_LOGS: false ALLOW_REPORTS: true + SAMPLE_DATA: true COVERALLS: ${{ secrets.COVERALLS }} DISCORD_URL: ${{ secrets.DISCORD_URL }} EMAIL_HOST: ${{ secrets.EMAIL_HOST }} diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 5ec814fd2..7d0c10b55 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -257,6 +257,7 @@ jobs: API_SECRET: demopassword123 DISABLE_LOGS: false ALLOW_REPORTS: true + SAMPLE_DATA: true COVERALLS: ${{ secrets.COVERALLS }} DISCORD_URL: ${{ secrets.DISCORD_URL }} EMAIL_HOST: ${{ secrets.EMAIL_HOST }} diff --git a/utils/utils_test.go b/utils/utils_test.go index 79900ff41..2880d69a5 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -192,7 +192,8 @@ func TestHttpRequest(t *testing.T) { } func TestConfigLoad(t *testing.T) { - InitLogs() + err := InitLogs() + require.Nil(t, err) InitEnvs() s := Params.GetString From a451db51f14b8f7bf1762ec758ea1bcf161c797c Mon Sep 17 00:00:00 2001 From: hunterlong Date: Mon, 31 Aug 2020 11:53:47 -0700 Subject: [PATCH 10/27] missing login banner image --- frontend/src/pages/Login.vue | 2 +- handlers/routes.go | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/frontend/src/pages/Login.vue b/frontend/src/pages/Login.vue index 44591370d..2de88b734 100644 --- a/frontend/src/pages/Login.vue +++ b/frontend/src/pages/Login.vue @@ -2,7 +2,7 @@
- Statping Login + Statping Login