diff --git a/app/graphql/mutations/user_preferences/update.rb b/app/graphql/mutations/user_preferences/update.rb
index 111bd2587757e78ad55bbd457249a23b0e959f50..8c4c545aa18291bc9a27012d9494a00efc4da55d 100644
--- a/app/graphql/mutations/user_preferences/update.rb
+++ b/app/graphql/mutations/user_preferences/update.rb
@@ -6,24 +6,28 @@ class Update < BaseMutation
graphql_name 'UserPreferencesUpdate'
NON_NULLABLE_ARGS = [
+ :extensions_marketplace_opt_in_status,
:use_web_ide_extension_marketplace,
:visibility_pipeline_id_type
].freeze
+ argument :extensions_marketplace_opt_in_status, Types::ExtensionsMarketplaceOptInStatusEnum,
+ required: false,
+ description: 'Status of the Web IDE Extension Marketplace opt-in for the user.'
argument :issues_sort, Types::IssueSortEnum,
- required: false,
- description: 'Sort order for issue lists.'
+ required: false,
+ description: 'Sort order for issue lists.'
argument :use_web_ide_extension_marketplace, GraphQL::Types::Boolean,
- required: false,
- description: 'Whether Web IDE Extension Marketplace is enabled for the user.'
+ required: false,
+ description: 'Whether Web IDE Extension Marketplace is enabled for the user.'
argument :visibility_pipeline_id_type, Types::VisibilityPipelineIdTypeEnum,
- required: false,
- description: 'Determines whether the pipeline list shows ID or IID.'
+ required: false,
+ description: 'Determines whether the pipeline list shows ID or IID.'
field :user_preferences,
- Types::UserPreferencesType,
- null: true,
- description: 'User preferences after mutation.'
+ Types::UserPreferencesType,
+ null: true,
+ description: 'User preferences after mutation.'
def resolve(**attributes)
attributes.delete_if { |key, value| NON_NULLABLE_ARGS.include?(key) && value.nil? }
diff --git a/app/graphql/types/extensions_marketplace_opt_in_status_enum.rb b/app/graphql/types/extensions_marketplace_opt_in_status_enum.rb
new file mode 100644
index 0000000000000000000000000000000000000000..4ea4b55a9923d03897350ba1600e61655b7307c9
--- /dev/null
+++ b/app/graphql/types/extensions_marketplace_opt_in_status_enum.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Types
+ class ExtensionsMarketplaceOptInStatusEnum < BaseEnum
+ graphql_name 'ExtensionsMarketplaceOptInStatus'
+ description 'Values for status of the Web IDE Extension Marketplace opt-in for the user'
+
+ UserPreference.extensions_marketplace_opt_in_statuses.each_key do |field|
+ value field.upcase, value: field, description: "Web IDE Extension Marketplace opt-in status: #{field.upcase}."
+ end
+ end
+end
diff --git a/app/graphql/types/user_preferences_type.rb b/app/graphql/types/user_preferences_type.rb
index e9ac3a28a5303c6a60996bcddcffcba2dd9becce..4d695a6e967cc9e2d616cbff48e63c9f23f66773 100644
--- a/app/graphql/types/user_preferences_type.rb
+++ b/app/graphql/types/user_preferences_type.rb
@@ -6,6 +6,10 @@ module Types
class UserPreferencesType < BaseObject
graphql_name 'UserPreferences'
+ field :extensions_marketplace_opt_in_status, Types::ExtensionsMarketplaceOptInStatusEnum,
+ description: 'Status of the Web IDE Extension Marketplace opt-in for the user.',
+ null: false
+
field :issues_sort, Types::IssueSortEnum,
description: 'Sort order for issue lists.',
null: true
@@ -16,7 +20,8 @@ class UserPreferencesType < BaseObject
field :use_web_ide_extension_marketplace, GraphQL::Types::Boolean,
description: 'Whether Web IDE Extension Marketplace is enabled for the user.',
- null: false
+ null: false,
+ deprecated: { reason: 'Use `extensions_marketplace_opt_in_status` instead', milestone: '16.11' }
def issues_sort
object.issues_sort.to_sym
diff --git a/app/models/concerns/enums/web_ide/extensions_marketplace_opt_in_status.rb b/app/models/concerns/enums/web_ide/extensions_marketplace_opt_in_status.rb
new file mode 100644
index 0000000000000000000000000000000000000000..44e63dcaa27f7baaac8916fc80f2a5ab7ff3e355
--- /dev/null
+++ b/app/models/concerns/enums/web_ide/extensions_marketplace_opt_in_status.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Enums
+ module WebIde
+ module ExtensionsMarketplaceOptInStatus
+ def self.statuses
+ { unset: 0, enabled: 1, disabled: 2 }
+ end
+ end
+ end
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index c5baae3957bb83927513819e10ac22ed9a442fb6..790f77d86d200c3c1f9c5e5d8582bc022ca2cb54 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -408,6 +408,7 @@ def update_tracked_fields!(request)
:sourcegraph_enabled, :sourcegraph_enabled=,
:gitpod_enabled, :gitpod_enabled=,
:use_web_ide_extension_marketplace, :use_web_ide_extension_marketplace=,
+ :extensions_marketplace_opt_in_status, :extensions_marketplace_opt_in_status=,
:setup_for_company, :setup_for_company=,
:project_shortcut_buttons, :project_shortcut_buttons=,
:keyboard_shortcuts_enabled, :keyboard_shortcuts_enabled=,
diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb
index caedf08fa44a52e7a96b0882aac78268cd42241a..19a7601be32783d02b083a6e8b695194737831dd 100644
--- a/app/models/user_preference.rb
+++ b/app/models/user_preference.rb
@@ -42,6 +42,7 @@ class UserPreference < MainClusterwide::ApplicationRecord
attribute :use_web_ide_extension_marketplace, default: false
enum visibility_pipeline_id_type: { id: 0, iid: 1 }
+ enum extensions_marketplace_opt_in_status: Enums::WebIde::ExtensionsMarketplaceOptInStatus.statuses
class << self
def notes_filters
diff --git a/db/migrate/20240410000000_add_extensions_marketplace_opt_in_status_to_user_preferences.rb b/db/migrate/20240410000000_add_extensions_marketplace_opt_in_status_to_user_preferences.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d81193d2a5da89eb3516da496c04309af3b06cfe
--- /dev/null
+++ b/db/migrate/20240410000000_add_extensions_marketplace_opt_in_status_to_user_preferences.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddExtensionsMarketplaceOptInStatusToUserPreferences < Gitlab::Database::Migration[2.2]
+ milestone '16.11'
+
+ def change
+ add_column :user_preferences, :extensions_marketplace_opt_in_status, :smallint, default: 0, null: false
+ end
+end
diff --git a/db/schema_migrations/20240410000000 b/db/schema_migrations/20240410000000
new file mode 100644
index 0000000000000000000000000000000000000000..48b31e3a3bcf3ba828ac2d63f709f69b86b2557e
--- /dev/null
+++ b/db/schema_migrations/20240410000000
@@ -0,0 +1 @@
+2f045332b7600514f8adeea441afca3c5cd8eddd5a7fab261e48fc373046ead1
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 25dfd0b1f3ca891ea04ca1501520b0ba53761109..42af8a3731642c91fda2486739b815543e958196 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -17089,6 +17089,7 @@ CREATE TABLE user_preferences (
time_display_format smallint DEFAULT 0 NOT NULL,
home_organization_id bigint,
use_web_ide_extension_marketplace boolean DEFAULT false NOT NULL,
+ extensions_marketplace_opt_in_status smallint DEFAULT 0 NOT NULL,
CONSTRAINT check_1d670edc68 CHECK ((time_display_relative IS NOT NULL)),
CONSTRAINT check_89bf269f41 CHECK ((char_length(diffs_deletion_color) <= 7)),
CONSTRAINT check_b22446f91a CHECK ((render_whitespace_in_code IS NOT NULL)),
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 0056ca079ed6c8ab1f451df48e4eba7c5eec9658..bf9b89873fa39c5cf4f6d3ff465effd1396daf54 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -8698,6 +8698,7 @@ Input type: `UserPreferencesUpdateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `extensionsMarketplaceOptInStatus` | [`ExtensionsMarketplaceOptInStatus`](#extensionsmarketplaceoptinstatus) | Status of the Web IDE Extension Marketplace opt-in for the user. |
| `issuesSort` | [`IssueSort`](#issuesort) | Sort order for issue lists. |
| `useWebIdeExtensionMarketplace` | [`Boolean`](#boolean) | Whether Web IDE Extension Marketplace is enabled for the user. |
| `visibilityPipelineIdType` | [`VisibilityPipelineIdType`](#visibilitypipelineidtype) | Determines whether the pipeline list shows ID or IID. |
@@ -29669,8 +29670,9 @@ fields relate to interactions between the two entities.
| Name | Type | Description |
| ---- | ---- | ----------- |
+| `extensionsMarketplaceOptInStatus` | [`ExtensionsMarketplaceOptInStatus!`](#extensionsmarketplaceoptinstatus) | Status of the Web IDE Extension Marketplace opt-in for the user. |
| `issuesSort` | [`IssueSort`](#issuesort) | Sort order for issue lists. |
-| `useWebIdeExtensionMarketplace` | [`Boolean!`](#boolean) | Whether Web IDE Extension Marketplace is enabled for the user. |
+| `useWebIdeExtensionMarketplace` **{warning-solid}** | [`Boolean!`](#boolean) | **Deprecated** in GitLab 16.11. Use `extensions_marketplace_opt_in_status` instead. |
| `visibilityPipelineIdType` | [`VisibilityPipelineIdType`](#visibilitypipelineidtype) | Determines whether the pipeline list shows ID or IID. |
### `UserStatus`
@@ -32100,6 +32102,16 @@ Event action.
| `REOPENED` | Reopened action. |
| `UPDATED` | Updated action. |
+### `ExtensionsMarketplaceOptInStatus`
+
+Values for status of the Web IDE Extension Marketplace opt-in for the user.
+
+| Value | Description |
+| ----- | ----------- |
+| `DISABLED` | Web IDE Extension Marketplace opt-in status: DISABLED. |
+| `ENABLED` | Web IDE Extension Marketplace opt-in status: ENABLED. |
+| `UNSET` | Web IDE Extension Marketplace opt-in status: UNSET. |
+
### `FindingReportsComparerStatus`
Report comparison status.
diff --git a/spec/graphql/types/extensions_marketplace_opt_in_status_enum_spec.rb b/spec/graphql/types/extensions_marketplace_opt_in_status_enum_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..84199f443b21e6a99640a5899e95f81ee1a03102
--- /dev/null
+++ b/spec/graphql/types/extensions_marketplace_opt_in_status_enum_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::ExtensionsMarketplaceOptInStatusEnum, feature_category: :web_ide do
+ specify { expect(described_class.graphql_name).to eq('ExtensionsMarketplaceOptInStatus') }
+
+ it 'exposes all the existing extensions_marketplace_opt_in_status values' do
+ expect(described_class.values.keys).to contain_exactly('UNSET', 'ENABLED', 'DISABLED')
+ end
+end
diff --git a/spec/graphql/types/user_preferences_type_spec.rb b/spec/graphql/types/user_preferences_type_spec.rb
index 87fac17a5ba6b7d21457950f8645009716152b18..1db51d27b221dd9abc891a93cb513405d4dffada 100644
--- a/spec/graphql/types/user_preferences_type_spec.rb
+++ b/spec/graphql/types/user_preferences_type_spec.rb
@@ -10,6 +10,7 @@
issues_sort
visibility_pipeline_id_type
use_web_ide_extension_marketplace
+ extensions_marketplace_opt_in_status
]
expect(described_class).to have_graphql_fields(*expected_fields)
diff --git a/spec/models/user_preference_spec.rb b/spec/models/user_preference_spec.rb
index 8852c14c1aadb3cb3795b09edbee4310e5d6a2fb..efcd1b620e1bc1bb38d3adb32c87b6a0358e2590 100644
--- a/spec/models/user_preference_spec.rb
+++ b/spec/models/user_preference_spec.rb
@@ -73,6 +73,19 @@
it { is_expected.to define_enum_for(:visibility_pipeline_id_type).with_values(id: 0, iid: 1) }
end
+ describe 'extensions_marketplace_opt_in_status' do
+ it 'is set to 0 by default' do
+ pref = described_class.new
+
+ expect(pref.extensions_marketplace_opt_in_status).to eq('unset')
+ end
+
+ it do
+ is_expected
+ .to define_enum_for(:extensions_marketplace_opt_in_status).with_values(unset: 0, enabled: 1, disabled: 2)
+ end
+ end
+
describe 'user belongs to the home organization' do
let_it_be(:organization) { create(:organization) }
diff --git a/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb b/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb
index b1cd3259eebe8ffab06e127dde36ccaf61ad45af..63a3a48fbd60deafff8d3951526b92ddd9061462 100644
--- a/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb
@@ -11,6 +11,7 @@
let(:input) do
{
+ 'extensionsMarketplaceOptInStatus' => 'ENABLED',
'issuesSort' => sort_value,
'visibilityPipelineIdType' => 'IID',
'useWebIdeExtensionMarketplace' => true
@@ -25,11 +26,13 @@
post_graphql_mutation(mutation, current_user: current_user)
expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['userPreferences']['extensionsMarketplaceOptInStatus']).to eq('ENABLED')
expect(mutation_response['userPreferences']['issuesSort']).to eq(sort_value)
expect(mutation_response['userPreferences']['visibilityPipelineIdType']).to eq('IID')
expect(mutation_response['userPreferences']['useWebIdeExtensionMarketplace']).to eq(true)
expect(current_user.user_preference.persisted?).to eq(true)
+ expect(current_user.user_preference.extensions_marketplace_opt_in_status).to eq('enabled')
expect(current_user.user_preference.issues_sort).to eq(Types::IssueSortEnum.values[sort_value].value.to_s)
expect(current_user.user_preference.visibility_pipeline_id_type).to eq('iid')
expect(current_user.user_preference.use_web_ide_extension_marketplace).to eq(true)
@@ -39,6 +42,7 @@
context 'when user has existing preference' do
let(:init_user_preference) do
{
+ extensions_marketplace_opt_in_status: 'enabled',
issues_sort: Types::IssueSortEnum.values['TITLE_DESC'].value,
visibility_pipeline_id_type: 'id',
use_web_ide_extension_marketplace: true
@@ -65,6 +69,7 @@
context 'when input has nil attributes' do
let(:input) do
{
+ 'extensionsMarketplaceOptInStatus' => nil,
'issuesSort' => nil,
'visibilityPipelineIdType' => nil,
'useWebIdeExtensionMarketplace' => nil
@@ -80,6 +85,7 @@
# These are nullable and are exepcted to change
issues_sort: nil,
# These should not have changed
+ extensions_marketplace_opt_in_status: init_user_preference[:extensions_marketplace_opt_in_status],
visibility_pipeline_id_type: init_user_preference[:visibility_pipeline_id_type],
use_web_ide_extension_marketplace: init_user_preference[:use_web_ide_extension_marketplace]
})