diff --git a/changes/19365-disable-ai-migration b/changes/19365-disable-ai-migration new file mode 100644 index 0000000000..41e096d242 --- /dev/null +++ b/changes/19365-disable-ai-migration @@ -0,0 +1 @@ +* Disabled AI features on non-new installations upgrading from < 4.50.X to >= 4.51.X. diff --git a/server/datastore/mysql/migrations/tables/20240430111727_CleanupQueryResults.go b/server/datastore/mysql/migrations/tables/20240430111727_CleanupQueryResults.go index 063a150617..c0be097472 100644 --- a/server/datastore/mysql/migrations/tables/20240430111727_CleanupQueryResults.go +++ b/server/datastore/mysql/migrations/tables/20240430111727_CleanupQueryResults.go @@ -2,7 +2,10 @@ package tables import ( "database/sql" + "encoding/json" "fmt" + + "github.com/pkg/errors" ) func init() { @@ -22,6 +25,67 @@ func Up_20240430111727(tx *sql.Tx) error { if err != nil { return fmt.Errorf("failed to delete query_results %w", err) } + + // + // The following "fix" was introduced after this migration was released in 4.50.0. + // We are adding it here to disable the AI features (set ai_features_disabled=true) + // for non-new installations that are upgrading from < 4.50.0 using the new version + // of this migration to be released in 4.51.X. + // + if err := fixDisableAIForNonNewInstallation(tx); err != nil { + return fmt.Errorf("failed to update ai_features_disabled: %w", err) + } + + return nil +} + +func fixDisableAIForNonNewInstallation(tx *sql.Tx) error { + var usersCount int + row := tx.QueryRow(`SELECT COUNT(*) FROM users;`) + if err := row.Scan(&usersCount); err != nil { + return fmt.Errorf("select count users: %w", err) + } + if usersCount == 0 { + return nil + } + + // + // At least a "setup" user was configured, + // thus we assume this is not a new installation. + // + + var raw json.RawMessage + row = tx.QueryRow(`SELECT json_value FROM app_config_json LIMIT 1;`) + if err := row.Scan(&raw); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil + } + return fmt.Errorf("select app_config_json: %w", err) + } + + var config map[string]interface{} + if err := json.Unmarshal(raw, &config); err != nil { + return fmt.Errorf("unmarshal appconfig: %w", err) + } + + ss, ok := config["server_settings"] + if !ok { + return errors.New("missing server_settings") + } + serverSettings, ok := ss.(map[string]interface{}) + if !ok { + return fmt.Errorf("invalid type for server_settings: %T", ss) + } + serverSettings["ai_features_disabled"] = true + + b, err := json.Marshal(config) + if err != nil { + return fmt.Errorf("marshal updated appconfig: %w", err) + } + if _, err := tx.Exec(`UPDATE app_config_json SET json_value = ? WHERE id = 1;`, b); err != nil { + return fmt.Errorf("update app_config_json: %w", err) + } + return nil }