1package backend 2 3import ( 4 "encoding/json" 5 "time" 6 7 "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" 8) 9 10const dataCustomOptionsKey = "grafanaData" 11const secureDataCustomOptionsKey = "grafanaSecureData" 12 13// User represents a Grafana user. 14type User struct { 15 Login string 16 Name string 17 Email string 18 Role string 19} 20 21// AppInstanceSettings represents settings for an app instance. 22// 23// In Grafana an app instance is an app plugin of certain 24// type that have been configured and enabled in a Grafana organization. 25type AppInstanceSettings struct { 26 // JSONData repeats the properties at this level of the object (excluding DataSourceConfig), and also includes any 27 // custom properties associated with the plugin config instance. 28 JSONData json.RawMessage 29 30 // DecryptedSecureJSONData contains key,value pairs where the encrypted configuration plugin instance in Grafana 31 // server have been decrypted before passing them to the plugin. 32 DecryptedSecureJSONData map[string]string 33 34 // Updated is the last time this plugin instance's configuration was updated. 35 Updated time.Time 36} 37 38// HTTPClientOptions creates httpclient.Options based on settings. 39func (s *AppInstanceSettings) HTTPClientOptions() (httpclient.Options, error) { 40 httpSettings, err := parseHTTPSettings(s.JSONData, s.DecryptedSecureJSONData) 41 if err != nil { 42 return httpclient.Options{}, err 43 } 44 45 opts := httpSettings.HTTPClientOptions() 46 setCustomOptionsFromHTTPSettings(&opts, httpSettings) 47 48 return opts, nil 49} 50 51// DataSourceInstanceSettings represents settings for a data source instance. 52// 53// In Grafana a data source instance is a data source plugin of certain 54// type that have been configured and created in a Grafana organization. 55type DataSourceInstanceSettings struct { 56 // ID is the Grafana assigned numeric identifier of the the data source instance. 57 ID int64 58 59 // UID is the Grafana assigned string identifier of the the data source instance. 60 UID string 61 62 // Name is the configured name of the data source instance. 63 Name string 64 65 // URL is the configured URL of a data source instance (e.g. the URL of an API endpoint). 66 URL string 67 68 // User is a configured user for a data source instance. This is not a Grafana user, rather an arbitrary string. 69 User string 70 71 // Database is the configured database for a data source instance. (e.g. the default Database a SQL data source would connect to). 72 Database string 73 74 // BasicAuthEnabled indicates if this data source instance should use basic authentication. 75 BasicAuthEnabled bool 76 77 // BasicAuthUser is the configured user for basic authentication. (e.g. when a data source uses basic 78 // authentication to connect to whatever API it fetches data from). 79 BasicAuthUser string 80 81 // JSONData contains the raw DataSourceConfig as JSON as stored by Grafana server. It repeats the properties in 82 // this object and includes custom properties. 83 JSONData json.RawMessage 84 85 // DecryptedSecureJSONData contains key,value pairs where the encrypted configuration in Grafana server have been 86 // decrypted before passing them to the plugin. 87 DecryptedSecureJSONData map[string]string 88 89 // Updated is the last time the configuration for the data source instance was updated. 90 Updated time.Time 91} 92 93// HTTPClientOptions creates httpclient.Options based on settings. 94func (s *DataSourceInstanceSettings) HTTPClientOptions() (httpclient.Options, error) { 95 httpSettings, err := parseHTTPSettings(s.JSONData, s.DecryptedSecureJSONData) 96 if err != nil { 97 return httpclient.Options{}, err 98 } 99 100 if s.BasicAuthEnabled { 101 httpSettings.BasicAuthEnabled = s.BasicAuthEnabled 102 httpSettings.BasicAuthUser = s.BasicAuthUser 103 httpSettings.BasicAuthPassword = s.DecryptedSecureJSONData["basicAuthPassword"] 104 } else if s.User != "" { 105 httpSettings.BasicAuthEnabled = true 106 httpSettings.BasicAuthUser = s.User 107 httpSettings.BasicAuthPassword = s.DecryptedSecureJSONData["password"] 108 } 109 110 opts := httpSettings.HTTPClientOptions() 111 opts.Labels["datasource_name"] = s.Name 112 opts.Labels["datasource_uid"] = s.UID 113 114 setCustomOptionsFromHTTPSettings(&opts, httpSettings) 115 116 return opts, nil 117} 118 119// PluginContext holds contextual information about a plugin request, such as 120// Grafana organization, user and plugin instance settings. 121type PluginContext struct { 122 // OrgID is The Grafana organization identifier the request originating from. 123 OrgID int64 124 125 // PluginID is the unique identifier of the plugin that the request is for. 126 PluginID string 127 128 // User is the Grafana user making the request. 129 // 130 // Will not be provided if Grafana backend initiated the request, 131 // for example when request is coming from Grafana Alerting. 132 User *User 133 134 // AppInstanceSettings is the configured app instance settings. 135 // 136 // In Grafana an app instance is an app plugin of certain 137 // type that have been configured and enabled in a Grafana organization. 138 // 139 // Will only be set if request targeting an app instance. 140 AppInstanceSettings *AppInstanceSettings 141 142 // DataSourceConfig is the configured data source instance 143 // settings. 144 // 145 // In Grafana a data source instance is a data source plugin of certain 146 // type that have been configured and created in a Grafana organization. 147 // 148 // Will only be set if request targeting a data source instance. 149 DataSourceInstanceSettings *DataSourceInstanceSettings 150} 151 152func setCustomOptionsFromHTTPSettings(opts *httpclient.Options, httpSettings *HTTPSettings) { 153 opts.CustomOptions = map[string]interface{}{} 154 155 if httpSettings.JSONData != nil { 156 opts.CustomOptions[dataCustomOptionsKey] = httpSettings.JSONData 157 } 158 159 if httpSettings.SecureJSONData != nil { 160 opts.CustomOptions[secureDataCustomOptionsKey] = httpSettings.SecureJSONData 161 } 162} 163 164// JSONDataFromHTTPClientOptions extracts JSON data from CustomOptions of httpclient.Options. 165func JSONDataFromHTTPClientOptions(opts httpclient.Options) (res map[string]interface{}) { 166 if opts.CustomOptions == nil { 167 return 168 } 169 170 val, exists := opts.CustomOptions[dataCustomOptionsKey] 171 if !exists { 172 return 173 } 174 175 jsonData, ok := val.(map[string]interface{}) 176 if !ok { 177 return 178 } 179 180 return jsonData 181} 182 183// SecureJSONDataFromHTTPClientOptions extracts secure JSON data from CustomOptions of httpclient.Options. 184func SecureJSONDataFromHTTPClientOptions(opts httpclient.Options) (res map[string]string) { 185 if opts.CustomOptions == nil { 186 return 187 } 188 189 val, exists := opts.CustomOptions[secureDataCustomOptionsKey] 190 if !exists { 191 return 192 } 193 194 secureJSONData, ok := val.(map[string]string) 195 if !ok { 196 return 197 } 198 199 return secureJSONData 200} 201