pull/78/head
Hunter Long 2018-10-06 21:48:33 -07:00
parent 55cb0808bd
commit 9061a97955
23 changed files with 162 additions and 154 deletions

2
.gitignore vendored
View File

@ -22,4 +22,4 @@ source/rice-box.go
sass
.DS_Store
source/css/base.css.map
/dev/test/node_modules/
dev/test/node_modules

View File

@ -13,6 +13,7 @@ PATH:=/usr/local/bin:$(GOPATH)/bin:$(PATH)
PUBLISH_BODY='{ "request": { "branch": "master", "config": { "env": { "VERSION": "$(VERSION)", "COMMIT": "$(TRAVIS_COMMIT)" } } } }'
TRAVIS_BUILD_CMD='{ "request": { "branch": "master", "message": "Compile master for Statup v$(VERSION)", "config": { "os": [ "linux" ], "language": "go", "go": [ "1.10.x" ], "go_import_path": "github.com/hunterlong/statup", "install": true, "sudo": "required", "services": [ "docker" ], "env": { "VERSION": "$(VERSION)" }, "matrix": { "allow_failures": [ { "go": "master" } ], "fast_finish": true }, "before_deploy": [ "git config --local user.name \"hunterlong\"", "git config --local user.email \"info@socialeck.com\"", "make tag" ], "deploy": [ { "provider": "releases", "api_key": "$(GH_TOKEN)", "file": [ "build/statup-osx-x64.tar.gz", "build/statup-osx-x32.tar.gz", "build/statup-linux-x64.tar.gz", "build/statup-linux-x32.tar.gz", "build/statup-linux-arm64.tar.gz", "build/statup-linux-arm7.tar.gz", "build/statup-linux-alpine.tar.gz", "build/statup-windows-x64.zip" ], "skip_cleanup": true } ], "notifications": { "email": false }, "before_script": ["gem install sass"], "script": [ "travis_wait 30 docker pull karalabe/xgo-latest", "make release" ], "after_success": [], "after_deploy": [ "make publish-dev" ] } } }'
TEST_DIR=$(GOPATH)/src/github.com/hunterlong/statup
PATH:=$(PATH)
# build and compile Statup and then test
all: dev-deps compile install test-all docker-build-all

View File

