mirror of https://github.com/statping/statping
dev
parent
eac1b0568c
commit
439ffc293e
87
cmd/cli.go
87
cmd/cli.go
|
@ -27,7 +27,6 @@ import (
|
||||||
"github.com/hunterlong/statup/utils"
|
"github.com/hunterlong/statup/utils"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -35,7 +34,9 @@ import (
|
||||||
// catchCLI will run functions based on the commands sent to Statup
|
// catchCLI will run functions based on the commands sent to Statup
|
||||||
func catchCLI(args []string) error {
|
func catchCLI(args []string) error {
|
||||||
dir := utils.Directory
|
dir := utils.Directory
|
||||||
utils.InitLogs()
|
if err := utils.InitLogs(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
source.Assets()
|
source.Assets()
|
||||||
loadDotEnvs()
|
loadDotEnvs()
|
||||||
|
|
||||||
|
@ -50,22 +51,21 @@ func catchCLI(args []string) error {
|
||||||
}
|
}
|
||||||
return errors.New("end")
|
return errors.New("end")
|
||||||
case "assets":
|
case "assets":
|
||||||
err := source.CreateAllAssets(dir)
|
var err error
|
||||||
if err != nil {
|
if err = source.CreateAllAssets(dir); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
|
||||||
return errors.New("end")
|
|
||||||
}
|
}
|
||||||
|
return errors.New("end")
|
||||||
case "sass":
|
case "sass":
|
||||||
err := source.CompileSASS(dir)
|
if err := source.CompileSASS(dir); err != nil {
|
||||||
if err == nil {
|
|
||||||
return errors.New("end")
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
return errors.New("end")
|
||||||
case "update":
|
case "update":
|
||||||
gitCurrent, err := checkGithubUpdates()
|
var err error
|
||||||
if err != nil {
|
var gitCurrent githubResponse
|
||||||
return nil
|
if gitCurrent, err = checkGithubUpdates(); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("Statup Version: v%v\nLatest Version: %v\n", VERSION, gitCurrent.TagName)
|
fmt.Printf("Statup Version: v%v\nLatest Version: %v\n", VERSION, gitCurrent.TagName)
|
||||||
if VERSION != gitCurrent.TagName[1:] {
|
if VERSION != gitCurrent.TagName[1:] {
|
||||||
|
@ -73,10 +73,7 @@ func catchCLI(args []string) error {
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("You have the latest version of Statup!\n")
|
fmt.Printf("You have the latest version of Statup!\n")
|
||||||
}
|
}
|
||||||
if err == nil {
|
|
||||||
return errors.New("end")
|
return errors.New("end")
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case "test":
|
case "test":
|
||||||
cmd := args[1]
|
cmd := args[1]
|
||||||
switch cmd {
|
switch cmd {
|
||||||
|
@ -84,19 +81,17 @@ func catchCLI(args []string) error {
|
||||||
plugin.LoadPlugins()
|
plugin.LoadPlugins()
|
||||||
}
|
}
|
||||||
return errors.New("end")
|
return errors.New("end")
|
||||||
case "export":
|
case "static":
|
||||||
var err error
|
var err error
|
||||||
fmt.Printf("Statup v%v Exporting Static 'index.html' page...\n", VERSION)
|
fmt.Printf("Statup v%v Exporting Static 'index.html' page...\n", VERSION)
|
||||||
utils.InitLogs()
|
utils.InitLogs()
|
||||||
core.Configs, err = core.LoadConfigFile(dir)
|
if core.Configs, err = core.LoadConfigFile(dir); err != nil {
|
||||||
if err != nil {
|
|
||||||
utils.Log(4, "config.yml file not found")
|
utils.Log(4, "config.yml file not found")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
indexSource := ExportIndexHTML()
|
indexSource := ExportIndexHTML()
|
||||||
core.CloseDB()
|
core.CloseDB()
|
||||||
err = utils.SaveFile(dir+"/index.html", indexSource)
|
if err = utils.SaveFile(dir+"/index.html", indexSource); err != nil {
|
||||||
if err != nil {
|
|
||||||
utils.Log(4, err)
|
utils.Log(4, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -104,6 +99,40 @@ func catchCLI(args []string) error {
|
||||||
case "help":
|
case "help":
|
||||||
HelpEcho()
|
HelpEcho()
|
||||||
return errors.New("end")
|
return errors.New("end")
|
||||||
|
case "export":
|
||||||
|
var err error
|
||||||
|
var data []byte
|
||||||
|
if err := utils.InitLogs(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if core.Configs, err = core.LoadConfigFile(dir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = core.Configs.Connect(false, dir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if data, err = core.ExportSettings(); err != nil {
|
||||||
|
return fmt.Errorf("could not export settings: %v", err.Error())
|
||||||
|
}
|
||||||
|
if err = utils.SaveFile(dir+"/statup-export.json", data); err != nil {
|
||||||
|
return fmt.Errorf("could not write file statup-export.json: %v", err.Error())
|
||||||
|
}
|
||||||
|
return errors.New("end")
|
||||||
|
case "import":
|
||||||
|
var err error
|
||||||
|
var data []byte
|
||||||
|
if len(args) != 2 {
|
||||||
|
return fmt.Errorf("did not include a JSON file to import\nstatup import filename.json")
|
||||||
|
}
|
||||||
|
filename := args[1]
|
||||||
|
if data, err = ioutil.ReadFile(filename); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var exportData core.ExportData
|
||||||
|
if err = json.Unmarshal(data, &exportData); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return errors.New("end")
|
||||||
case "run":
|
case "run":
|
||||||
utils.Log(1, "Running 1 time and saving to database...")
|
utils.Log(1, "Running 1 time and saving to database...")
|
||||||
RunOnce()
|
RunOnce()
|
||||||
|
@ -175,11 +204,13 @@ func HelpEcho() {
|
||||||
fmt.Println(" statup version - Returns the current version of Statup")
|
fmt.Println(" statup version - Returns the current version of Statup")
|
||||||
fmt.Println(" statup run - Check all services 1 time and then quit")
|
fmt.Println(" statup run - Check all services 1 time and then quit")
|
||||||
fmt.Println(" statup assets - Dump all assets used locally to be edited.")
|
fmt.Println(" statup assets - Dump all assets used locally to be edited.")
|
||||||
fmt.Println(" statup export - Exports the index page as a static HTML for pushing")
|
fmt.Println(" statup static - Creates a static HTML file of the index page")
|
||||||
fmt.Println(" statup sass - Compile .scss files into the css directory")
|
fmt.Println(" statup sass - Compile .scss files into the css directory")
|
||||||
fmt.Println(" statup test plugins - Test all plugins for required information")
|
fmt.Println(" statup test plugins - Test all plugins for required information")
|
||||||
fmt.Println(" statup env - Show all environment variables being used for Statup")
|
fmt.Println(" statup env - Show all environment variables being used for Statup")
|
||||||
fmt.Println(" statup update - Attempts to update to the latest version")
|
fmt.Println(" statup update - Attempts to update to the latest version")
|
||||||
|
fmt.Println(" statup export - Exports your Statup settings to a 'statup-export.json' file.")
|
||||||
|
fmt.Println(" statup import <file> - Imports settings from a previously saved JSON file.")
|
||||||
fmt.Println(" statup help - Shows the user basic information about Statup")
|
fmt.Println(" statup help - Shows the user basic information about Statup")
|
||||||
fmt.Printf("Flags:\n")
|
fmt.Printf("Flags:\n")
|
||||||
fmt.Println(" -ip 127.0.0.1 - Run HTTP server on specific IP address (default: localhost)")
|
fmt.Println(" -ip 127.0.0.1 - Run HTTP server on specific IP address (default: localhost)")
|
||||||
|
@ -190,7 +221,7 @@ func HelpEcho() {
|
||||||
fmt.Println(" DB_HOST - Database hostname or IP address")
|
fmt.Println(" DB_HOST - Database hostname or IP address")
|
||||||
fmt.Println(" DB_USER - Database username")
|
fmt.Println(" DB_USER - Database username")
|
||||||
fmt.Println(" DB_PASS - Database password")
|
fmt.Println(" DB_PASS - Database password")
|
||||||
fmt.Println(" DB_PORT - Database port (5432, 3306, ...")
|
fmt.Println(" DB_PORT - Database port (5432, 3306, ...)")
|
||||||
fmt.Println(" DB_DATABASE - Database connection's database name")
|
fmt.Println(" DB_DATABASE - Database connection's database name")
|
||||||
fmt.Println(" GO_ENV - Run Statup in testmode, will bypass HTTP authentication (if set as 'true')")
|
fmt.Println(" GO_ENV - Run Statup in testmode, will bypass HTTP authentication (if set as 'true')")
|
||||||
fmt.Println(" NAME - Set a name for the Statup status page")
|
fmt.Println(" NAME - Set a name for the Statup status page")
|
||||||
|
@ -198,19 +229,15 @@ func HelpEcho() {
|
||||||
fmt.Println(" DOMAIN - Set a URL for the Statup status page")
|
fmt.Println(" DOMAIN - Set a URL for the Statup status page")
|
||||||
fmt.Println(" ADMIN_USER - Username for administrator account (default: admin)")
|
fmt.Println(" ADMIN_USER - Username for administrator account (default: admin)")
|
||||||
fmt.Println(" ADMIN_PASS - Password for administrator account (default: admin)")
|
fmt.Println(" ADMIN_PASS - Password for administrator account (default: admin)")
|
||||||
|
fmt.Println(" SASS - Set the absolute path to the sass binary location")
|
||||||
fmt.Println(" * You can insert environment variables into a '.env' file in root directory.")
|
fmt.Println(" * You can insert environment variables into a '.env' file in root directory.")
|
||||||
|
|
||||||
fmt.Println("Give Statup a Star at https://github.com/hunterlong/statup")
|
fmt.Println("Give Statup a Star at https://github.com/hunterlong/statup")
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkGithubUpdates() (githubResponse, error) {
|
func checkGithubUpdates() (githubResponse, error) {
|
||||||
var gitResp githubResponse
|
var gitResp githubResponse
|
||||||
response, err := http.Get("https://api.github.com/repos/hunterlong/statup/releases/latest")
|
url := "https://api.github.com/repos/hunterlong/statup/releases/latest"
|
||||||
if err != nil {
|
contents, err := utils.HttpRequest(url, "GET", nil, nil, nil, time.Duration(10*time.Second))
|
||||||
return githubResponse{}, err
|
|
||||||
}
|
|
||||||
defer response.Body.Close()
|
|
||||||
contents, err := ioutil.ReadAll(response.Body)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return githubResponse{}, err
|
return githubResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,9 +61,9 @@ func TestHelpCommand(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExportCommand(t *testing.T) {
|
func TestExportCommand(t *testing.T) {
|
||||||
cmd := helperCommand(nil, "export")
|
cmd := helperCommand(nil, "static")
|
||||||
var got = make(chan string)
|
var got = make(chan string)
|
||||||
commandAndSleep(cmd, time.Duration(4*time.Second), got)
|
commandAndSleep(cmd, time.Duration(10*time.Second), got)
|
||||||
gg, _ := <-got
|
gg, _ := <-got
|
||||||
t.Log(gg)
|
t.Log(gg)
|
||||||
assert.Contains(t, gg, "Exporting Static 'index.html' page...")
|
assert.Contains(t, gg, "Exporting Static 'index.html' page...")
|
||||||
|
@ -72,10 +72,12 @@ func TestExportCommand(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateCommand(t *testing.T) {
|
func TestUpdateCommand(t *testing.T) {
|
||||||
c := testcli.Command("statup", "update")
|
cmd := helperCommand(nil, "version")
|
||||||
c.Run()
|
var got = make(chan string)
|
||||||
assert.True(t, c.StdoutContains("Statup Version: "+VERSION))
|
commandAndSleep(cmd, time.Duration(10*time.Second), got)
|
||||||
assert.True(t, c.StdoutContains("Latest Version:"))
|
gg, _ := <-got
|
||||||
|
t.Log(gg)
|
||||||
|
assert.Contains(t, gg, "Statup")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAssetsCommand(t *testing.T) {
|
func TestAssetsCommand(t *testing.T) {
|
||||||
|
|
|
@ -74,13 +74,11 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
utils.Log(1, fmt.Sprintf("Starting Statup v%v", VERSION))
|
utils.Log(1, fmt.Sprintf("Starting Statup v%v", VERSION))
|
||||||
defer core.CloseDB()
|
|
||||||
|
|
||||||
c := make(chan os.Signal, 1)
|
c := make(chan os.Signal, 1)
|
||||||
signal.Notify(c, os.Interrupt)
|
signal.Notify(c, os.Interrupt)
|
||||||
go func() {
|
go func() {
|
||||||
<-c
|
<-c
|
||||||
core.CloseDB()
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ func RunInit(db string, t *testing.T) {
|
||||||
func TestRunAll(t *testing.T) {
|
func TestRunAll(t *testing.T) {
|
||||||
//t.Parallel()
|
//t.Parallel()
|
||||||
|
|
||||||
databases := []string{"sqlite", "postgres", "mysql"}
|
databases := []string{"postgres", "sqlite", "mysql"}
|
||||||
if os.Getenv("ONLY_DB") != "" {
|
if os.Getenv("ONLY_DB") != "" {
|
||||||
databases = []string{os.Getenv("ONLY_DB")}
|
databases = []string{os.Getenv("ONLY_DB")}
|
||||||
}
|
}
|
||||||
|
@ -89,6 +89,8 @@ func TestRunAll(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run(dbt+" Drop Database", func(t *testing.T) {
|
t.Run(dbt+" Drop Database", func(t *testing.T) {
|
||||||
assert.NotNil(t, core.Configs)
|
assert.NotNil(t, core.Configs)
|
||||||
|
assert.NotNil(t, core.DbSession)
|
||||||
|
assert.Nil(t, core.DbSession.DB().Ping())
|
||||||
RunDropDatabase(t)
|
RunDropDatabase(t)
|
||||||
})
|
})
|
||||||
t.Run(dbt+" Connect to Database Again", func(t *testing.T) {
|
t.Run(dbt+" Connect to Database Again", func(t *testing.T) {
|
||||||
|
@ -209,14 +211,13 @@ func TestRunAll(t *testing.T) {
|
||||||
RunSettingsHandler(t)
|
RunSettingsHandler(t)
|
||||||
})
|
})
|
||||||
t.Run(dbt+" Cleanup", func(t *testing.T) {
|
t.Run(dbt+" Cleanup", func(t *testing.T) {
|
||||||
core.Configs.Close()
|
//core.CloseDB()
|
||||||
core.DbSession = nil
|
|
||||||
if dbt == "mssql" {
|
if dbt == "mssql" {
|
||||||
os.Setenv("DB_DATABASE", "root")
|
os.Setenv("DB_DATABASE", "root")
|
||||||
os.Setenv("DB_PASS", "password123")
|
os.Setenv("DB_PASS", "password123")
|
||||||
os.Setenv("DB_PORT", "1433")
|
os.Setenv("DB_PORT", "1433")
|
||||||
}
|
}
|
||||||
//Clean()
|
Clean()
|
||||||
})
|
})
|
||||||
|
|
||||||
//<-done
|
//<-done
|
||||||
|
|
|
@ -69,7 +69,7 @@ func usersDB() *gorm.DB {
|
||||||
|
|
||||||
// checkinDB returns the Checkin records for a service
|
// checkinDB returns the Checkin records for a service
|
||||||
func checkinDB() *gorm.DB {
|
func checkinDB() *gorm.DB {
|
||||||
return DbSession.Table("checkins").Model(&types.Checkin{})
|
return DbSession.Model(&types.Checkin{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkinHitsDB returns the Checkin Hits records for a service
|
// checkinHitsDB returns the Checkin Hits records for a service
|
||||||
|
@ -100,11 +100,6 @@ func CloseDB() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close shutsdown the database connection
|
|
||||||
func (db *DbConfig) Close() error {
|
|
||||||
return DbSession.DB().Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// AfterFind for Core will set the timezone
|
// AfterFind for Core will set the timezone
|
||||||
func (c *Core) AfterFind() (err error) {
|
func (c *Core) AfterFind() (err error) {
|
||||||
c.CreatedAt = utils.Timezoner(c.CreatedAt, CoreApp.Timezone)
|
c.CreatedAt = utils.Timezoner(c.CreatedAt, CoreApp.Timezone)
|
||||||
|
|
|
@ -17,7 +17,9 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"github.com/hunterlong/statup/source"
|
"github.com/hunterlong/statup/source"
|
||||||
|
"github.com/hunterlong/statup/types"
|
||||||
"github.com/hunterlong/statup/utils"
|
"github.com/hunterlong/statup/utils"
|
||||||
"html/template"
|
"html/template"
|
||||||
)
|
)
|
||||||
|
@ -42,3 +44,28 @@ func ExportChartsJs() string {
|
||||||
result := tpl.String()
|
result := tpl.String()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExportData struct {
|
||||||
|
Core *types.Core `json:"core"`
|
||||||
|
Services []types.ServiceInterface `json:"services"`
|
||||||
|
Messages []*types.Message `json:"messages"`
|
||||||
|
Checkins []*Checkin `json:"checkins"`
|
||||||
|
Users []*User `json:"users"`
|
||||||
|
Notifiers []types.AllNotifiers `json:"notifiers"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExportSettings() ([]byte, error) {
|
||||||
|
users, err := SelectAllUsers()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
data := ExportData{
|
||||||
|
Core: CoreApp.Core,
|
||||||
|
Notifiers: CoreApp.Notifications,
|
||||||
|
Checkins: AllCheckins(),
|
||||||
|
Users: users,
|
||||||
|
Services: CoreApp.Services,
|
||||||
|
}
|
||||||
|
export, err := json.Marshal(data)
|
||||||
|
return export, err
|
||||||
|
}
|
||||||
|
|
|
@ -80,7 +80,9 @@ type NotificationForm struct {
|
||||||
DbField string `json:"field"` // true variable key for input
|
DbField string `json:"field"` // true variable key for input
|
||||||
SmallText string `json:"small_text"` // insert small text under a html input
|
SmallText string `json:"small_text"` // insert small text under a html input
|
||||||
Required bool `json:"required"` // require this input on the html form
|
Required bool `json:"required"` // require this input on the html form
|
||||||
Hidden bool `json:"hidden"` // hide this form element from end user
|
IsHidden bool `json:"hidden"` // hide this form element from end user
|
||||||
|
IsList bool `json:"list"` // make this form element a comma separated list
|
||||||
|
IsSwitch bool `json:"switch"` // make the notifier a boolean true/false switch
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotificationLog contains the normalized message from previously sent notifications
|
// NotificationLog contains the normalized message from previously sent notifications
|
||||||
|
|
|
@ -217,7 +217,7 @@ func (s *Service) DowntimeText() string {
|
||||||
|
|
||||||
// Dbtimestamp will return a SQL query for grouping by date
|
// Dbtimestamp will return a SQL query for grouping by date
|
||||||
func Dbtimestamp(group string, column string) string {
|
func Dbtimestamp(group string, column string) string {
|
||||||
var seconds int64
|
seconds := 3600
|
||||||
switch group {
|
switch group {
|
||||||
case "minute":
|
case "minute":
|
||||||
seconds = 60
|
seconds = 60
|
||||||
|
@ -268,7 +268,10 @@ func GraphDataRaw(service types.ServiceInterface, start, end time.Time, group st
|
||||||
return &DateScanObj{[]DateScan{}}
|
return &DateScanObj{[]DateScan{}}
|
||||||
}
|
}
|
||||||
model = model.Order("timeframe asc", false).Group("timeframe")
|
model = model.Order("timeframe asc", false).Group("timeframe")
|
||||||
rows, _ := model.Rows()
|
rows, err := model.Debug().Rows()
|
||||||
|
if err != nil {
|
||||||
|
utils.Log(3, fmt.Errorf("issue fetching service chart data: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var gd DateScan
|
var gd DateScan
|
||||||
|
|
|
@ -18,6 +18,7 @@ package handlers
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/hunterlong/statup/core"
|
"github.com/hunterlong/statup/core"
|
||||||
"github.com/hunterlong/statup/core/notifier"
|
"github.com/hunterlong/statup/core/notifier"
|
||||||
"github.com/hunterlong/statup/types"
|
"github.com/hunterlong/statup/types"
|
||||||
|
@ -62,6 +63,7 @@ func apiRenewHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendErrorJson(err error, w http.ResponseWriter, r *http.Request) {
|
func sendErrorJson(err error, w http.ResponseWriter, r *http.Request) {
|
||||||
|
utils.Log(2, fmt.Errorf("sending error response for %v: %v", r.URL.String(), err.Error()))
|
||||||
output := apiResponse{
|
output := apiResponse{
|
||||||
Status: "error",
|
Status: "error",
|
||||||
Error: err.Error(),
|
Error: err.Error(),
|
||||||
|
|
|
@ -17,11 +17,9 @@ package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
|
||||||
"github.com/hunterlong/statup/core"
|
"github.com/hunterlong/statup/core"
|
||||||
"github.com/hunterlong/statup/core/notifier"
|
"github.com/hunterlong/statup/core/notifier"
|
||||||
"github.com/hunterlong/statup/source"
|
"github.com/hunterlong/statup/source"
|
||||||
"github.com/hunterlong/statup/types"
|
|
||||||
"github.com/hunterlong/statup/utils"
|
"github.com/hunterlong/statup/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -99,15 +97,6 @@ func logsLineHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type exportData struct {
|
|
||||||
Core *types.Core `json:"core"`
|
|
||||||
Services []types.ServiceInterface `json:"services"`
|
|
||||||
Messages []*types.Message `json:"messages"`
|
|
||||||
Checkins []*core.Checkin `json:"checkins"`
|
|
||||||
Users []*core.User `json:"users"`
|
|
||||||
Notifiers []types.AllNotifiers `json:"notifiers"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func exportHandler(w http.ResponseWriter, r *http.Request) {
|
func exportHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if !IsAuthenticated(r) {
|
if !IsAuthenticated(r) {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
@ -120,17 +109,7 @@ func exportHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
notifiers = append(notifiers, notifier.Select())
|
notifiers = append(notifiers, notifier.Select())
|
||||||
}
|
}
|
||||||
|
|
||||||
users, _ := core.SelectAllUsers()
|
export, _ := core.ExportSettings()
|
||||||
|
|
||||||
data := exportData{
|
|
||||||
Core: core.CoreApp.Core,
|
|
||||||
Notifiers: core.CoreApp.Notifications,
|
|
||||||
Checkins: core.AllCheckins(),
|
|
||||||
Users: users,
|
|
||||||
Services: core.CoreApp.Services,
|
|
||||||
}
|
|
||||||
|
|
||||||
export, _ := json.Marshal(data)
|
|
||||||
|
|
||||||
mime := http.DetectContentType(export)
|
mime := http.DetectContentType(export)
|
||||||
fileSize := len(string(export))
|
fileSize := len(string(export))
|
||||||
|
|
|
@ -16,13 +16,9 @@
|
||||||
package notifiers
|
package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"github.com/hunterlong/statup/core/notifier"
|
"github.com/hunterlong/statup/core/notifier"
|
||||||
"github.com/hunterlong/statup/types"
|
"github.com/hunterlong/statup/types"
|
||||||
"github.com/hunterlong/statup/utils"
|
"github.com/hunterlong/statup/utils"
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -69,59 +65,10 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCommand(app, cmd string) (string, string, error) {
|
func runCommand(app, cmd string) (string, string, error) {
|
||||||
testCmd := exec.Command(app, "-c", cmd)
|
outStr, errStr, err := utils.Command(cmd)
|
||||||
|
|
||||||
var stdout, stderr []byte
|
|
||||||
var errStdout, errStderr error
|
|
||||||
stdoutIn, _ := testCmd.StdoutPipe()
|
|
||||||
stderrIn, _ := testCmd.StderrPipe()
|
|
||||||
testCmd.Start()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
stdout, errStdout = copyAndCapture(os.Stdout, stdoutIn)
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
stderr, errStderr = copyAndCapture(os.Stderr, stderrIn)
|
|
||||||
}()
|
|
||||||
|
|
||||||
err := testCmd.Wait()
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if errStdout != nil || errStderr != nil {
|
|
||||||
return "", "", errors.New("failed to capture stdout or stderr")
|
|
||||||
}
|
|
||||||
|
|
||||||
outStr, errStr := string(stdout), string(stderr)
|
|
||||||
return outStr, errStr, err
|
return outStr, errStr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// copyAndCapture captures the response from a terminal command
|
|
||||||
func copyAndCapture(w io.Writer, r io.Reader) ([]byte, error) {
|
|
||||||
var out []byte
|
|
||||||
buf := make([]byte, 1024, 1024)
|
|
||||||
for {
|
|
||||||
n, err := r.Read(buf[:])
|
|
||||||
if n > 0 {
|
|
||||||
d := buf[:n]
|
|
||||||
out = append(out, d...)
|
|
||||||
_, err := w.Write(d)
|
|
||||||
if err != nil {
|
|
||||||
return out, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
// Read returns io.EOF at the end of file, which is not an error for us
|
|
||||||
if err == io.EOF {
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
return out, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *commandLine) Select() *notifier.Notification {
|
func (u *commandLine) Select() *notifier.Notification {
|
||||||
return u.Notification
|
return u.Notification
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hunterlong/statup/core/notifier"
|
"github.com/hunterlong/statup/core/notifier"
|
||||||
"github.com/hunterlong/statup/types"
|
"github.com/hunterlong/statup/types"
|
||||||
"io/ioutil"
|
"github.com/hunterlong/statup/utils"
|
||||||
"net/http"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -59,14 +59,8 @@ func init() {
|
||||||
// Send will send a HTTP Post to the discord API. It accepts type: []byte
|
// Send will send a HTTP Post to the discord API. It accepts type: []byte
|
||||||
func (u *discord) Send(msg interface{}) error {
|
func (u *discord) Send(msg interface{}) error {
|
||||||
message := msg.(string)
|
message := msg.(string)
|
||||||
req, _ := http.NewRequest("POST", discorder.GetValue("host"), bytes.NewBuffer([]byte(message)))
|
_, err := utils.HttpRequest(discorder.GetValue("host"), "POST", "application/json", nil, strings.NewReader(message), time.Duration(10*time.Second))
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
client := &http.Client{}
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
return resp.Body.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *discord) Select() *notifier.Notification {
|
func (u *discord) Select() *notifier.Notification {
|
||||||
|
@ -101,15 +95,7 @@ func (u *discord) OnSave() error {
|
||||||
func (u *discord) OnTest() error {
|
func (u *discord) OnTest() error {
|
||||||
outError := errors.New("Incorrect discord URL, please confirm URL is correct")
|
outError := errors.New("Incorrect discord URL, please confirm URL is correct")
|
||||||
message := `{"content": "Testing the discord notifier"}`
|
message := `{"content": "Testing the discord notifier"}`
|
||||||
req, _ := http.NewRequest("POST", discorder.Host, bytes.NewBuffer([]byte(message)))
|
contents, err := utils.HttpRequest(discorder.Host, "POST", "application/json", nil, bytes.NewBuffer([]byte(message)), time.Duration(10*time.Second))
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
client := &http.Client{}
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
contents, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
if string(contents) == "" {
|
if string(contents) == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,12 +26,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
EMAIL_HOST = os.Getenv("EMAIL_HOST")
|
EMAIL_HOST string
|
||||||
EMAIL_USER = os.Getenv("EMAIL_USER")
|
EMAIL_USER string
|
||||||
EMAIL_PASS = os.Getenv("EMAIL_PASS")
|
EMAIL_PASS string
|
||||||
EMAIL_OUTGOING = os.Getenv("EMAIL_OUTGOING")
|
EMAIL_OUTGOING string
|
||||||
EMAIL_SEND_TO = os.Getenv("EMAIL_SEND_TO")
|
EMAIL_SEND_TO string
|
||||||
EMAIL_PORT = utils.StringInt(os.Getenv("EMAIL_PORT"))
|
EMAIL_PORT int64
|
||||||
)
|
)
|
||||||
|
|
||||||
var testEmail *emailOutgoing
|
var testEmail *emailOutgoing
|
||||||
|
@ -42,7 +42,7 @@ func init() {
|
||||||
EMAIL_PASS = os.Getenv("EMAIL_PASS")
|
EMAIL_PASS = os.Getenv("EMAIL_PASS")
|
||||||
EMAIL_OUTGOING = os.Getenv("EMAIL_OUTGOING")
|
EMAIL_OUTGOING = os.Getenv("EMAIL_OUTGOING")
|
||||||
EMAIL_SEND_TO = os.Getenv("EMAIL_SEND_TO")
|
EMAIL_SEND_TO = os.Getenv("EMAIL_SEND_TO")
|
||||||
EMAIL_PORT = utils.StringInt(os.Getenv("EMAIL_PORT"))
|
EMAIL_PORT = utils.ToInt(os.Getenv("EMAIL_PORT"))
|
||||||
|
|
||||||
emailer.Host = EMAIL_HOST
|
emailer.Host = EMAIL_HOST
|
||||||
emailer.Username = EMAIL_USER
|
emailer.Username = EMAIL_USER
|
||||||
|
|
|
@ -20,9 +20,9 @@ import (
|
||||||
"github.com/hunterlong/statup/core/notifier"
|
"github.com/hunterlong/statup/core/notifier"
|
||||||
"github.com/hunterlong/statup/types"
|
"github.com/hunterlong/statup/types"
|
||||||
"github.com/hunterlong/statup/utils"
|
"github.com/hunterlong/statup/utils"
|
||||||
"net/http"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -59,21 +59,11 @@ func init() {
|
||||||
// Send will send a HTTP Post with the Authorization to the notify-api.line.me server. It accepts type: string
|
// Send will send a HTTP Post with the Authorization to the notify-api.line.me server. It accepts type: string
|
||||||
func (u *lineNotifier) Send(msg interface{}) error {
|
func (u *lineNotifier) Send(msg interface{}) error {
|
||||||
message := msg.(string)
|
message := msg.(string)
|
||||||
client := new(http.Client)
|
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
v.Set("message", message)
|
v.Set("message", message)
|
||||||
req, err := http.NewRequest("POST", "https://notify-api.line.me/api/notify", strings.NewReader(v.Encode()))
|
headers := []string{fmt.Sprintf("Authorization=Bearer %v", u.GetValue("api_secret"))}
|
||||||
if err != nil {
|
_, err := utils.HttpRequest("https://notify-api.line.me/api/notify", "POST", "application/x-www-form-urlencoded", headers, strings.NewReader(v.Encode()), time.Duration(10*time.Second))
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
req.Header.Add("Authorization", fmt.Sprintf("Bearer %v", u.GetValue("api_secret")))
|
|
||||||
req.Header.Add("Accept", "application/json")
|
|
||||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
_, err = client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *lineNotifier) Select() *notifier.Notification {
|
func (u *lineNotifier) Select() *notifier.Notification {
|
||||||
|
|
|
@ -43,7 +43,7 @@ var mobile = &mobilePush{¬ifier.Notification{
|
||||||
Title: "Device Identifiers",
|
Title: "Device Identifiers",
|
||||||
Placeholder: "A list of your mobile device push notification ID's.",
|
Placeholder: "A list of your mobile device push notification ID's.",
|
||||||
DbField: "var1",
|
DbField: "var1",
|
||||||
Hidden: true,
|
IsHidden: true,
|
||||||
}}},
|
}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hunterlong/statup/core/notifier"
|
"github.com/hunterlong/statup/core/notifier"
|
||||||
"github.com/hunterlong/statup/types"
|
"github.com/hunterlong/statup/types"
|
||||||
"io/ioutil"
|
"github.com/hunterlong/statup/utils"
|
||||||
"net/http"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -85,14 +85,8 @@ func init() {
|
||||||
// Send will send a HTTP Post to the slack webhooker API. It accepts type: string
|
// Send will send a HTTP Post to the slack webhooker API. It accepts type: string
|
||||||
func (u *slack) Send(msg interface{}) error {
|
func (u *slack) Send(msg interface{}) error {
|
||||||
message := msg.(string)
|
message := msg.(string)
|
||||||
client := new(http.Client)
|
_, err := utils.HttpRequest(u.Host, "POST", "application/json", nil, strings.NewReader(message), time.Duration(10*time.Second))
|
||||||
res, err := client.Post(u.Host, "application/json", bytes.NewBuffer([]byte(message)))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
//contents, _ := ioutil.ReadAll(res.Body)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *slack) Select() *notifier.Notification {
|
func (u *slack) Select() *notifier.Notification {
|
||||||
|
@ -100,13 +94,7 @@ func (u *slack) Select() *notifier.Notification {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *slack) OnTest() error {
|
func (u *slack) OnTest() error {
|
||||||
client := new(http.Client)
|
contents, err := utils.HttpRequest(u.Host, "POST", "application/json", nil, bytes.NewBuffer([]byte(`{"text":"testing message"}`)), time.Duration(10*time.Second))
|
||||||
res, err := client.Post(u.Host, "application/json", bytes.NewBuffer([]byte(`{"text":"testing message"}`)))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
contents, _ := ioutil.ReadAll(res.Body)
|
|
||||||
if string(contents) != "ok" {
|
if string(contents) != "ok" {
|
||||||
return errors.New("The slack response was incorrect, check the URL")
|
return errors.New("The slack response was incorrect, check the URL")
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,6 @@ import (
|
||||||
"github.com/hunterlong/statup/core/notifier"
|
"github.com/hunterlong/statup/core/notifier"
|
||||||
"github.com/hunterlong/statup/types"
|
"github.com/hunterlong/statup/types"
|
||||||
"github.com/hunterlong/statup/utils"
|
"github.com/hunterlong/statup/utils"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -84,32 +82,21 @@ func (u *twilio) Select() *notifier.Notification {
|
||||||
func (u *twilio) Send(msg interface{}) error {
|
func (u *twilio) Send(msg interface{}) error {
|
||||||
message := msg.(string)
|
message := msg.(string)
|
||||||
twilioUrl := fmt.Sprintf("https://api.twilio.com/2010-04-01/Accounts/%v/Messages.json", u.GetValue("api_key"))
|
twilioUrl := fmt.Sprintf("https://api.twilio.com/2010-04-01/Accounts/%v/Messages.json", u.GetValue("api_key"))
|
||||||
client := &http.Client{}
|
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
v.Set("To", "+"+u.Var1)
|
v.Set("To", "+"+u.Var1)
|
||||||
v.Set("From", "+"+u.Var2)
|
v.Set("From", "+"+u.Var2)
|
||||||
v.Set("Body", message)
|
v.Set("Body", message)
|
||||||
rb := *strings.NewReader(v.Encode())
|
rb := *strings.NewReader(v.Encode())
|
||||||
req, err := http.NewRequest("POST", twilioUrl, &rb)
|
|
||||||
if err != nil {
|
contents, err := utils.HttpRequest(twilioUrl, "POST", "application/x-www-form-urlencoded", nil, &rb, time.Duration(10*time.Second))
|
||||||
return err
|
|
||||||
}
|
|
||||||
req.SetBasicAuth(u.ApiKey, u.ApiSecret)
|
|
||||||
req.Header.Add("Accept", "application/json")
|
|
||||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
contents, _ := ioutil.ReadAll(res.Body)
|
|
||||||
success, _ := twilioSuccess(contents)
|
success, _ := twilioSuccess(contents)
|
||||||
if !success {
|
if !success {
|
||||||
errorOut := twilioError(contents)
|
errorOut := twilioError(contents)
|
||||||
out := fmt.Sprintf("Error code %v - %v", errorOut.Code, errorOut.Message)
|
out := fmt.Sprintf("Error code %v - %v", errorOut.Code, errorOut.Message)
|
||||||
return errors.New(out)
|
return errors.New(out)
|
||||||
}
|
}
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// OnFailure will trigger failing service
|
||||||
|
|
|
@ -59,7 +59,14 @@
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="notify_before" class="col-sm-4 col-form-label">Notify Before</label>
|
<label for="notify_before" class="col-sm-4 col-form-label">Notify Before</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<input type="text" name="notify_before" class="form-control" id="notify_before" value="{{.NotifyBefore}}">
|
<div class="form-inline">
|
||||||
|
<input type="number" name="notify_before_scale" class="col-4 form-control" id="notify_before" value="{{.NotifyBefore.Int64}}" >
|
||||||
|
<select class="ml-2 col-7 form-control" name="notify_before_scale" id="notify_before_scale">
|
||||||
|
<option value="minute"{{if ne .Id 0}} selected{{end}}>Minutes</option>
|
||||||
|
<option value="hour">Hours</option>
|
||||||
|
<option value="day">Days</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
<div class="form-group row{{if (eq .Type "tcp") or (eq .Type "udp")}} d-none{{end}}">
|
<div class="form-group row{{if (eq .Type "tcp") or (eq .Type "udp")}} d-none{{end}}">
|
||||||
<label for="service_response_code" class="col-sm-4 col-form-label">Expected Status Code</label>
|
<label for="service_response_code" class="col-sm-4 col-form-label">Expected Status Code</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<input type="number" name="expected_status" class="form-control" value="{{if ne .ExpectedStatus 0}}{{.ExpectedStatus}}{{end}}" placeholder="200" id="service_response_code">
|
<input type="number" name="expected_status" class="form-control" value="{{if ne .ExpectedStatus 0}}{{.ExpectedStatus}}{{else}}200{{end}}" placeholder="200" id="service_response_code">
|
||||||
<small class="form-text text-muted">A status code of 200 is success, or view all the <a target="_blank" href="https://www.restapitutorial.com/httpstatuscodes.html">HTTP Status Codes</a></small>
|
<small class="form-text text-muted">A status code of 200 is success, or view all the <a target="_blank" href="https://www.restapitutorial.com/httpstatuscodes.html">HTTP Status Codes</a></small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -90,6 +90,15 @@
|
||||||
<small class="form-text text-muted">You can also drag and drop services to reorder on the Services tab.</small>
|
<small class="form-text text-muted">You can also drag and drop services to reorder on the Services tab.</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="order" class="col-sm-4 col-form-label">Notifications</label>
|
||||||
|
<div class="col-8 mt-1">
|
||||||
|
<span class="switch float-left">
|
||||||
|
<input type="checkbox" name="allow_notifications" class="switch" id="switch-service" {{if eq .Id 0}}checked{{end}}{{if .AllowNotifications.Bool}}checked{{end}}>
|
||||||
|
<label for="switch-service">Allow notifications to be sent for this service</label>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<div class="{{if ne .Id 0}}col-6{{else}}col-12{{end}}">
|
<div class="{{if ne .Id 0}}col-6{{else}}col-12{{end}}">
|
||||||
<button type="submit" class="btn btn-success btn-block">{{if ne .Id 0}}Update Service{{else}}Create Service{{end}}</button>
|
<button type="submit" class="btn btn-success btn-block">{{if ne .Id 0}}Update Service{{else}}Create Service{{end}}</button>
|
||||||
|
|
|
@ -940,8 +940,12 @@
|
||||||
"exec": [
|
"exec": [
|
||||||
"pm.test(\"Create Message\", function () {",
|
"pm.test(\"Create Message\", function () {",
|
||||||
" var jsonData = pm.response.json();",
|
" var jsonData = pm.response.json();",
|
||||||
" pm.expect(jsonData.output.title).to.eql(\"API Message\");",
|
" var object = jsonData.output;",
|
||||||
" pm.expect(jsonData.output.service).to.eql(1);",
|
" pm.expect(object.title).to.eql(\"API Message\");",
|
||||||
|
" pm.expect(object.description).to.eql(\"This is an example a upcoming message for a service!\");",
|
||||||
|
" pm.expect(object.service).to.eql(1);",
|
||||||
|
" pm.expect(object.notify_before).to.eql(6);",
|
||||||
|
" pm.expect(object.notify_before_scale).to.eql(\"hour\");",
|
||||||
"});"
|
"});"
|
||||||
],
|
],
|
||||||
"type": "text/javascript"
|
"type": "text/javascript"
|
||||||
|
@ -960,7 +964,7 @@
|
||||||
],
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"mode": "raw",
|
"mode": "raw",
|
||||||
"raw": "{\n \"title\": \"API Message\",\n \"description\": \"This is an example a upcoming message for a service!\",\n \"start_on\": \"2022-11-17T03:28:16.323797-08:00\",\n \"end_on\": \"2022-11-17T05:13:16.323798-08:00\",\n \"service\": 1,\n \"notify_users\": null,\n \"notify_method\": \"\",\n \"notify_before\": 0\n}"
|
"raw": "{\n \"title\": \"API Message\",\n \"description\": \"This is an example a upcoming message for a service!\",\n \"start_on\": \"2022-11-17T03:28:16.323797-08:00\",\n \"end_on\": \"2022-11-17T05:13:16.323798-08:00\",\n \"service\": 1,\n \"notify_users\": true,\n \"notify_method\": \"email\",\n \"notify_before\": 6,\n \"notify_before_scale\": \"hour\"\n}"
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"raw": "{{endpoint}}/api/messages",
|
"raw": "{{endpoint}}/api/messages",
|
||||||
|
@ -981,7 +985,7 @@
|
||||||
{
|
{
|
||||||
"listen": "test",
|
"listen": "test",
|
||||||
"script": {
|
"script": {
|
||||||
"id": "abbb5178-9613-418c-b5ee-be2d6b4fdb8f",
|
"id": "c30cc333-53f4-4e9a-9c32-958c905ec163",
|
||||||
"exec": [
|
"exec": [
|
||||||
"pm.test(\"View Message\", function () {",
|
"pm.test(\"View Message\", function () {",
|
||||||
" var jsonData = pm.response.json();",
|
" var jsonData = pm.response.json();",
|
||||||
|
@ -1020,13 +1024,16 @@
|
||||||
{
|
{
|
||||||
"listen": "test",
|
"listen": "test",
|
||||||
"script": {
|
"script": {
|
||||||
"id": "a0403c03-0838-4fd2-9cce-aebaf8a128c3",
|
"id": "e9dd78cc-0f38-4516-bf82-38dd3451b2e7",
|
||||||
"exec": [
|
"exec": [
|
||||||
"pm.test(\"Update Message\", function () {",
|
"pm.test(\"Update Message\", function () {",
|
||||||
" var jsonData = pm.response.json();",
|
" var jsonData = pm.response.json();",
|
||||||
" pm.expect(jsonData.status).to.eql(\"success\");",
|
" var object = jsonData.output;",
|
||||||
" pm.expect(jsonData.method).to.eql(\"update\");",
|
" pm.expect(object.title).to.eql(\"Updated Message\");",
|
||||||
" pm.expect(jsonData.id).to.eql(1);",
|
" pm.expect(object.description).to.eql(\"This message was updated\");",
|
||||||
|
" pm.expect(object.service).to.eql(1);",
|
||||||
|
" pm.expect(object.notify_before).to.eql(3);",
|
||||||
|
" pm.expect(object.notify_before_scale).to.eql(\"hour\");",
|
||||||
"});"
|
"});"
|
||||||
],
|
],
|
||||||
"type": "text/javascript"
|
"type": "text/javascript"
|
||||||
|
@ -1045,7 +1052,7 @@
|
||||||
],
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"mode": "raw",
|
"mode": "raw",
|
||||||
"raw": "{\n \"title\": \"Routine Downtime\",\n \"description\": \"This is an example a upcoming message for a service!\",\n \"start_on\": \"2055-11-17T03:28:16.323797-08:00\",\n \"end_on\": \"2055-11-17T05:13:16.323798-08:00\",\n \"service\": 2,\n \"notify_users\": true,\n \"notify_method\": \"email\",\n \"notify_before\": 900\n}"
|
"raw": "{\n \"title\": \"Updated Message\",\n \"description\": \"This message was updated\",\n \"start_on\": \"2022-11-17T03:28:16.323797-08:00\",\n \"end_on\": \"2022-11-17T05:13:16.323798-08:00\",\n \"service\": 1,\n \"notify_users\": true,\n \"notify_method\": \"email\",\n \"notify_before\": 3,\n \"notify_before_scale\": \"hour\"\n}"
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"raw": "{{endpoint}}/api/messages/1",
|
"raw": "{{endpoint}}/api/messages/1",
|
||||||
|
|
|
@ -29,7 +29,8 @@ type Message struct {
|
||||||
ServiceId int64 `gorm:"index;column:service" json:"service"`
|
ServiceId int64 `gorm:"index;column:service" json:"service"`
|
||||||
NotifyUsers NullBool `gorm:"column:notify_users" json:"notify_users"`
|
NotifyUsers NullBool `gorm:"column:notify_users" json:"notify_users"`
|
||||||
NotifyMethod string `gorm:"column:notify_method" json:"notify_method"`
|
NotifyMethod string `gorm:"column:notify_method" json:"notify_method"`
|
||||||
NotifyBefore time.Duration `gorm:"column:notify_before" json:"notify_before"`
|
NotifyBefore NullInt64 `gorm:"column:notify_before" json:"notify_before"`
|
||||||
|
NotifyBeforeScale string `gorm:"column:notify_before_scale" json:"notify_before_scale"`
|
||||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at" json:"created_at"`
|
CreatedAt time.Time `gorm:"column:created_at" json:"created_at" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at" json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,13 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/ararog/timeago"
|
"github.com/ararog/timeago"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -221,3 +223,39 @@ func SaveFile(filename string, data []byte) error {
|
||||||
err := ioutil.WriteFile(filename, data, 0644)
|
err := ioutil.WriteFile(filename, data, 0644)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HttpRequest is a global function to send a HTTP request
|
||||||
|
func HttpRequest(url, method string, content interface{}, headers []string, body io.Reader, timeout time.Duration) ([]byte, error) {
|
||||||
|
var err error
|
||||||
|
var contentType string
|
||||||
|
if content != nil {
|
||||||
|
contentType = content.(string)
|
||||||
|
}
|
||||||
|
transport := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
},
|
||||||
|
TLSHandshakeTimeout: timeout,
|
||||||
|
}
|
||||||
|
client := &http.Client{
|
||||||
|
Transport: transport,
|
||||||
|
Timeout: timeout,
|
||||||
|
}
|
||||||
|
var response *http.Response
|
||||||
|
response.Header.Set("User-Agent", "Statup")
|
||||||
|
for _, h := range headers {
|
||||||
|
keyVal := strings.Split(h, "=")
|
||||||
|
response.Header.Add(keyVal[0], keyVal[1])
|
||||||
|
}
|
||||||
|
if method == "POST" {
|
||||||
|
response, err = client.Post(url, contentType, body)
|
||||||
|
} else {
|
||||||
|
response, err = client.Get(url)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
contents, err := ioutil.ReadAll(response.Body)
|
||||||
|
return contents, err
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue