mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
chore: add check to validate wakatime api key before accepting it
This commit is contained in:
parent
417d4789ab
commit
fd239e4f21
@ -33,6 +33,12 @@ const (
|
|||||||
KeyLatestTotalUsers = "latest_total_users"
|
KeyLatestTotalUsers = "latest_total_users"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
WakatimeApiUrl = "https://wakatime.com/api/v1"
|
||||||
|
WakatimeApiHeartbeatsEndpoint = "/users/current/heartbeats.bulk"
|
||||||
|
WakatimeApiUserEndpoint = "/users/current"
|
||||||
|
)
|
||||||
|
|
||||||
var cfg *Config
|
var cfg *Config
|
||||||
var cFlag = flag.String("config", defaultConfigPath, "config file location")
|
var cFlag = flag.String("config", defaultConfigPath, "config file location")
|
||||||
|
|
||||||
|
@ -13,11 +13,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
WakatimeApiUrl = "https://wakatime.com/api/v1"
|
|
||||||
WakatimeApiHeartbeatsEndpoint = "/users/current/heartbeats.bulk"
|
|
||||||
)
|
|
||||||
|
|
||||||
/* Middleware to conditionally relay heartbeats to Wakatime */
|
/* Middleware to conditionally relay heartbeats to Wakatime */
|
||||||
type WakatimeRelayMiddleware struct {
|
type WakatimeRelayMiddleware struct {
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
@ -68,7 +63,7 @@ func (m *WakatimeRelayMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Reque
|
|||||||
|
|
||||||
go m.send(
|
go m.send(
|
||||||
http.MethodPost,
|
http.MethodPost,
|
||||||
WakatimeApiUrl+WakatimeApiHeartbeatsEndpoint,
|
config.WakatimeApiUrl+config.WakatimeApiHeartbeatsEndpoint,
|
||||||
bytes.NewReader(body),
|
bytes.NewReader(body),
|
||||||
headers,
|
headers,
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package routes
|
package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/gorilla/schema"
|
"github.com/gorilla/schema"
|
||||||
@ -12,6 +13,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SettingsHandler struct {
|
type SettingsHandler struct {
|
||||||
@ -21,6 +23,7 @@ type SettingsHandler struct {
|
|||||||
aliasSrvc services.IAliasService
|
aliasSrvc services.IAliasService
|
||||||
aggregationSrvc services.IAggregationService
|
aggregationSrvc services.IAggregationService
|
||||||
languageMappingSrvc services.ILanguageMappingService
|
languageMappingSrvc services.ILanguageMappingService
|
||||||
|
httpClient *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
var credentialsDecoder = schema.NewDecoder()
|
var credentialsDecoder = schema.NewDecoder()
|
||||||
@ -33,6 +36,7 @@ func NewSettingsHandler(userService services.IUserService, summaryService servic
|
|||||||
aggregationSrvc: aggregationService,
|
aggregationSrvc: aggregationService,
|
||||||
languageMappingSrvc: languageMappingService,
|
languageMappingSrvc: languageMappingService,
|
||||||
userSrvc: userService,
|
userSrvc: userService,
|
||||||
|
httpClient: &http.Client{Timeout: 10 * time.Second},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +259,15 @@ func (h *SettingsHandler) PostSetWakatimeApiKey(w http.ResponseWriter, r *http.R
|
|||||||
}
|
}
|
||||||
|
|
||||||
user := r.Context().Value(models.UserKey).(*models.User)
|
user := r.Context().Value(models.UserKey).(*models.User)
|
||||||
if _, err := h.userSrvc.SetWakatimeApiKey(user, r.PostFormValue("api_key")); err != nil {
|
apiKey := r.PostFormValue("api_key")
|
||||||
|
|
||||||
|
// Healthcheck, if a new API key is set, i.e. the feature is activated
|
||||||
|
if (user.WakatimeApiKey == "" && apiKey != "") && !h.validateWakatimeKey(apiKey) {
|
||||||
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("failed to connect to WakaTime, API key invalid?"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := h.userSrvc.SetWakatimeApiKey(user, apiKey); err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithError("internal server error"))
|
||||||
return
|
return
|
||||||
@ -304,6 +316,33 @@ func (h *SettingsHandler) PostRegenerateSummaries(w http.ResponseWriter, r *http
|
|||||||
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("summaries are being regenerated – this may take a few seconds"))
|
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r).WithSuccess("summaries are being regenerated – this may take a few seconds"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *SettingsHandler) validateWakatimeKey(apiKey string) bool {
|
||||||
|
headers := http.Header{
|
||||||
|
"Accept": []string{"application/json"},
|
||||||
|
"Authorization": []string{
|
||||||
|
fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(apiKey))),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
request, err := http.NewRequest(
|
||||||
|
http.MethodGet,
|
||||||
|
conf.WakatimeApiUrl+conf.WakatimeApiUserEndpoint,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
request.Header = headers
|
||||||
|
|
||||||
|
response, err := h.httpClient.Do(request)
|
||||||
|
if err != nil || response.StatusCode < 200 || response.StatusCode >= 300 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (h *SettingsHandler) buildViewModel(r *http.Request) *view.SettingsViewModel {
|
func (h *SettingsHandler) buildViewModel(r *http.Request) *view.SettingsViewModel {
|
||||||
user := r.Context().Value(models.UserKey).(*models.User)
|
user := r.Context().Value(models.UserKey).(*models.User)
|
||||||
mappings, _ := h.languageMappingSrvc.GetByUser(user.ID)
|
mappings, _ := h.languageMappingSrvc.GetByUser(user.ID)
|
||||||
|
Loading…
Reference in New Issue
Block a user