tests, email rendered from MJML, db changes

pull/778/head
hunterlong 2020-08-05 21:17:14 -07:00
parent 31c93751f7
commit 6e76b1cf29
22 changed files with 407 additions and 681 deletions

View File

@ -8,6 +8,8 @@
- Modified index page to use /assets directory for assets, (main.css, style.css)
- Modified index page to use CDN asset paths
- Fixed New Checkin form
- Modified email notifier template to be rendered from MJML
- Modified database relationships with services using gorm
# 0.90.61 (07-22-2020)
- Modified sass layouts, organized and split up sections

View File

@ -145,7 +145,9 @@ frontend-build:
@cp -r frontend/dist source/
@cp -r frontend/src/assets/scss source/dist/
@cp -r frontend/public/main.scss source/dist/scss/
@cp -r source/tmpl/*.* source/dist/
@cp frontend/public/favicon.ico source/dist/
@cp frontend/public/robots.txt source/dist/
@cp frontend/public/banner.png source/dist/
@cp -r frontend/public/favicon source/dist/
@echo "Frontend build complete at ./source/dist"
@ -157,7 +159,7 @@ yarn:
cd frontend && yarn
# compile assets using SASS and Rice. compiles scss -> css, and run rice embed-go
compile: frontend-build
compile: generate frontend-build
rm -f source/rice-box.go
cd source && rice embed-go
@ -175,7 +177,7 @@ install-darwin:
mv $(BINARY_NAME) /usr/local/bin/$(BINARY_NAME)
generate:
cd source && go generate
go generate ./...
build-all: clean compile build-folders build-linux build-linux-arm build-darwin build-win compress-folders

View File

@ -6,4 +6,4 @@
export default {
name: 'Help',
}
</script>
</script>

8
go.mod
View File

@ -17,7 +17,6 @@ require (
github.com/hako/durafmt v0.0.0-20200605151348-3a43fc422dd9
github.com/jinzhu/gorm v1.9.12
github.com/mattn/go-sqlite3 v2.0.3+incompatible
github.com/pavius/impi v0.0.3 // indirect
github.com/pelletier/go-toml v1.7.0 // indirect
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.1.0
@ -30,14 +29,15 @@ require (
github.com/spf13/viper v1.6.3
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
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d // indirect
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 // indirect
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c // indirect
google.golang.org/grpc v1.28.1
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/mail.v2 v2.3.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v2 v2.2.8
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect
mvdan.cc/unindent v0.0.0-20170829200357-ff6a34147cea // indirect
)

23
go.sum
View File

@ -114,6 +114,7 @@ github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@ -397,6 +398,7 @@ github.com/liquidweb/liquidweb-go v1.6.1/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVL
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@ -470,8 +472,6 @@ github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014 h1:37VE5TYj2m/FLA9SNr4z
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pavius/impi v0.0.3 h1:DND6MzU+BLABhOZXbELR3FU8b+zDgcq4dOCNLhiTYuI=
github.com/pavius/impi v0.0.3/go.mod h1:x/hU0bfdWIhuOT1SKwiJg++yvkk6EuOtJk8WtDZqgr8=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
@ -576,6 +576,13 @@ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/t-tiger/gorm-bulk-insert/v2 v2.0.1 h1:HGVkRrwDCbmSP6h1CoBDj6l/mhnvsP5JbYaQ4ss0R6o=
github.com/t-tiger/gorm-bulk-insert/v2 v2.0.1/go.mod h1:I3xbaE9ud9/TEXzehwkHx86SyJwqeSNsX2X5oV61jIg=
github.com/tdewolff/minify v1.1.0 h1:nxHQi1ML+g3ZbZHffiZ6eC7vMqNvSRfX3KB5Y5y/kfw=
github.com/tdewolff/minify v2.3.6+incompatible h1:2hw5/9ZvxhWLvBUnHE06gElGYz+Jv9R4Eys0XUzItYo=
github.com/tdewolff/minify/v2 v2.8.0 h1:t3tOPWkTpKhsgxm3IM9Sy8hE2eIt30Oaa+2havJGGIE=
github.com/tdewolff/minify/v2 v2.8.0/go.mod h1:6zN8VLhMfFxNrwHROcboYNo2+huPNu4SV8DPh3PUQ8E=
github.com/tdewolff/parse/v2 v2.4.4 h1:uMdbQRtYbKR/msP9CbI7li9wK6pionYiH6s7ipltyGY=
github.com/tdewolff/parse/v2 v2.4.4/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7 h1:CpHxIaZzVy26GqJn8ptRyto8fuoYOd1v0fXm9bG3wQ8=
github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@ -609,7 +616,6 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@ -677,8 +683,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -730,6 +734,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -771,6 +776,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c=
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -822,8 +829,6 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4 h1:kDtqNkeBrZb8B+atrj50B5XLHpzXXqcCdZPP/ApQ5NY=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d h1:szSOL78iTCl0LF1AMjhSWJj8tIM0KixlUUnBtYXsmd8=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
@ -941,10 +946,6 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unindent v0.0.0-20170829200357-ff6a34147cea h1:M9wqFYtIbcU4ya22owATTPClIVAKkxqoYt2HAn02/JI=
mvdan.cc/unindent v0.0.0-20170829200357-ff6a34147cea/go.mod h1:uK66ibKYZGgWb8OWRdHaAVsidCOAFXHXLpYh0P+WFgA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@ -269,8 +269,7 @@ func servicesDeleteFailuresHandler(w http.ResponseWriter, r *http.Request) {
sendErrorJson(err, w, r)
return
}
err = service.DeleteFailures()
if err != nil {
if err := service.AllFailures().DeleteAll(); err != nil {
sendErrorJson(err, w, r)
return
}

View File

@ -92,7 +92,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)
tmpl := renderEmail(s, f, emailFailure)
email := &emailOutgoing{
To: e.Var2.String,
Subject: subject,
@ -105,7 +105,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{})
tmpl := renderEmail(s, failures.Failure{}, emailSuccess)
email := &emailOutgoing{
To: e.Var2.String,
Subject: subject,
@ -115,13 +115,13 @@ func (e *emailer) OnSuccess(s services.Service) (string, error) {
return tmpl, e.dialSend(email)
}
func renderEmail(s services.Service, f failures.Failure) string {
func renderEmail(s services.Service, f failures.Failure, emailData string) string {
wr := bytes.NewBuffer(nil)
tmpl := template.New("email")
tmpl, err := tmpl.Parse(emailBase)
tmpl, err := tmpl.Parse(emailData)
if err != nil {
log.Errorln(err)
return emailBase
return emailData
}
data := replacer{
@ -133,7 +133,7 @@ func renderEmail(s services.Service, f failures.Failure) string {
if err = tmpl.ExecuteTemplate(wr, "email", data); err != nil {
log.Errorln(err)
return emailBase
return emailData
}
return wr.String()
@ -146,7 +146,7 @@ func (e *emailer) OnTest() (string, error) {
email := &emailOutgoing{
To: e.Var2.String,
Subject: subject,
Template: renderEmail(service, failures.Example()),
Template: renderEmail(service, failures.Example(), emailFailure),
From: e.Var1.String,
}
return subject, e.dialSend(email)

54
notifiers/email_rendered.go Executable file

File diff suppressed because one or more lines are too long

View File

@ -1,628 +0,0 @@
package notifiers
const emailBase = `
{{$banner := "https://assets.statping.com/greenbackground.png"}}
{{$color := "#4caf50"}}
{{if not .Service.Online}}
{{$banner = "https://assets.statping.com/offlinebanner.png"}}
{{$color = "#c30c0c"}}
{{end}}
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<title> Statping Service Notification </title>
<!--[if !mso]><!-- -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!--<![endif]-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
#outlook a {
padding: 0;
}
body {
margin: 0;
padding: 0;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
table,
td {
border-collapse: collapse;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
img {
border: 0;
height: auto;
line-height: 100%;
outline: none;
text-decoration: none;
-ms-interpolation-mode: bicubic;
}
p {
display: block;
margin: 13px 0;
}
</style>
<!--[if mso]>
<xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
<![endif]-->
<!--[if lte mso 11]>
<style type="text/css">
.mj-outlook-group-fix { width:100% !important; }
</style>
<![endif]-->
<!--[if !mso]><!-->
<link href="https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700" rel="stylesheet" type="text/css">
<style type="text/css">
@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700);
</style>
<!--<![endif]-->
<style type="text/css">
@media only screen and (min-width:480px) {
.mj-column-per-100 {
width: 100% !important;
max-width: 100%;
}
}
</style>
<style type="text/css">
@media only screen and (max-width:480px) {
table.mj-full-width-mobile {
width: 100% !important;
}
td.mj-full-width-mobile {
width: auto !important;
}
}
</style>
</head>
<body style="background-color:#E7E7E7;">
<div style="background-color:#E7E7E7;">
<!-- Top Bar -->
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<v:rect style="width:600px;" xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false">
<v:fill origin="0.5, 0" position="0.5, 0" src="{{$banner}}" color="#FF3FB4" type="tile" />
<v:textbox style="mso-fit-shape-to-text:true" inset="0,0,0,0">
<![endif]-->
<div style="background:#FF3FB4 url({{$banner}}) top center / auto repeat;margin:0px auto;max-width:600px;">
<div style="line-height:0;font-size:0;">
<table align="center" background="{{$banner}}" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#FF3FB4 url({{$banner}}) top center / auto repeat;width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:0px;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tr>
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;">
<tbody>
<tr>
<td style="width:45px;"> <a href="https://statping.com" target="_blank">
<img
alt="Statping" height="auto" src="https://assets.statping.com/iconlight.png" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:13px;" width="45"
/>
</a> </td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!--[if mso | IE]>
</v:textbox>
</v:rect>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tr>
<td align="left" style="font-size:0px;padding:15px;word-break:break-word;">
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:22px;line-height:30px;text-align:left;color:#000000;">
{{if .Service.Online}}
{{.Service.Name}} is back online.
{{else}}
{{.Service.Name}} is currently offline, you might want to check it.
{{end}}
</div>
</td>
</tr>
<tr>
<td style="font-size:0px;padding:20px 0;padding-top:10px;padding-right:0px;padding-bottom:10px;padding-left:0px;word-break:break-word;">
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div style="margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 0;padding-bottom:10px;padding-left:0px;padding-right:0px;padding-top:10px;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tr>
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:20px;line-height:1;text-align:center;color:#626262;">
{{if .Service.Online}}
Online for {{.Service.Uptime.Human}}
{{else}}
Offline for {{.Service.Downtime.Human}}
{{end}}
</div>
</td>
</tr>
<tr>
<td align="center" vertical-align="middle" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:separate;line-height:100%;">
<tr>
<td align="center" bgcolor="{{$color}}" role="presentation" style="border:none;border-radius:4px;cursor:auto;mso-padding-alt:10px 25px;background:{{$color}};" valign="middle">
<a href="{{.Core.Domain}}/service/{{.Service.Id}}" style="display:inline-block;background:{{$color}};color:#ffffff;font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;font-weight:normal;line-height:120%;margin:0;text-decoration:none;text-transform:none;padding:10px 25px;mso-padding-alt:0px;border-radius:4px;"
target="_blank">
View Dashboard
</a> </td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
<!-- Bottom Graphic -->
<tr>
<td style="font-size:0px;padding:0px;word-break:break-word;">
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div style="background:#fafafa;background-color:#fafafa;margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#fafafa;background-color:#fafafa;width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:0px;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:20px;line-height:1;text-align:left;color:#626262;">Service Domain</div>
</td>
</tr>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;padding-top:0px;word-break:break-word;">
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:14px;line-height:1;text-align:left;color:#626262;">{{.Service.Domain}}</div>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
<tr>
<td style="font-size:0px;padding:0px;word-break:break-word;">
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:0px;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
{{if .Failure}}
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:20px;line-height:1;text-align:left;color:#626262;">Current Issue</div>
</td>
</tr>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;padding-top:0px;word-break:break-word;">
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:14px;line-height:1;text-align:left;color:#626262;">{{.Failure.Issue}}</div>
</td>
</tr>
</table>
</div>
{{end}}
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
<tr>
<td style="font-size:0px;word-break:break-word;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td height="30" style="vertical-align:top;height:30px;">
<![endif]-->
<div style="height:30px;"> &nbsp; </div>
<!--[if mso | IE]>
</td></tr></table>
<![endif]-->
</td>
</tr>
<tr>
<td style="font-size:0px;padding:0;word-break:break-word;">
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<v:rect style="width:600px;" xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false">
<v:fill origin="0.5, 0" position="0.5, 0" src="{{$banner}}" color="#F15822" type="tile" />
<v:textbox style="mso-fit-shape-to-text:true" inset="0,0,0,0">
<![endif]-->
<div style="background:#F15822 url({{$banner}}) top center / auto repeat;margin:0px auto;max-width:600px;">
<div style="line-height:0;font-size:0;">
<table align="center" background="{{$banner}}" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#F15822 url({{$banner}}) top center / auto repeat;width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tr>
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;">
<tbody>
<tr>
<td style="width:250px;"> <a href="https://www.sphero.com" target="_blank">
<img
height="auto" src="https://assets.statping.com/statpingcom.png" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:13px;" width="250"
/>
</a> </td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!--[if mso | IE]>
</v:textbox>
</v:rect>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
<tr>
<td style="font-size:0px;padding:20px 0;padding-top:10px;padding-bottom:0;word-break:break-word;">
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div style="margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 0;padding-bottom:0;padding-top:10px;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tr>
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:11px;line-height:16px;text-align:center;color:#445566;">You are receiving this email because one of your services has changed on your Statping instance. You can modify this email on the Email Notifier page in Settings.</div>
</td>
</tr>
<tr>
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:11px;line-height:16px;text-align:center;color:#445566;">&copy; Statping</div>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
<tr>
<td style="font-size:0px;padding:20px 0;padding-top:0;padding-bottom:0;word-break:break-word;">
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div style="margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 0;padding-bottom:0;padding-top:0;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0;line-height:0;text-align:left;display:inline-block;width:100%;direction:ltr;">
<!--[if mso | IE]>
<table
border="0" cellpadding="0" cellspacing="0" role="presentation"
>
<tr>
<td
style="vertical-align:top;width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%">
<tbody>
<tr>
<td style="vertical-align:top;padding-right:0;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="" width="100%">
<tr>
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:11px;font-weight:bold;line-height:16px;text-align:center;color:#445566;"><a class="footer-link" href="https://statping.com">Statping.com</a>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0; <a class="footer-link" href="https://github.com/statping/statping">Github</a>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;
<a class="footer-link" href="https://statping.com/privacy">Privacy</a>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0; <a class="footer-link" href="https://www.google.com">Unsubscribe</a></div>
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</div>
</body>
</html>
`

269
notifiers/generate/main.go Normal file
View File

@ -0,0 +1,269 @@
// +build ignore
package main
import (
"bytes"
"encoding/json"
"fmt"
"github.com/statping/statping/utils"
"github.com/tdewolff/minify/v2"
"github.com/tdewolff/minify/v2/html"
"os"
"time"
)
var (
mjmlApplication string
mjmlPrivate string
)
func main() {
utils.InitEnvs()
mjmlApplication = os.Getenv("MJML_APP")
mjmlPrivate = os.Getenv("MJML_PRIVATE")
fmt.Println(mjmlApplication)
success := convertMJML(emailSuccessMJML)
fail := convertMJML(emailFailureMJML)
htmlOut := `// DO NOT EDIT ** This file was generated with go generate on ` + utils.Now().String() + ` ** DO NOT EDIT //
package notifiers
const emailSuccess = ` + minimize(success) + `
const emailFailure = ` + minimize(fail) + `
`
fmt.Println(htmlOut)
utils.SaveFile("email_rendered.go", []byte(htmlOut))
}
type mjmlInput struct {
Mjml string `json:"mjml"`
}
func minimize(val string) string {
m := minify.New()
m.Add("text/html", &html.Minifier{
KeepDefaultAttrVals: true,
})
s, err := m.String("text/html", val)
if err != nil {
panic(err)
}
return fmt.Sprintf("`%s`", s)
}
func convertMJML(mjml string) string {
input, _ := json.Marshal(mjmlInput{mjml})
auth := fmt.Sprintf("%s:%s", mjmlApplication, mjmlPrivate)
resp, _, err := utils.HttpRequest("https://"+auth+"@api.mjml.io/v1/render", "POST", "application/json", nil, bytes.NewBuffer(input), 15*time.Minute, false, nil)
if err != nil {
panic(err)
}
var respData mjmlApi
if err := json.Unmarshal(resp, &respData); err != nil {
panic(err)
}
return respData.Html
}
type mjmlApi struct {
Html string `json:"html"`
Mjml string `json:"mjml"`
Version string `json:"mjml_version"`
}
const emailFailureMJML = `<mjml>
<mj-head>
<mj-title>Statping Service Notification</mj-title>
</mj-head>
<mj-body background-color="#E7E7E7">
<mj-raw>
<!-- Top Bar -->
</mj-raw>
<mj-section background-color="#a30911" background-url="https://assets.statping.com/offlinebanner.png" padding="0px">
<mj-column>
<mj-image width="45px" href="https://statping.com" src="https://assets.statping.com/iconlight.png" align="center" alt="Sphero"></mj-image>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff">
<mj-column width="100%">
<mj-text font-family="Ubuntu, Helvetica, Arial, sans-serif" font-size="22px" padding="15px" line-height="30px">
{{.Service.Name}} is currently offline, you might want to check it.
</mj-text>
<mj-section padding-left="0px" padding-right="0px" padding-top="10px" padding-bottom="10px">
<mj-column>
<mj-text font-color="#d50d0d" align="center" font-size="20px" color="#626262">Offline for {{.Service.Downtime.Human}}</mj-text>
<mj-button border-radius="4px" background-color="#cb121c" href="{{.Core.Domain}}/service/{{.Service.Id}}">View Dashboard</mj-button>
</mj-column>
</mj-section>
<mj-raw>
<!-- Bottom Graphic -->
</mj-raw>
<mj-section padding="0px" background-color="#fafafa">
<mj-column>
<mj-text font-size="20px" color="#626262">Service Domain</mj-text>
<mj-text padding-top="0px" font-size="14px" color="#626262">{{.Service.Domain}}</mj-text>
</mj-column>
</mj-section>
<mj-section padding="0px" background-color="#ffffff">
<mj-column>
<mj-text font-size="20px" color="#626262">Current Issue</mj-text>
<mj-text padding-top="0px" font-size="14px" color="#626262">{{.Failure.Issue}}</mj-text>
</mj-column>
</mj-section>
<mj-spacer height="30px" />
<mj-section padding="0" background-url="https://assets.statping.com/offlinebanner.png" background-color="#a30911">
<mj-column>
<mj-image width="250px" href="https://www.sphero.com" src="https://assets.statping.com/statpingcom.png" align="center"></mj-image>
</mj-column>
</mj-section>
<mj-section padding-bottom="0" padding-top="10px">
<mj-column>
<mj-text color="#445566" font-size="11px" align="center" line-height="16px">
You are receiving this email because one of your services has changed on your Statping instance. You can modify this email on the Email Notifier page in Settings.
</mj-text>
<mj-text color="#445566" font-size="11px" align="center" line-height="16px">
&copy; Statping
</mj-text>
</mj-column>
</mj-section>
<mj-section padding-top="0" padding-bottom="0">
<mj-group>
<mj-column width="100%" padding-right="0">
<mj-text color="#445566" font-size="11px" align="center" line-height="16px" font-weight="bold">
<a class="footer-link" href="https://statping.com">Statping.com</a>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;
<a class="footer-link" href="https://github.com/statping/statping">Github</a>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;
<a class="footer-link" href="https://statping.com/privacy">Privacy</a>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;
<a class="footer-link" href="https://news.statping.com/delete?email={{.Email}}">Unsubscribe</a>
</mj-text>
</mj-column>
</mj-group>
</mj-section>
</mj-column>
</mj-section>
</mj-body>
</mjml>`
const emailSuccessMJML = `<mjml>
<mj-head>
<mj-title>Statping Service Notification</mj-title>
</mj-head>
<mj-body background-color="#E7E7E7">
<mj-raw>
<!-- Top Bar -->
</mj-raw>
<mj-section background-color="#12ab0c" background-url="https://assets.statping.com/greenbackground.png" padding="0px">
<mj-column>
<mj-image width="45px" href="https://statping.com" src="https://assets.statping.com/iconlight.png" align="center" alt="Sphero"></mj-image>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff">
<mj-column width="100%">
<mj-text font-family="Ubuntu, Helvetica, Arial, sans-serif" font-size="22px" padding="15px" line-height="30px">
{{.Service.Name}} is currently offline, you might want to check it.
</mj-text>
<mj-section padding-left="0px" padding-right="0px" padding-top="10px" padding-bottom="10px">
<mj-column>
<mj-text font-color="#d50d0d" align="center" font-size="20px" color="#626262">Offline for {{.Service.Downtime.Human}}</mj-text>
<mj-button border-radius="4px" background-color="#4caf50" href="{{.Core.Domain}}/service/{{.Service.Id}}">View Dashboard</mj-button>
</mj-column>
</mj-section>
<mj-raw>
<!-- Bottom Graphic -->
</mj-raw>
<mj-section padding="0px" background-color="#fafafa">
<mj-column>
<mj-text font-size="20px" color="#626262">Service Domain</mj-text>
<mj-text padding-top="0px" font-size="14px" color="#626262">{{.Service.Domain}}</mj-text>
</mj-column>
</mj-section>
<mj-section padding="0px" background-color="#ffffff">
<mj-column>
<mj-text font-size="20px" color="#626262">Current Issue</mj-text>
<mj-text padding-top="0px" font-size="14px" color="#626262">{{.Failure.Issue}}</mj-text>
</mj-column>
</mj-section>
<mj-spacer height="30px" />
<mj-section padding="0" background-url="https://assets.statping.com/greenbackground.png" background-color="#12ab0c">
<mj-column>
<mj-image width="250px" href="https://www.sphero.com" src="https://assets.statping.com/statpingcom.png" align="center"></mj-image>
</mj-column>
</mj-section>
<mj-section padding-bottom="0" padding-top="10px">
<mj-column>
<mj-text color="#445566" font-size="11px" align="center" line-height="16px">
You are receiving this email because one of your services has changed on your Statping instance. You can modify this email on the Email Notifier page in Settings.
</mj-text>
<mj-text color="#445566" font-size="11px" align="center" line-height="16px">
&copy; Statping
</mj-text>
</mj-column>
</mj-section>
<mj-section padding-top="0" padding-bottom="0">
<mj-group>
<mj-column width="100%" padding-right="0">
<mj-text color="#445566" font-size="11px" align="center" line-height="16px" font-weight="bold">
<a class="footer-link" href="https://statping.com">Statping.com</a>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;
<a class="footer-link" href="https://github.com/statping/statping">Github</a>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;
<a class="footer-link" href="https://statping.com/privacy">Privacy</a>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;
<a class="footer-link" href="https://news.statping.com/delete?email={{.Email}}">Unsubscribe</a>
</mj-text>
</mj-column>
</mj-group>
</mj-section>
</mj-column>
</mj-section>
</mj-body>
</mjml>`

View File

@ -10,6 +10,8 @@ import (
"time"
)
//go:generate go run generate/main.go
var log = utils.Log.WithField("type", "notifier")
type replacer struct {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

View File

@ -1,3 +0,0 @@
package checkins
//go:generate counterfeiter . Checkin

View File

@ -61,7 +61,6 @@ func (h Hitters) DeleteAll() error {
func (h Hitters) Sum() int64 {
var r IntResult
h.db.Select("CAST(SUM(latency) as INT) as amount").Scan(&r)
return r.Amount
}

View File

@ -10,7 +10,7 @@ type Incident struct {
ServiceId int64 `gorm:"index;column:service" json:"service"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at" json:"updated_at"`
Updates []*IncidentUpdate `gorm:"foreignkey:incident;association_foreignkey:id;association_autoupdate:false;association_autocreate:false" json:"updates,omitempty"`
Updates []*IncidentUpdate `gorm:"foreignkey:incident;association_foreignkey:id" json:"updates,omitempty"`
}
// IncidentUpdate contains updates based on a Incident

View File

@ -16,7 +16,7 @@ var (
)
func (s *Service) AfterFind() {
db.Model(s).Related(&s.Incidents).Related(&s.Messages).Related(&s.Checkins)
db.Model(s).Related(&s.Incidents).Related(&s.Messages).Related(&s.Checkins).Related(&s.Incidents)
metrics.Query("service", "find")
}
@ -87,8 +87,8 @@ func (s *Service) Create() error {
func (s *Service) Update() error {
q := db.Update(s)
allServices[s.Id] = s
s.Close()
allServices[s.Id] = s
s.SleepDuration = s.Duration()
go ServiceCheckQueue(allServices[s.Id], true)
return q.Error()
@ -96,29 +96,38 @@ func (s *Service) Update() error {
func (s *Service) Delete() error {
s.Close()
if err := s.DeleteFailures(); err != nil {
if err := s.AllFailures().DeleteAll(); err != nil {
return err
}
if err := s.DeleteHits(); err != nil {
if err := s.AllHits().DeleteAll(); err != nil {
return err
}
if err := s.DeleteCheckins(); err != nil {
return err
}
db.Model(s).Association("Checkins").Clear()
if err := s.DeleteIncidents(); err != nil {
return err
}
db.Model(s).Association("Incidents").Clear()
if err := s.DeleteMessages(); err != nil {
return err
}
db.Model(s).Association("Messages").Clear()
delete(allServices, s.Id)
q := db.Model(&Service{}).Delete(s)
return q.Error()
}
func (s *Service) DeleteFailures() error {
return s.AllFailures().DeleteAll()
}
func (s *Service) DeleteHits() error {
return s.AllHits().DeleteAll()
func (s *Service) DeleteMessages() error {
for _, m := range s.Messages {
if err := m.Delete(); err != nil {
return err
}
}
db.Model(s).Association("messages").Clear()
return nil
}
func (s *Service) DeleteCheckins() error {
@ -127,5 +136,6 @@ func (s *Service) DeleteCheckins() error {
return err
}
}
db.Model(s).Association("checkins").Clear()
return nil
}

View File

@ -6,5 +6,6 @@ func (s *Service) DeleteIncidents() error {
return err
}
}
db.Model(s).Association("Updates").Clear()
return nil
}

View File

@ -10,6 +10,7 @@ import (
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/hits"
"github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
"github.com/statping/statping/utils"
@ -99,6 +100,20 @@ var incidentUpdate1 = &incidents.IncidentUpdate{
CreatedAt: utils.Now().Add(-5 * time.Second),
}
var message1 = &messages.Message{
Title: "Example Message",
Description: "Used for testing",
StartOn: utils.Now().Add(15 * time.Minute),
EndOn: utils.Now().Add(30 * time.Minute),
ServiceId: 1,
NotifyUsers: null.NewNullBool(false),
NotifyMethod: "",
NotifyBefore: null.NewNullInt64(0),
NotifyBeforeScale: "",
CreatedAt: utils.Now(),
UpdatedAt: utils.Now(),
}
type exampleGRPC struct {
pb.UnimplementedRouteGuideServer
}
@ -183,11 +198,12 @@ func startupDb(t *testing.T) {
require.Nil(t, err)
db, err := database.OpenTester()
require.Nil(t, err)
db.AutoMigrate(&Service{}, &notifications.Notification{}, &hits.Hit{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &failures.Failure{}, &incidents.Incident{}, &incidents.IncidentUpdate{})
db.AutoMigrate(&Service{}, &notifications.Notification{}, &messages.Message{}, &hits.Hit{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &failures.Failure{}, &incidents.Incident{}, &incidents.IncidentUpdate{})
checkins.SetDB(db)
failures.SetDB(db)
incidents.SetDB(db)
notifications.SetDB(db)
messages.SetDB(db)
hits.SetDB(db)
SetDB(db)
@ -201,6 +217,7 @@ func startupDb(t *testing.T) {
db.Create(&incident1)
db.Create(&incidentUpdate1)
db.Create(&notification.Notification)
db.Create(&message1)
}
func TestServices(t *testing.T) {
@ -521,6 +538,10 @@ func TestServices(t *testing.T) {
err = item.Delete()
require.Nil(t, err)
// after deleted service, make sure checkins, failures, hits, and incidents are also delete
assert.Len(t, item.AllFailures().List(), 0)
assert.Len(t, item.AllHits().List(), 0)
checkin := item.Checkins
assert.Len(t, checkin, 0)
for _, c := range checkin {
@ -529,9 +550,6 @@ func TestServices(t *testing.T) {
assert.False(t, c.IsRunning())
}
assert.Len(t, item.AllFailures().List(), 0)
assert.Len(t, item.AllHits().List(), 0)
inc := item.Incidents
assert.Len(t, inc, 0)
for _, i := range inc {

View File

@ -8,13 +8,13 @@ import (
// AuthUser will return the User and a boolean if authentication was correct.
// accepts username, and password as a string
func AuthUser(username, password string) (*User, bool) {
func AuthUser(username, passwordHash string) (*User, bool) {
user, err := FindByUsername(username)
if err != nil {
log.Warnln(fmt.Errorf("user %v not found", username))
return nil, false
}
if utils.CheckHash(password, user.Password) {
if utils.CheckHash(passwordHash, user.Password) {
user.UpdatedAt = time.Now().UTC()
user.Update()
return user, true

View File

@ -36,7 +36,7 @@ func TestFind(t *testing.T) {
}
func TestAuthUser(t *testing.T) {
u, err := AuthUser("example_user", "password12345")
u, err := AuthUser("example_user", utils.HashPassword("password12345"))
require.Nil(t, err)
assert.Equal(t, "example_user", u.Username)

View File

@ -162,7 +162,7 @@ func DurationReadable(d time.Duration) string {
// // body - The body or form data to send with HTTP request
// // timeout - Specific duration to timeout on. time.Duration(30 * time.Seconds)
// // You can use a HTTP Proxy if you HTTP_PROXY environment variable
func HttpRequest(endpoint, method string, content interface{}, headers []string, body io.Reader, timeout time.Duration, verifySSL bool, customTLS *tls.Config) ([]byte, *http.Response, error) {
func HttpRequest(endpoint, method string, contentType interface{}, headers []string, body io.Reader, timeout time.Duration, verifySSL bool, customTLS *tls.Config) ([]byte, *http.Response, error) {
var err error
var req *http.Request
if method == "" {
@ -175,8 +175,8 @@ func HttpRequest(endpoint, method string, content interface{}, headers []string,
// set default headers so end user can overwrite them if needed
req.Header.Set("User-Agent", "Statping")
req.Header.Set("Statping-Version", Version)
if content != nil {
req.Header.Set("Content-Type", content.(string))
if contentType != nil {
req.Header.Set("Content-Type", contentType.(string))
}
verifyHost := req.URL.Hostname()