pull/10/head
Hunter Long 2018-06-22 21:17:57 -07:00
parent 8d8f25ea23
commit 68b42dcb8b
16 changed files with 285 additions and 94 deletions

View File

@ -10,6 +10,8 @@ import (
func CheckServices() { func CheckServices() {
services, _ = SelectAllServices() services, _ = SelectAllServices()
core.Communications, _ = SelectAllCommunications()
LoadDefaultCommunications()
for _, v := range services { for _, v := range services {
obj := v obj := v
go obj.StartCheckins() go obj.StartCheckins()

View File

@ -4,50 +4,74 @@ import (
"bytes" "bytes"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"github.com/hunterlong/statup/types"
"gopkg.in/gomail.v2" "gopkg.in/gomail.v2"
"html/template" "html/template"
"log" "log"
"os" "time"
) )
var ( var (
mailer *gomail.Dialer Emailer *gomail.Dialer
Outgoing []*types.Email
) )
func NewMailer() { func AddEmail(email *types.Email) {
mailer = gomail.NewDialer(os.Getenv("HOST"), 587, os.Getenv("USER"), os.Getenv("PASS")) Outgoing = append(Outgoing, email)
mailer.TLSConfig = &tls.Config{InsecureSkipVerify: true} }
source := EmailTemplate("comms/templates/error.html", "this is coooool") func EmailerQueue() {
defer EmailerQueue()
for _, out := range Outgoing {
fmt.Printf("sending email to: %v \n", out.To)
Send(out)
}
Outgoing = nil
fmt.Println("running emailer queue")
time.Sleep(10 * time.Second)
}
fmt.Println("source: ", source) func Send(em *types.Email) {
source := EmailTemplate("comms/templates/error.html", nil)
m := gomail.NewMessage()
m.SetHeader("From", "info@betatude.com")
m.SetHeader("To", em.To)
m.SetHeader("Subject", em.Subject)
m.SetBody("text/html", source)
if err := Emailer.DialAndSend(m); err != nil {
fmt.Println(err)
}
}
func SendSample(em *types.Email) {
source := EmailTemplate("comms/templates/error.html", nil)
m := gomail.NewMessage()
m.SetHeader("From", "info@betatude.com")
m.SetHeader("To", em.To)
m.SetHeader("Subject", em.Subject)
m.SetBody("text/html", source)
if err := Emailer.DialAndSend(m); err != nil {
fmt.Println(err)
}
}
func LoadMailer(config *types.Communication) *gomail.Dialer {
Emailer = gomail.NewDialer(config.Host, config.Port, config.Username, config.Password)
Emailer.TLSConfig = &tls.Config{InsecureSkipVerify: true}
return Emailer
} }
func EmailTemplate(tmpl string, data interface{}) string { func EmailTemplate(tmpl string, data interface{}) string {
t := template.New("error.html") t := template.New("error.html")
var err error var err error
t, err = t.ParseFiles(tmpl) t, err = t.ParseFiles(tmpl)
if err != nil { if err != nil {
panic(err) panic(err)
} }
var tpl bytes.Buffer var tpl bytes.Buffer
if err := t.Execute(&tpl, data); err != nil { if err := t.Execute(&tpl, data); err != nil {
log.Println(err) log.Println(err)
} }
result := tpl.String() result := tpl.String()
return result return result
} }
func SendEmail(to, subject, body string) {
m := gomail.NewMessage()
m.SetHeader("From", "info@email.com")
m.SetHeader("To", to)
m.SetHeader("Subject", subject)
m.SetBody("text/html", body)
if err := mailer.DialAndSend(m); err != nil {
fmt.Println(err)
}
}

View File

@ -1,15 +1,61 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
<html> <head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Sample Email</title>
</head> </head>
<body style="-webkit-text-size-adjust: none; box-sizing: border-box; color: #74787E; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; height: 100%; line-height: 1.4; margin: 0; width: 100% !important;" bgcolor="#F2F4F6"><style type="text/css">
body {
width: 100% !important; height: 100%; margin: 0; line-height: 1.4; background-color: #F2F4F6; color: #74787E; -webkit-text-size-adjust: none;
}
@media only screen and (max-width: 600px) {
.email-body_inner {
width: 100% !important;
}
.email-footer {
width: 100% !important;
}
}
@media only screen and (max-width: 500px) {
.button {
width: 100% !important;
}
}
</style>
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" style="box-sizing: border-box; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0; padding: 0; width: 100%;" bgcolor="#F2F4F6">
<tr>
<td align="center" style="box-sizing: border-box; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; word-break: break-word;">
<table class="email-content" width="100%" cellpadding="0" cellspacing="0" style="box-sizing: border-box; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0; padding: 0; width: 100%;">
<body> <tr>
<p> <td class="email-body" width="100%" cellpadding="0" cellspacing="0" style="-premailer-cellpadding: 0; -premailer-cellspacing: 0; border-bottom-color: #EDEFF2; border-bottom-style: solid; border-bottom-width: 1px; border-top-color: #EDEFF2; border-top-style: solid; border-top-width: 1px; box-sizing: border-box; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0; padding: 0; width: 100%; word-break: break-word;" bgcolor="#FFFFFF">
<strong>Hello {{.}}</strong> <table class="email-body_inner" align="center" width="570" cellpadding="0" cellspacing="0" style="box-sizing: border-box; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0 auto; padding: 0; width: 570px;" bgcolor="#FFFFFF">
</p> <tr>
<td class="content-cell" style="box-sizing: border-box; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; padding: 35px; word-break: break-word;">
<h1 style="box-sizing: border-box; color: #2F3133; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; font-size: 19px; font-weight: bold; margin-top: 0;" align="left">Looks like emails work!</h1>
<p style="box-sizing: border-box; color: #74787E; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; font-size: 16px; line-height: 1.5em; margin-top: 0;" align="left">
Since you got this email, it confirms that your Statup Status Page email system is working correctly.
</p>
</p>
<p style="box-sizing: border-box; color: #74787E; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; font-size: 16px; line-height: 1.5em; margin-top: 0;" align="left">
Enjoy using Statup!
<br />Statup.io Team</p>
<table class="body-sub" style="border-top-color: #EDEFF2; border-top-style: solid; border-top-width: 1px; box-sizing: border-box; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; margin-top: 25px; padding-top: 25px;">
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body> </body>
</html> </html>

View File

@ -1,77 +1,75 @@
package main package main
import "time" import (
"github.com/hunterlong/statup/comms"
var ( "github.com/hunterlong/statup/types"
Communications []*Communication "time"
) )
type Communication struct { func LoadDefaultCommunications() {
Id int64 `db:"id,omitempty" json:"id"` emailer := SelectCommunication(1)
Method string `db:"method" json:"method"` comms.LoadMailer(emailer)
Host string `db:"host" json:"host"` go comms.EmailerQueue()
Port int64 `db:"port" json:"port"`
User string `db:"user" json:"user"`
Password string `db:"password" json:"-"`
Var1 string `db:"var1" json:"var1"`
Var2 string `db:"var2" json:"var2"`
ApiKey string `db:"api_key" json:"api_key"`
ApiSecret string `db:"api_secret" json:"api_secret"`
Enabled bool `db:"enabled" json:"enabled"`
Limits int64 `db:"limits" json:"limits"`
Removable bool `db:"removable" json:"removable"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
} }
func OnCommunicate() { func LoadComms() {
for _, c := range Communications { for _, c := range core.Communications {
if c.Enabled { if c.Enabled {
c.Run()
} }
} }
} }
func (c *Communication) Run() { func Run(c *types.Communication) {
sample := &types.Email{
To: "info@socialeck.com",
Subject: "Test Email from Statup",
}
comms.AddEmail(sample)
} }
func SelectAllCommunications() ([]*Communication, error) { func SelectAllCommunications() ([]*types.Communication, error) {
var c []*Communication var c []*types.Communication
col := dbSession.Collection("communication").Find() col := dbSession.Collection("communication").Find()
err := col.All(&c) err := col.All(&c)
Communications = c core.Communications = c
return c, err return c, err
} }
func (c *Communication) Create() (int64, error) { func Create(c *types.Communication) (int64, error) {
c.CreatedAt = time.Now() c.CreatedAt = time.Now()
uuid, err := dbSession.Collection("communication").Insert(c) uuid, err := dbSession.Collection("communication").Insert(c)
if err != nil {
panic(err)
}
if uuid == nil { if uuid == nil {
return 0, err return 0, err
} }
c.Id = uuid.(int64) c.Id = uuid.(int64)
Communications = append(Communications, c) core.Communications = append(core.Communications, c)
return uuid.(int64), err return uuid.(int64), err
} }
func (c *Communication) Disable() { func Disable(c *types.Communication) {
c.Enabled = false c.Enabled = false
c.Update() Update(c)
} }
func (c *Communication) Enable() { func Enable(c *types.Communication) {
c.Enabled = true c.Enabled = true
c.Update() Update(c)
} }
func (c *Communication) Update() *Communication { func Update(c *types.Communication) *types.Communication {
col := dbSession.Collection("communication").Find("id", c.Id) col := dbSession.Collection("communication").Find("id", c.Id)
col.Update(c) col.Update(c)
return c return c
} }
func SelectCommunication(id int64) *Communication { func SelectCommunication(id int64) *types.Communication {
for _, c := range Communications { for _, c := range core.Communications {
if c.Id == id { if c.Id == id {
return c return c
} }

26
core.go
View File

@ -3,21 +3,23 @@ package main
import ( import (
"github.com/gorilla/sessions" "github.com/gorilla/sessions"
"github.com/hunterlong/statup/plugin" "github.com/hunterlong/statup/plugin"
"github.com/hunterlong/statup/types"
) )
type Core struct { type Core struct {
Name string `db:"name"` Name string `db:"name"`
Description string `db:"description"` Description string `db:"description"`
Config string `db:"config"` Config string `db:"config"`
ApiKey string `db:"api_key"` ApiKey string `db:"api_key"`
ApiSecret string `db:"api_secret"` ApiSecret string `db:"api_secret"`
Style string `db:"style"` Style string `db:"style"`
Footer string `db:"footer"` Footer string `db:"footer"`
Domain string `db:"domain"` Domain string `db:"domain"`
Version string `db:"version"` Version string `db:"version"`
Plugins []plugin.Info Plugins []plugin.Info
Repos []PluginJSON Repos []PluginJSON
PluginFields []PluginSelect PluginFields []PluginSelect
Communications []*types.Communication
} }
func (c *Core) Update() (*Core, error) { func (c *Core) Update() (*Core, error) {

View File

@ -61,3 +61,7 @@ func DbConnection(dbType string) error {
OnLoad(dbSession) OnLoad(dbSession)
return err return err
} }
func Backup() {
}

View File

@ -8,6 +8,7 @@ import (
type Failure struct { type Failure struct {
Id int `db:"id,omitempty"` Id int `db:"id,omitempty"`
Issue string `db:"issue"` Issue string `db:"issue"`
Method string `db:"method"`
Service int64 `db:"service"` Service int64 `db:"service"`
CreatedAt time.Time `db:"created_at"` CreatedAt time.Time `db:"created_at"`
} }

View File

@ -23,7 +23,10 @@
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical"> <div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
<a class="nav-link active" id="v-pills-home-tab" data-toggle="pill" href="#v-pills-home" role="tab" aria-controls="v-pills-home" aria-selected="true">Settings</a> <a class="nav-link active" id="v-pills-home-tab" data-toggle="pill" href="#v-pills-home" role="tab" aria-controls="v-pills-home" aria-selected="true">Settings</a>
<a class="nav-link" id="v-pills-home-tab" data-toggle="pill" href="#v-pills-style" role="tab" aria-controls="v-pills-style" aria-selected="false">Styling</a> <a class="nav-link" id="v-pills-style-tab" data-toggle="pill" href="#v-pills-style" role="tab" aria-controls="v-pills-style" aria-selected="false">Styling</a>
{{ range .Communications }}
<a class="nav-link text-uppercase" id="v-pills-{{ .Method }}-tab" data-toggle="pill" href="#v-pills-{{ .Method }}" role="tab" aria-controls="v-pills-{{ .Method }}" aria-selected="false">{{ .Method }}</a>
{{ end }}
<a class="nav-link" id="v-pills-browse-tab" data-toggle="pill" href="#v-pills-browse" role="tab" aria-controls="v-pills-home" aria-selected="false">Browse Plugins</a> <a class="nav-link" id="v-pills-browse-tab" data-toggle="pill" href="#v-pills-browse" role="tab" aria-controls="v-pills-home" aria-selected="false">Browse Plugins</a>
{{ range .Plugins }} {{ range .Plugins }}
<a class="nav-link text-capitalize" id="v-pills-{{underscore .Name}}-tab" data-toggle="pill" href="#v-pills-{{underscore .Name}}" role="tab" aria-controls="v-pills-profile" aria-selected="false">{{.Name}}</a> <a class="nav-link text-capitalize" id="v-pills-{{underscore .Name}}-tab" data-toggle="pill" href="#v-pills-{{underscore .Name}}" role="tab" aria-controls="v-pills-profile" aria-selected="false">{{.Name}}</a>
@ -72,6 +75,48 @@
</form> </form>
</div> </div>
{{ range .Communications }}
<div class="tab-pane fade" id="v-pills-{{ .Method }}" role="tabpanel" aria-labelledby="v-pills-{{ .Method }}-tab">
<form method="POST" action="/settings/{{ .Method }}">
<div class="form-group">
<label for="formGroupExampleInput">SMTP Host</label>
<input type="text" name="host" class="form-control" value="{{ .Host }}" id="formGroupExampleInput" placeholder="Great Uptime">
</div>
<div class="form-group">
<label for="formGroupExampleInput">SMTP Username</label>
<input type="text" name="username" class="form-control" value="{{ .Username }}" id="formGroupExampleInput" placeholder="Great Uptime">
</div>
<div class="form-group">
<label for="formGroupExampleInput">SMTP Password</label>
<input type="password" name="password" class="form-control" value="{{ .Password }}" id="formGroupExampleInput">
</div>
<div class="form-group">
<label for="formGroupExampleInput">SMTP Port</label>
<input type="number" name="port" class="form-control" value="{{ .Port }}" id="formGroupExampleInput" placeholder="587">
</div>
<div class="form-group">
<label for="formGroupExampleInput">Outgoing Email Address</label>
<input type="text" name="address" class="form-control" value="{{ .Var1 }}" id="formGroupExampleInput" placeholder="noreply@domain.com">
</div>
<div class="form-group">
<label for="formGroupExampleInput">Limit Emails per Hour</label>
<input type="number" name="limit" class="form-control" value="30" id="formGroupExampleInput" placeholder="noreply@domain.com">
</div>
<button type="submit" class="btn btn-primary btn-block">Save Email Settings</button>
</form>
</div>
{{ end }}
<div class="tab-pane fade" id="v-pills-browse" role="tabpanel" aria-labelledby="v-pills-browse-tab"> <div class="tab-pane fade" id="v-pills-browse" role="tabpanel" aria-labelledby="v-pills-browse-tab">
{{ range .Repos }} {{ range .Repos }}
<div class="card col-6" style="width: 18rem;"> <div class="card col-6" style="width: 18rem;">

View File

@ -6,7 +6,6 @@ import (
"github.com/GeertJohan/go.rice" "github.com/GeertJohan/go.rice"
"github.com/go-yaml/yaml" "github.com/go-yaml/yaml"
"github.com/gorilla/sessions" "github.com/gorilla/sessions"
"github.com/hunterlong/statup/comms"
"github.com/hunterlong/statup/plugin" "github.com/hunterlong/statup/plugin"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"io" "io"
@ -126,8 +125,6 @@ func main() {
var err error var err error
fmt.Printf("Starting Statup v%v\n", VERSION) fmt.Printf("Starting Statup v%v\n", VERSION)
comms.NewMailer()
RenderBoxes() RenderBoxes()
configs, err = LoadConfig() configs, err = LoadConfig()
if err != nil { if err != nil {

View File

@ -23,6 +23,7 @@ func TestMySQLMakeConfig(t *testing.T) {
3306, 3306,
"Testing MYSQL", "Testing MYSQL",
"This is a test of Statup.io!", "This is a test of Statup.io!",
"",
"admin", "admin",
"admin", "admin",
nil, nil,
@ -36,7 +37,7 @@ func TestMySQLMakeConfig(t *testing.T) {
err = DbConnection(configs.Connection) err = DbConnection(configs.Connection)
assert.Nil(t, err) assert.Nil(t, err)
InsertDefaultComms()
} }
func TestInsertMysqlSample(t *testing.T) { func TestInsertMysqlSample(t *testing.T) {
@ -62,6 +63,7 @@ func TestSqliteMakeConfig(t *testing.T) {
5432, 5432,
"Testing SQLITE", "Testing SQLITE",
"This is a test of Statup.io!", "This is a test of Statup.io!",
"",
"admin", "admin",
"admin", "admin",
nil, nil,
@ -75,6 +77,7 @@ func TestSqliteMakeConfig(t *testing.T) {
err = DbConnection(configs.Connection) err = DbConnection(configs.Connection)
assert.Nil(t, err) assert.Nil(t, err)
InsertDefaultComms()
} }
func TestInsertSqliteSample(t *testing.T) { func TestInsertSqliteSample(t *testing.T) {
@ -92,6 +95,7 @@ func TestPostgresMakeConfig(t *testing.T) {
5432, 5432,
"Testing POSTGRES", "Testing POSTGRES",
"This is a test of Statup.io!", "This is a test of Statup.io!",
"",
"admin", "admin",
"admin", "admin",
nil, nil,
@ -105,6 +109,7 @@ func TestPostgresMakeConfig(t *testing.T) {
err = DbConnection(configs.Connection) err = DbConnection(configs.Connection)
assert.Nil(t, err) assert.Nil(t, err)
InsertDefaultComms()
} }
func TestInsertPostgresSample(t *testing.T) { func TestInsertPostgresSample(t *testing.T) {
@ -130,8 +135,8 @@ func TestSelectCore(t *testing.T) {
func TestUser_Create(t *testing.T) { func TestUser_Create(t *testing.T) {
user := &User{ user := &User{
Username: "testuserhere", Username: "admin",
Password: "password123", Password: "admin",
Email: "info@testuser.com", Email: "info@testuser.com",
} }
id, err := user.Create() id, err := user.Create()
@ -215,7 +220,7 @@ func TestService_Hits(t *testing.T) {
assert.NotNil(t, service) assert.NotNil(t, service)
hits, err := service.Hits() hits, err := service.Hits()
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 20, len(hits)) assert.Equal(t, 26, len(hits))
} }
func TestService_LimitedHits(t *testing.T) { func TestService_LimitedHits(t *testing.T) {
@ -223,7 +228,7 @@ func TestService_LimitedHits(t *testing.T) {
assert.NotNil(t, service) assert.NotNil(t, service)
hits, err := service.LimitedHits() hits, err := service.LimitedHits()
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 20, len(hits)) assert.Equal(t, 26, len(hits))
} }
func Test(t *testing.T) { func Test(t *testing.T) {

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/go-yaml/yaml" "github.com/go-yaml/yaml"
"github.com/hunterlong/statup/plugin" "github.com/hunterlong/statup/plugin"
"github.com/hunterlong/statup/types"
"net/http" "net/http"
"os" "os"
"strconv" "strconv"
@ -20,13 +21,14 @@ type DbConfig struct {
DbPort int `yaml:"port"` DbPort int `yaml:"port"`
Project string `yaml:"-"` Project string `yaml:"-"`
Description string `yaml:"-"` Description string `yaml:"-"`
Domain string `yaml:"-"`
Username string `yaml:"-"` Username string `yaml:"-"`
Password string `yaml:"-"` Password string `yaml:"-"`
Error error Error error `yaml:"-"`
} }
func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) { func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
if core.ApiKey != "" { if core != nil {
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
@ -42,6 +44,7 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
password := r.PostForm.Get("password") password := r.PostForm.Get("password")
sample := r.PostForm.Get("sample_data") sample := r.PostForm.Get("sample_data")
description := r.PostForm.Get("description") description := r.PostForm.Get("description")
domain := r.PostForm.Get("domain")
config := &DbConfig{ config := &DbConfig{
dbConn, dbConn,
@ -52,6 +55,7 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
dbPort, dbPort,
project, project,
description, description,
domain,
username, username,
password, password,
nil, nil,
@ -97,12 +101,12 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
} }
func InsertDefaultComms() { func InsertDefaultComms() {
emailer := &Communication{ emailer := &types.Communication{
Method: "email", Method: "email",
Removable: false, Removable: false,
Enabled: false, Enabled: false,
} }
emailer.Create() Create(emailer)
} }
func DeleteConfig() { func DeleteConfig() {
@ -166,6 +170,7 @@ func (c *DbConfig) Save() error {
[]plugin.Info{}, []plugin.Info{},
[]PluginJSON{}, []PluginJSON{},
[]PluginSelect{}, []PluginSelect{},
nil,
} }
col := dbSession.Collection("core") col := dbSession.Collection("core")

View File

@ -46,6 +46,7 @@ CREATE TABLE hits (
CREATE TABLE failures ( CREATE TABLE failures (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
issue text, issue text,
method text,
service INTEGER NOT NULL, service INTEGER NOT NULL,
created_at TIMESTAMP, created_at TIMESTAMP,
INDEX (id, service), INDEX (id, service),
@ -65,7 +66,7 @@ CREATE TABLE communication (
method text, method text,
host text, host text,
port integer, port integer,
user text, username text,
password text, password text,
var1 text, var1 text,
var2 text, var2 text,

View File

@ -64,7 +64,7 @@ CREATE TABLE communication (
method text, method text,
host text, host text,
port integer, port integer,
user text, username text,
password text, password text,
var1 text, var1 text,
var2 text, var2 text,
@ -76,7 +76,6 @@ CREATE TABLE communication (
created_at TIMESTAMP created_at TIMESTAMP
); );
CREATE INDEX idx_hits ON hits(service); CREATE INDEX idx_hits ON hits(service);
CREATE INDEX idx_failures ON failures(service); CREATE INDEX idx_failures ON failures(service);
CREATE INDEX idx_checkins ON checkins(service); CREATE INDEX idx_checkins ON checkins(service);

View File

@ -46,6 +46,7 @@ CREATE TABLE hits (
CREATE TABLE failures ( CREATE TABLE failures (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
issue text, issue text,
method text,
service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE, service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE,
created_at TIMESTAMP created_at TIMESTAMP
); );
@ -63,7 +64,7 @@ CREATE TABLE communication (
method text, method text,
host text, host text,
port integer, port integer,
user text, username text,
password text, password text,
var1 text, var1 text,
var2 text, var2 text,

28
types/types.go Normal file
View File

@ -0,0 +1,28 @@
package types
import "time"
type Communication struct {
Id int64 `db:"id,omitempty" json:"id"`
Method string `db:"method" json:"method"`
Host string `db:"host" json:"host"`
Port int `db:"port" json:"port"`
Username string `db:"username" json:"user"`
Password string `db:"password" json:"-"`
Var1 string `db:"var1" json:"var1"`
Var2 string `db:"var2" json:"var2"`
ApiKey string `db:"api_key" json:"api_key"`
ApiSecret string `db:"api_secret" json:"api_secret"`
Enabled bool `db:"enabled" json:"enabled"`
Limits int64 `db:"limits" json:"limits"`
Removable bool `db:"removable" json:"removable"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
}
type Email struct {
To string
Subject string
Template string
Data interface{}
Body string
}

35
web.go
View File

@ -5,6 +5,8 @@ import (
"github.com/fatih/structs" "github.com/fatih/structs"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/gorilla/sessions" "github.com/gorilla/sessions"
"github.com/hunterlong/statup/comms"
"github.com/hunterlong/statup/types"
"html/template" "html/template"
"net/http" "net/http"
"regexp" "regexp"
@ -45,6 +47,7 @@ func Router() *mux.Router {
r.Handle("/users/{id}/delete", http.HandlerFunc(UsersDeleteHandler)).Methods("GET") r.Handle("/users/{id}/delete", http.HandlerFunc(UsersDeleteHandler)).Methods("GET")
r.Handle("/settings", http.HandlerFunc(PluginsHandler)).Methods("GET") r.Handle("/settings", http.HandlerFunc(PluginsHandler)).Methods("GET")
r.Handle("/settings", http.HandlerFunc(SaveSettingsHandler)).Methods("POST") r.Handle("/settings", http.HandlerFunc(SaveSettingsHandler)).Methods("POST")
r.Handle("/settings/email", http.HandlerFunc(SaveEmailSettingsHandler)).Methods("POST")
r.Handle("/plugins/download/{name}", http.HandlerFunc(PluginsDownloadHandler)) r.Handle("/plugins/download/{name}", http.HandlerFunc(PluginsDownloadHandler))
r.Handle("/plugins/{name}/save", http.HandlerFunc(PluginSavedHandler)).Methods("POST") r.Handle("/plugins/{name}/save", http.HandlerFunc(PluginSavedHandler)).Methods("POST")
r.Handle("/help", http.HandlerFunc(HelpHandler)) r.Handle("/help", http.HandlerFunc(HelpHandler))
@ -150,7 +153,7 @@ func CreateServiceHandler(w http.ResponseWriter, r *http.Request) {
} }
func SetupHandler(w http.ResponseWriter, r *http.Request) { func SetupHandler(w http.ResponseWriter, r *http.Request) {
if core.ApiKey != "" { if core != nil {
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
@ -245,6 +248,34 @@ func IsAuthenticated(r *http.Request) bool {
return session.Values["authenticated"].(bool) return session.Values["authenticated"].(bool)
} }
func SaveEmailSettingsHandler(w http.ResponseWriter, r *http.Request) {
auth := IsAuthenticated(r)
if !auth {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
emailer := SelectCommunication(1)
r.ParseForm()
emailer.Host = r.PostForm.Get("host")
emailer.Username = r.PostForm.Get("username")
emailer.Password = r.PostForm.Get("password")
emailer.Port = int(StringInt(r.PostForm.Get("port")))
emailer.Var1 = r.PostForm.Get("address")
Update(emailer)
sample := &types.Email{
To: "info@socialeck.com",
Subject: "Sample Email",
Template: "templates/error.html",
Body: "okkokkok",
}
comms.AddEmail(sample)
http.Redirect(w, r, "/settings", http.StatusSeeOther)
}
func SaveSettingsHandler(w http.ResponseWriter, r *http.Request) { func SaveSettingsHandler(w http.ResponseWriter, r *http.Request) {
auth := IsAuthenticated(r) auth := IsAuthenticated(r)
if !auth { if !auth {
@ -290,6 +321,8 @@ func PluginsHandler(w http.ResponseWriter, r *http.Request) {
} }
core.PluginFields = pluginFields core.PluginFields = pluginFields
fmt.Println(core.Communications)
ExecuteResponse(w, r, "plugins.html", core) ExecuteResponse(w, r, "plugins.html", core)
} }