Skip to content

Commit

Permalink
Fixing Org scoping to rely on HTTP header rather for Org Preferences (#…
Browse files Browse the repository at this point in the history
…294)

Fixes #277
  • Loading branch information
safaci2000 authored Sep 11, 2024
1 parent 07329ac commit e9b3f74
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 88 deletions.
14 changes: 6 additions & 8 deletions cli/tools/org_preferences.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,21 @@ func newUpdateOrgPreferenceCmd() simplecobra.Commander {
log.Fatal("At least one of [--homeDashUid, --theme, --weekstart] needs to be set")
}

rootCmd.GrafanaSvc().InitOrganizations()
prefere, err := rootCmd.GrafanaSvc().GetOrgPreferences(org)
preferences, err := rootCmd.GrafanaSvc().GetOrgPreferences(org)
if err != nil {
log.Fatal(err.Error())
}
if home != "" {
prefere.HomeDashboardUID = home
preferences.HomeDashboardUID = home
}
if theme != "" {
prefere.Theme = theme
preferences.Theme = theme
}
if weekstart != "" {
prefere.WeekStart = weekstart
preferences.WeekStart = weekstart
}

err = rootCmd.GrafanaSvc().UploadOrgPreferences(org, prefere)
err = rootCmd.GrafanaSvc().UploadOrgPreferences(org, preferences)
if err != nil {
log.Fatalf("Failed to update org preferences, %v", err)
}
Expand All @@ -84,14 +83,13 @@ func newGetOrgPreferenceCmd() simplecobra.Commander {
return &support.SimpleCommand{
NameP: "get",
Short: "get <orgName> returns org preferences",
Long: "get <orgId> returns org preferences",
Long: "get <orgName> returns org preferences",
WithCFunc: func(cmd *cobra.Command, r *support.RootCommand) {
cmd.PersistentFlags().StringP("orgName", "", "", "Organization Name")
},
RunFunc: func(ctx context.Context, cd *simplecobra.Commandeer, rootCmd *support.RootCommand, args []string) error {
orgName, _ := cd.CobraCommand.Flags().GetString("orgName")

rootCmd.GrafanaSvc().InitOrganizations()
pref, err := rootCmd.GrafanaSvc().GetOrgPreferences(orgName)
if err != nil {
log.Fatal(err.Error())
Expand Down
58 changes: 37 additions & 21 deletions internal/service/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,24 @@ func ignoreSSL(transportConfig *client.TransportConfig) {

type NewClientOpts func(transportConfig *client.TransportConfig)

func GetOrgNameClientOpts(orgName string) NewClientOpts {
if orgName != "" {
return func(transportConfig *client.TransportConfig) {
orgId, err := api.NewExtendedApi().GetConfiguredOrgId(orgName)
if err != nil {
slog.Error("unable to determine org ID, falling back", slog.Any("err", err))
orgId = 1
}

transportConfig.OrgID = orgId
}
}

return func(clientCfg *client.TransportConfig) {
clientCfg.OrgID = config.DefaultOrganizationId
}
}

func (s *DashNGoImpl) getNewClient(opts ...NewClientOpts) (*client.GrafanaHTTPAPI, *client.TransportConfig) {
var err error
u, err := url.Parse(s.grafanaConf.URL)
Expand All @@ -58,21 +76,9 @@ func (s *DashNGoImpl) getNewClient(opts ...NewClientOpts) (*client.GrafanaHTTPAP
Debug: s.apiDebug,
}

if s.grafanaConf.IsBasicAuth() {
if s.grafanaConf.OrganizationName != "" {
orgId, err := api.NewExtendedApi().GetConfiguredOrgId(s.grafanaConf.OrganizationName)
if err != nil {
slog.Error("unable to determine org ID, falling back", slog.Any("err", err))
orgId = 1
}
opts = append(opts, func(clientCfg *client.TransportConfig) {
clientCfg.OrgID = orgId
})
} else {
opts = append(opts, func(clientCfg *client.TransportConfig) {
clientCfg.OrgID = config.DefaultOrganizationId
})
}
// If more than one opts is passed, depend on the caller to setup his required configuration
if s.grafanaConf.IsBasicAuth() && len(opts) == 1 {
opts = append(opts, GetOrgNameClientOpts(s.grafanaConf.OrganizationName))
}
for _, opt := range opts {
if opt != nil {
Expand All @@ -99,21 +105,31 @@ func (s *DashNGoImpl) GetClient() *client.GrafanaHTTPAPI {
}
}

func (s *DashNGoImpl) GetBasicClientWithOpts(opts ...NewClientOpts) *client.GrafanaHTTPAPI {
allOpts := s.getDefaultBasicOpts()
allOpts = append(allOpts, opts...)
grafanaClient, _ := s.getNewClient(allOpts...)
return grafanaClient
}

// GetAdminClient Returns the admin defaultClient if one is configured
func (s *DashNGoImpl) GetAdminClient() *client.GrafanaHTTPAPI {
if !s.grafanaConf.IsGrafanaAdmin() || s.grafanaConf.UserName == "" {
log.Fatal("Unable to get Grafana Admin SecureData. ")
}
return s.GetBasicAuthClient()
return s.GetBasicClientWithOpts()
}

// GetBasicAuthClient returns a basic auth grafana API Client
func (s *DashNGoImpl) GetBasicAuthClient() *client.GrafanaHTTPAPI {
grafanaClient, _ := s.getNewClient(func(clientCfg *client.TransportConfig) {
func (s *DashNGoImpl) getDefaultBasicOpts() []NewClientOpts {
return []NewClientOpts{func(clientCfg *client.TransportConfig) {
clientCfg.BasicAuth = url.UserPassword(s.grafanaConf.UserName, s.grafanaConf.Password)
clientCfg.Debug = s.apiDebug
})
return grafanaClient
}}
}

// GetBasicAuthClient returns a basic auth grafana API Client
func (s *DashNGoImpl) GetBasicAuthClient() *client.GrafanaHTTPAPI {
return s.GetBasicClientWithOpts()
}

// ignoreSSLErrors when called replaces the default http legacyClient to ignore invalid SSL issues.
Expand Down
75 changes: 16 additions & 59 deletions internal/service/org_preferences.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package service
import (
"errors"
"fmt"
"log/slog"

"github.com/gosimple/slug"
"github.com/grafana/grafana-openapi-client-go/models"
)

Expand All @@ -15,75 +13,34 @@ func (s *DashNGoImpl) GetOrgPreferences(orgName string) (*models.Preferences, er
if !s.grafanaConf.IsGrafanaAdmin() {
return nil, errors.New("no valid Grafana Admin configured, cannot retrieve Organizations Preferences")
}
f := func() (interface{}, error) {
orgPreferences, err := s.GetClient().OrgPreferences.GetOrgPreferences()
if err != nil {
return nil, err
}
return orgPreferences.GetPayload(), nil
}
result, err := s.scopeIntoOrg(orgName, f)
orgPreferences, err := s.GetBasicClientWithOpts(GetOrgNameClientOpts(orgName)).OrgPreferences.GetOrgPreferences()
if err != nil {
return nil, err
}
return result.(*models.Preferences), nil
return orgPreferences.GetPayload(), nil
}

// scopeIntoOrg changes the organization, performs an operation, and reverts the Org to the previous value.
func (s *DashNGoImpl) scopeIntoOrg(orgName string, runTask func() (interface{}, error)) (interface{}, error) {
currentOrg := s.getAssociatedActiveOrg(s.GetClient())
orgNameBackup := s.grafanaConf.OrganizationName
s.grafanaConf.OrganizationName = orgName
orgEntity, err := s.getOrgIdFromSlug(slug.Make(orgName), false)
if err != nil {
return nil, err
}
defer func() {
s.grafanaConf.OrganizationName = orgNameBackup
// restore scoped Org
err = s.SetUserOrganizations(currentOrg.ID)
if err != nil {
slog.Warn("unable to restore previous Org", slog.Any("err", err))
}
}()

err = s.SetUserOrganizations(orgEntity.OrgID)
if err != nil {
return nil, fmt.Errorf("unable to scope into requested org. %w", err)
// UploadOrgPreferences Updates the preferences for a given organization. Returns error if org is not found.
func (s *DashNGoImpl) UploadOrgPreferences(orgName string, preferenceRequest *models.Preferences) error {
if !s.grafanaConf.IsGrafanaAdmin() {
return errors.New("no valid Grafana Admin configured, cannot update Organizations Preferences")
}

res, err := runTask()
if err != nil {
return nil, err
if preferenceRequest == nil {
return fmt.Errorf("preferences are nil, cannot update")
}

return res, nil
}

// UploadOrgPreferences Updates the preferences for a given organization. Returns error if org is not found.
func (s *DashNGoImpl) UploadOrgPreferences(orgName string, pref *models.Preferences) error {
runTask := func() (interface{}, error) {
if pref == nil {
return nil, fmt.Errorf("preferences are nil, cannot update")
}

update := &models.UpdatePrefsCmd{}
update.HomeDashboardUID = pref.HomeDashboardUID
update.Language = pref.Language
update.Timezone = pref.Timezone
update.Theme = pref.Theme
update.WeekStart = pref.WeekStart
update := &models.UpdatePrefsCmd{}
update.HomeDashboardUID = preferenceRequest.HomeDashboardUID
update.Language = preferenceRequest.Language
update.Timezone = preferenceRequest.Timezone
update.Theme = preferenceRequest.Theme
update.WeekStart = preferenceRequest.WeekStart

status, err := s.GetClient().OrgPreferences.UpdateOrgPreferences(update)
if err != nil {
return nil, err
}
return status, nil
}
_, err := s.scopeIntoOrg(orgName, runTask)
_, err := s.GetBasicClientWithOpts(GetOrgNameClientOpts(orgName)).OrgPreferences.UpdateOrgPreferences(update)
if err != nil {
return err
}
slog.Info("Organization Preferences were updated")

return nil
}

0 comments on commit e9b3f74

Please sign in to comment.