@ -92,7 +92,7 @@ func CatchCLI(args []string) error {
return err
}
indexSource := core.ExportIndexHTML()
err = core.SaveFile("./index.html", []byte(indexSource))
err = utils.SaveFile("./index.html", []byte(indexSource))
if err != nil {
utils.Log(4, err)
return err
@ -194,7 +194,7 @@ func HelpEcho() {
// core.OnSuccess(core.SelectService(1))
// fmt.Println("\n" + BRAKER)
// fmt.Println(POINT + "Sending 'OnFailure(Service, FailureData)'")
// fakeFailD := &types.Failure{
// fakeFailD := &types.failure{
// Issue: "No issue, just testing this plugin. This would include HTTP failure information though",
// }
// core.OnFailure(core.SelectService(1), fakeFailD)
@ -206,7 +206,7 @@ func HelpEcho() {
// fmt.Println(POINT + "Sending 'OnNewService(Service)'")
// core.OnNewService(core.SelectService(2))
// fmt.Println("\n" + BRAKER)
// fmt.Println(POINT + "Sending 'OnNewUser(User)'")
// fmt.Println(POINT + "Sending 'OnNewUser(user)'")
// user, _ := core.SelectUser(1)
// core.OnNewUser(user)
// fmt.Println("\n" + BRAKER)
@ -258,7 +258,7 @@ func HelpEcho() {
// }}
// fakeSrv2.Create()
//
// fakeUser := &types.User{
// fakeUser := &types.user{
// Id: 6334,
// Username: "Bulbasaur",
// Password: "$2a$14$NzT/fLdE3f9iB1Eux2C84O6ZoPhI4NfY0Ke32qllCFo8pMTkUPZzy",
@ -268,7 +268,7 @@ func HelpEcho() {
// }
// fakeUser.Create()
//
// fakeUser = &types.User{
// fakeUser = &types.user{
// Id: 6335,
// Username: "Billy",
// Password: "$2a$14$NzT/fLdE3f9iB1Eux2C84O6ZoPhI4NfY0Ke32qllCFo8pMTkUPZzy",
@ -288,12 +288,12 @@ func HelpEcho() {
// }
// fakeSrv2.CreateHit(dd)
//
// fail := &types.Failure{
// fail := &types.failure{
// Issue: "This is not an issue, but it would container HTTP response errors.",
// }
// fakeSrv.CreateFailure(fail)
//
// fail = &types.Failure{
// fail = &types.failure{
// Issue: "HTTP Status Code 521 did not match 200",
// }
// fakeSrv.CreateFailure(fail)

View File

@ -28,10 +28,10 @@ import (
)
var (
VERSION string
// VERSION stores the current version of Statup
VERSION string
// COMMIT stores the git commit hash for this version of Statup
COMMIT string
usingEnv bool
directory string
ipAddress string
port int
)

View File

@ -121,12 +121,12 @@ func TestRunAll(t *testing.T) {
t.Run(dbt+" Create Users", func(t *testing.T) {
RunUserCreate(t)
})
t.Run(dbt+" Update User", func(t *testing.T) {
RunUser_Update(t)
t.Run(dbt+" Update user", func(t *testing.T) {
runUserUpdate(t)
})
t.Run(dbt+" Create Non Unique Users", func(t *testing.T) {
t.SkipNow()
RunUser_NonUniqueCreate(t)
runUserNonUniqueCreate(t)
})
t.Run(dbt+" Select Users", func(t *testing.T) {
RunUserSelectAll(t)
@ -147,7 +147,7 @@ func TestRunAll(t *testing.T) {
RunServiceToJSON(t)
})
t.Run(dbt+" Avg Time", func(t *testing.T) {
RunService_AvgTime(t)
runServiceAvgTime(t)
})
t.Run(dbt+" Online 24h", func(t *testing.T) {
RunServiceOnline24(t)
@ -173,7 +173,7 @@ func TestRunAll(t *testing.T) {
t.Run(dbt+" Delete Service", func(t *testing.T) {
RunDeleteService(t)
})
t.Run(dbt+" Delete User", func(t *testing.T) {
t.Run(dbt+" Delete user", func(t *testing.T) {
RunUserDelete(t)
})
t.Run(dbt+" HTTP /", func(t *testing.T) {
@ -341,7 +341,7 @@ func RunUserCreate(t *testing.T) {
assert.Equal(t, int64(4), id)
}
func RunUser_Update(t *testing.T) {
func runUserUpdate(t *testing.T) {
user, err := core.SelectUser(1)
user.Email = "info@updatedemail.com"
assert.Nil(t, err)
@ -352,7 +352,7 @@ func RunUser_Update(t *testing.T) {
assert.Equal(t, "info@updatedemail.com", updatedUser.Email)
}
func RunUser_NonUniqueCreate(t *testing.T) {
func runUserNonUniqueCreate(t *testing.T) {
user := core.ReturnUser(&types.User{
Username: "admin",
Password: "admin",
@ -410,7 +410,7 @@ func RunServiceToJSON(t *testing.T) {
assert.NotEmpty(t, jsoned)
}
func RunService_AvgTime(t *testing.T) {
func runServiceAvgTime(t *testing.T) {
service := core.SelectService(1)
assert.NotNil(t, service)
avg := service.AvgUptime24()

View File

@ -176,7 +176,7 @@ func (s *Service) checkHttp(record bool) *Service {
return s
}
response.Header.Set("Connection", "close")
response.Header.Set("User-Agent", "StatupMonitor")
response.Header.Set("user-Agent", "StatupMonitor")
t2 := time.Now()
s.Latency = t2.Sub(t1).Seconds()
if err != nil {

View File

@ -23,84 +23,84 @@ import (
"time"
)
type Checkin struct {
type checkin struct {
*types.Checkin
}
type CheckinHit struct {
type checkinHit struct {
*types.CheckinHit
}
// String will return a Checkin API string
func (c *Checkin) String() string {
// String will return a checkin API string
func (c *checkin) String() string {
return c.ApiKey
}
// ReturnCheckin converts *types.Checking to *core.Checkin
func ReturnCheckin(s *types.Checkin) *Checkin {
return &Checkin{Checkin: s}
// ReturnCheckin converts *types.Checking to *core.checkin
func ReturnCheckin(s *types.Checkin) *checkin {
return &checkin{Checkin: s}
}
// ReturnCheckinHit converts *types.CheckinHit to *core.CheckinHit
func ReturnCheckinHit(h *types.CheckinHit) *CheckinHit {
return &CheckinHit{CheckinHit: h}
// ReturnCheckinHit converts *types.checkinHit to *core.checkinHit
func ReturnCheckinHit(h *types.CheckinHit) *checkinHit {
return &checkinHit{CheckinHit: h}
}
// SelectCheckin will find a Checkin based on the API supplied
func SelectCheckin(api string) *Checkin {
var checkin Checkin
// SelectCheckin will find a checkin based on the API supplied
func SelectCheckin(api string) *checkin {
var checkin checkin
checkinDB().Where("api_key = ?", api).First(&checkin)
return &checkin
}
// Period will return the duration of the Checkin interval
func (u *Checkin) Period() time.Duration {
duration, _ := time.ParseDuration(fmt.Sprintf("%vs", u.Interval))
// Period will return the duration of the checkin interval
func (c *checkin) Period() time.Duration {
duration, _ := time.ParseDuration(fmt.Sprintf("%vs", c.Interval))
return duration
}
// Grace will return the duration of the Checkin Grace Period (after service hasn't responded, wait a bit for a response)
func (u *Checkin) Grace() time.Duration {
duration, _ := time.ParseDuration(fmt.Sprintf("%vs", u.GracePeriod))
// Grace will return the duration of the checkin Grace Period (after service hasn't responded, wait a bit for a response)
func (c *checkin) Grace() time.Duration {
duration, _ := time.ParseDuration(fmt.Sprintf("%vs", c.GracePeriod))
return duration
}
// Expected returns the duration of when the serviec should receive a checkin
func (u *Checkin) Expected() time.Duration {
last := u.Last().CreatedAt
func (c *checkin) Expected() time.Duration {
last := c.Last().CreatedAt
now := time.Now()
lastDir := now.Sub(last)
sub := time.Duration(u.Period() - lastDir)
sub := time.Duration(c.Period() - lastDir)
return sub
}
// Last returns the last CheckinHit for a Checkin
func (u *Checkin) Last() CheckinHit {
var hit CheckinHit
checkinHitsDB().Where("checkin = ?", u.Id).Last(&hit)
// Last returns the last checkinHit for a checkin
func (c *checkin) Last() checkinHit {
var hit checkinHit
checkinHitsDB().Where("checkin = ?", c.Id).Last(&hit)
return hit
}
// Hits returns all of the CheckinHits for a given Checkin
func (u *Checkin) Hits() []CheckinHit {
var checkins []CheckinHit
checkinHitsDB().Where("checkin = ?", u.Id).Order("id DESC").Find(&checkins)
// Hits returns all of the CheckinHits for a given checkin
func (c *checkin) Hits() []checkinHit {
var checkins []checkinHit
checkinHitsDB().Where("checkin = ?", c.Id).Order("id DESC").Find(&checkins)
return checkins
}
// Create will create a new Checkin
func (u *Checkin) Create() (int64, error) {
u.ApiKey = utils.RandomString(7)
row := checkinDB().Create(&u)
// Create will create a new checkin
func (c *checkin) Create() (int64, error) {
c.ApiKey = utils.RandomString(7)
row := checkinDB().Create(&c)
if row.Error != nil {
utils.Log(2, row.Error)
return 0, row.Error
}
return u.Id, row.Error
return c.Id, row.Error
}
// Update will update a Checkin
func (u *Checkin) Update() (int64, error) {
// Update will update a checkin
func (u *checkin) Update() (int64, error) {
row := checkinDB().Update(&u)
if row.Error != nil {
utils.Log(2, row.Error)
@ -109,8 +109,8 @@ func (u *Checkin) Update() (int64, error) {
return u.Id, row.Error
}
// Create will create a new successful CheckinHit
func (u *CheckinHit) Create() (int64, error) {
// Create will create a new successful checkinHit
func (u *checkinHit) Create() (int64, error) {
if u.CreatedAt.IsZero() {
u.CreatedAt = time.Now()
}
@ -122,14 +122,14 @@ func (u *CheckinHit) Create() (int64, error) {
return u.Id, row.Error
}
// Ago returns the duration of time between now and the last successful CheckinHit
func (f *CheckinHit) Ago() string {
// Ago returns the duration of time between now and the last successful checkinHit
func (f *checkinHit) Ago() string {
got, _ := timeago.TimeAgoWithTime(time.Now(), f.CreatedAt)
return got
}
// RecheckCheckinFailure will check if a Service Checkin has been reported yet
func (c *Checkin) RecheckCheckinFailure(guard chan struct{}) {
// RecheckCheckinFailure will check if a Service checkin has been reported yet
func (c *checkin) RecheckCheckinFailure(guard chan struct{}) {
between := time.Now().Sub(time.Now()).Seconds()
if between > float64(c.Interval) {
fmt.Println("rechecking every 15 seconds!")

View File

@ -61,12 +61,12 @@ func usersDB() *gorm.DB {
return DbSession.Model(&types.User{})
}
// checkinDB returns the Checkin records for a service
// checkinDB returns the checkin records for a service
func checkinDB() *gorm.DB {
return DbSession.Model(&types.Checkin{})
}
// checkinHitsDB returns the 'hits' from the Checkin record
// checkinHitsDB returns the 'hits' from the checkin record
func checkinHitsDB() *gorm.DB {
return DbSession.Model(&types.CheckinHit{})
}
@ -101,26 +101,26 @@ func (s *Hit) AfterFind() (err error) {
return
}
// AfterFind for Failure will set the timezone
func (f *Failure) AfterFind() (err error) {
// AfterFind for failure will set the timezone
func (f *failure) AfterFind() (err error) {
f.CreatedAt = utils.Timezoner(f.CreatedAt, CoreApp.Timezone)
return
}
// AfterFind for USer will set the timezone
func (u *User) AfterFind() (err error) {
func (u *user) AfterFind() (err error) {
u.CreatedAt = utils.Timezoner(u.CreatedAt, CoreApp.Timezone)
return
}
// AfterFind for Checkin will set the timezone
func (s *Checkin) AfterFind() (err error) {
// AfterFind for checkin will set the timezone
func (s *checkin) AfterFind() (err error) {
s.CreatedAt = utils.Timezoner(s.CreatedAt, CoreApp.Timezone)
return
}
// AfterFind for CheckinHit will set the timezone
func (s *CheckinHit) AfterFind() (err error) {
// AfterFind for checkinHit will set the timezone
func (s *checkinHit) AfterFind() (err error) {
s.CreatedAt = utils.Timezoner(s.CreatedAt, CoreApp.Timezone)
return
}
@ -133,16 +133,16 @@ func (u *Hit) BeforeCreate() (err error) {
return
}
// BeforeCreate for Failure will set CreatedAt to UTC
func (u *Failure) BeforeCreate() (err error) {
// BeforeCreate for failure will set CreatedAt to UTC
func (u *failure) BeforeCreate() (err error) {
if u.CreatedAt.IsZero() {
u.CreatedAt = time.Now().UTC()
}
return
}
// BeforeCreate for User will set CreatedAt to UTC
func (u *User) BeforeCreate() (err error) {
// BeforeCreate for user will set CreatedAt to UTC
func (u *user) BeforeCreate() (err error) {
if u.CreatedAt.IsZero() {
u.CreatedAt = time.Now().UTC()
}
@ -157,16 +157,16 @@ func (u *Service) BeforeCreate() (err error) {
return
}
// BeforeCreate for Checkin will set CreatedAt to UTC
func (u *Checkin) BeforeCreate() (err error) {
// BeforeCreate for checkin will set CreatedAt to UTC
func (u *checkin) BeforeCreate() (err error) {
if u.CreatedAt.IsZero() {
u.CreatedAt = time.Now().UTC()
}
return
}
// BeforeCreate for CheckinHit will set CreatedAt to UTC
func (u *CheckinHit) BeforeCreate() (err error) {
// BeforeCreate for checkinHit will set CreatedAt to UTC
func (u *checkinHit) BeforeCreate() (err error) {
if u.CreatedAt.IsZero() {
u.CreatedAt = time.Now().UTC()
}

View File

@ -21,13 +21,13 @@ import (
"github.com/hunterlong/statup/source"
"github.com/hunterlong/statup/utils"
"html/template"
"io/ioutil"
)
func injectDatabase() {
Configs.Connect(false, utils.Directory)
}
// ExportIndexHTML returns the HTML of the index page as a string
func ExportIndexHTML() string {
source.Assets()
injectDatabase()
@ -83,6 +83,7 @@ func ExportIndexHTML() string {
return result
}
// ExportChartsJs renders the charts for the index page
func ExportChartsJs() string {
render, err := source.JsBox.String("charts.js")
if err != nil {
@ -102,8 +103,3 @@ func ExportChartsJs() string {
result := tpl.String()
return result
}
func SaveFile(filename string, data []byte) error {
err := ioutil.WriteFile(filename, data, 0644)
return err
}

View File

@ -24,7 +24,7 @@ import (
"time"
)
type Failure struct {
type failure struct {
*types.Failure
}
@ -41,8 +41,8 @@ func (s *Service) CreateFailure(f *types.Failure) (int64, error) {
}
// AllFailures will return all failures attached to a service
func (s *Service) AllFailures() []*Failure {
var fails []*Failure
func (s *Service) AllFailures() []*failure {
var fails []*failure
col := failuresDB().Where("service = ?", s.Id).Order("id desc")
err := col.Find(&fails)
if err.Error != nil {
@ -56,30 +56,30 @@ func (s *Service) AllFailures() []*Failure {
}
// DeleteFailures will delete all failures for a service
func (u *Service) DeleteFailures() {
err := DbSession.Exec(`DELETE FROM failures WHERE service = ?`, u.Id)
func (s *Service) DeleteFailures() {
err := DbSession.Exec(`DELETE FROM failures WHERE service = ?`, s.Id)
if err.Error != nil {
utils.Log(3, fmt.Sprintf("failed to delete all failures: %v", err))
}
u.Failures = nil
s.Failures = nil
}
// LimitedFailures will return the last 10 failures from a service
func (s *Service) LimitedFailures() []*Failure {
var failArr []*Failure
func (s *Service) LimitedFailures() []*failure {
var failArr []*failure
col := failuresDB().Where("service = ?", s.Id).Order("id desc").Limit(10)
col.Find(&failArr)
return failArr
}
// Ago returns a human readable timestamp for a failure
func (f *Failure) Ago() string {
func (f *failure) Ago() string {
got, _ := timeago.TimeAgoWithTime(time.Now(), f.CreatedAt)
return got
}
// Delete will remove a failure record from the database
func (f *Failure) Delete() error {
func (f *failure) Delete() error {
db := failuresDB().Delete(f)
return db.Error
}
@ -129,7 +129,7 @@ func (s *Service) TotalFailuresSince(ago time.Time) (uint64, error) {
}
// ParseError returns a human readable error for a failure
func (f *Failure) ParseError() string {
func (f *failure) ParseError() string {
err := strings.Contains(f.Issue, "connection reset by peer")
if err {
return fmt.Sprintf("Connection Reset")

View File

@ -22,15 +22,15 @@ import (
)
var (
allowed_vars = []string{"host", "username", "password", "port", "api_key", "api_secret", "var1", "var2"}
allowedVars = []string{"host", "username", "password", "port", "api_key", "api_secret", "var1", "var2"}
)
func checkNotifierForm(n Notifier) error {
notifier := asNotification(n)
for _, f := range notifier.Form {
contains := contains(f.DbField, allowed_vars)
contains := contains(f.DbField, allowedVars)
if !contains {
return errors.New(fmt.Sprintf("the DbField '%v' is not allowed, allowed vars: %v", f.DbField, allowed_vars))
return errors.New(fmt.Sprintf("the DbField '%v' is not allowed, allowed vars: %v", f.DbField, allowedVars))
}
}
return nil

View File

@ -110,7 +110,7 @@ func OnUpdatedCore(c *types.Core) {
}
}
// OnUpdatedCore is triggered when the CoreApp settings are saved - CoreEvents interface
// OnStart is triggered when the Statup service has started
func OnStart(c *types.Core) {
for _, comm := range AllCommunications {
if isType(comm, new(CoreEvents)) && isEnabled(comm) && inLimits(comm) {
@ -128,7 +128,7 @@ func OnNewNotifier(n *Notification) {
}
}
// NotifierEvents interface
// OnUpdatedNotifier is triggered when a notifier has been updated
func OnUpdatedNotifier(n *Notification) {
for _, comm := range AllCommunications {
if isType(comm, new(NotifierEvents)) && isEnabled(comm) && inLimits(comm) {

View File

@ -28,8 +28,10 @@ import (
)
var (
AllCommunications []types.AllNotifiers // AllCommunications holds all the loaded notifiers
db *gorm.DB // db holds the Statup database connection
// AllCommunications holds all the loaded notifiers
AllCommunications []types.AllNotifiers
// db holds the Statup database connection
db *gorm.DB
)
// Notification contains all the fields for a Statup Notifier.
@ -225,7 +227,7 @@ func SelectNotifier(method string) (*Notification, Notifier, error) {
for _, comm := range AllCommunications {
n, ok := comm.(Notifier)
if !ok {
return nil, nil, errors.New(fmt.Sprintf("incorrect notification type: %v", reflect.TypeOf(n).String()))
return nil, nil, fmt.Errorf("incorrect notification type: %v", reflect.TypeOf(n).String())
}
notifier := n.Select()
if notifier.Method == method {
@ -305,31 +307,31 @@ func install(n Notifier) error {
}
// LastSent returns a time.Duration of the last sent notification for the notifier
func (f *Notification) LastSent() time.Duration {
if len(f.logs) == 0 {
func (n *Notification) LastSent() time.Duration {
if len(n.logs) == 0 {
return time.Duration(0)
}
last := f.Logs()[0]
last := n.Logs()[0]
since := time.Since(last.Timestamp)
return since
}
// SentLastHour returns the total amount of notifications sent in last 1 hour
func (f *Notification) SentLastHour() int {
func (n *Notification) SentLastHour() int {
since := time.Now().Add(-1 * time.Hour)
return f.SentLast(since)
return n.SentLast(since)
}
// SentLastMinute returns the total amount of notifications sent in last 1 minute
func (f *Notification) SentLastMinute() int {
func (n *Notification) SentLastMinute() int {
since := time.Now().Add(-1 * time.Minute)
return f.SentLast(since)
return n.SentLast(since)
}
// SentLast accept a time.Time and returns the amount of sent notifications within your time to current
func (f *Notification) SentLast(since time.Time) int {
func (n *Notification) SentLast(since time.Time) int {
sent := 0
for _, v := range f.Logs() {
for _, v := range n.Logs() {
lastTime := time.Time(v.Time)
if lastTime.After(since) {
sent++
@ -387,21 +389,21 @@ func inLimits(n interface{}) bool {
}
// WithinLimits returns true if the notifier is within its sending limits
func (notify *Notification) WithinLimits() (bool, error) {
if notify.SentLastMinute() == 0 {
func (n *Notification) WithinLimits() (bool, error) {
if n.SentLastMinute() == 0 {
return true, nil
}
if notify.SentLastMinute() >= notify.Limits {
return false, errors.New(fmt.Sprintf("notifier sent %v out of %v in last minute", notify.SentLastMinute(), notify.Limits))
if n.SentLastMinute() >= n.Limits {
return false, fmt.Errorf("notifier sent %v out of %v in last minute", n.SentLastMinute(), n.Limits)
}
if notify.Delay.Seconds() == 0 {
notify.Delay = time.Duration(500 * time.Millisecond)
if n.Delay.Seconds() == 0 {
n.Delay = time.Duration(500 * time.Millisecond)
}
if notify.LastSent().Seconds() == 0 {
if n.LastSent().Seconds() == 0 {
return true, nil
}
if notify.Delay.Seconds() >= notify.LastSent().Seconds() {
return false, errors.New(fmt.Sprintf("notifiers delay (%v) is greater than last message sent (%v)", notify.Delay.Seconds(), notify.LastSent().Seconds()))
if n.Delay.Seconds() >= n.LastSent().Seconds() {
return false, fmt.Errorf("notifiers delay (%v) is greater than last message sent (%v)", n.Delay.Seconds(), n.LastSent().Seconds())
}
return true, nil
}

View File

@ -175,7 +175,7 @@ func insertSampleUsers() {
u3.Create()
}
// InsertSampleData will create the example/dummy services for a brand new Statup installation
// InsertLargeSampleData will create the example/dummy services for testing the Statup server
func InsertLargeSampleData() error {
insertSampleCore()
InsertSampleData()

View File

@ -52,8 +52,8 @@ func SelectService(id int64) *Service {
}
// Checkins will return a slice of Checkins for a Service
func (s *Service) Checkins() []*Checkin {
var checkin []*Checkin
func (s *Service) Checkins() []*checkin {
var checkin []*checkin
checkinDB().Where("service = ?", s.Id).Find(&checkin)
return checkin
}
@ -141,7 +141,7 @@ type DateScanObj struct {
}
// lastFailure returns the last failure a service had
func (s *Service) lastFailure() *Failure {
func (s *Service) lastFailure() *failure {
limited := s.LimitedFailures()
if len(limited) == 0 {
return nil

View File

@ -23,37 +23,37 @@ import (
"time"
)
type User struct {
type user struct {
*types.User
}
// ReturnUser returns *core.User based off a *types.User
func ReturnUser(u *types.User) *User {
return &User{u}
// ReturnUser returns *core.user based off a *types.user
func ReturnUser(u *types.User) *user {
return &user{u}
}
// SelectUser returns the User based on the user's ID.
func SelectUser(id int64) (*User, error) {
var user User
// SelectUser returns the user based on the user's ID.
func SelectUser(id int64) (*user, error) {
var user user
err := usersDB().First(&user, id)
return &user, err.Error
}
// SelectUser returns the User based on the user's username
func SelectUsername(username string) (*User, error) {
var user User
// SelectUsername returns the user based on the user's username
func SelectUsername(username string) (*user, error) {
var user user
res := usersDB().Where("username = ?", username)
err := res.First(&user)
return &user, err.Error
}
// Delete will remove the user record from the database
func (u *User) Delete() error {
func (u *user) Delete() error {
return usersDB().Delete(u).Error
}
// Update will update the user's record in database
func (u *User) Update() error {
func (u *user) Update() error {
u.Password = utils.HashPassword(u.Password)
u.ApiKey = utils.NewSHA1Hash(5)
u.ApiSecret = utils.NewSHA1Hash(10)
@ -61,7 +61,7 @@ func (u *User) Update() error {
}
// Create will insert a new user into the database
func (u *User) Create() (int64, error) {
func (u *user) Create() (int64, error) {
u.CreatedAt = time.Now()
u.Password = utils.HashPassword(u.Password)
u.ApiKey = utils.NewSHA1Hash(5)
@ -78,8 +78,8 @@ func (u *User) Create() (int64, error) {
}
// SelectAllUsers returns all users
func SelectAllUsers() ([]*User, error) {
var users []*User
func SelectAllUsers() ([]*user, error) {
var users []*user
db := usersDB().Find(&users)
if db.Error != nil {
utils.Log(3, fmt.Sprintf("Failed to load all users. %v", db.Error))
@ -87,9 +87,9 @@ func SelectAllUsers() ([]*User, error) {
return users, db.Error
}
// AuthUser will return the User and a boolean if authentication was correct.
// AuthUser will return the user and a boolean if authentication was correct.
// AuthUser accepts username, and password as a string
func AuthUser(username, password string) (*User, bool) {
func AuthUser(username, password string) (*user, bool) {
user, err := SelectUsername(username)
if err != nil {
utils.Log(2, err)

View File

@ -244,7 +244,7 @@ func TestUsersEditHandler(t *testing.T) {
body := rr.Body.String()
assert.Equal(t, 200, rr.Code)
assert.Contains(t, body, "<title>Statup | admin</title>")
assert.Contains(t, body, "<h3>User admin</h3>")
assert.Contains(t, body, "<h3>user admin</h3>")
assert.Contains(t, body, "value=\"info@statup.io\"")
assert.Contains(t, body, "value=\"##########\"")
assert.Contains(t, body, "Statup made with ❤️")

View File

@ -22,10 +22,6 @@ import (
"net/http"
)
type index struct {
Core *core.Core
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
if core.Configs == nil {
http.Redirect(w, r, "/setup", http.StatusSeeOther)
@ -38,6 +34,7 @@ func trayHandler(w http.ResponseWriter, r *http.Request) {
executeResponse(w, r, "tray.html", core.CoreApp, nil)
}
// DesktopInit will run the Statup server on a specific IP and port using SQLite database
func DesktopInit(ip string, port int) {
var err error
exists := utils.FileExists(utils.Directory + "/statup.db")

View File

@ -44,7 +44,7 @@ func prometheusHandler(w http.ResponseWriter, r *http.Request) {
system += fmt.Sprintf("statup_total_services %v", len(core.CoreApp.Services))
metrics = append(metrics, system)
for _, ser := range core.CoreApp.Services {
v := ser.(*core.Service)
v := ser.Select()
online := 1
if !v.Online {
online = 0

View File

@ -61,11 +61,16 @@ $('form').submit(function() {
$('select#service_type').on('change', function() {
var selected = $('#service_type option:selected').val();
var typeLabel = $('#service_type_label');
if (selected === 'tcp' || selected === 'udp') {
if (selected === 'tcp') {
typeLabel.html('TCP Port')
} else {
typeLabel.html('UDP Port')
}
$('#service_port').parent().parent().removeClass('d-none');
$('#service_check_type').parent().parent().addClass('d-none');
$('#service_url').attr('placeholder', 'localhost');
$('#post_data').parent().parent().addClass('d-none');
$('#service_response').parent().parent().addClass('d-none');
$('#service_response_code').parent().parent().addClass('d-none');
@ -75,10 +80,8 @@ $('select#service_type').on('change', function() {
$('#service_response_code').parent().parent().removeClass('d-none');
$('#service_check_type').parent().parent().removeClass('d-none');
$('#service_url').attr('placeholder', 'https://google.com');
$('#service_port').parent().parent().addClass('d-none');
}
});
function AjaxChart(chart, service, start=0, end=9999999999, group="hour") {

View File

@ -54,7 +54,7 @@
</div>
</div>
<div class="form-group row{{if eq .Type ""}} d-none{{else if eq .Type "http"}} d-none{{end}}">
<label for="service_port" class="col-sm-4 col-form-label">TCP Port</label>
<label id="service_type_label" for="service_port" class="col-sm-4 col-form-label">TCP Port</label>
<div class="col-sm-8">
<input type="number" name="port" class="form-control" value="{{if ne .Port 0}}{{.Port}}{{end}}" id="service_port" placeholder="8080">
</div>

View File

@ -20,6 +20,7 @@ import (
"time"
)
// FormatDuration converts a time.Duration into a string
func FormatDuration(d time.Duration) string {
var out string
if d.Hours() >= 24 {

View File

@ -20,6 +20,7 @@ import (
"fmt"
"github.com/ararog/timeago"
"io"
"io/ioutil"
"os"
"os/exec"
"regexp"
@ -29,6 +30,7 @@ import (
)
var (
// Directory returns the current path or the STATUP_DIR environment variable
Directory string
)
@ -207,3 +209,9 @@ func DurationReadable(d time.Duration) string {
}
return d.String()
}
// SaveFile
func SaveFile(filename string, data []byte) error {
err := ioutil.WriteFile(filename, data, 0644)
return err
}