- Clean up login/redirect flow
- Add redirect when not authed on other endpoints
- Add GET /stats endpoint for overal stats
This commit is contained in:
Daniel Mason 2021-03-30 15:02:04 +13:00
parent 5fd9d41069
commit 038823055a
Signed by: idanoo
GPG key ID: 387387CDBC02F132
23 changed files with 413 additions and 178 deletions

View file

@ -54,6 +54,7 @@ func HandleRequests(port string) {
// No Auth
v1.HandleFunc("/register", limitMiddleware(handleRegister, heavyLimiter)).Methods("POST")
v1.HandleFunc("/login", limitMiddleware(handleLogin, standardLimiter)).Methods("POST")
v1.HandleFunc("/stats", handleStats).Methods("GET")
// This just prevents it serving frontend stuff over /api
r.PathPrefix("/api")
@ -233,6 +234,19 @@ func handleLogin(w http.ResponseWriter, r *http.Request) {
w.Write(data)
}
// handleStats - Returns stats for homepage
func handleStats(w http.ResponseWriter, r *http.Request) {
stats, err := getStats()
if err != nil {
throwOkError(w, err.Error())
return
}
js, _ := json.Marshal(&stats)
w.WriteHeader(http.StatusOK)
w.Write(js)
}
// serveEndpoint - API stuffs
func handleIngress(w http.ResponseWriter, r *http.Request, userUuid string) {
bodyJson, err := decodeJson(r.Body)

View file

@ -0,0 +1,94 @@
package goscrobble
import (
"encoding/json"
"errors"
"log"
"time"
)
type StatsRequest struct {
Users int `json:"users"`
Scrobbles int `json:"scrobbles"`
Tracks int `json:"songs"`
Artists int `json:"artists"`
LastUpdated time.Time `json:"last_updated"`
}
func getStats() (StatsRequest, error) {
js := getRedisVal("stats")
statsReq := StatsRequest{}
var err error
if js != "" {
// If cached, deserialize and return
err = json.Unmarshal([]byte(js), &statsReq)
if err != nil {
log.Printf("Error unmarshalling stats json: %+v", err)
return statsReq, errors.New("Error fetching stats")
}
// Check if older than 5 min - we want to update async for the next caller
now := time.Now()
if now.Sub(statsReq.LastUpdated) > time.Duration(5)*time.Minute {
go goFetchStats()
}
} else {
// If not cached, pull data then return
statsReq, err = fetchStats()
if err != nil {
log.Printf("Error fetching stats: %+v", err)
return statsReq, errors.New("Error fetching stats")
}
}
return statsReq, nil
}
// goFetchStats - Async call
func goFetchStats() {
_, _ = fetchStats()
}
func fetchStats() (StatsRequest, error) {
statsReq := StatsRequest{}
var err error
statsReq.Users, err = getDbCount("SELECT COUNT(*) FROM `users` WHERE `active` = 1")
if err != nil {
log.Printf("Failed to fetch user count: %+v", err)
return statsReq, errors.New("Failed to fetch stats")
}
statsReq.Scrobbles, err = getDbCount("SELECT COUNT(*) FROM `scrobbles`")
if err != nil {
log.Printf("Failed to fetch scrobble count: %+v", err)
return statsReq, errors.New("Failed to fetch stats")
}
statsReq.Tracks, err = getDbCount("SELECT COUNT(*) FROM `tracks`")
if err != nil {
log.Printf("Failed to fetch track count: %+v", err)
return statsReq, errors.New("Failed to fetch stats")
}
statsReq.Artists, err = getDbCount("SELECT COUNT(*) FROM `artists`")
if err != nil {
log.Printf("Failed to fetch artist count: %+v", err)
return statsReq, errors.New("Failed to fetch stats")
}
// Mark the time this was last updated
statsReq.LastUpdated = time.Now()
b, err := json.Marshal(statsReq)
if err != nil {
return statsReq, errors.New("Failed to fetch stats")
}
err = setRedisVal("stats", string(b))
if err != nil {
return statsReq, errors.New("Failed to fetch stats")
}
return statsReq, nil
}