+
diff --git a/frontend/src/pages/Settings.vue b/frontend/src/pages/Settings.vue
index 29fb201a..527cf0c5 100644
--- a/frontend/src/pages/Settings.vue
+++ b/frontend/src/pages/Settings.vue
@@ -60,12 +60,7 @@
-
+
@@ -82,10 +77,12 @@
API Secret is used for read, create, update and delete routes
You can Regenerate API Keys if you need to.
- Regenerate API Keys
+
diff --git a/go.mod b/go.mod
index 6b2974f5..5f29be9e 100644
--- a/go.mod
+++ b/go.mod
@@ -5,9 +5,7 @@ go 1.14
require (
github.com/GeertJohan/go.rice v1.0.0
- github.com/ararog/timeago v0.0.0-20160328174124-e9969cf18b8d
github.com/dgrijalva/jwt-go v3.2.0+incompatible
- github.com/dustin/go-humanize v1.0.0
github.com/fatih/structs v1.1.0
github.com/foomo/simplecert v1.7.5
github.com/foomo/tlsconfig v0.0.0-20180418120404-b67861b076c9
@@ -15,16 +13,12 @@ require (
github.com/getsentry/sentry-go v0.5.1
github.com/go-mail/mail v2.3.1+incompatible
github.com/gorilla/mux v1.7.4
- github.com/gorilla/securecookie v1.1.1
github.com/hako/durafmt v0.0.0-20200605151348-3a43fc422dd9
github.com/jinzhu/gorm v1.9.12
- github.com/magiconair/properties v1.8.1
github.com/mattn/go-sqlite3 v2.0.3+incompatible
- github.com/mitchellh/mapstructure v1.2.2 // 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
- github.com/russross/blackfriday/v2 v2.0.1
github.com/sirupsen/logrus v1.5.0
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/cast v1.3.1 // indirect
@@ -36,10 +30,8 @@ require (
github.com/t-tiger/gorm-bulk-insert/v2 v2.0.1
golang.org/x/crypto v0.0.0-20200420201142-3c4aac89819a
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
- golang.org/x/text v0.3.2 // indirect
google.golang.org/grpc v1.28.1
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
- gopkg.in/ini.v1 v1.55.0 // indirect
gopkg.in/mail.v2 v2.3.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v2 v2.2.8
diff --git a/go.sum b/go.sum
index b3b94e18..9715f9c4 100755
--- a/go.sum
+++ b/go.sum
@@ -54,6 +54,7 @@ github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSW
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
+github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
github.com/Azure/go-autorest/autorest/to v0.3.0 h1:zebkZaadz7+wIQYgC7GXaz3Wb28yKYfVkkBKwc38VF8=
@@ -98,8 +99,6 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.61.112/go.mod h1:pUKYbK5JQ+1Dfxk80P0qx
github.com/aliyun/alibaba-cloud-sdk-go v1.61.131 h1:ePFkFbwr/u1HM9/p+azqI5UaxwY1hYKv+H8dkaRCLs4=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.131/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
-github.com/ararog/timeago v0.0.0-20160328174124-e9969cf18b8d h1:ZX0t+GA3MWiP7LWt5xWOphWRQd5JwL4VW5uLW83KM8g=
-github.com/ararog/timeago v0.0.0-20160328174124-e9969cf18b8d/go.mod h1:EcJ034SpbWy4heOSDiBZJRn3b5wKJM1b4sFfYeVAkI4=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-sdk-go v1.30.20 h1:ktsy2vodSZxz/arYqo7DlpkIeNohHL+4Rmjdo7YGtrE=
github.com/aws/aws-sdk-go v1.30.20/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
@@ -287,18 +286,18 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
-github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
-github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hako/durafmt v0.0.0-20200605151348-3a43fc422dd9 h1:IEhIezS5kcD4ZzOwVl8dAyJ9JCi4Xo6tg44Vj/z7UsI=
github.com/hako/durafmt v0.0.0-20200605151348-3a43fc422dd9/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE=
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
@@ -368,6 +367,7 @@ github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b h1:DzHy0GlWeF0KAglaTMY
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -439,6 +439,7 @@ github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY
github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM=
github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
+github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@@ -561,6 +562,7 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y
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/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=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -613,6 +615,7 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y=
@@ -714,6 +717,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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/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=
@@ -753,8 +757,6 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
-golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/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/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -829,6 +831,7 @@ google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO50
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -887,6 +890,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
+gopkg.in/h2non/gock.v1 v1.0.15 h1:SzLqcIlb/fDfg7UvukMpNcWsu7sI5tWwL+KCATZqks0=
gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
diff --git a/handlers/dashboard.go b/handlers/dashboard.go
index 915163f8..0f2c7fa9 100644
--- a/handlers/dashboard.go
+++ b/handlers/dashboard.go
@@ -33,12 +33,15 @@ func logsHandler(w http.ResponseWriter, r *http.Request) {
type themeApi struct {
Directory string `json:"directory,omitempty"`
Base string `json:"base"`
- Variables string `json:"variables"`
+ Forms string `json:"forms"`
+ Layout string `json:"layout"`
+ Mixins string `json:"mixins"`
Mobile string `json:"mobile"`
+ Variables string `json:"variables"`
}
func apiThemeViewHandler(w http.ResponseWriter, r *http.Request) {
- var base, variables, mobile, dir string
+ var base, forms, layout, mixins, variables, mobile, dir string
assets := utils.Directory + "/assets"
if _, err := os.Stat(assets); err == nil {
@@ -49,10 +52,16 @@ func apiThemeViewHandler(w http.ResponseWriter, r *http.Request) {
base, _ = utils.OpenFile(dir + "/scss/base.scss")
variables, _ = utils.OpenFile(dir + "/scss/variables.scss")
mobile, _ = utils.OpenFile(dir + "/scss/mobile.scss")
+ layout, _ = utils.OpenFile(dir + "/scss/layout.scss")
+ forms, _ = utils.OpenFile(dir + "/scss/forms.scss")
+ mixins, _ = utils.OpenFile(dir + "/scss/mixin.scss")
} else {
base, _ = source.TmplBox.String("scss/base.scss")
variables, _ = source.TmplBox.String("scss/variables.scss")
mobile, _ = source.TmplBox.String("scss/mobile.scss")
+ layout, _ = source.TmplBox.String("scss/layout.scss")
+ forms, _ = source.TmplBox.String("scss/forms.scss")
+ mixins, _ = source.TmplBox.String("scss/mixin.scss")
}
resp := &themeApi{
@@ -60,6 +69,9 @@ func apiThemeViewHandler(w http.ResponseWriter, r *http.Request) {
Base: base,
Variables: variables,
Mobile: mobile,
+ Layout: layout,
+ Forms: forms,
+ Mixins: mixins,
}
returnJson(resp, w, r)
}
diff --git a/handlers/routes.go b/handlers/routes.go
index 45d1bd76..93695ca5 100644
--- a/handlers/routes.go
+++ b/handlers/routes.go
@@ -128,6 +128,7 @@ func Router() *mux.Router {
api.Handle("/api/services/{id}", scoped(apiServiceHandler)).Methods("GET")
api.Handle("/api/reorder/services", authenticated(reorderServiceHandler, false)).Methods("POST")
api.Handle("/api/services/{id}", authenticated(apiServiceUpdateHandler, false)).Methods("POST")
+ api.Handle("/api/services/{id}", authenticated(apiServicePatchHandler, false)).Methods("PATCH")
api.Handle("/api/services/{id}", authenticated(apiServiceDeleteHandler, false)).Methods("DELETE")
api.Handle("/api/services/{id}/failures", scoped(apiServiceFailuresHandler)).Methods("GET")
api.Handle("/api/services/{id}/failures", authenticated(servicesDeleteFailuresHandler, false)).Methods("DELETE")
diff --git a/handlers/services.go b/handlers/services.go
index be1a7b12..38d55e74 100644
--- a/handlers/services.go
+++ b/handlers/services.go
@@ -74,6 +74,46 @@ func apiCreateServiceHandler(w http.ResponseWriter, r *http.Request) {
sendJsonAction(service, "create", w, r)
}
+type servicePatchReq struct {
+ Online bool `json:"online"`
+ Issue string `json:"issue,omitempty"`
+ Latency int64 `json:"latency,omitempty"`
+}
+
+func apiServicePatchHandler(w http.ResponseWriter, r *http.Request) {
+ service, err := findService(r)
+ if err != nil {
+ sendErrorJson(err, w, r)
+ return
+ }
+ var req servicePatchReq
+ if err := DecodeJSON(r, &req); err != nil {
+ sendErrorJson(err, w, r)
+ return
+ }
+
+ service.Online = req.Online
+ service.Latency = req.Latency
+
+ issueDefault := "Service was triggered to be offline"
+ if req.Issue != "" {
+ issueDefault = req.Issue
+ }
+
+ if !req.Online {
+ services.RecordFailure(service, issueDefault)
+ } else {
+ services.RecordSuccess(service)
+ }
+
+ if err := service.Update(); err != nil {
+ sendErrorJson(err, w, r)
+ return
+ }
+
+ sendJsonAction(service, "update", w, r)
+}
+
func apiServiceUpdateHandler(w http.ResponseWriter, r *http.Request) {
service, err := findService(r)
if err != nil {
@@ -84,9 +124,7 @@ func apiServiceUpdateHandler(w http.ResponseWriter, r *http.Request) {
sendErrorJson(err, w, r)
return
}
-
- err = service.Update()
- if err != nil {
+ if err := service.Update(); err != nil {
sendErrorJson(err, w, r)
return
}
diff --git a/handlers/services_test.go b/handlers/services_test.go
index 5a0afb02..981c8b85 100644
--- a/handlers/services_test.go
+++ b/handlers/services_test.go
@@ -61,11 +61,11 @@ func TestApiServiceRoutes(t *testing.T) {
Method: "GET",
ExpectedContains: []string{`"name":"Google"`},
ExpectedStatus: 200,
- ResponseLen: 6,
+ ResponseLen: 7,
BeforeTest: SetTestENV,
FuncTest: func(t *testing.T) error {
count := len(services.Services())
- if count != 6 {
+ if count != 7 {
return errors.Errorf("incorrect services count: %d", count)
}
return nil
@@ -77,11 +77,11 @@ func TestApiServiceRoutes(t *testing.T) {
Method: "GET",
ExpectedContains: []string{`"name":"Google"`},
ExpectedStatus: 200,
- ResponseLen: 5,
+ ResponseLen: 6,
BeforeTest: UnsetTestENV,
FuncTest: func(t *testing.T) error {
count := len(services.Services())
- if count != 6 {
+ if count != 7 {
return errors.Errorf("incorrect services count: %d", count)
}
return nil
@@ -261,10 +261,10 @@ func TestApiServiceRoutes(t *testing.T) {
"order_id": 0
}`,
ExpectedStatus: 200,
- ExpectedContains: []string{Success, `"type":"service","method":"create"`, `"public":false`, `"group_id":1`},
+ ExpectedContains: []string{Success, MethodCreate, `"type":"service",`, `"public":false`, `"group_id":1`},
FuncTest: func(t *testing.T) error {
count := len(services.Services())
- if count != 7 {
+ if count != 8 {
return errors.Errorf("incorrect services count: %d", count)
}
return nil
@@ -326,7 +326,27 @@ func TestApiServiceRoutes(t *testing.T) {
ExpectedContains: []string{Success, MethodDelete},
FuncTest: func(t *testing.T) error {
count := len(services.Services())
- if count != 6 {
+ if count != 7 {
+ return errors.Errorf("incorrect services count: %d", count)
+ }
+ return nil
+ },
+ SecureRoute: true,
+ },
+ {
+ Name: "Statping Patch Static Service",
+ URL: "/api/services/7",
+ Method: "PATCH",
+ ExpectedStatus: 200,
+ Body: `{
+ "online": false,
+ "latency": 30500,
+ "issue": "This is a failure string you can create"
+ },`,
+ ExpectedContains: []string{Success, MethodUpdate},
+ FuncTest: func(t *testing.T) error {
+ count := len(services.Services())
+ if count != 7 {
return errors.Errorf("incorrect services count: %d", count)
}
return nil
diff --git a/notifiers/notifiers_test.go b/notifiers/notifiers_test.go
index e1f25d82..248f4245 100644
--- a/notifiers/notifiers_test.go
+++ b/notifiers/notifiers_test.go
@@ -1,9 +1,9 @@
package notifiers
import (
- "github.com/magiconair/properties/assert"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/services"
+ "github.com/stretchr/testify/assert"
"testing"
)
diff --git a/types/configs/config_test.go b/types/configs/config_test.go
index 946b052e..ff5da88f 100644
--- a/types/configs/config_test.go
+++ b/types/configs/config_test.go
@@ -2,6 +2,7 @@ package configs
import (
"github.com/statping/statping/utils"
+ "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
)
@@ -51,3 +52,9 @@ func TestPostgresConfig(t *testing.T) {
err := Connect(postgres, false)
require.Nil(t, err)
}
+
+func TestFileSQLFile(t *testing.T) {
+ file, err := findSQLin(utils.Directory)
+ require.Nil(t, err)
+ assert.Equal(t, "statping.db", file)
+}
diff --git a/types/services/failures.go b/types/services/failures.go
index 36027249..75cff278 100644
--- a/types/services/failures.go
+++ b/types/services/failures.go
@@ -2,7 +2,6 @@ package services
import (
"fmt"
- humanize "github.com/dustin/go-humanize"
"github.com/statping/statping/types/failures"
"strings"
"time"
@@ -20,13 +19,6 @@ func (s *Service) FailuresSince(t time.Time) failures.Failurer {
return failures.Since(t, s)
}
-func (s Service) DowntimeAgo() string {
- if s.LastOnline.IsZero() {
- return "Never been online"
- }
- return humanize.Time(s.LastOnline)
-}
-
func (s Service) DowntimeText() string {
last := s.AllFailures().Last()
if last == nil {
diff --git a/types/services/routine.go b/types/services/routine.go
index 7860b3c3..da85ffdd 100644
--- a/types/services/routine.go
+++ b/types/services/routine.go
@@ -94,7 +94,7 @@ func CheckIcmp(s *Service, record bool) (*Service, error) {
dur, err := utils.Ping(s.Domain, s.Timeout)
if err != nil {
if record {
- recordFailure(s, fmt.Sprintf("Could not send ICMP to service %v, %v", s.Domain, err))
+ RecordFailure(s, fmt.Sprintf("Could not send ICMP to service %v, %v", s.Domain, err))
}
return s, err
}
@@ -104,7 +104,7 @@ func CheckIcmp(s *Service, record bool) (*Service, error) {
s.LastResponse = ""
s.Online = true
if record {
- recordSuccess(s)
+ RecordSuccess(s)
}
return s, nil
}
@@ -118,7 +118,7 @@ func CheckGrpc(s *Service, record bool) (*Service, error) {
dnsLookup, err := dnsCheck(s)
if err != nil {
if record {
- recordFailure(s, fmt.Sprintf("Could not get IP address for GRPC service %v, %v", s.Domain, err))
+ RecordFailure(s, fmt.Sprintf("Could not get IP address for GRPC service %v, %v", s.Domain, err))
}
return s, err
}
@@ -137,13 +137,13 @@ func CheckGrpc(s *Service, record bool) (*Service, error) {
}
if err != nil {
if record {
- recordFailure(s, fmt.Sprintf("Dial Error %v", err))
+ RecordFailure(s, fmt.Sprintf("Dial Error %v", err))
}
return s, err
}
if err := conn.Close(); err != nil {
if record {
- recordFailure(s, fmt.Sprintf("%v Socket Close Error %v", strings.ToUpper(s.Type), err))
+ RecordFailure(s, fmt.Sprintf("%v Socket Close Error %v", strings.ToUpper(s.Type), err))
}
return s, err
}
@@ -151,7 +151,7 @@ func CheckGrpc(s *Service, record bool) (*Service, error) {
s.LastResponse = ""
s.Online = true
if record {
- recordSuccess(s)
+ RecordSuccess(s)
}
return s, nil
}
@@ -165,7 +165,7 @@ func CheckTcp(s *Service, record bool) (*Service, error) {
dnsLookup, err := dnsCheck(s)
if err != nil {
if record {
- recordFailure(s, fmt.Sprintf("Could not get IP address for TCP service %v, %v", s.Domain, err))
+ RecordFailure(s, fmt.Sprintf("Could not get IP address for TCP service %v, %v", s.Domain, err))
}
return s, err
}
@@ -189,7 +189,7 @@ func CheckTcp(s *Service, record bool) (*Service, error) {
conn, err := net.DialTimeout(s.Type, domain, time.Duration(s.Timeout)*time.Second)
if err != nil {
if record {
- recordFailure(s, fmt.Sprintf("Dial Error: %v", err))
+ RecordFailure(s, fmt.Sprintf("Dial Error: %v", err))
}
return s, err
}
@@ -203,7 +203,7 @@ func CheckTcp(s *Service, record bool) (*Service, error) {
conn, err := tls.DialWithDialer(dialer, s.Type, domain, tlsConfig)
if err != nil {
if record {
- recordFailure(s, fmt.Sprintf("Dial Error: %v", err))
+ RecordFailure(s, fmt.Sprintf("Dial Error: %v", err))
}
return s, err
}
@@ -214,7 +214,7 @@ func CheckTcp(s *Service, record bool) (*Service, error) {
s.LastResponse = ""
s.Online = true
if record {
- recordSuccess(s)
+ RecordSuccess(s)
}
return s, nil
}
@@ -232,7 +232,7 @@ func CheckHttp(s *Service, record bool) (*Service, error) {
dnsLookup, err := dnsCheck(s)
if err != nil {
if record {
- recordFailure(s, fmt.Sprintf("Could not get IP address for domain %v, %v", s.Domain, err))
+ RecordFailure(s, fmt.Sprintf("Could not get IP address for domain %v, %v", s.Domain, err))
}
return s, err
}
@@ -284,7 +284,7 @@ func CheckHttp(s *Service, record bool) (*Service, error) {
content, res, err = utils.HttpRequest(s.Domain, s.Method, contentType, headers, data, timeout, s.VerifySSL.Bool, customTLS)
if err != nil {
if record {
- recordFailure(s, fmt.Sprintf("HTTP Error %v", err))
+ RecordFailure(s, fmt.Sprintf("HTTP Error %v", err))
}
return s, err
}
@@ -301,26 +301,26 @@ func CheckHttp(s *Service, record bool) (*Service, error) {
}
if !match {
if record {
- recordFailure(s, fmt.Sprintf("HTTP Response Body did not match '%v'", s.Expected))
+ RecordFailure(s, fmt.Sprintf("HTTP Response Body did not match '%v'", s.Expected))
}
return s, err
}
}
if s.ExpectedStatus != res.StatusCode {
if record {
- recordFailure(s, fmt.Sprintf("HTTP Status Code %v did not match %v", res.StatusCode, s.ExpectedStatus))
+ RecordFailure(s, fmt.Sprintf("HTTP Status Code %v did not match %v", res.StatusCode, s.ExpectedStatus))
}
return s, err
}
if record {
- recordSuccess(s)
+ RecordSuccess(s)
}
s.Online = true
return s, err
}
-// recordSuccess will create a new 'hit' record in the database for a successful/online service
-func recordSuccess(s *Service) {
+// RecordSuccess will create a new 'hit' record in the database for a successful/online service
+func RecordSuccess(s *Service) {
s.LastOnline = utils.Now()
s.Online = true
hit := &hits.Hit{
@@ -371,8 +371,8 @@ func sendSuccess(s *Service) {
s.notifyAfterCount = 0
}
-// recordFailure will create a new 'Failure' record in the database for a offline service
-func recordFailure(s *Service, issue string) {
+// RecordFailure will create a new 'Failure' record in the database for a offline service
+func RecordFailure(s *Service, issue string) {
s.LastOffline = utils.Now()
fail := &failures.Failure{
diff --git a/types/services/samples.go b/types/services/samples.go
index c979ac8c..838eb295 100644
--- a/types/services/samples.go
+++ b/types/services/samples.go
@@ -176,5 +176,16 @@ func Samples() error {
return err
}
+ s7 := &Service{
+ Name: "Static Service",
+ Type: "static",
+ Order: 7,
+ Public: null.NewNullBool(true),
+ CreatedAt: createdOn,
+ }
+ if err := s7.Create(); err != nil {
+ return err
+ }
+
return nil
}