mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 08:05:43 -06:00
ContextHandler: Use stdlib format for middleware (#54219)
This commit is contained in:
parent
aace0b1e7f
commit
0ffbf901d7
@ -534,7 +534,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
|
||||
m.Use(middleware.RequestTracing(hs.tracer))
|
||||
m.Use(middleware.RequestMetrics(hs.Features))
|
||||
|
||||
m.Use(middleware.Logger(hs.Cfg))
|
||||
m.UseMiddleware(middleware.Logger(hs.Cfg))
|
||||
|
||||
if hs.Cfg.EnableGzip {
|
||||
m.UseMiddleware(middleware.Gziper())
|
||||
@ -566,7 +566,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
|
||||
m.Use(hs.metricsEndpoint)
|
||||
m.Use(hs.pluginMetricsEndpoint)
|
||||
|
||||
m.Use(hs.ContextHandler.Middleware)
|
||||
m.UseMiddleware(hs.ContextHandler.Middleware)
|
||||
m.Use(middleware.OrgRedirect(hs.Cfg, hs.SQLStore))
|
||||
m.Use(accesscontrol.LoadPermissionsMiddleware(hs.accesscontrolService))
|
||||
|
||||
|
@ -90,84 +90,90 @@ func FromContext(c context.Context) *models.ReqContext {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Middleware provides a middleware to initialize the Macaron context.
|
||||
func (h *ContextHandler) Middleware(mContext *web.Context) {
|
||||
_, span := h.tracer.Start(mContext.Req.Context(), "Auth - Middleware")
|
||||
defer span.End()
|
||||
// Middleware provides a middleware to initialize the request context.
|
||||
func (h *ContextHandler) Middleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
mContext := web.FromContext(ctx)
|
||||
_, span := h.tracer.Start(ctx, "Auth - Middleware")
|
||||
defer span.End()
|
||||
|
||||
reqContext := &models.ReqContext{
|
||||
Context: mContext,
|
||||
SignedInUser: &user.SignedInUser{},
|
||||
IsSignedIn: false,
|
||||
AllowAnonymous: false,
|
||||
SkipCache: false,
|
||||
Logger: log.New("context"),
|
||||
}
|
||||
|
||||
// Inject ReqContext into http.Request.Context
|
||||
mContext.Req = mContext.Req.WithContext(ctxkey.Set(mContext.Req.Context(), reqContext))
|
||||
|
||||
traceID := tracing.TraceIDFromContext(mContext.Req.Context(), false)
|
||||
if traceID != "" {
|
||||
reqContext.Logger = reqContext.Logger.New("traceID", traceID)
|
||||
}
|
||||
|
||||
const headerName = "X-Grafana-Org-Id"
|
||||
orgID := int64(0)
|
||||
orgIDHeader := reqContext.Req.Header.Get(headerName)
|
||||
if orgIDHeader != "" {
|
||||
id, err := strconv.ParseInt(orgIDHeader, 10, 64)
|
||||
if err == nil {
|
||||
orgID = id
|
||||
} else {
|
||||
reqContext.Logger.Debug("Received invalid header", "header", headerName, "value", orgIDHeader)
|
||||
reqContext := &models.ReqContext{
|
||||
Context: mContext,
|
||||
SignedInUser: &user.SignedInUser{},
|
||||
IsSignedIn: false,
|
||||
AllowAnonymous: false,
|
||||
SkipCache: false,
|
||||
Logger: log.New("context"),
|
||||
}
|
||||
}
|
||||
|
||||
queryParameters, err := url.ParseQuery(reqContext.Req.URL.RawQuery)
|
||||
if err != nil {
|
||||
reqContext.Logger.Error("Failed to parse query parameters", "error", err)
|
||||
}
|
||||
if queryParameters.Has("targetOrgId") {
|
||||
targetOrg, err := strconv.ParseInt(queryParameters.Get("targetOrgId"), 10, 64)
|
||||
if err == nil {
|
||||
orgID = targetOrg
|
||||
} else {
|
||||
reqContext.Logger.Error("Invalid target organization ID", "error", err)
|
||||
// Inject ReqContext into http.Request.Context
|
||||
*r = *r.WithContext(context.WithValue(ctx, reqContextKey{}, reqContext))
|
||||
|
||||
traceID := tracing.TraceIDFromContext(mContext.Req.Context(), false)
|
||||
if traceID != "" {
|
||||
reqContext.Logger = reqContext.Logger.New("traceID", traceID)
|
||||
}
|
||||
}
|
||||
|
||||
// the order in which these are tested are important
|
||||
// look for api key in Authorization header first
|
||||
// then init session and look for userId in session
|
||||
// then look for api key in session (special case for render calls via api)
|
||||
// then test if anonymous access is enabled
|
||||
switch {
|
||||
case h.initContextWithRenderAuth(reqContext):
|
||||
case h.initContextWithAPIKey(reqContext):
|
||||
case h.initContextWithBasicAuth(reqContext, orgID):
|
||||
case h.initContextWithAuthProxy(reqContext, orgID):
|
||||
case h.initContextWithToken(reqContext, orgID):
|
||||
case h.initContextWithJWT(reqContext, orgID):
|
||||
case h.initContextWithAnonymousUser(reqContext):
|
||||
}
|
||||
|
||||
reqContext.Logger = reqContext.Logger.New("userId", reqContext.UserID, "orgId", reqContext.OrgID, "uname", reqContext.Login)
|
||||
span.AddEvents(
|
||||
[]string{"uname", "orgId", "userId"},
|
||||
[]tracing.EventValue{
|
||||
{Str: reqContext.Login},
|
||||
{Num: reqContext.OrgID},
|
||||
{Num: reqContext.UserID}},
|
||||
)
|
||||
|
||||
// update last seen every 5min
|
||||
if reqContext.ShouldUpdateLastSeenAt() {
|
||||
reqContext.Logger.Debug("Updating last user_seen_at", "user_id", reqContext.UserID)
|
||||
if err := h.userService.UpdateLastSeenAt(mContext.Req.Context(), &user.UpdateUserLastSeenAtCommand{UserID: reqContext.UserID}); err != nil {
|
||||
reqContext.Logger.Error("Failed to update last_seen_at", "error", err)
|
||||
const headerName = "X-Grafana-Org-Id"
|
||||
orgID := int64(0)
|
||||
orgIDHeader := reqContext.Req.Header.Get(headerName)
|
||||
if orgIDHeader != "" {
|
||||
id, err := strconv.ParseInt(orgIDHeader, 10, 64)
|
||||
if err == nil {
|
||||
orgID = id
|
||||
} else {
|
||||
reqContext.Logger.Debug("Received invalid header", "header", headerName, "value", orgIDHeader)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
queryParameters, err := url.ParseQuery(reqContext.Req.URL.RawQuery)
|
||||
if err != nil {
|
||||
reqContext.Logger.Error("Failed to parse query parameters", "error", err)
|
||||
}
|
||||
if queryParameters.Has("targetOrgId") {
|
||||
targetOrg, err := strconv.ParseInt(queryParameters.Get("targetOrgId"), 10, 64)
|
||||
if err == nil {
|
||||
orgID = targetOrg
|
||||
} else {
|
||||
reqContext.Logger.Error("Invalid target organization ID", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
// the order in which these are tested are important
|
||||
// look for api key in Authorization header first
|
||||
// then init session and look for userId in session
|
||||
// then look for api key in session (special case for render calls via api)
|
||||
// then test if anonymous access is enabled
|
||||
switch {
|
||||
case h.initContextWithRenderAuth(reqContext):
|
||||
case h.initContextWithAPIKey(reqContext):
|
||||
case h.initContextWithBasicAuth(reqContext, orgID):
|
||||
case h.initContextWithAuthProxy(reqContext, orgID):
|
||||
case h.initContextWithToken(reqContext, orgID):
|
||||
case h.initContextWithJWT(reqContext, orgID):
|
||||
case h.initContextWithAnonymousUser(reqContext):
|
||||
}
|
||||
|
||||
reqContext.Logger = reqContext.Logger.New("userId", reqContext.UserID, "orgId", reqContext.OrgID, "uname", reqContext.Login)
|
||||
span.AddEvents(
|
||||
[]string{"uname", "orgId", "userId"},
|
||||
[]tracing.EventValue{
|
||||
{Str: reqContext.Login},
|
||||
{Num: reqContext.OrgID},
|
||||
{Num: reqContext.UserID}},
|
||||
)
|
||||
|
||||
// update last seen every 5min
|
||||
if reqContext.ShouldUpdateLastSeenAt() {
|
||||
reqContext.Logger.Debug("Updating last user_seen_at", "user_id", reqContext.UserID)
|
||||
if err := h.userService.UpdateLastSeenAt(mContext.Req.Context(), &user.UpdateUserLastSeenAtCommand{UserID: reqContext.UserID}); err != nil {
|
||||
reqContext.Logger.Error("Failed to update last_seen_at", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func (h *ContextHandler) initContextWithAnonymousUser(reqContext *models.ReqContext) bool {
|
||||
|
Loading…
Reference in New Issue
Block a user