3
0
mirror of https://github.com/grafana/grafana.git synced 2025-02-25 18:55:37 -06:00

Access Control: Get org from request data for authorization ()

* Access Control: Get org from request data for authorization

* move type to models

* Update pkg/services/accesscontrol/middleware.go

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>

* refactor

* refactor

* Fix linter

---------

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
This commit is contained in:
Alexander Zobnin 2024-03-13 17:05:03 +01:00 committed by GitHub
parent d480d3296c
commit fd9031ca37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 83 additions and 0 deletions
pkg/services/accesscontrol

View File

@ -5,6 +5,7 @@ import (
"context"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"regexp"
@ -320,6 +321,83 @@ func UseGlobalOrSingleOrg(cfg *setting.Cfg) OrgIDGetter {
}
}
// UseOrgFromRequestData returns the organization from the request data.
// If no org is specified, then the org where user is logged in is returned.
func UseOrgFromRequestData(c *contextmodel.ReqContext) (int64, error) {
query, err := getOrgQueryFromRequest(c)
if err != nil {
// Special case of macaron handling invalid params
return NoOrgID, org.ErrOrgNotFound.Errorf("failed to get organization from context: %w", err)
}
if query.OrgId == nil {
return c.SignedInUser.GetOrgID(), nil
}
return *query.OrgId, nil
}
// UseGlobalOrgFromRequestData returns global org if `global` flag is set or the org where user is logged in.
func UseGlobalOrgFromRequestData(c *contextmodel.ReqContext) (int64, error) {
query, err := getOrgQueryFromRequest(c)
if err != nil {
// Special case of macaron handling invalid params
return NoOrgID, org.ErrOrgNotFound.Errorf("failed to get organization from context: %w", err)
}
if query.Global {
return GlobalOrgID, nil
}
return c.SignedInUser.GetOrgID(), nil
}
func getOrgQueryFromRequest(c *contextmodel.ReqContext) (*QueryWithOrg, error) {
query := &QueryWithOrg{}
req, err := CloneRequest(c.Req)
if err != nil {
return nil, err
}
if err := web.Bind(req, query); err != nil {
// Special case of macaron handling invalid params
return nil, err
}
return query, nil
}
// CloneRequest creates request copy including request body
func CloneRequest(req *http.Request) (*http.Request, error) {
// Get copy of body to prevent error when reading closed body in request handler
bodyCopy, err := CopyRequestBody(req)
if err != nil {
return nil, err
}
reqCopy := req.Clone(req.Context())
reqCopy.Body = bodyCopy
return reqCopy, nil
}
// CopyRequestBody returns copy of request body and keeps the original one to prevent error when reading closed body
func CopyRequestBody(req *http.Request) (io.ReadCloser, error) {
if req.Body == nil {
return nil, nil
}
body := req.Body
var buf bytes.Buffer
if _, err := buf.ReadFrom(body); err != nil {
return nil, err
}
if err := body.Close(); err != nil {
return nil, err
}
req.Body = io.NopCloser(&buf)
return io.NopCloser(bytes.NewReader(buf.Bytes())), nil
}
// scopeParams holds the parameters used to fill in scope templates
type scopeParams struct {
OrgID int64

View File

@ -562,3 +562,8 @@ var OrgsCreateAccessEvaluator = EvalAll(
// ApiKeyAccessEvaluator is used to protect the "Configuration > API keys" page access
var ApiKeyAccessEvaluator = EvalPermission(ActionAPIKeyRead)
type QueryWithOrg struct {
OrgId *int64 `json:"orgId"`
Global bool `json:"global"`
}