package results import ( "html/template" "net/http" "github.com/go-chi/render" log "github.com/sirupsen/logrus" "github.com/gorilla/securecookie" "github.com/gorilla/sessions" "github.com/librespeed/speedtest/config" "github.com/librespeed/speedtest/database" "github.com/librespeed/speedtest/database/schema" ) type StatsData struct { NoPassword bool LoggedIn bool Data []schema.TelemetryData } var ( key = []byte(securecookie.GenerateRandomKey(32)) store = sessions.NewCookieStore(key) ) func init() { store.Options = &sessions.Options{ Path: "/stats", MaxAge: 3600 * 1, // 1 hour HttpOnly: true, SameSite: http.SameSiteStrictMode, } } func Stats(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") t, err := template.New("template").Parse(htmlTemplate) if err != nil { log.Errorf("Failed to parse template: %s", err) w.WriteHeader(http.StatusInternalServerError) return } conf := config.LoadedConfig() if conf.DatabaseType == "none" { render.PlainText(w, r, "Statistics are disabled") return } var data StatsData if conf.StatsPassword == "PASSWORD" { data.NoPassword = true } if !data.NoPassword { op := r.FormValue("op") session, _ := store.Get(r, "logged") auth, ok := session.Values["authenticated"].(bool) if auth && ok { if op == "logout" { session.Values["authenticated"] = false session.Options.MaxAge = -1 session.Save(r, w) http.Redirect(w, r, conf.BaseURL+"/stats", http.StatusTemporaryRedirect) } else { data.LoggedIn = true id := r.FormValue("id") switch id { case "L100": stats, err := database.DB.FetchLast100() if err != nil { log.Errorf("Error fetching data from database: %s", err) w.WriteHeader(http.StatusInternalServerError) return } data.Data = stats case "": default: stat, err := database.DB.FetchByUUID(id) if err != nil { log.Errorf("Error fetching data from database: %s", err) w.WriteHeader(http.StatusInternalServerError) return } data.Data = append(data.Data, *stat) } } } else { if op == "login" { session, _ := store.Get(r, "logged") password := r.FormValue("password") if password == conf.StatsPassword { session.Values["authenticated"] = true session.Save(r, w) http.Redirect(w, r, conf.BaseURL+"/stats", http.StatusTemporaryRedirect) } else { w.WriteHeader(http.StatusForbidden) } } } } if err := t.Execute(w, data); err != nil { log.Errorf("Error executing template: %s", err) w.WriteHeader(http.StatusInternalServerError) } } const htmlTemplate = `
Test ID | {{ $v.UUID }} |
---|---|
Date and time | {{ $v.Timestamp }} |
IP and ISP Info | {{ $v.IPAddress }} {{ $v.ISPInfo }} |
User agent and locale | {{ $v.UserAgent }} {{ $v.Language }} |
Download speed | {{ $v.Download }} |
Upload speed | {{ $v.Upload }} |
Ping | {{ $v.Ping }} |
Jitter | {{ $v.Jitter }} |
Log | {{ $v.Log }} |
Extra info | {{ $v.Extra }} |