Merge pull request #582 from statping/features-notifiers-fixes

Features notifiers fixes
pull/585/head v0.90.39
Hunter Long 2020-05-15 03:42:24 -07:00 committed by GitHub
commit dab8c6ce83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 84 additions and 115 deletions

View File

@ -220,18 +220,8 @@ jobs:
make xz-utils cpio wget zip unzip p7zip git mercurial bzr texinfo help2man cmake --no-install-recommends make xz-utils cpio wget zip unzip p7zip git mercurial bzr texinfo help2man cmake --no-install-recommends
sudo ln -s /usr/include/asm-generic/ /usr/include/asm sudo ln -s /usr/include/asm-generic/ /usr/include/asm
- name: Install MacOSX compiler
run: |
cd /
git clone https://github.com/tpoechtrager/osxcross.git
cd osxcross && git checkout 88cb6e8d0d7675cae7c8a2d66c11f58237101df0 && cd ../
wget https://s3.dockerproject.org/darwin/v2/MacOSX10.11.sdk.tar.xz
mv MacOSX10.11.sdk.tar.xz /osxcross/tarballs/
OSX_VERSION_MIN=10.10 UNATTENDED=1 LD_LIBRARY_PATH=/osxcross/target/lib /osxcross/build.sh
- name: Setting ENV's - name: Setting ENV's
run: | run: |
echo "::add-path::/osxcross/target/bin"
echo "::add-path::$(go env GOPATH)/bin" echo "::add-path::$(go env GOPATH)/bin"
echo "::add-path::/opt/hostedtoolcache/node/10.20.1/x64/bin" echo "::add-path::/opt/hostedtoolcache/node/10.20.1/x64/bin"
echo ::set-env name=VERSION::$(cat version.txt) echo ::set-env name=VERSION::$(cat version.txt)

View File

@ -1,3 +1,7 @@
# 0.90.39 (05-15-2020)
- Modified some SCSS designs for services failures in group
- Fixed Twilio notifier and tests
# 0.90.38 (05-10-2020) # 0.90.38 (05-10-2020)
- Added service timeframe/interval on index charts - Added service timeframe/interval on index charts
- Added --config flag to specify config.yml file - Added --config flag to specify config.yml file

View File

@ -163,7 +163,6 @@ build-win:
build-darwin: build-darwin:
GO111MODULE="on" GOOS=darwin GOARCH=amd64 go build -a -ldflags "-s -w -X main.VERSION=${VERSION}" -o releases/statping-darwin-amd64/statping --tags "darwin" ./cmd GO111MODULE="on" GOOS=darwin GOARCH=amd64 go build -a -ldflags "-s -w -X main.VERSION=${VERSION}" -o releases/statping-darwin-amd64/statping --tags "darwin" ./cmd
GO111MODULE="on" GOOS=darwin GOARCH=386 go build -a -ldflags "-s -w -X main.VERSION=${VERSION}" -o releases/statping-darwin-386/statping --tags "darwin" ./cmd
build-linux: build-linux:
CGO_ENABLED=1 GO111MODULE="on" GOOS=linux GOARCH=amd64 \ CGO_ENABLED=1 GO111MODULE="on" GOOS=linux GOARCH=amd64 \

View File

