diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/Makefile | 7 | ||||
| -rw-r--r-- | app/config.go | 12 | ||||
| -rw-r--r-- | app/db.go | 4 | ||||
| -rw-r--r-- | app/email.go | 58 | ||||
| -rwxr-xr-x | app/env.sh | 6 | ||||
| -rw-r--r-- | app/fetch.go | 14 | ||||
| -rw-r--r-- | app/handler.go | 222 | ||||
| -rw-r--r-- | app/jobs.go | 2 | ||||
| -rw-r--r-- | app/main.go | 18 | ||||
| -rw-r--r-- | app/struct.go | 23 | ||||
| -rw-r--r-- | app/test.go | 16 | ||||
| -rw-r--r-- | app/utilities_test.go | 2 |
12 files changed, 338 insertions, 46 deletions
diff --git a/app/Makefile b/app/Makefile index c53bfbb..70a07b1 100644 --- a/app/Makefile +++ b/app/Makefile @@ -143,4 +143,11 @@ gen_config: _test_build @echo "# Http" >> _env.sh echo "export STATUS_HTTP_IP=$(STATUS_HTTP_IP)" >> _env.sh echo "export STATUS_HTTP_PORT=$(STATUS_HTTP_PORT)" >> _env.sh + @echo "" + echo "export STATUS_SECRET=$(STATUS_SECRET)" >> _env.sh + @echo "" + @echo "# Smtp" >> _env.sh + echo "export STATUS_SMTP_MAILER=$(STATUS_SMTP_MAILER)" >> _env.sh + echo "export STATUS_SMTP_PASSWORD=$(STATUS_SMTP_PASSWORD)" >> _env.sh + echo "export STATUS_SMTP_ADRESS=$(STATUS_SMTP_ADRESS)" >> _env.sh @chmod +x _env.sh diff --git a/app/config.go b/app/config.go index dafc846..c03d910 100644 --- a/app/config.go +++ b/app/config.go @@ -30,4 +30,16 @@ func checkConfig() { if check == "" { log.Fatal("Env STATUS_HTTP_PORT not found.") } + check = os.Getenv("STATUS_SMTP_MAILER") + if check == "" { + log.Fatal("Env STATUS_MAILTER not found.") + } + check = os.Getenv("STATUS_SMTP_PASSWORD") + if check == "" { + log.Fatal("Env STATUS_PASSWORD not found.") + } + check = os.Getenv("STATUS_SMTP_ADRESS") + if check == "" { + log.Fatal("Env STATUS_ADRESS not found.") + } } @@ -23,10 +23,10 @@ func InitDB() { u := User{} h := Host{} Db.Debug().AutoMigrate(&u) - db := Db - db.Debug().AutoMigrate(&h) + Db.Debug().AutoMigrate(&h) Db.Model(&u).AddUniqueIndex("idx_user_name", "name") Db.Model(&u).AddUniqueIndex("idx_user_email", "email") Db.Model(&h).AddUniqueIndex("idx_host_url", "url") + Db.Model(&c).AddUniqueIndex("idx_config_sticky", "sticky") } diff --git a/app/email.go b/app/email.go new file mode 100644 index 0000000..b497bf7 --- /dev/null +++ b/app/email.go @@ -0,0 +1,58 @@ +package main + +import ( + "bytes" + "github.com/jordan-wright/email" + "log" + "net/smtp" + "os" +) + +func SendEmail(u []User, h []Host) { + log.Println("Sending E-Mail") + if len(u) == 0 { + return + } + if len(h) == 0 { + return + } + log.Println("Sending E-Mail - Checked") + adresses := getEmails(u) + h = getHosts(h) + e := &email.Email{ + To: adresses, + From: "StatusPage <" + os.Getenv("STATUS_HTTP_ADRESS") + ">", + Subject: "Host is down (" + h[0].Host + ")", + HTML: getBody(h), + } + err := e.Send(os.Getenv("STATUS_HTTP_MAILER"), smtp.PlainAuth("", os.Getenv("STATUS_HTTP_ADRESS"), os.Getenv("STATUS_HTTP_PASSWORD"), os.Getenv("STATUS_HTTP_MAILER"))) + log.Println(err) +} + +func getEmails(u []User) []string { + var emails []string + for k, _ := range u { + emails = append(emails, u[k].Email) + } + return emails +} + +func getHosts(hosts []Host) []Host { + var h []Host + for k, _ := range hosts { + if !hosts[k].Monitored { + h = append(h, hosts[k]) + } + } + return h +} + +func getBody(hosts []Host) []byte { + + index := emailTempl.Lookup("index.html") + + var ret bytes.Buffer + index.ExecuteTemplate(&ret, "index.html", hosts) + + return ret.Bytes() +} @@ -6,6 +6,7 @@ #export STATUS_DB_CREDENTIALS=../db/status.db #export STATUS_DB_IMPORT_DRIVER=github.com/mattn/go-sqlite3 #export STATUS_DB_LOG=true +#export STATUS_SECRET=verylongsecret # Redis #export STATUS_REDIS_SERVER=127.0.0.1 @@ -14,3 +15,8 @@ # Http #export STATUS_HTTP_IP=127.0.0.1 #export STATUS_HTTP_PORT=8080 + +# SMTP +#export STATUS_SMTP_MAILER="smtp.example.org:25" +#export STATUS_SMTP_PASSWORD="password" +#export STATUS_SMTP_ADRESS="statuspage@example.org" diff --git a/app/fetch.go b/app/fetch.go index 18721fc..f4be5c0 100644 --- a/app/fetch.go +++ b/app/fetch.go @@ -15,6 +15,7 @@ func healthCheck() { } func CheckPages(h []Host) []Host { + wentWrong := false for k, v := range h { if !h[k].Monitored { @@ -36,10 +37,17 @@ func CheckPages(h []Host) []Host { } } + if wentWrong { + u := []User{} + Db.Find(&u) + SendEmail(u, h) + } return h } func CheckAllPages(h []Host) []Host { + wentWrong := false + for k, v := range h { if resp, _, err := HttpGet(v.Url); err != nil { h[k].Status = "Error" @@ -48,6 +56,7 @@ func CheckAllPages(h []Host) []Host { h[k].Monitored = false h[k].Reason = fmt.Sprintf("%v", err) h[k].Class = "danger" + wentWrong = true } else { h[k].Status = resp.Status h[k].StatusCode = int64(resp.StatusCode) @@ -57,5 +66,10 @@ func CheckAllPages(h []Host) []Host { } } + if wentWrong { + u := []User{} + Db.Find(&u) + SendEmail(u, h) + } return h } diff --git a/app/handler.go b/app/handler.go index 97c3558..e7bc738 100644 --- a/app/handler.go +++ b/app/handler.go @@ -9,28 +9,38 @@ import ( ) func IndexHandler(w http.ResponseWriter, r *http.Request) { + log.Println("Get Index") hosts := []Host{} - c := pool.Get() - defer c.Close() - j, err := GetCache(cache_prefix + "database") if j != "" { err = json.Unmarshal([]byte(j), &hosts) if err != nil { log.Println("Error JSON decoding: ", err) + //Db.Where("private = ?", 0).Find(&hosts) Db.Find(&hosts) CacheHosts(cache_prefix+"database", hosts) } } else { log.Println("Cache miss on Index page.") + //Db.Where("private = ?", 0).Find(&hosts) Db.Find(&hosts) CacheHosts(cache_prefix+"database", hosts) } index := mainTempl.Lookup("index.html") + jobs := c.Entries() + + h := []Host{} + for k, _ := range hosts { + if !hosts[k].Private { + h = append(h, hosts[k]) + } + } + sticky, _ := GetCache(cache_prefix + "sticky") + m := Messages{Hosts: h, NextRun: jobs[0].Next, Sticky: sticky} - err = index.ExecuteTemplate(w, "index.html", hosts) + err = index.ExecuteTemplate(w, "index.html", m) if err != nil { log.Println(err) http.Error(w, err.Error(), http.StatusInternalServerError) @@ -38,16 +48,70 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) { } } +func SetupHandler(w http.ResponseWriter, r *http.Request) { + log.Println("Get Setup") + u := User{} + if Db.Find(&u).RecordNotFound() { + PrintRegisterHandler(w, r) + } else { + http.Redirect(w, r, "/login", 302) + } +} + func RegisterHandler(w http.ResponseWriter, r *http.Request) { log.Println("Processing registration!") - fmt.Fprintf(w, "Processing registration! \n") + session, err := store.Get(r, "_SID") + if err != nil { + log.Println(err) + } + u := User{} + err = r.ParseForm() + if err != nil { + log.Println(err) + } + err = decoder.Decode(&u, r.PostForm) + if err != nil { + log.Println(err) + } + u.Password, _ = HashPassword(u.Password) + query := Db.Create(&u) + if query.Error != nil { + session.AddFlash("Registration failed.", "error") + session.Save(r, w) + http.Redirect(w, r, "/register", 302) + return + } + session.AddFlash("Registration completed!", "success") + session.Values["login"] = true + session.Save(r, w) + http.Redirect(w, r, "/admin", 302) } func PrintRegisterHandler(w http.ResponseWriter, r *http.Request) { + log.Println("Get Registration") + session, err := store.Get(r, "_SID") + if err != nil { + log.Println(err) + } + if session.Values["login"] == true { + http.Redirect(w, r, "/admin", 302) + log.Println("Schon erfolgreich eingeloggt!") + return + } + m := Messages{} + m.Success = session.Flashes("success") + m.Error = session.Flashes("error") + session.Save(r, w) + templ := mainTempl.Lookup("login.html") + + err = templ.ExecuteTemplate(w, "register.html", m) + if err != nil { + log.Panic(err) + } - fmt.Fprintf(w, "Printing register etc! \n") } +/* func PrintNewJobHandler(w http.ResponseWriter, r *http.Request) { log.Println("Printing job") @@ -65,6 +129,7 @@ func PrintNewJobHandler(w http.ResponseWriter, r *http.Request) { log.Panic(err) } } +*/ func AddNewJobHandler(w http.ResponseWriter, r *http.Request) { log.Printf("Add new job") @@ -72,6 +137,12 @@ func AddNewJobHandler(w http.ResponseWriter, r *http.Request) { if err != nil { log.Println(err) } + if session.Values["login"] != true { + session.Values["history"] = "/new" + session.Save(r, w) + http.Redirect(w, r, "/login", 302) + return + } err = r.ParseForm() if err != nil { @@ -96,29 +167,27 @@ func AddNewJobHandler(w http.ResponseWriter, r *http.Request) { } if u.Scheme != "http" && u.Scheme != "https" { - log.Println("Scheme neither http nor https.", u.Scheme) session.AddFlash("Unsurportted scheme. Only http:// and https:// is valid.", "error") session.Save(r, w) http.Redirect(w, r, "/admin", 302) - // http.Error(w, "Scheme neither http nor https.", http.StatusInternalServerError) return } host.Monitored = true host.Host = u.Host - log.Printf("%v", host) - query := Db.Debug().Save(&host) + query := Db.Save(&host) if query.Error != nil { log.Println(err) - session.AddFlash("Befehl konnte auf Grund eines Problems nicht ausgeführt werden.", "error") + //session.AddFlash("Befehl konnte auf Grund eines Problems nicht ausgeführt werden.", "error") + session.AddFlash("There was an error. :(", "error") session.Save(r, w) http.Redirect(w, r, "/admin", 302) } go func() { h := []Host{} - h = append(h, host) + Db.Find(&h) h = CheckPages(h) for k, _ := range h { Db.Debug().Save(&h[k]) @@ -133,6 +202,7 @@ func AddNewJobHandler(w http.ResponseWriter, r *http.Request) { } +/* func ShowJobHandler(w http.ResponseWriter, r *http.Request) { jobs := c.Entries() @@ -140,6 +210,7 @@ func ShowJobHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Job: %v, Schedule: %v; Next %v; Prev %v \n", i.Job, i.Schedule, i.Next, i.Prev) } } +*/ func LoginHandler(w http.ResponseWriter, r *http.Request) { session, err := store.Get(r, "_SID") @@ -155,20 +226,19 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) { if err != nil { log.Println(err) } - log.Println(u) + log.Println("Processing Login", u.Name) login := login(u.Name, u.Password, session) if !login { session.AddFlash("Login failed.", "error") session.Save(r, w) log.Println("Login failed.") - log.Println(u.Name, u.Password) http.Redirect(w, r, "/login", 302) return } session.Values["login"] = true session.Save(r, w) var redirectTarget string - if session.Values["history"] != "" { + if session.Values["history"] != "" && session.Values["history"] != nil { redirectTarget = fmt.Sprintf("%v", session.Values["history"]) session.Values["history"] = "" session.Save(r, w) @@ -178,16 +248,12 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) { } func PrintLoginHandler(w http.ResponseWriter, r *http.Request) { + log.Println("Get Login") session, err := store.Get(r, "_SID") if err != nil { log.Println(err) } - if session.Values["login"] == true { - log.Println("Schon erfolgreich eingeloggt!") - // http.Redirect(w, r, "/", 301) - } else { - log.Println("Nicht eingeloggt.") - } + m := Messages{} m.Success = session.Flashes("success") m.Error = session.Flashes("error") @@ -201,23 +267,21 @@ func PrintLoginHandler(w http.ResponseWriter, r *http.Request) { } func LogoutHandler(w http.ResponseWriter, r *http.Request) { + log.Println("Logout") session, _ := store.Get(r, "_SID") session.Values["login"] = false session.Save(r, w) + log.Println("Logout ", session.Values["login"]) http.Redirect(w, r, "/login", 301) } func AdminHandler(w http.ResponseWriter, r *http.Request) { + log.Println("Get Admin") session, err := store.Get(r, "_SID") - //session.Values["login"] = true // löschen! - //session.Save(r, w) // löschen! if err != nil { log.Println(err) } if session.Values["login"] != true { - // http.Redirect(w, r, "/login", 401) - // w.WriteHeader(403) - // PrintLoginHandler(w, r) session.Values["history"] = "/admin" session.Save(r, w) http.Redirect(w, r, "/login", 302) @@ -226,10 +290,14 @@ func AdminHandler(w http.ResponseWriter, r *http.Request) { hosts := []Host{} Db.Find(&hosts) + jobs := c.Entries() + m := Messages{} m.Success = session.Flashes("success") m.Error = session.Flashes("error") m.Hosts = hosts + m.NextRun = jobs[0].Next + m.Sticky, _ = GetCache(cache_prefix + "sticky") session.Save(r, w) index := mainTempl.Lookup("admin.html") @@ -243,6 +311,7 @@ func AdminHandler(w http.ResponseWriter, r *http.Request) { } func RefreshAllHandler(w http.ResponseWriter, r *http.Request) { + log.Println("Get RefreshAllHandler") session, err := store.Get(r, "_SID") if err != nil { log.Println(err) @@ -266,3 +335,104 @@ func RefreshAllHandler(w http.ResponseWriter, r *http.Request) { session.Save(r, w) http.Redirect(w, r, "/admin", 302) } + +func DeleteHandler(w http.ResponseWriter, r *http.Request) { + log.Println("Get Delete") + session, err := store.Get(r, "_SID") + if err != nil { + log.Println(err) + } + if session.Values["login"] != true { + session.Values["history"] = "/admin" + session.Save(r, w) + http.Redirect(w, r, "/login", 302) + return + } + err = r.ParseForm() + if err != nil { + log.Println(err) + session.AddFlash("Error parsing form.", "error") + session.Save(r, w) + http.Redirect(w, r, "/admin", 302) + return + } + host := Host{} + log.Println(r.PostForm) + log.Println(r.URL.Query()) + err = decoder.Decode(&host, r.URL.Query()) + if err != nil { + log.Println(err) + session.AddFlash("Error parsing form.", "error") + session.Save(r, w) + http.Redirect(w, r, "/admin", 302) + return + } + log.Println("Deleting host where id = ", host.Id) + query := Db.Where("id = ?", host.Id).Delete(&host) + if query.Error != nil { + session.AddFlash("Deleting failed.", "error") + } else { + session.AddFlash("We removed the host.", "success") + } + session.Save(r, w) + http.Redirect(w, r, "/admin", 302) + go FillCache() +} + +func NewStickyHandler(w http.ResponseWriter, r *http.Request) { + log.Println("Get NewStickyHandler") + session, err := store.Get(r, "_SID") + if err != nil { + log.Println(err) + } + if session.Values["login"] != true { + log.Println("Login required. File: New Sticky") + session.AddFlash("Login required.", "error") + session.Values["history"] = "/admin" + session.Save(r, w) + http.Redirect(w, r, "/login", 302) + return + } + err = r.ParseForm() + if err != nil { + log.Println(err) + session.AddFlash("Error Parsing form.", "error") + session.Save(r, w) + http.Redirect(w, r, "/admin", 302) + return + } + sticky := Sticky{} + err = decoder.Decode(&sticky, r.PostForm) + if err != nil { + log.Println(err) + session.AddFlash("Error Parsing form.", "error") + session.Save(r, w) + http.Redirect(w, r, "/admin", 302) + return + } + if r.PostFormValue("Action") == "delete" { + log.Println("Deleting sticky post.") + DelCache(cache_prefix + "sticky") + session.AddFlash("Deleted the information post!", "success") + } else { + if sticky.Sticky == "" { + session.AddFlash("Empty form. Please fill out some text.", "error") + session.Save(r, w) + http.Redirect(w, r, "/admin", 302) + return + } + c := pool.Get() + defer c.Close() + + _, err = c.Do("SET", cache_prefix+"sticky", sticky.Sticky) + if err != nil { + log.Println(err) + session.AddFlash("Error while storing.", "error") + } else { + log.Println("Adding new sticky post.") + session.AddFlash("Updated the information post.", "success") + } + } + session.Save(r, w) + http.Redirect(w, r, "/admin", 302) +} diff --git a/app/jobs.go b/app/jobs.go index 6f0d456..7363699 100644 --- a/app/jobs.go +++ b/app/jobs.go @@ -1,7 +1,7 @@ package main func jobRun() { - c.AddFunc("@every 30s", healthCheck) + c.AddFunc("@every 3h", healthCheck) c.Start() } diff --git a/app/main.go b/app/main.go index 6190b1a..f4bddda 100644 --- a/app/main.go +++ b/app/main.go @@ -13,9 +13,11 @@ import ( var decoder = schema.NewDecoder() -var store = sessions.NewCookieStore([]byte(RandomKey())) +//var store = sessions.NewCookieStore([]byte(RandomKey())) +var store = sessions.NewCookieStore([]byte(os.Getenv("STATUS_SECRET"))) var mainTempl = template.Must(template.New("global").Funcs(template.FuncMap{"add": add}).ParseGlob("../views/*.html")) +var emailTempl = template.Must(template.New("email").Funcs(template.FuncMap{"add": add}).ParseGlob("../views/email/*.html")) var c = cron.New() @@ -33,8 +35,6 @@ func main() { checkConfig() jobRun() InitDB() - insertHost() - insertAdmin() go func() { err := FillCache() if err != nil { @@ -46,15 +46,19 @@ func main() { r.HandleFunc("/", IndexHandler) r.HandleFunc("/login", LoginHandler).Methods("POST") r.HandleFunc("/login", PrintLoginHandler).Methods("GET") - r.HandleFunc("/logout", LogoutHandler) + r.HandleFunc("/logout", LogoutHandler).Methods("POST") r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./../static")))) r.HandleFunc("/register", RegisterHandler).Methods("POST") - r.HandleFunc("/register", PrintRegisterHandler).Methods("GET") + //r.HandleFunc("/register", PrintRegisterHandler).Methods("GET") r.HandleFunc("/new", AddNewJobHandler).Methods("POST") - r.HandleFunc("/new", PrintNewJobHandler).Methods("GET") + //r.HandleFunc("/new", PrintNewJobHandler).Methods("GET") r.HandleFunc("/refresh", RefreshAllHandler).Methods("POST") - r.HandleFunc("/jobs", ShowJobHandler) + //r.HandleFunc("/jobs", ShowJobHandler) r.HandleFunc("/admin", AdminHandler) + r.HandleFunc("/register", SetupHandler) + //r.HandleFunc("/delete", DeleteHandler).Methods("POST") + r.HandleFunc("/delete", DeleteHandler) + r.HandleFunc("/sticky/new", NewStickyHandler).Methods("POST") http.Handle("/", r) diff --git a/app/struct.go b/app/struct.go index 49a201d..fdbbced 100644 --- a/app/struct.go +++ b/app/struct.go @@ -11,20 +11,21 @@ type Host struct { Host string Url string // Protocoll string // e.g. http - Monitored bool // disable monitoring on error - Private bool - Status string - StatusCode int64 - Success bool - Reason string // Connection failure + Monitored bool // disable monitoring on error + Private bool + Status string + StatusCode int64 + Success bool + Reason string // Connection failure + Description string /* Date time.Time Include string // Website must include this string Except string // Website must not include this string Alert bool // True to send alert on failure + DeletedAt time.Time */ CreatedAt time.Time - DeletedAt time.Time UpdatedAt time.Time Class string } @@ -35,13 +36,19 @@ type User struct { Email string Password string CreatedAt time.Time - DeletedAt time.Time UpdatedAt time.Time } +type Sticky struct { + Id int64 + Sticky string +} + type Messages struct { Success []interface{} Error []interface{} Hosts []Host moreScripts []string + NextRun time.Time + Sticky string } diff --git a/app/test.go b/app/test.go index 419cd7f..a323b31 100644 --- a/app/test.go +++ b/app/test.go @@ -10,6 +10,8 @@ func insertHost() { Db.Create(&h) h = Host{Host: "iamfabulousadsfadfdsf.de", Url: "https://iamfabulousadsfadfdsf.de/", Monitored: true, Private: false, Class: "info"} Db.Create(&h) + h = Host{Host: "git.iamfabulous.de", Url: "https://git.iamfabulous.de", Monitored: true, Private: true, Class: "info"} + Db.Create(&h) // c := pool.Get() // defer c.Close() @@ -28,6 +30,18 @@ func insertAdmin() { if err != nil { log.Panic(err) } - u := User{Name: "admin", Email: "root@localhost", Password: password} + u := User{Name: "admin", Email: "raspi@dns.iamfabulous.de", Password: password} Db.Create(&u) } + +func testMail() { + u := []User{} + h := []Host{} + Db.Find(&u) + Db.Find(&h) + SendEmail(u, h) +} + +func t() { + log.Println(VerifyPassword("password", "$2a$10$5NRfN3E05of0oF53zHvfy.xcseY7DjlqEylMYDrF69a9Y/7L96JEW")) +} diff --git a/app/utilities_test.go b/app/utilities_test.go index 86ea3bf..1865c61 100644 --- a/app/utilities_test.go +++ b/app/utilities_test.go @@ -48,7 +48,7 @@ func TestRandomKey(t *testing.T) { var key string for i := 0; i < 100; i++ { key = RandomKey() - //t.Log(key) // Uncomment to see every generated key. + t.Log(key) // Uncomment to see every generated key. if m[key] { t.Fatal("Key not random.") } else { |
