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
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
run: |
echo "::add-path::/osxcross/target/bin"
echo "::add-path::$(go env GOPATH)/bin"
echo "::add-path::/opt/hostedtoolcache/node/10.20.1/x64/bin"
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)
- Added service timeframe/interval on index charts
- Added --config flag to specify config.yml file

View File

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

View File

@ -168,6 +168,22 @@ HTML,BODY {
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 {
width: 60pt;
float: left !important;

View File

@ -1,7 +1,9 @@
<template>
<div>
<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 class="row mt-2">
<div class="col-4 text-left font-2 text-muted">30 Days Ago</div>
@ -23,7 +25,7 @@ export default {
},
data() {
return {
failureData: null,
failureData: [],
}
},
props: {
@ -50,7 +52,11 @@ export default {
methods: {
async lastDaysFailures() {
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 -->
<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>

View File

@ -32,7 +32,7 @@
</div>
<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}">
<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}}
@ -58,7 +58,7 @@
</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}">
View Service
</button>

View File

@ -1,5 +1,5 @@
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 format from 'date-fns/format'
import parseISO from 'date-fns/parseISO'
@ -15,6 +15,9 @@ export default Vue.mixin({
},
current() {
return parseISO(new Date())
},
startToday() {
return startOfToday()
},
secondsHumanize (val) {
const t2 = addSeconds(new Date(0), val)

View File

@ -235,6 +235,7 @@ func TestMainApiRoutes(t *testing.T) {
URL: "/metrics",
Method: "GET",
BeforeTest: SetTestENV,
AfterTest: UnsetTestENV,
ExpectedStatus: 200,
ExpectedContains: []string{
`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 {
Username string `json:"username"`
Admin bool `json:"admin"`

View File

@ -1,6 +1,7 @@
package handlers
import (
"github.com/statping/statping/types/core"
"github.com/statping/statping/types/groups"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -113,6 +114,21 @@ func TestGroupAPIRoutes(t *testing.T) {
ExpectedStatus: 200,
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",
URL: "/api/reorder/groups",

View File

@ -5,6 +5,7 @@ import (
"fmt"
"github.com/pkg/errors"
"github.com/statping/statping/types"
"github.com/statping/statping/types/core"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"github.com/stretchr/testify/assert"
@ -108,6 +109,21 @@ func TestApiServiceRoutes(t *testing.T) {
ExpectedStatus: 200,
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",
URL: "/api/services/1",

View File

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

View File

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

View File

@ -25,7 +25,6 @@ func init() {
}
func TestTelegramNotifier(t *testing.T) {
t.SkipNow()
db, err := database.OpenTester()
require.Nil(t, err)
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
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.Set("To", "+"+t.Var1)
v.Set("From", "+"+t.Var2)
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)
if !success {
errorOut := twilioError(contents)

View File

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

View File

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

View File

@ -1 +1 @@
0.90.38
0.90.39