mirror of https://github.com/statping/statping
notifier updates - API changes - Messages update
parent
8e31fb4e96
commit
e9818372f2
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/ararog/timeago"
|
||||
"github.com/hunterlong/statup/types"
|
||||
"github.com/hunterlong/statup/utils"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
@ -29,7 +30,7 @@ type failure struct {
|
|||
}
|
||||
|
||||
const (
|
||||
limitedFailures = 64
|
||||
limitedFailures = 32
|
||||
)
|
||||
|
||||
// CreateFailure will create a new failure record for a service
|
||||
|
@ -41,8 +42,9 @@ func (s *Service) CreateFailure(fail types.FailureInterface) (int64, error) {
|
|||
utils.Log(3, row.Error)
|
||||
return 0, row.Error
|
||||
}
|
||||
s.Failures = append(s.Failures, f.Select())
|
||||
if len(s.Failures) >= limitedFailures {
|
||||
sort.Sort(types.FailSort(s.Failures))
|
||||
s.Failures = append(s.Failures, f)
|
||||
if len(s.Failures) > limitedFailures {
|
||||
s.Failures = s.Failures[1:]
|
||||
}
|
||||
return f.Id, row.Error
|
||||
|
|
|
@ -102,10 +102,9 @@ func (c *Core) SelectAllServices(start bool) ([]*Service, error) {
|
|||
service.Start()
|
||||
service.CheckinProcess()
|
||||
}
|
||||
failures := service.LimitedFailures(limitedFailures)
|
||||
service.Failures = nil
|
||||
for _, fail := range failures {
|
||||
service.Failures = append(service.Failures, fail.Select())
|
||||
fails := service.LimitedFailures(limitedFailures)
|
||||
for _, f := range fails {
|
||||
service.Failures = append(service.Failures, f)
|
||||
}
|
||||
CoreApp.Services = append(CoreApp.Services, service)
|
||||
}
|
||||
|
|
|
@ -128,14 +128,14 @@ func apiServiceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
vars := mux.Vars(r)
|
||||
service := core.SelectServicer(utils.StringInt(vars["id"]))
|
||||
if service == nil {
|
||||
servicer := core.SelectServicer(utils.StringInt(vars["id"]))
|
||||
if servicer == nil {
|
||||
sendErrorJson(errors.New("service not found"), w, r)
|
||||
return
|
||||
}
|
||||
|
||||
service := servicer.Select()
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(service.Select())
|
||||
json.NewEncoder(w).Encode(service)
|
||||
}
|
||||
|
||||
func apiCreateServiceHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -181,7 +181,7 @@ func apiServiceUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
service.Check(true)
|
||||
go service.Check(true)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(service)
|
||||
}
|
||||
|
@ -218,12 +218,8 @@ func apiAllServicesHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
services := core.Services()
|
||||
var servicesOut []*types.Service
|
||||
for _, s := range services {
|
||||
servicesOut = append(servicesOut, s.Select())
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(servicesOut)
|
||||
json.NewEncoder(w).Encode(services)
|
||||
}
|
||||
|
||||
func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -250,8 +246,11 @@ func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
var notification *notifier.Notification
|
||||
fmt.Println(r.Body)
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
decoder.Decode(¬ification)
|
||||
|
||||
err := decoder.Decode(¬ification)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
notifer, not, err := notifier.SelectNotifier(vars["notifier"])
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
|
@ -264,9 +263,9 @@ func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
notifer.Port = notification.Port
|
||||
notifer.Password = notification.Password
|
||||
notifer.Username = notification.Username
|
||||
notifer.Enabled = notification.Enabled
|
||||
notifer.ApiKey = notification.ApiKey
|
||||
notifer.ApiSecret = notification.ApiSecret
|
||||
notifer.Enabled = types.NewNullBool(notification.Enabled.Bool)
|
||||
|
||||
_, err = notifier.Update(not, notifer)
|
||||
if err != nil {
|
||||
|
@ -293,6 +292,28 @@ func apiAllMessagesHandler(w http.ResponseWriter, r *http.Request) {
|
|||
json.NewEncoder(w).Encode(messages)
|
||||
}
|
||||
|
||||
func apiMessageCreateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !isAPIAuthorized(r) {
|
||||
sendUnauthorizedJson(w, r)
|
||||
return
|
||||
}
|
||||
var message *types.Message
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
err := decoder.Decode(&message)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
msg := core.ReturnMessage(message)
|
||||
_, err = msg.Create()
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(msg)
|
||||
}
|
||||
|
||||
func apiMessageGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !isAPIAuthorized(r) {
|
||||
sendUnauthorizedJson(w, r)
|
||||
|
@ -388,27 +409,6 @@ func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) {
|
|||
json.NewEncoder(w).Encode(notifiers)
|
||||
}
|
||||
|
||||
func apiAllServiceFailuresHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !isAPIAuthorized(r) {
|
||||
sendUnauthorizedJson(w, r)
|
||||
return
|
||||
}
|
||||
allServices, _ := core.CoreApp.SelectAllServices(false)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(allServices)
|
||||
}
|
||||
|
||||
func apiServiceFailuresHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !isAPIAuthorized(r) {
|
||||
sendUnauthorizedJson(w, r)
|
||||
return
|
||||
}
|
||||
vars := mux.Vars(r)
|
||||
service := core.SelectService(utils.StringInt(vars["id"]))
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(service.AllFailures())
|
||||
}
|
||||
|
||||
func sendErrorJson(err error, w http.ResponseWriter, r *http.Request) {
|
||||
output := apiResponse{
|
||||
Status: "error",
|
||||
|
|
|
@ -17,7 +17,6 @@ package handlers
|
|||
|
||||
import (
|
||||
"github.com/hunterlong/statup/core"
|
||||
"github.com/hunterlong/statup/core/notifier"
|
||||
_ "github.com/hunterlong/statup/notifiers"
|
||||
"github.com/hunterlong/statup/source"
|
||||
"github.com/hunterlong/statup/utils"
|
||||
|
@ -364,34 +363,6 @@ func TestPrometheusHandler(t *testing.T) {
|
|||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestSaveNotificationHandler(t *testing.T) {
|
||||
notification, _, err := notifier.SelectNotifier("email")
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, notification.IsRunning())
|
||||
|
||||
form := url.Values{}
|
||||
form.Add("enable", "on")
|
||||
form.Add("host", "smtp.emailer.com")
|
||||
form.Add("port", "587")
|
||||
form.Add("username", "exampleuser")
|
||||
form.Add("password", "password123")
|
||||
form.Add("var1", "info@betatude.com")
|
||||
form.Add("var2", "sendto@gmail.com")
|
||||
form.Add("api_key", "")
|
||||
form.Add("api_secret", "")
|
||||
form.Add("limits", "7")
|
||||
req, err := http.NewRequest("POST", "/settings/notifier/email", strings.NewReader(form.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
notification, _, err = notifier.SelectNotifier("email")
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, notification.IsRunning())
|
||||
}
|
||||
|
||||
func TestViewNotificationSettingsHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/settings", nil)
|
||||
assert.Nil(t, err)
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/hunterlong/statup/core"
|
||||
"github.com/hunterlong/statup/utils"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
|
@ -28,3 +30,18 @@ func messagesHandler(w http.ResponseWriter, r *http.Request) {
|
|||
messages, _ := core.SelectMessages()
|
||||
executeResponse(w, r, "messages.html", messages, nil)
|
||||
}
|
||||
|
||||
func viewMessageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !IsAuthenticated(r) {
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
vars := mux.Vars(r)
|
||||
id := utils.StringInt(vars["id"])
|
||||
message, err := core.SelectMessage(id)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
executeResponse(w, r, "message.html", message, nil)
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ func Router() *mux.Router {
|
|||
|
||||
// MESSAGES Routes
|
||||
r.Handle("/messages", http.HandlerFunc(messagesHandler)).Methods("GET")
|
||||
r.Handle("/message/{id}", http.HandlerFunc(viewMessageHandler)).Methods("GET")
|
||||
|
||||
// SETTINGS Routes
|
||||
r.Handle("/settings", http.HandlerFunc(settingsHandler)).Methods("GET")
|
||||
|
@ -76,7 +77,6 @@ func Router() *mux.Router {
|
|||
r.Handle("/settings/css", http.HandlerFunc(saveSASSHandler)).Methods("POST")
|
||||
r.Handle("/settings/build", http.HandlerFunc(saveAssetsHandler)).Methods("GET")
|
||||
r.Handle("/settings/delete_assets", http.HandlerFunc(deleteAssetsHandler)).Methods("GET")
|
||||
r.Handle("/settings/notifier/{method}", http.HandlerFunc(saveNotificationHandler)).Methods("POST")
|
||||
r.Handle("/settings/notifier/{method}/test", http.HandlerFunc(testNotificationHandler)).Methods("POST")
|
||||
r.Handle("/settings/export", http.HandlerFunc(exportHandler)).Methods("GET")
|
||||
|
||||
|
@ -104,7 +104,6 @@ func Router() *mux.Router {
|
|||
r.Handle("/api/services/{id}/ping", http.HandlerFunc(apiServicePingDataHandler)).Methods("GET")
|
||||
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceUpdateHandler)).Methods("POST")
|
||||
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceDeleteHandler)).Methods("DELETE")
|
||||
r.Handle("/api/service/{id}/failures", http.HandlerFunc(apiServiceFailuresHandler)).Methods("GET")
|
||||
r.Handle("/api/checkin/{api}", http.HandlerFunc(apiCheckinHandler))
|
||||
|
||||
// API USER Routes
|
||||
|
@ -121,7 +120,7 @@ func Router() *mux.Router {
|
|||
|
||||
// API MESSAGES Routes
|
||||
r.Handle("/api/messages", http.HandlerFunc(apiAllMessagesHandler)).Methods("GET")
|
||||
r.Handle("/api/messages", http.HandlerFunc(apiNotifierUpdateHandler)).Methods("POST")
|
||||
r.Handle("/api/messages", http.HandlerFunc(apiMessageCreateHandler)).Methods("POST")
|
||||
r.Handle("/api/messages/{id}", http.HandlerFunc(apiMessageGetHandler)).Methods("GET")
|
||||
r.Handle("/api/messages/{id}", http.HandlerFunc(apiMessageUpdateHandler)).Methods("POST")
|
||||
r.Handle("/api/messages/{id}", http.HandlerFunc(apiMessageDeleteHandler)).Methods("DELETE")
|
||||
|
|
|
@ -135,70 +135,6 @@ func parseGet(r *http.Request) url.Values {
|
|||
return r.Form
|
||||
}
|
||||
|
||||
func saveNotificationHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
if !IsAuthenticated(r) {
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
form := parseForm(r)
|
||||
vars := mux.Vars(r)
|
||||
method := vars["method"]
|
||||
enabled := form.Get("enable")
|
||||
host := form.Get("host")
|
||||
port := int(utils.StringInt(form.Get("port")))
|
||||
username := form.Get("username")
|
||||
password := form.Get("password")
|
||||
var1 := form.Get("var1")
|
||||
var2 := form.Get("var2")
|
||||
apiKey := form.Get("api_key")
|
||||
apiSecret := form.Get("api_secret")
|
||||
limits := int(utils.StringInt(form.Get("limits")))
|
||||
|
||||
notifer, notif, err := notifier.SelectNotifier(method)
|
||||
if err != nil {
|
||||
utils.Log(3, fmt.Sprintf("issue saving notifier %v: %v", method, err))
|
||||
executeResponse(w, r, "settings.html", core.CoreApp, "/settings")
|
||||
return
|
||||
}
|
||||
|
||||
if host != "" {
|
||||
notifer.Host = host
|
||||
}
|
||||
if port != 0 {
|
||||
notifer.Port = port
|
||||
}
|
||||
if username != "" {
|
||||
notifer.Username = username
|
||||
}
|
||||
if password != "" && password != "##########" {
|
||||
notifer.Password = password
|
||||
}
|
||||
if var1 != "" {
|
||||
notifer.Var1 = var1
|
||||
}
|
||||
if var2 != "" {
|
||||
notifer.Var2 = var2
|
||||
}
|
||||
if apiKey != "" {
|
||||
notifer.ApiKey = apiKey
|
||||
}
|
||||
if apiSecret != "" {
|
||||
notifer.ApiSecret = apiSecret
|
||||
}
|
||||
if limits != 0 {
|
||||
notifer.Limits = limits
|
||||
}
|
||||
notifer.Enabled = types.NewNullBool(enabled == "on")
|
||||
|
||||
_, err = notifier.Update(notif, notifer)
|
||||
if err != nil {
|
||||
utils.Log(3, fmt.Sprintf("issue updating notifier: %v", err))
|
||||
}
|
||||
notifier.OnSave(notifer.Method)
|
||||
executeResponse(w, r, "settings.html", core.CoreApp, "/settings")
|
||||
}
|
||||
|
||||
func testNotificationHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
if !IsAuthenticated(r) {
|
||||
|
|
|
@ -185,7 +185,7 @@ $('form.ajax_form').on('submit', function() {
|
|||
return
|
||||
}
|
||||
if (k.value === "on") {
|
||||
k.value = true
|
||||
k.value = (k.value === "on")
|
||||
}
|
||||
if($.isNumeric(k.value)){
|
||||
if (k.name !== "password") {
|
||||
|
|
|
@ -14,15 +14,14 @@
|
|||
{{define "extra_scripts"}}
|
||||
<script src="/js/flatpickr.js"></script>
|
||||
<script src="/js/rangePlugin.js"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$("#start_on").flatpickr({
|
||||
enableTime: true,
|
||||
dateFormat: "Y-m-d H:i",
|
||||
minDate: "today",
|
||||
"plugins": [new rangePlugin({ input: "#end_on"})]
|
||||
});
|
||||
$(document).ready(function() {
|
||||
$("#start_on").flatpickr({
|
||||
enableTime: true,
|
||||
dateFormat: "Z",
|
||||
minDate: "today",
|
||||
"plugins": [new rangePlugin({ input: "#end_on"})]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{{end}}
|
|
@ -45,15 +45,14 @@
|
|||
{{define "extra_scripts"}}
|
||||
<script src="/js/flatpickr.js"></script>
|
||||
<script src="/js/rangePlugin.js"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$("#start_on").flatpickr({
|
||||
enableTime: true,
|
||||
dateFormat: "Y-m-d H:i",
|
||||
minDate: "today",
|
||||
"plugins": [new rangePlugin({ input: "#end_on"})]
|
||||
});
|
||||
$(document).ready(function() {
|
||||
$("#start_on").flatpickr({
|
||||
enableTime: true,
|
||||
dateFormat: "Z",
|
||||
minDate: "today",
|
||||
"plugins": [new rangePlugin({ input: "#end_on"})]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{{end}}
|
|
@ -36,3 +36,15 @@ type FailureInterface interface {
|
|||
Ago() string // Ago returns a human readable timestamp
|
||||
ParseError() string // ParseError returns a human readable error for a service failure
|
||||
}
|
||||
|
||||
type FailSort []FailureInterface
|
||||
|
||||
func (s FailSort) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
func (s FailSort) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
func (s FailSort) Less(i, j int) bool {
|
||||
return s[i].Select().Id < s[j].Select().Id
|
||||
}
|
||||
|
|
|
@ -21,33 +21,33 @@ import (
|
|||
|
||||
// Service is the main struct for Services
|
||||
type Service struct {
|
||||
Id int64 `gorm:"primary_key;column:id" json:"id"`
|
||||
Name string `gorm:"column:name" json:"name"`
|
||||
Domain string `gorm:"column:domain" json:"domain"`
|
||||
Expected NullString `gorm:"column:expected" json:"expected"`
|
||||
ExpectedStatus int `gorm:"default:200;column:expected_status" json:"expected_status"`
|
||||
Interval int `gorm:"default:30;column:check_interval" json:"check_interval"`
|
||||
Type string `gorm:"column:check_type" json:"type"`
|
||||
Method string `gorm:"column:method" json:"method"`
|
||||
PostData NullString `gorm:"column:post_data" json:"post_data"`
|
||||
Port int `gorm:"not null;column:port" json:"port"`
|
||||
Timeout int `gorm:"default:30;column:timeout" json:"timeout"`
|
||||
Order int `gorm:"default:0;column:order_id" json:"order_id"`
|
||||
AllowNotifications NullBool `gorm:"default:false;column:allow_notifications" json:"allow_notifications"`
|
||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||
Online bool `gorm:"-" json:"online"`
|
||||
Latency float64 `gorm:"-" json:"latency"`
|
||||
PingTime float64 `gorm:"-" json:"ping_time"`
|
||||
Online24Hours float32 `gorm:"-" json:"online_24_hours"`
|
||||
AvgResponse string `gorm:"-" json:"avg_response"`
|
||||
Running chan bool `gorm:"-" json:"-"`
|
||||
Checkpoint time.Time `gorm:"-" json:"-"`
|
||||
SleepDuration time.Duration `gorm:"-" json:"-"`
|
||||
LastResponse string `gorm:"-" json:"-"`
|
||||
LastStatusCode int `gorm:"-" json:"status_code"`
|
||||
LastOnline time.Time `gorm:"-" json:"last_online"`
|
||||
Failures []*Failure `gorm:"-" json:"failures,omitempty"`
|
||||
Id int64 `gorm:"primary_key;column:id" json:"id"`
|
||||
Name string `gorm:"column:name" json:"name"`
|
||||
Domain string `gorm:"column:domain" json:"domain"`
|
||||
Expected NullString `gorm:"column:expected" json:"expected"`
|
||||
ExpectedStatus int `gorm:"default:200;column:expected_status" json:"expected_status"`
|
||||
Interval int `gorm:"default:30;column:check_interval" json:"check_interval"`
|
||||
Type string `gorm:"column:check_type" json:"type"`
|
||||
Method string `gorm:"column:method" json:"method"`
|
||||
PostData NullString `gorm:"column:post_data" json:"post_data"`
|
||||
Port int `gorm:"not null;column:port" json:"port"`
|
||||
Timeout int `gorm:"default:30;column:timeout" json:"timeout"`
|
||||
Order int `gorm:"default:0;column:order_id" json:"order_id"`
|
||||
AllowNotifications NullBool `gorm:"default:false;column:allow_notifications" json:"allow_notifications"`
|
||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||
Online bool `gorm:"-" json:"online"`
|
||||
Latency float64 `gorm:"-" json:"latency"`
|
||||
PingTime float64 `gorm:"-" json:"ping_time"`
|
||||
Online24Hours float32 `gorm:"-" json:"online_24_hours"`
|
||||
AvgResponse string `gorm:"-" json:"avg_response"`
|
||||
Running chan bool `gorm:"-" json:"-"`
|
||||
Checkpoint time.Time `gorm:"-" json:"-"`
|
||||
SleepDuration time.Duration `gorm:"-" json:"-"`
|
||||
LastResponse string `gorm:"-" json:"-"`
|
||||
LastStatusCode int `gorm:"-" json:"status_code"`
|
||||
LastOnline time.Time `gorm:"-" json:"last_online"`
|
||||
Failures []FailureInterface `gorm:"-" json:"failures,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceInterface interface {
|
||||
|
|
Loading…
Reference in New Issue