notifier updates - API changes - Messages update

pull/99/head
Hunter Long 2018-11-13 19:05:36 -08:00
parent 8e31fb4e96
commit e9818372f2
12 changed files with 115 additions and 181 deletions

View File

@ -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

View File

@ -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)
}

View File

@ -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(&notification)
err := decoder.Decode(&notification)
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",

View File

@ -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)

View File

@ -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)
}

View File

@ -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")

View File

@ -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) {

View File

@ -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") {

View File

@ -14,12 +14,11 @@
{{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",
dateFormat: "Z",
minDate: "today",
"plugins": [new rangePlugin({ input: "#end_on"})]
});

View File

@ -45,12 +45,11 @@
{{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",
dateFormat: "Z",
minDate: "today",
"plugins": [new rangePlugin({ input: "#end_on"})]
});

View File

@ -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
}

View File

@ -47,7 +47,7 @@ type Service struct {
LastResponse string `gorm:"-" json:"-"`
LastStatusCode int `gorm:"-" json:"status_code"`
LastOnline time.Time `gorm:"-" json:"last_online"`
Failures []*Failure `gorm:"-" json:"failures,omitempty"`
Failures []FailureInterface `gorm:"-" json:"failures,omitempty"`
}
type ServiceInterface interface {