Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing Org scoping to rely on HTTP header rather for Org Preferences #294

Merged
merged 1 commit into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
Loading