Chore: Move ReqContext to contexthandler service (#62102)

* Chore: Move ReqContext to contexthandler service

* Rename package to contextmodel

* Generate ngalert files

* Remove unused imports
This commit is contained in:
idafurjes
2023-01-27 08:50:36 +01:00
committed by GitHub
parent 8379a29b53
commit 6c5a573772
180 changed files with 1208 additions and 1182 deletions
-166
View File
@@ -1,166 +0,0 @@
package models
import (
"errors"
"net/http"
"strings"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/models/usertoken"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util/errutil"
"github.com/grafana/grafana/pkg/web"
"github.com/prometheus/client_golang/prometheus"
)
type ReqContext struct {
*web.Context
*user.SignedInUser
UserToken *usertoken.UserToken
IsSignedIn bool
IsRenderCall bool
AllowAnonymous bool
SkipCache bool
Logger log.Logger
// RequestNonce is a cryptographic request identifier for use with Content Security Policy.
RequestNonce string
IsPublicDashboardView bool
PerfmonTimer prometheus.Summary
LookupTokenErr error
}
// Handle handles and logs error by given status.
func (ctx *ReqContext) Handle(cfg *setting.Cfg, status int, title string, err error) {
data := struct {
Title string
AppTitle string
AppSubUrl string
Theme string
ErrorMsg error
}{title, "Grafana", cfg.AppSubURL, "dark", nil}
if err != nil {
ctx.Logger.Error(title, "error", err)
if setting.Env != setting.Prod {
data.ErrorMsg = err
}
}
ctx.HTML(status, cfg.ErrTemplateName, data)
}
func (ctx *ReqContext) IsApiRequest() bool {
return strings.HasPrefix(ctx.Req.URL.Path, "/api")
}
func (ctx *ReqContext) JsonApiErr(status int, message string, err error) {
resp := make(map[string]interface{})
traceID := tracing.TraceIDFromContext(ctx.Req.Context(), false)
if err != nil {
resp["traceID"] = traceID
if status == http.StatusInternalServerError {
ctx.Logger.Error(message, "error", err, "traceID", traceID)
} else {
ctx.Logger.Warn(message, "error", err, "traceID", traceID)
}
if setting.Env != setting.Prod {
resp["error"] = err.Error()
}
}
switch status {
case http.StatusNotFound:
resp["message"] = "Not Found"
case http.StatusInternalServerError:
resp["message"] = "Internal Server Error"
}
if message != "" {
resp["message"] = message
}
ctx.JSON(status, resp)
}
// WriteErr writes an error response based on errutil.Error.
// If provided error is not errutil.Error a 500 response is written.
func (ctx *ReqContext) WriteErr(err error) {
ctx.writeErrOrFallback(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), err)
}
// WriteErrOrFallback uses the information in an errutil.Error if available
// and otherwise falls back to the status and message provided as arguments.
func (ctx *ReqContext) WriteErrOrFallback(status int, message string, err error) {
ctx.writeErrOrFallback(status, message, err)
}
func (ctx *ReqContext) writeErrOrFallback(status int, message string, err error) {
data := make(map[string]interface{})
traceID := tracing.TraceIDFromContext(ctx.Req.Context(), false)
if err != nil {
data["traceID"] = traceID
var logMessage string
logger := ctx.Logger.Warn
gfErr := errutil.Error{}
if errors.As(err, &gfErr) {
logger = gfErr.LogLevel.LogFunc(ctx.Logger)
publicErr := gfErr.Public()
// need to manually set these fields because we want to include the trace id
data["extra"] = publicErr.Extra
data["message"] = publicErr.Message
data["messageId"] = publicErr.MessageID
data["statusCode"] = publicErr.StatusCode
} else {
if message != "" {
logMessage = message
} else {
logMessage = http.StatusText(status)
data["message"] = logMessage
}
if status == http.StatusInternalServerError {
logger = ctx.Logger.Error
}
}
logger(logMessage, "error", err, "remote_addr", ctx.RemoteAddr(), "traceID", traceID)
}
if _, ok := data["message"]; !ok && message != "" {
data["message"] = message
}
ctx.JSON(status, data)
}
func (ctx *ReqContext) HasUserRole(role org.RoleType) bool {
return ctx.OrgRole.Includes(role)
}
func (ctx *ReqContext) HasHelpFlag(flag user.HelpFlags1) bool {
return ctx.HelpFlags1.HasFlag(flag)
}
func (ctx *ReqContext) TimeRequest(timer prometheus.Summary) {
ctx.PerfmonTimer = timer
}
// QueryBoolWithDefault extracts a value from the request query params and applies a bool default if not present.
func (ctx *ReqContext) QueryBoolWithDefault(field string, d bool) bool {
f := ctx.Query(field)
if f == "" {
return d
}
return ctx.QueryBool(field)
}
-39
View File
@@ -1,39 +0,0 @@
package models
import (
"net/http"
"testing"
"github.com/grafana/grafana/pkg/web"
"github.com/stretchr/testify/require"
)
func TestQueryBoolWithDefault(t *testing.T) {
tc := map[string]struct {
url string
defaultValue bool
expected bool
}{
"with no value specified, the default value is returned": {
url: "http://localhost/api/v2/alerts",
defaultValue: true,
expected: true,
},
"with a value specified, the default value is overridden": {
url: "http://localhost/api/v2/alerts?silenced=false",
defaultValue: true,
expected: false,
},
}
for name, tt := range tc {
t.Run(name, func(t *testing.T) {
req, err := http.NewRequest("GET", tt.url, nil)
require.NoError(t, err)
r := ReqContext{
Context: &web.Context{Req: req},
}
require.Equal(t, tt.expected, r.QueryBoolWithDefault("silenced", tt.defaultValue))
})
}
}
+3 -2
View File
@@ -4,6 +4,7 @@ import (
"fmt"
"time"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
@@ -59,7 +60,7 @@ type RequestURIKey struct{}
// COMMANDS
type UpsertUserCommand struct {
ReqContext *ReqContext
ReqContext *contextmodel.ReqContext
ExternalUser *ExternalUserInfo
UserLookupParams
SignupAllowed bool
@@ -89,7 +90,7 @@ type DeleteAuthInfoCommand struct {
// QUERIES
type LoginUserQuery struct {
ReqContext *ReqContext
ReqContext *contextmodel.ReqContext
Username string
Password string
User *user.User