mirror of
https://github.com/grafana/grafana.git
synced 2025-01-18 20:43:26 -06:00
9a59ccd644
Co-authored-by: Alexander Emelin <frvzmb@gmail.com>
142 lines
3.8 KiB
Go
142 lines
3.8 KiB
Go
package searchV2
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
"github.com/grafana/grafana/pkg/registry"
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
|
"github.com/grafana/grafana/pkg/services/store"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
)
|
|
|
|
type StandardSearchService struct {
|
|
registry.BackgroundService
|
|
|
|
cfg *setting.Cfg
|
|
sql *sqlstore.SQLStore
|
|
auth FutureAuthService // eventually injected from elsewhere
|
|
ac accesscontrol.AccessControl
|
|
|
|
logger log.Logger
|
|
dashboardIndex *dashboardIndex
|
|
extender DashboardIndexExtender
|
|
}
|
|
|
|
func ProvideService(cfg *setting.Cfg, sql *sqlstore.SQLStore, entityEventStore store.EntityEventsService, ac accesscontrol.AccessControl) SearchService {
|
|
extender := &NoopExtender{}
|
|
s := &StandardSearchService{
|
|
cfg: cfg,
|
|
sql: sql,
|
|
ac: ac,
|
|
auth: &simpleSQLAuthService{
|
|
sql: sql,
|
|
ac: ac,
|
|
},
|
|
dashboardIndex: newDashboardIndex(
|
|
newSQLDashboardLoader(sql),
|
|
entityEventStore,
|
|
extender.GetDocumentExtender(),
|
|
newFolderIDLookup(sql),
|
|
),
|
|
logger: log.New("searchV2"),
|
|
extender: extender,
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (s *StandardSearchService) IsDisabled() bool {
|
|
if s.cfg == nil {
|
|
return true
|
|
}
|
|
return !s.cfg.IsFeatureToggleEnabled(featuremgmt.FlagPanelTitleSearch)
|
|
}
|
|
|
|
func (s *StandardSearchService) Run(ctx context.Context) error {
|
|
return s.dashboardIndex.run(ctx)
|
|
}
|
|
|
|
func (s *StandardSearchService) RegisterDashboardIndexExtender(ext DashboardIndexExtender) {
|
|
s.extender = ext
|
|
s.dashboardIndex.extender = ext.GetDocumentExtender()
|
|
}
|
|
|
|
func (s *StandardSearchService) getUser(ctx context.Context, backendUser *backend.User, orgId int64) (*models.SignedInUser, error) {
|
|
// TODO: get user & user's permissions from the request context
|
|
|
|
getSignedInUserQuery := &models.GetSignedInUserQuery{
|
|
Login: backendUser.Login,
|
|
Email: backendUser.Email,
|
|
OrgId: orgId,
|
|
}
|
|
|
|
err := s.sql.GetSignedInUser(ctx, getSignedInUserQuery)
|
|
if err != nil {
|
|
s.logger.Error("Error while retrieving user", "error", err, "email", backendUser.Email)
|
|
return nil, errors.New("auth error")
|
|
}
|
|
|
|
if getSignedInUserQuery.Result == nil {
|
|
s.logger.Error("No user found", "email", backendUser.Email)
|
|
return nil, errors.New("auth error")
|
|
}
|
|
|
|
user := getSignedInUserQuery.Result
|
|
|
|
if s.ac.IsDisabled() {
|
|
return user, nil
|
|
}
|
|
|
|
if user.Permissions == nil {
|
|
user.Permissions = make(map[int64]map[string][]string)
|
|
}
|
|
|
|
if _, ok := user.Permissions[orgId]; ok {
|
|
// permissions as part of the `s.sql.GetSignedInUser` query - return early
|
|
return user, nil
|
|
}
|
|
|
|
// TODO: ensure this is cached
|
|
permissions, err := s.ac.GetUserPermissions(ctx, user,
|
|
accesscontrol.Options{ReloadCache: false})
|
|
if err != nil {
|
|
s.logger.Error("failed to retrieve user permissions", "error", err, "email", backendUser.Email)
|
|
return nil, errors.New("auth error")
|
|
}
|
|
|
|
user.Permissions[orgId] = accesscontrol.GroupScopesByAction(permissions)
|
|
return user, nil
|
|
}
|
|
|
|
func (s *StandardSearchService) DoDashboardQuery(ctx context.Context, user *backend.User, orgID int64, q DashboardQuery) *backend.DataResponse {
|
|
rsp := &backend.DataResponse{}
|
|
signedInUser, err := s.getUser(ctx, user, orgID)
|
|
if err != nil {
|
|
rsp.Error = err
|
|
return rsp
|
|
}
|
|
|
|
filter, err := s.auth.GetDashboardReadFilter(signedInUser)
|
|
if err != nil {
|
|
rsp.Error = err
|
|
return rsp
|
|
}
|
|
|
|
reader, ok := s.dashboardIndex.getOrgReader(orgID)
|
|
if !ok {
|
|
go func() {
|
|
s.dashboardIndex.buildSignals <- orgID
|
|
}()
|
|
rsp.Error = errors.New("search index is not ready, try again later")
|
|
return rsp
|
|
}
|
|
|
|
return doSearchQuery(ctx, s.logger, reader, filter, q, s.extender.GetQueryExtender(q))
|
|
}
|