diff --git a/api/authorization.go b/api/authorization.go index ec6d2a1..960f20c 100644 --- a/api/authorization.go +++ b/api/authorization.go @@ -37,9 +37,14 @@ var ( Transport: promhttp.InstrumentRoundTripperDuration(authRequestDuration, http.DefaultTransport), } - userIdContextKey = &struct{}{} + userIdContextKey = &contextKeys{"userId"} + isCallerAdminContextKey = &contextKeys{"isCallerAdmin"} ) +type contextKeys struct { + str string +} + func authorization(authUrl string) middleware { return inlineMiddleware(func(rw http.ResponseWriter, r *http.Request, next http.Handler) { ctx, cancel := context.WithTimeout(r.Context(), authTimeout) @@ -88,6 +93,11 @@ func authorization(authUrl string) middleware { r = r.WithContext(ctx) } + if isCallerAdmin := authRes.Header.Get("X-Livepeer-Is-Caller-Admin"); isCallerAdmin != "" { + ctx := context.WithValue(r.Context(), isCallerAdminContextKey, isCallerAdmin) + r = r.WithContext(ctx) + } + next.ServeHTTP(rw, r) }) } diff --git a/api/handler.go b/api/handler.go index 535c2aa..e8748ce 100644 --- a/api/handler.go +++ b/api/handler.go @@ -320,6 +320,20 @@ func (h *apiHandler) queryUsage() http.HandlerFunc { return } + isCallerAdmin, ok := r.Context().Value(isCallerAdminContextKey).(string) + + if qs := r.URL.Query(); qs.Has("userId") { + if !ok { + respondError(rw, http.StatusInternalServerError, errors.New("request not authenticated - cannot retrieve usage for other users")) + return + } + if isCallerAdmin != "true" { + respondError(rw, http.StatusForbidden, errors.New("only admins can query usage for other users")) + return + } + userId = qs.Get("userId") + } + qs := r.URL.Query() creatorId := qs.Get("creatorId")