@ -168,6 +168,22 @@ HTML,BODY {
background-color: #efefef; background-color: #efefef;
} }
.service_day {
height: 20px;
margin-right: 2px;
border-radius: 4px;
max-width: 25px;
}
.service_day SPAN {
font-size: 6pt;
color: white;
margin: auto;
display: flex;
justify-content: center;
margin-top: 4px;
}
.service_scale { .service_scale {
width: 60pt; width: 60pt;
float: left !important; float: left !important;

View File

@ -1,7 +1,9 @@
<template> <template>
<div> <div>
<div class="d-flex mt-3 mb-2"> <div class="d-flex mt-3 mb-2">
<div class="flex-fill service_day" v-for="(d, index) in failureData" :class="{'mini_error': d.amount > 0, 'mini_success': d.amount === 0}"></div> <div class="flex-fill service_day" v-for="(d, index) in failureData" :class="{'mini_error': d.amount > 0, 'mini_success': d.amount === 0}">
<span v-if="d.amount != 0" class="small">{{d.amount}}</span>
</div>
</div> </div>
<div class="row mt-2"> <div class="row mt-2">
<div class="col-4 text-left font-2 text-muted">30 Days Ago</div> <div class="col-4 text-left font-2 text-muted">30 Days Ago</div>
@ -23,7 +25,7 @@ export default {
}, },
data() { data() {
return { return {
failureData: null, failureData: [],
} }
}, },
props: { props: {
@ -50,7 +52,11 @@ export default {
methods: { methods: {
async lastDaysFailures() { async lastDaysFailures() {
const start = this.nowSubtract(86400 * 30) const start = this.nowSubtract(86400 * 30)
this.failureData = await Api.service_failures_data(this.service.id, this.toUnix(start), this.toUnix(this.now()), "24h") const data = await Api.service_failures_data(this.service.id, this.toUnix(start), this.toUnix(this.startToday()), "24h")
data.forEach((d) => {
let date = this.parseISO(d.timeframe)
this.failureData.push({month: 1, day: date.getDate(), amount: d.amount})
})
} }
} }
} }
@ -58,63 +64,4 @@ export default {
<!-- Add "scoped" attribute to limit CSS to this component only --> <!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped> <style scoped>
.service_day {
height: 20px;
margin-right: 2px;
border-radius: 4px;
}
@keyframes pulse_animation {
0% { transform: scale(1); }
30% { transform: scale(1); }
40% { transform: scale(1.02); }
50% { transform: scale(1); }
60% { transform: scale(1); }
70% { transform: scale(1.05); }
80% { transform: scale(1); }
100% { transform: scale(1); }
}
.pulse {
animation-name: pulse_animation;
animation-duration: 1500ms;
transform-origin:70% 70%;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
@keyframes glow-grow {
0% {
opacity: 0;
transform: scale(1);
}
80% {
opacity: 1;
}
100% {
transform: scale(2);
opacity: 0;
}
}
.pulse-glow {
animation-name: glow-grown;
animation-duration: 100ms;
transform-origin: 70% 30%;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
.pulse-glow:before,
.pulse-glow:after {
position: absolute;
content: "";
height: 0.4rem;
width: 1.7rem;
top: 1.3rem;
right: 2.15rem;
border-radius: 0;
box-shadow: 0 0 6px #47d337;
animation: glow-grow 2s ease-out infinite;
}
</style> </style>

View File

@ -32,7 +32,7 @@
</div> </div>
<div class="row lower_canvas full-col-12 text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}"> <div class="row lower_canvas full-col-12 text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}">
<div class="col-md-8 col-6"> <div class="col-md-10 col-6">
<div class="dropup" :class="{show: dropDownMenu}"> <div class="dropup" :class="{show: dropDownMenu}">
<button style="font-size: 10pt;" @click.prevent="openMenu('timeframe')" type="button" class="col-4 float-left btn btn-sm float-right btn-block text-white dropdown-toggle service_scale pr-2"> <button style="font-size: 10pt;" @click.prevent="openMenu('timeframe')" type="button" class="col-4 float-left btn btn-sm float-right btn-block text-white dropdown-toggle service_scale pr-2">
{{timeframepick.text}} {{timeframepick.text}}
@ -58,7 +58,7 @@
</div> </div>
<div class="col-md-4 col-6 float-right"> <div class="col-md-2 col-6 float-right">
<button v-if="!expanded" @click="setService" class="btn btn-sm float-right dyn-dark text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}"> <button v-if="!expanded" @click="setService" class="btn btn-sm float-right dyn-dark text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}">
View Service View Service
</button> </button>

View File

@ -1,5 +1,5 @@
import Vue from "vue"; import Vue from "vue";
const { zonedTimeToUtc, utcToZonedTime, lastDayOfMonth, subSeconds, parse, getUnixTime, fromUnixTime, differenceInSeconds, formatDistance } = require('date-fns') const { zonedTimeToUtc, utcToZonedTime, startOfToday, lastDayOfMonth, subSeconds, parse, getUnixTime, fromUnixTime, differenceInSeconds, formatDistance } = require('date-fns')
import formatDistanceToNow from 'date-fns/formatDistanceToNow' import formatDistanceToNow from 'date-fns/formatDistanceToNow'
import format from 'date-fns/format' import format from 'date-fns/format'
import parseISO from 'date-fns/parseISO' import parseISO from 'date-fns/parseISO'
@ -15,6 +15,9 @@ export default Vue.mixin({
}, },
current() { current() {
return parseISO(new Date()) return parseISO(new Date())
},
startToday() {
return startOfToday()
}, },
secondsHumanize (val) { secondsHumanize (val) {
const t2 = addSeconds(new Date(0), val) const t2 = addSeconds(new Date(0), val)

View File

@ -235,6 +235,7 @@ func TestMainApiRoutes(t *testing.T) {
URL: "/metrics", URL: "/metrics",
Method: "GET", Method: "GET",
BeforeTest: SetTestENV, BeforeTest: SetTestENV,
AfterTest: UnsetTestENV,
ExpectedStatus: 200, ExpectedStatus: 200,
ExpectedContains: []string{ ExpectedContains: []string{
`Statping Totals`, `Statping Totals`,

View File

@ -132,29 +132,6 @@ func logsLineHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
//func exportHandler(w http.ResponseWriter, r *http.Request) {
// var notifiers []*notifier.Notification
// for _, v := range core.CoreApp.Notifications {
// notifier := v.(notifier.Notifier)
// notifiers = append(notifiers, notifier.Select())
// }
//
// export, _ := core.ExportSettings()
//
// mime := http.DetectContentType(export)
// fileSize := len(string(export))
//
// w.Header().Set("Content-Type", mime)
// w.Header().Set("Content-Disposition", "attachment; filename=export.json")
// w.Header().Set("Expires", "0")
// w.Header().Set("Content-Transfer-Encoding", "binary")
// w.Header().Set("Content-Length", strconv.Itoa(fileSize))
// w.Header().Set("Content-Control", "private, no-transform, no-store, must-revalidate")
//
// http.ServeContent(w, r, "export.json", utils.Now(), bytes.NewReader(export))
//
//}
type JwtClaim struct { type JwtClaim struct {
Username string `json:"username"` Username string `json:"username"`
Admin bool `json:"admin"` Admin bool `json:"admin"`

View File

@ -1,6 +1,7 @@
package handlers package handlers
import ( import (
"github.com/statping/statping/types/core"
"github.com/statping/statping/types/groups" "github.com/statping/statping/types/groups"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -113,6 +114,21 @@ func TestGroupAPIRoutes(t *testing.T) {
ExpectedStatus: 200, ExpectedStatus: 200,
BeforeTest: SetTestENV, BeforeTest: SetTestENV,
}, },
{
Name: "Statping View Private Group with API Key",
URL: "/api/groups/2?api=" + core.App.ApiSecret,
Method: "GET",
ExpectedStatus: 200,
BeforeTest: UnsetTestENV,
},
{
Name: "Statping View Private Group with API Header",
URL: "/api/groups/2",
Method: "GET",
HttpHeaders: []string{"Authorization=" + core.App.ApiSecret},
ExpectedStatus: 200,
BeforeTest: UnsetTestENV,
},
{ {
Name: "Statping Reorder Groups", Name: "Statping Reorder Groups",
URL: "/api/reorder/groups", URL: "/api/reorder/groups",

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/statping/statping/types" "github.com/statping/statping/types"
"github.com/statping/statping/types/core"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -108,6 +109,21 @@ func TestApiServiceRoutes(t *testing.T) {
ExpectedStatus: 200, ExpectedStatus: 200,
BeforeTest: SetTestENV, BeforeTest: SetTestENV,
}, },
{
Name: "Statping Private Service with API Key",
URL: "/api/services/6?api=" + core.App.ApiSecret,
Method: "GET",
ExpectedStatus: 200,
BeforeTest: UnsetTestENV,
},
{
Name: "Statping Private Service with API Header",
URL: "/api/services/6?api=" + core.App.ApiSecret,
Method: "GET",
HttpHeaders: []string{"Authorization=" + core.App.ApiSecret},
ExpectedStatus: 200,
BeforeTest: UnsetTestENV,
},
{ {
Name: "Statping Service 1 with Private responses", Name: "Statping Service 1 with Private responses",
URL: "/api/services/1", URL: "/api/services/1",

View File

@ -11,7 +11,6 @@ import (
) )
func TestCommandNotifier(t *testing.T) { func TestCommandNotifier(t *testing.T) {
t.SkipNow()
db, err := database.OpenTester() db, err := database.OpenTester()
require.Nil(t, err) require.Nil(t, err)
db.AutoMigrate(&notifications.Notification{}) db.AutoMigrate(&notifications.Notification{})

View File

@ -16,7 +16,6 @@ var (
) )
func TestPushoverNotifier(t *testing.T) { func TestPushoverNotifier(t *testing.T) {
t.SkipNow()
db, err := database.OpenTester() db, err := database.OpenTester()
require.Nil(t, err) require.Nil(t, err)
db.AutoMigrate(&notifications.Notification{}) db.AutoMigrate(&notifications.Notification{})

View File

@ -25,7 +25,6 @@ func init() {
} }
func TestTelegramNotifier(t *testing.T) { func TestTelegramNotifier(t *testing.T) {
t.SkipNow()
db, err := database.OpenTester() db, err := database.OpenTester()
require.Nil(t, err) require.Nil(t, err)
db.AutoMigrate(&notifications.Notification{}) db.AutoMigrate(&notifications.Notification{})

View File

@ -62,15 +62,17 @@ var Twilio = &twilio{&notifications.Notification{
// Send will send a HTTP Post to the Twilio SMS API. It accepts type: string // Send will send a HTTP Post to the Twilio SMS API. It accepts type: string
func (t *twilio) sendMessage(message string) (string, error) { func (t *twilio) sendMessage(message string) (string, error) {
twilioUrl := fmt.Sprintf("https://api.twilio.com/2010-04-01/Accounts/%v/Messages.json", t.GetValue("api_key")) twilioUrl := fmt.Sprintf("https://api.twilio.com/2010-04-01/Accounts/%v/Messages.json", t.ApiKey)
v := url.Values{} v := url.Values{}
v.Set("To", "+"+t.Var1) v.Set("To", "+"+t.Var1)
v.Set("From", "+"+t.Var2) v.Set("From", "+"+t.Var2)
v.Set("Body", message) v.Set("Body", message)
rb := *strings.NewReader(v.Encode()) rb := strings.NewReader(v.Encode())
contents, _, err := utils.HttpRequest(twilioUrl, "POST", "application/x-www-form-urlencoded", nil, &rb, time.Duration(10*time.Second), true) authHeader := utils.Base64(fmt.Sprintf("%s:%s", t.ApiKey, t.ApiSecret))
contents, _, err := utils.HttpRequest(twilioUrl, "POST", "application/x-www-form-urlencoded", []string{"Authorization=Basic " + authHeader}, rb, 10*time.Second, true)
success, _ := twilioSuccess(contents) success, _ := twilioSuccess(contents)
if !success { if !success {
errorOut := twilioError(contents) errorOut := twilioError(contents)

View File

@ -21,29 +21,25 @@ var (
func init() { func init() {
TWILIO_SID = os.Getenv("TWILIO_SID") TWILIO_SID = os.Getenv("TWILIO_SID")
TWILIO_SECRET = os.Getenv("TWILIO_SECRET") TWILIO_SECRET = os.Getenv("TWILIO_SECRET")
TWILIO_FROM = os.Getenv("TWILIO_FROM")
TWILIO_TO = os.Getenv("TWILIO_TO")
} }
func TestTwilioNotifier(t *testing.T) { func TestTwilioNotifier(t *testing.T) {
t.SkipNow()
db, err := database.OpenTester() db, err := database.OpenTester()
require.Nil(t, err) require.Nil(t, err)
db.AutoMigrate(&notifications.Notification{}) db.AutoMigrate(&notifications.Notification{})
notifications.SetDB(db) notifications.SetDB(db)
if TWILIO_SID == "" || TWILIO_SECRET == "" || TWILIO_FROM == "" { if TWILIO_SID == "" || TWILIO_SECRET == "" {
t.Log("twilio notifier testing skipped, missing TWILIO_SID environment variable") t.Log("twilio notifier testing skipped, missing TWILIO_SID and TWILIO_SECRET environment variable")
t.SkipNow() t.SkipNow()
} }
t.Run("Load Twilio", func(t *testing.T) { t.Run("Load Twilio", func(t *testing.T) {
Twilio.ApiKey = TWILIO_SID Twilio.ApiKey = TWILIO_SID
Twilio.ApiSecret = TWILIO_SECRET Twilio.ApiSecret = TWILIO_SECRET
Twilio.Var1 = TWILIO_TO Twilio.Var1 = "15005550006"
Twilio.Var2 = TWILIO_FROM Twilio.Var2 = "15005550006"
Twilio.Delay = time.Duration(100 * time.Millisecond) Twilio.Delay = 100 * time.Millisecond
Twilio.Enabled = null.NewNullBool(true) Twilio.Enabled = null.NewNullBool(true)
Add(Twilio) Add(Twilio)

View File

@ -2,6 +2,7 @@ package utils
import ( import (
"crypto/sha256" "crypto/sha256"
"encoding/base64"
"fmt" "fmt"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"math/rand" "math/rand"
@ -22,6 +23,10 @@ func NewSHA256Hash() string {
return fmt.Sprintf("%x", sha256.Sum256(d)) return fmt.Sprintf("%x", sha256.Sum256(d))
} }
func Base64(s string) string {
return base64.StdEncoding.EncodeToString([]byte(s))
}
var characterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") var characterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
// RandomString generates a random string of n length // RandomString generates a random string of n length

View File

@ -1 +1 @@
0.90.38 0.90.39