1
0
Fork 0
mirror of https://github.com/Luzifer/mondash.git synced 2024-11-10 00:20:02 +00:00
mondash/main.go

205 lines
5.1 KiB
Go
Raw Normal View History

2015-02-07 18:32:44 +00:00
package main
import (
"crypto/md5"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"sort"
"time"
"log"
"launchpad.net/goamz/aws"
"launchpad.net/goamz/s3"
"github.com/flosch/pongo2"
"github.com/go-martini/martini"
_ "github.com/flosch/pongo2-addons"
)
var templates = make(map[string]*pongo2.Template)
var s3Storage *s3.Bucket
func main() {
preloadTemplates()
// Initialize S3 storage
awsAuth, err := aws.EnvAuth()
if err != nil {
log.Fatal(err)
}
s3Conn := s3.New(awsAuth, aws.EUWest)
s3Storage = s3Conn.Bucket(os.Getenv("S3Bucket"))
m := martini.Classic()
// Assets are in assets folder
m.Use(martini.Static("assets", martini.StaticOptions{Prefix: "/assets"}))
// Real handlers
m.Get("/", func(res http.ResponseWriter, req *http.Request) {
http.Redirect(res, req, "/welcome", 302)
})
m.Get("/create", func(res http.ResponseWriter, req *http.Request) {
urlProposal := generateAPIKey()[0:20]
_, err := s3Storage.Get(urlProposal)
for err == nil {
urlProposal = generateAPIKey()[0:20]
_, err = s3Storage.Get(urlProposal)
}
http.Redirect(res, req, fmt.Sprintf("/%s", urlProposal), http.StatusTemporaryRedirect)
})
m.Get("/:dashid", func(params martini.Params, res http.ResponseWriter) {
2015-02-20 18:41:36 +00:00
dash, err := loadDashboard(params["dashid"])
2015-02-07 18:32:44 +00:00
if err != nil {
2015-02-20 18:41:36 +00:00
dash = &dashboard{APIKey: generateAPIKey(), Metrics: dashboardMetrics{}}
2015-02-07 18:32:44 +00:00
}
2015-02-08 08:16:32 +00:00
// Filter out expired metrics
2015-02-20 18:41:36 +00:00
metrics := dashboardMetrics{}
2015-02-08 08:16:32 +00:00
for _, m := range dash.Metrics {
if m.Meta.LastUpdate.After(time.Now().Add(time.Duration(m.Expires*-1) * time.Second)) {
metrics = append(metrics, m)
}
}
2015-02-20 18:41:36 +00:00
sort.Sort(sort.Reverse(dashboardMetrics(metrics)))
2015-02-07 18:32:44 +00:00
renderTemplate("dashboard.html", pongo2.Context{
"dashid": params["dashid"],
2015-02-08 08:16:32 +00:00
"metrics": metrics,
2015-02-07 18:32:44 +00:00
"apikey": dash.APIKey,
"baseurl": os.Getenv("BASE_URL"),
}, res)
})
m.Delete("/:dashid", func(params martini.Params, req *http.Request, res http.ResponseWriter) {
2015-02-20 18:41:36 +00:00
dash, err := loadDashboard(params["dashid"])
2015-02-07 18:32:44 +00:00
if err != nil {
http.Error(res, "This dashboard does not exist.", http.StatusInternalServerError)
return
}
if dash.APIKey != req.Header.Get("Authorization") {
http.Error(res, "APIKey did not match.", http.StatusUnauthorized)
return
}
2015-02-20 18:47:36 +00:00
_ = s3Storage.Del(params["dashid"])
2015-02-07 18:32:44 +00:00
http.Error(res, "OK", http.StatusOK)
})
m.Put("/:dashid/:metricid", func(params martini.Params, req *http.Request, res http.ResponseWriter) {
body, err := ioutil.ReadAll(req.Body)
if err != nil {
http.Error(res, "Internal Server Error", http.StatusInternalServerError)
return
}
2015-02-20 18:41:36 +00:00
metricUpdate := newDashboardMetric()
2015-02-07 18:32:44 +00:00
err = json.Unmarshal(body, metricUpdate)
if err != nil {
http.Error(res, "Unable to unmarshal json", http.StatusInternalServerError)
return
}
2015-02-20 18:41:36 +00:00
dash, err := loadDashboard(params["dashid"])
2015-02-07 18:32:44 +00:00
if err != nil {
if len(req.Header.Get("Authorization")) < 10 {
http.Error(res, "APIKey is too insecure", http.StatusUnauthorized)
return
}
2015-02-20 18:41:36 +00:00
dash = &dashboard{APIKey: req.Header.Get("Authorization"), Metrics: dashboardMetrics{}, DashboardID: params["dashid"]}
2015-02-07 18:32:44 +00:00
}
if dash.APIKey != req.Header.Get("Authorization") {
http.Error(res, "APIKey did not match.", http.StatusUnauthorized)
return
}
valid, reason := metricUpdate.IsValid()
if !valid {
http.Error(res, fmt.Sprintf("Invalid data: %s", reason), http.StatusInternalServerError)
return
}
2015-02-07 18:32:44 +00:00
updated := false
for _, m := range dash.Metrics {
if m.MetricID == params["metricid"] {
m.Update(metricUpdate)
updated = true
break
}
}
if !updated {
2015-02-20 18:41:36 +00:00
tmp := newDashboardMetric()
tmp.MetricID = params["metricid"]
2015-02-07 18:32:44 +00:00
tmp.Update(metricUpdate)
dash.Metrics = append(dash.Metrics, tmp)
}
dash.Save()
http.Error(res, "OK", http.StatusOK)
})
m.Delete("/:dashid/:metricid", func(params martini.Params, req *http.Request, res http.ResponseWriter) {
2015-02-20 18:41:36 +00:00
dash, err := loadDashboard(params["dashid"])
2015-02-07 18:32:44 +00:00
if err != nil {
2015-02-20 18:41:36 +00:00
dash = &dashboard{APIKey: req.Header.Get("Authorization"), Metrics: dashboardMetrics{}, DashboardID: params["dashid"]}
2015-02-07 18:32:44 +00:00
}
if dash.APIKey != req.Header.Get("Authorization") {
http.Error(res, "APIKey did not match.", http.StatusUnauthorized)
return
}
2015-02-20 18:41:36 +00:00
tmp := dashboardMetrics{}
2015-02-07 18:32:44 +00:00
for _, m := range dash.Metrics {
if m.MetricID != params["metricid"] {
tmp = append(tmp, m)
}
}
dash.Metrics = tmp
dash.Save()
http.Error(res, "OK", http.StatusOK)
})
2015-02-20 18:41:36 +00:00
go runWelcomePage()
2015-02-07 18:32:44 +00:00
// GO!
m.Run()
}
func generateAPIKey() string {
t := time.Now().String()
sum := md5.Sum([]byte(t))
return fmt.Sprintf("%x", sum)
}
func renderTemplate(templateName string, context pongo2.Context, res http.ResponseWriter) {
if tpl, ok := templates[templateName]; ok {
2015-02-20 18:47:36 +00:00
_ = tpl.ExecuteWriter(context, res)
2015-02-07 18:32:44 +00:00
} else {
res.WriteHeader(http.StatusInternalServerError)
2015-02-20 18:47:36 +00:00
_, _ = res.Write([]byte(fmt.Sprintf("Template %s not found!", templateName)))
2015-02-07 18:32:44 +00:00
}
}
func preloadTemplates() {
templateNames, err := ioutil.ReadDir("templates")
if err != nil {
panic("Templates directory not available!")
}
for _, tplname := range templateNames {
templates[tplname.Name()] = pongo2.Must(pongo2.FromFile(fmt.Sprintf("templates/%s", tplname.Name())))
}
}