mirror of https://github.com/grafana/grafana.git
Alerting: Remove usages of ReceiverType (#111508)
* remove usages of ReceiverType
This commit is contained in:
parent
217990ded9
commit
24c10b4fb9
|
|
@ -204,7 +204,7 @@ require (
|
|||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/grafana/alerting v0.0.0-20250915130141-a8ee25091876 // indirect
|
||||
github.com/grafana/alerting v0.0.0-20250925193206-bd061d3d9185 // indirect
|
||||
github.com/grafana/authlib/types v0.0.0-20250917093142-83a502239781 // indirect
|
||||
github.com/grafana/dataplane/sdata v0.0.9 // indirect
|
||||
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect
|
||||
|
|
|
|||
|
|
@ -721,8 +721,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
|||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/grafana/alerting v0.0.0-20250915130141-a8ee25091876 h1:BzoGpzARwRCNOHcqQdYPAFp2LS1pqnkLWhIuDdq1zho=
|
||||
github.com/grafana/alerting v0.0.0-20250915130141-a8ee25091876/go.mod h1:T5sitas9VhVj8/S9LeRLy6H75kTBdh/sCCqHo7gaQI8=
|
||||
github.com/grafana/alerting v0.0.0-20250925193206-bd061d3d9185 h1:R494uXJOz7glN76hJXKjbwu+VBYFsT0CFprsXmdHla0=
|
||||
github.com/grafana/alerting v0.0.0-20250925193206-bd061d3d9185/go.mod h1:T5sitas9VhVj8/S9LeRLy6H75kTBdh/sCCqHo7gaQI8=
|
||||
github.com/grafana/authlib v0.0.0-20250924100039-ea07223cdb6c h1:8GIMe1KclDdfogaeRsiU69Ev2zTF9kmjqjQqqZMzerc=
|
||||
github.com/grafana/authlib v0.0.0-20250924100039-ea07223cdb6c/go.mod h1:C6CmTG6vfiqebjJswKsc6zes+1F/OtTCi6aAtL5Um6A=
|
||||
github.com/grafana/authlib/types v0.0.0-20250917093142-83a502239781 h1:jymmOFIWnW26DeUjFgYEoltI170KeT5r1rI8a/dUf0E=
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -86,7 +86,7 @@ require (
|
|||
github.com/googleapis/gax-go/v2 v2.14.2 // @grafana/grafana-backend-group
|
||||
github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // @grafana/grafana-app-platform-squad
|
||||
github.com/grafana/alerting v0.0.0-20250915130141-a8ee25091876 // @grafana/alerting-backend
|
||||
github.com/grafana/alerting v0.0.0-20250925193206-bd061d3d9185 // @grafana/alerting-backend
|
||||
github.com/grafana/authlib v0.0.0-20250924100039-ea07223cdb6c // @grafana/identity-access-team
|
||||
github.com/grafana/authlib/types v0.0.0-20250917093142-83a502239781 // @grafana/identity-access-team
|
||||
github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -1585,8 +1585,8 @@ github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7Fsg
|
|||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/grafana/alerting v0.0.0-20250915130141-a8ee25091876 h1:BzoGpzARwRCNOHcqQdYPAFp2LS1pqnkLWhIuDdq1zho=
|
||||
github.com/grafana/alerting v0.0.0-20250915130141-a8ee25091876/go.mod h1:T5sitas9VhVj8/S9LeRLy6H75kTBdh/sCCqHo7gaQI8=
|
||||
github.com/grafana/alerting v0.0.0-20250925193206-bd061d3d9185 h1:R494uXJOz7glN76hJXKjbwu+VBYFsT0CFprsXmdHla0=
|
||||
github.com/grafana/alerting v0.0.0-20250925193206-bd061d3d9185/go.mod h1:T5sitas9VhVj8/S9LeRLy6H75kTBdh/sCCqHo7gaQI8=
|
||||
github.com/grafana/authlib v0.0.0-20250924100039-ea07223cdb6c h1:8GIMe1KclDdfogaeRsiU69Ev2zTF9kmjqjQqqZMzerc=
|
||||
github.com/grafana/authlib v0.0.0-20250924100039-ea07223cdb6c/go.mod h1:C6CmTG6vfiqebjJswKsc6zes+1F/OtTCi6aAtL5Um6A=
|
||||
github.com/grafana/authlib/types v0.0.0-20250917093142-83a502239781 h1:jymmOFIWnW26DeUjFgYEoltI170KeT5r1rI8a/dUf0E=
|
||||
|
|
|
|||
|
|
@ -1040,6 +1040,10 @@ github.com/grafana/alerting v0.0.0-20250701210250-cea2d1683945 h1:3imTbxFpZSVI6I
|
|||
github.com/grafana/alerting v0.0.0-20250701210250-cea2d1683945/go.mod h1:gtR7agmxVfJOmNKV/n2ZULgOYTYNL+PDKYB5N48tQ7Q=
|
||||
github.com/grafana/alerting v0.0.0-20250709204613-c5c6f9c1653d/go.mod h1:gtR7agmxVfJOmNKV/n2ZULgOYTYNL+PDKYB5N48tQ7Q=
|
||||
github.com/grafana/alerting v0.0.0-20250911172908-2b26ef8f17eb/go.mod h1:XWqj/rlsy4OV/E9XNNyFn+a7U4GNsSugPb2rDBj9+58=
|
||||
github.com/grafana/alerting v0.0.0-20250923203439-adb598e7d509 h1:8JMtYCClxrxRXsF5jc64GTURZFHJHFK/kzC7joRNTtI=
|
||||
github.com/grafana/alerting v0.0.0-20250923203439-adb598e7d509/go.mod h1:T5sitas9VhVj8/S9LeRLy6H75kTBdh/sCCqHo7gaQI8=
|
||||
github.com/grafana/alerting v0.0.0-20250925193206-bd061d3d9185 h1:R494uXJOz7glN76hJXKjbwu+VBYFsT0CFprsXmdHla0=
|
||||
github.com/grafana/alerting v0.0.0-20250925193206-bd061d3d9185/go.mod h1:T5sitas9VhVj8/S9LeRLy6H75kTBdh/sCCqHo7gaQI8=
|
||||
github.com/grafana/authlib v0.0.0-20250123104008-e99947858901/go.mod h1:/gYfphsNu9v1qYWXxpv1NSvMEMSwvdf8qb8YlgwIRl8=
|
||||
github.com/grafana/authlib v0.0.0-20250909101823-1b466dbd19a1/go.mod h1:C6CmTG6vfiqebjJswKsc6zes+1F/OtTCi6aAtL5Um6A=
|
||||
github.com/grafana/authlib/types v0.0.0-20250120144156-d6737a7dc8f5/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
|
||||
|
|
@ -1074,8 +1078,6 @@ github.com/grafana/grafana-aws-sdk v0.38.2/go.mod h1:j3vi+cXYHEFqjhBGrI6/lw1TNM+
|
|||
github.com/grafana/grafana-aws-sdk v1.0.2 h1:98eBuHYFmgvH0xO9kKf4RBsEsgQRp8EOA/9yhDIpkss=
|
||||
github.com/grafana/grafana-aws-sdk v1.0.2/go.mod h1:hO7q7yWV+t6dmiyJjMa3IbuYnYkBua+G/IAlOPVIYKE=
|
||||
github.com/grafana/grafana-azure-sdk-go/v2 v2.1.6/go.mod h1:V7y2BmsWxS3A9Ohebwn4OiSfJJqi//4JQydQ8fHTduo=
|
||||
github.com/grafana/grafana-google-sdk-go v0.4.2 h1:F44hQF1y6UVJhlJPi+Mz+GCJsioVgezEgPMMEQbUZRo=
|
||||
github.com/grafana/grafana-google-sdk-go v0.4.2/go.mod h1:U73+w9DlbEtUonhQUzERwlXnzWTtfRoyrtKH8d3VY40=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.263.0/go.mod h1:U43Cnrj/9DNYyvFcNdeUWNjMXTKNB0jcTcQGpWKd2gw=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.267.0/go.mod h1:OuwS4c/JYgn0rr/w5zhJBpLo4gKm/vw15RsfpYAvK9Q=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.269.1/go.mod h1:yv2KbO4mlr9WuDK2f+2gHAMTwwLmLuqaEnrPXTRU+OI=
|
||||
|
|
|
|||
|
|
@ -206,8 +206,10 @@ func (f *AlertmanagerApiHandler) handleRoutePostAlertingConfig(ctx *contextmodel
|
|||
if err != nil {
|
||||
return errorToResponse(err)
|
||||
}
|
||||
if !body.AlertmanagerConfig.ReceiverType().Can(apimodels.AlertmanagerReceiverType) {
|
||||
return errorToResponse(backendTypeDoesNotMatchPayloadTypeError(apimodels.AlertmanagerBackend, body.AlertmanagerConfig.ReceiverType().String()))
|
||||
for _, p := range body.AlertmanagerConfig.Receivers {
|
||||
if p.HasGrafanaIntegrations() {
|
||||
return errorToResponse(backendTypeDoesNotMatchPayloadTypeError(apimodels.AlertmanagerBackend, apimodels.GrafanaBackend.String()))
|
||||
}
|
||||
}
|
||||
return s.RoutePostAlertingConfig(ctx, body)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -267,7 +267,6 @@ type (
|
|||
ObjectMatchers = definition.ObjectMatchers
|
||||
PostableApiReceiver = definition.PostableApiReceiver
|
||||
PostableGrafanaReceivers = definition.PostableGrafanaReceivers
|
||||
ReceiverType = definition.ReceiverType
|
||||
)
|
||||
|
||||
type MergeResult definition.MergeResult
|
||||
|
|
@ -295,9 +294,6 @@ func (m MergeResult) LogContext() []any {
|
|||
}
|
||||
|
||||
const (
|
||||
GrafanaReceiverType = definition.GrafanaReceiverType
|
||||
AlertmanagerReceiverType = definition.AlertmanagerReceiverType
|
||||
|
||||
errInvalidExtraConfigurationMsg = "Invalid Alertmanager configuration: {{.Public.Error}}"
|
||||
)
|
||||
|
||||
|
|
@ -870,12 +866,8 @@ func (c *PostableUserConfig) validate() error {
|
|||
func (c *PostableUserConfig) GetGrafanaReceiverMap() map[string]*PostableGrafanaReceiver {
|
||||
UIDs := make(map[string]*PostableGrafanaReceiver)
|
||||
for _, r := range c.AlertmanagerConfig.Receivers {
|
||||
switch r.Type() {
|
||||
case GrafanaReceiverType:
|
||||
for _, gr := range r.GrafanaManagedReceivers {
|
||||
UIDs[gr.UID] = gr
|
||||
}
|
||||
default:
|
||||
for _, gr := range r.GrafanaManagedReceivers {
|
||||
UIDs[gr.UID] = gr
|
||||
}
|
||||
}
|
||||
return UIDs
|
||||
|
|
@ -975,12 +967,8 @@ func (c *GettableUserConfig) MarshalJSON() ([]byte, error) {
|
|||
func (c *GettableUserConfig) GetGrafanaReceiverMap() map[string]*GettableGrafanaReceiver {
|
||||
UIDs := make(map[string]*GettableGrafanaReceiver)
|
||||
for _, r := range c.AlertmanagerConfig.Receivers {
|
||||
switch r.Type() {
|
||||
case GrafanaReceiverType:
|
||||
for _, gr := range r.GrafanaManagedReceivers {
|
||||
UIDs[gr.UID] = gr
|
||||
}
|
||||
default:
|
||||
for _, gr := range r.GrafanaManagedReceivers {
|
||||
UIDs[gr.UID] = gr
|
||||
}
|
||||
}
|
||||
return UIDs
|
||||
|
|
@ -1097,47 +1085,7 @@ type GettableApiReceiver struct {
|
|||
|
||||
func (r *GettableApiReceiver) UnmarshalJSON(b []byte) error {
|
||||
type plain GettableApiReceiver
|
||||
if err := json.Unmarshal(b, (*plain)(r)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hasGrafanaReceivers := len(r.GrafanaManagedReceivers) > 0
|
||||
|
||||
if hasGrafanaReceivers {
|
||||
if len(r.EmailConfigs) > 0 {
|
||||
return fmt.Errorf("cannot have both Alertmanager EmailConfigs & Grafana receivers together")
|
||||
}
|
||||
if len(r.PagerdutyConfigs) > 0 {
|
||||
return fmt.Errorf("cannot have both Alertmanager PagerdutyConfigs & Grafana receivers together")
|
||||
}
|
||||
if len(r.SlackConfigs) > 0 {
|
||||
return fmt.Errorf("cannot have both Alertmanager SlackConfigs & Grafana receivers together")
|
||||
}
|
||||
if len(r.WebhookConfigs) > 0 {
|
||||
return fmt.Errorf("cannot have both Alertmanager WebhookConfigs & Grafana receivers together")
|
||||
}
|
||||
if len(r.OpsGenieConfigs) > 0 {
|
||||
return fmt.Errorf("cannot have both Alertmanager OpsGenieConfigs & Grafana receivers together")
|
||||
}
|
||||
if len(r.WechatConfigs) > 0 {
|
||||
return fmt.Errorf("cannot have both Alertmanager WechatConfigs & Grafana receivers together")
|
||||
}
|
||||
if len(r.PushoverConfigs) > 0 {
|
||||
return fmt.Errorf("cannot have both Alertmanager PushoverConfigs & Grafana receivers together")
|
||||
}
|
||||
if len(r.VictorOpsConfigs) > 0 {
|
||||
return fmt.Errorf("cannot have both Alertmanager VictorOpsConfigs & Grafana receivers together")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *GettableApiReceiver) Type() ReceiverType {
|
||||
if len(r.GrafanaManagedReceivers) > 0 {
|
||||
return GrafanaReceiverType
|
||||
}
|
||||
return AlertmanagerReceiverType
|
||||
return json.Unmarshal(b, (*plain)(r))
|
||||
}
|
||||
|
||||
func (r *GettableApiReceiver) GetName() string {
|
||||
|
|
|
|||
|
|
@ -452,26 +452,22 @@ func assignReceiverConfigsUIDs(c []*definitions.PostableApiReceiver) error {
|
|||
seenUIDs := make(map[string]struct{})
|
||||
// encrypt secure settings for storing them in DB
|
||||
for _, r := range c {
|
||||
switch r.Type() {
|
||||
case definitions.GrafanaReceiverType:
|
||||
for _, gr := range r.GrafanaManagedReceivers {
|
||||
if gr.UID == "" {
|
||||
retries := 5
|
||||
for i := 0; i < retries; i++ {
|
||||
gen := util.GenerateShortUID()
|
||||
_, ok := seenUIDs[gen]
|
||||
if !ok {
|
||||
gr.UID = gen
|
||||
break
|
||||
}
|
||||
}
|
||||
if gr.UID == "" {
|
||||
return fmt.Errorf("all %d attempts to generate UID for receiver have failed; please retry", retries)
|
||||
for _, gr := range r.GrafanaManagedReceivers {
|
||||
if gr.UID == "" {
|
||||
retries := 5
|
||||
for i := 0; i < retries; i++ {
|
||||
gen := util.GenerateShortUID()
|
||||
_, ok := seenUIDs[gen]
|
||||
if !ok {
|
||||
gr.UID = gen
|
||||
break
|
||||
}
|
||||
}
|
||||
seenUIDs[gr.UID] = struct{}{}
|
||||
if gr.UID == "" {
|
||||
return fmt.Errorf("all %d attempts to generate UID for receiver have failed; please retry", retries)
|
||||
}
|
||||
}
|
||||
default:
|
||||
seenUIDs[gr.UID] = struct{}{}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -87,81 +87,77 @@ func EncryptReceiverConfigSettings(c []*definitions.PostableApiReceiver, encrypt
|
|||
func encryptReceiverConfigs(c []*definitions.PostableApiReceiver, encrypt definitions.EncryptFn, encryptExisting bool) error {
|
||||
// encrypt secure settings for storing them in DB
|
||||
for _, r := range c {
|
||||
switch r.Type() {
|
||||
case definitions.GrafanaReceiverType:
|
||||
for _, gr := range r.GrafanaManagedReceivers {
|
||||
if encryptExisting {
|
||||
for k, v := range gr.SecureSettings {
|
||||
encryptedData, err := encrypt(context.Background(), []byte(v))
|
||||
for _, gr := range r.GrafanaManagedReceivers {
|
||||
if encryptExisting {
|
||||
for k, v := range gr.SecureSettings {
|
||||
encryptedData, err := encrypt(context.Background(), []byte(v))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to encrypt secure settings: %w", err)
|
||||
}
|
||||
gr.SecureSettings[k] = base64.StdEncoding.EncodeToString(encryptedData)
|
||||
}
|
||||
}
|
||||
|
||||
if len(gr.Settings) > 0 {
|
||||
// We need to parse the settings to check for secret keys. If we find any, we encrypt them and
|
||||
// store them in SecureSettings. This can happen from incorrect configuration or when an integration
|
||||
// definition is updated to make a field secure.
|
||||
settings := make(map[string]any)
|
||||
if err := json.Unmarshal(gr.Settings, &settings); err != nil {
|
||||
return fmt.Errorf("integration '%s' of receiver '%s' has settings that cannot be parsed as JSON: %w", gr.Type, gr.Name, err)
|
||||
}
|
||||
|
||||
secretKeys, err := channels_config.GetSecretKeysForContactPointType(gr.Type, channels_config.V1)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get secret keys for contact point type %s: %w", gr.Type, err)
|
||||
}
|
||||
|
||||
secureSettings := gr.SecureSettings
|
||||
if secureSettings == nil {
|
||||
secureSettings = make(map[string]string)
|
||||
}
|
||||
|
||||
settingsChanged := false
|
||||
secureSettingsChanged := false
|
||||
for _, secretKey := range secretKeys {
|
||||
settingsValue, ok := settings[secretKey]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Secrets should not be stored in settings regardless.
|
||||
delete(settings, secretKey)
|
||||
settingsChanged = true
|
||||
|
||||
// If the secret is already encrypted, we don't need to encrypt it again.
|
||||
if _, ok := secureSettings[secretKey]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if strVal, isString := settingsValue.(string); isString {
|
||||
encrypted, err := encrypt(context.Background(), []byte(strVal))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to encrypt secure settings: %w", err)
|
||||
}
|
||||
gr.SecureSettings[k] = base64.StdEncoding.EncodeToString(encryptedData)
|
||||
secureSettings[secretKey] = base64.StdEncoding.EncodeToString(encrypted)
|
||||
secureSettingsChanged = true
|
||||
}
|
||||
}
|
||||
|
||||
if len(gr.Settings) > 0 {
|
||||
// We need to parse the settings to check for secret keys. If we find any, we encrypt them and
|
||||
// store them in SecureSettings. This can happen from incorrect configuration or when an integration
|
||||
// definition is updated to make a field secure.
|
||||
settings := make(map[string]any)
|
||||
if err := json.Unmarshal(gr.Settings, &settings); err != nil {
|
||||
return fmt.Errorf("integration '%s' of receiver '%s' has settings that cannot be parsed as JSON: %w", gr.Type, gr.Name, err)
|
||||
}
|
||||
|
||||
secretKeys, err := channels_config.GetSecretKeysForContactPointType(gr.Type, channels_config.V1)
|
||||
// Defensive checks to limit the risk of unintentional edge case changes in this legacy API.
|
||||
if settingsChanged {
|
||||
// If we removed any secret keys from settings, we need to save the updated settings.
|
||||
jsonBytes, err := json.Marshal(settings)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get secret keys for contact point type %s: %w", gr.Type, err)
|
||||
}
|
||||
|
||||
secureSettings := gr.SecureSettings
|
||||
if secureSettings == nil {
|
||||
secureSettings = make(map[string]string)
|
||||
}
|
||||
|
||||
settingsChanged := false
|
||||
secureSettingsChanged := false
|
||||
for _, secretKey := range secretKeys {
|
||||
settingsValue, ok := settings[secretKey]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Secrets should not be stored in settings regardless.
|
||||
delete(settings, secretKey)
|
||||
settingsChanged = true
|
||||
|
||||
// If the secret is already encrypted, we don't need to encrypt it again.
|
||||
if _, ok := secureSettings[secretKey]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if strVal, isString := settingsValue.(string); isString {
|
||||
encrypted, err := encrypt(context.Background(), []byte(strVal))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to encrypt secure settings: %w", err)
|
||||
}
|
||||
secureSettings[secretKey] = base64.StdEncoding.EncodeToString(encrypted)
|
||||
secureSettingsChanged = true
|
||||
}
|
||||
}
|
||||
|
||||
// Defensive checks to limit the risk of unintentional edge case changes in this legacy API.
|
||||
if settingsChanged {
|
||||
// If we removed any secret keys from settings, we need to save the updated settings.
|
||||
jsonBytes, err := json.Marshal(settings)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gr.Settings = jsonBytes
|
||||
}
|
||||
if secureSettingsChanged {
|
||||
// If we added any secure settings, we need to save the updated secure settings.
|
||||
gr.SecureSettings = secureSettings
|
||||
return err
|
||||
}
|
||||
gr.Settings = jsonBytes
|
||||
}
|
||||
if secureSettingsChanged {
|
||||
// If we added any secure settings, we need to save the updated secure settings.
|
||||
gr.SecureSettings = secureSettings
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
Loading…
Reference in New Issue