API basic auth support
parent
630d85487c
commit
4dc8bcefb9
|
@ -60,7 +60,7 @@ func Listen(parentLogger *slog.Logger, readme []byte) {
|
||||||
})
|
})
|
||||||
|
|
||||||
router.Route("/api", func(r chi.Router) {
|
router.Route("/api", func(r chi.Router) {
|
||||||
r.Use(tokenAuthMiddleware)
|
r.Use(authMiddleware)
|
||||||
r.Get(`/state/{entityId}`, getEntityStateHandler)
|
r.Get(`/state/{entityId}`, getEntityStateHandler)
|
||||||
r.Post("/state/{entityId}/{service}", setEntityStateHandler)
|
r.Post("/state/{entityId}/{service}", setEntityStateHandler)
|
||||||
|
|
||||||
|
@ -91,20 +91,32 @@ func Close() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func tokenAuthMiddleware(next http.Handler) http.Handler {
|
// authMiddleware checks both basic and bearer auth schemes for a token
|
||||||
|
//
|
||||||
|
// When using basic auth: the username does not matter and the the password should equal the configured token
|
||||||
|
// When using bearer auth: set the "Authorization" header to "Bearer your-token-here"
|
||||||
|
func authMiddleware(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if cfg.HatsToken == "" { // No token required
|
if cfg.HatsToken == "" { // No token required
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
authHeaderParts := strings.Split(r.Header.Get("Authorization"), " ")
|
_, p, ok := r.BasicAuth()
|
||||||
if len(authHeaderParts) != 2 || authHeaderParts[0] != "Bearer" || authHeaderParts[1] != cfg.HatsToken {
|
|
||||||
logger.Warn("Unauthorized request", "method", r.Method, "path", r.URL.Path, "address", r.RemoteAddr)
|
if ok && p == cfg.HatsToken {
|
||||||
http.Error(w, "Bearer authorization header doesn't match configured token", http.StatusUnauthorized)
|
next.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
next.ServeHTTP(w, r)
|
|
||||||
|
authHeaderPars := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
|
||||||
|
if len(authHeaderPars) > 1 && strings.EqualFold(authHeaderPars[0], "bearer") && authHeaderPars[1] == cfg.HatsToken {
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Warn("Unauthorized request", "method", r.Method, "path", r.URL.Path, "address", r.RemoteAddr)
|
||||||
|
http.Error(w, "Bearer authorization header doesn't match configured token", http.StatusUnauthorized)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ func PublishRequest(subject string, message []byte, timeout time.Duration, retri
|
||||||
for {
|
for {
|
||||||
attempts += 1
|
attempts += 1
|
||||||
if attempts > retries {
|
if attempts > retries {
|
||||||
logger.Error("Request retries exceeded", "subject", subject)
|
logger.Warn("Request retries exceeded", "subject", subject)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp, err := client.Conn.Request(subject, message, timeout)
|
resp, err := client.Conn.Request(subject, message, timeout)
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
package purpleair
|
||||||
|
|
||||||
|
type WebhookPayload struct {
|
||||||
|
SensorID string `json:"SensorId,omitempty"`
|
||||||
|
DateTime string `json:"DateTime,omitempty"`
|
||||||
|
Geo string `json:"Geo,omitempty"`
|
||||||
|
Mem int `json:"Mem,omitempty"`
|
||||||
|
Memfrag int `json:"memfrag,omitempty"`
|
||||||
|
Memfb int `json:"memfb,omitempty"`
|
||||||
|
Memcs int `json:"memcs,omitempty"`
|
||||||
|
ID int `json:"Id,omitempty"`
|
||||||
|
Lat float64 `json:"lat,omitempty"`
|
||||||
|
Lon float64 `json:"lon,omitempty"`
|
||||||
|
Adc float64 `json:"Adc,omitempty"`
|
||||||
|
Loggingrate int `json:"loggingrate,omitempty"`
|
||||||
|
Place string `json:"place,omitempty"`
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
Uptime int `json:"uptime,omitempty"`
|
||||||
|
Rssi int `json:"rssi,omitempty"`
|
||||||
|
Period int `json:"period,omitempty"`
|
||||||
|
Httpsuccess int `json:"httpsuccess,omitempty"`
|
||||||
|
Httpsends int `json:"httpsends,omitempty"`
|
||||||
|
Hardwareversion string `json:"hardwareversion,omitempty"`
|
||||||
|
Hardwarediscovered string `json:"hardwarediscovered,omitempty"`
|
||||||
|
CurrentTempF int `json:"current_temp_f,omitempty"`
|
||||||
|
CurrentHumidity int `json:"current_humidity,omitempty"`
|
||||||
|
CurrentDewpointF int `json:"current_dewpoint_f,omitempty"`
|
||||||
|
Pressure float64 `json:"pressure,omitempty"`
|
||||||
|
P25AqicB string `json:"p25aqic_b,omitempty"`
|
||||||
|
Pm25AqiB int `json:"pm2.5_aqi_b,omitempty"`
|
||||||
|
Pm10Cf1B float64 `json:"pm1_0_cf_1_b,omitempty"`
|
||||||
|
P03UmB float64 `json:"p_0_3_um_b,omitempty"`
|
||||||
|
Pm25Cf1B float64 `json:"pm2_5_cf_1_b,omitempty"`
|
||||||
|
P05UmB float64 `json:"p_0_5_um_b,omitempty"`
|
||||||
|
Pm100Cf1B float64 `json:"pm10_0_cf_1_b,omitempty"`
|
||||||
|
P10UmB float64 `json:"p_1_0_um_b,omitempty"`
|
||||||
|
Pm10AtmB float64 `json:"pm1_0_atm_b,omitempty"`
|
||||||
|
P25UmB float64 `json:"p_2_5_um_b,omitempty"`
|
||||||
|
Pm25AtmB float64 `json:"pm2_5_atm_b,omitempty"`
|
||||||
|
P50UmB float64 `json:"p_5_0_um_b,omitempty"`
|
||||||
|
Pm100AtmB float64 `json:"pm10_0_atm_b,omitempty"`
|
||||||
|
P100UmB float64 `json:"p_10_0_um_b,omitempty"`
|
||||||
|
P25Aqic string `json:"p25aqic,omitempty"`
|
||||||
|
Pm25Aqi int `json:"pm2.5_aqi,omitempty"`
|
||||||
|
Pm10Cf1 float64 `json:"pm1_0_cf_1,omitempty"`
|
||||||
|
P03Um float64 `json:"p_0_3_um,omitempty"`
|
||||||
|
Pm25Cf1 float64 `json:"pm2_5_cf_1,omitempty"`
|
||||||
|
P05Um float64 `json:"p_0_5_um,omitempty"`
|
||||||
|
Pm100Cf1 float64 `json:"pm10_0_cf_1,omitempty"`
|
||||||
|
P10Um float64 `json:"p_1_0_um,omitempty"`
|
||||||
|
Pm10Atm float64 `json:"pm1_0_atm,omitempty"`
|
||||||
|
P25Um float64 `json:"p_2_5_um,omitempty"`
|
||||||
|
Pm25Atm float64 `json:"pm2_5_atm,omitempty"`
|
||||||
|
P50Um float64 `json:"p_5_0_um,omitempty"`
|
||||||
|
Pm100Atm float64 `json:"pm10_0_atm,omitempty"`
|
||||||
|
P100Um float64 `json:"p_10_0_um,omitempty"`
|
||||||
|
PaLatency int `json:"pa_latency,omitempty"`
|
||||||
|
Response int `json:"response,omitempty"`
|
||||||
|
ResponseDate int `json:"response_date,omitempty"`
|
||||||
|
Latency int `json:"latency,omitempty"`
|
||||||
|
ResponseB int `json:"response_b,omitempty"`
|
||||||
|
ResponseDateB int `json:"response_date_b,omitempty"`
|
||||||
|
LatencyB int `json:"latency_b,omitempty"`
|
||||||
|
Wlstate string `json:"wlstate,omitempty"`
|
||||||
|
Status0 int `json:"status_0,omitempty"`
|
||||||
|
Status1 int `json:"status_1,omitempty"`
|
||||||
|
Status2 int `json:"status_2,omitempty"`
|
||||||
|
Status3 int `json:"status_3,omitempty"`
|
||||||
|
Status4 int `json:"status_4,omitempty"`
|
||||||
|
Status5 int `json:"status_5,omitempty"`
|
||||||
|
Status6 int `json:"status_6,omitempty"`
|
||||||
|
Status7 int `json:"status_7,omitempty"`
|
||||||
|
Status8 int `json:"status_8,omitempty"`
|
||||||
|
Status9 int `json:"status_9,omitempty"`
|
||||||
|
Status10 int `json:"status_10,omitempty"`
|
||||||
|
}
|
Loading…
Reference in New Issue