diff --git a/app/graphql/types/ide_type.rb b/app/graphql/types/ide_type.rb new file mode 100644 index 0000000000000000000000000000000000000000..34447577f23f00b886a5f28531116dcd1f993148 --- /dev/null +++ b/app/graphql/types/ide_type.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Types + class IdeType < BaseObject + graphql_name 'Ide' + description 'IDE settings and feature flags.' + + authorize :read_user + + field :code_suggestions_enabled, GraphQL::Types::Boolean, null: false, + description: 'Indicates whether AI assisted code suggestions are enabled.' + + def code_suggestions_enabled + object.can?(:access_code_suggestions) + end + end +end diff --git a/app/graphql/types/user_interface.rb b/app/graphql/types/user_interface.rb index 0a67cdf749ed78662a0ea8d8be95d9a2ddaa740c..9e5f6810aca6fa3a31444917b59cb493b568e49c 100644 --- a/app/graphql/types/user_interface.rb +++ b/app/graphql/types/user_interface.rb @@ -202,6 +202,12 @@ module UserInterface null: true, description: 'Pronouns of the user.' + field :ide, + type: Types::IdeType, + null: true, + description: 'IDE settings.', + method: :itself + definition_methods do def resolve_type(object, context) # in the absence of other information, we cannot tell - just default to diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 456a396284ad144eb4314a401e70e5d6a5023573..aa2607e259bdcb1aa86995de4392e9475390d5e2 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -17005,6 +17005,16 @@ Helm file metadata. | <a id="helmfilemetadatametadata"></a>`metadata` | [`PackageHelmMetadataType!`](#packagehelmmetadatatype) | Metadata of the Helm chart. | | <a id="helmfilemetadataupdatedat"></a>`updatedAt` | [`Time!`](#time) | Date of most recent update. | +### `Ide` + +IDE settings and feature flags. + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="idecodesuggestionsenabled"></a>`codeSuggestionsEnabled` | [`Boolean!`](#boolean) | Indicates whether AI assisted code suggestions are enabled. | + ### `IncidentManagementOncallRotation` Describes an incident management on-call rotation. @@ -17859,6 +17869,7 @@ A user assigned to a merge request. | <a id="mergerequestassigneegroupcount"></a>`groupCount` | [`Int`](#int) | Group count for the user. | | <a id="mergerequestassigneegroupmemberships"></a>`groupMemberships` | [`GroupMemberConnection`](#groupmemberconnection) | Group memberships of the user. (see [Connections](#connections)) | | <a id="mergerequestassigneeid"></a>`id` | [`ID!`](#id) | ID of the user. | +| <a id="mergerequestassigneeide"></a>`ide` | [`Ide`](#ide) | IDE settings. | | <a id="mergerequestassigneejobtitle"></a>`jobTitle` | [`String`](#string) | Job title of the user. | | <a id="mergerequestassigneelinkedin"></a>`linkedin` | [`String`](#string) | LinkedIn profile name of the user. | | <a id="mergerequestassigneelocation"></a>`location` | [`String`](#string) | Location of the user. | @@ -18138,6 +18149,7 @@ The author of the merge request. | <a id="mergerequestauthorgroupcount"></a>`groupCount` | [`Int`](#int) | Group count for the user. | | <a id="mergerequestauthorgroupmemberships"></a>`groupMemberships` | [`GroupMemberConnection`](#groupmemberconnection) | Group memberships of the user. (see [Connections](#connections)) | | <a id="mergerequestauthorid"></a>`id` | [`ID!`](#id) | ID of the user. | +| <a id="mergerequestauthoride"></a>`ide` | [`Ide`](#ide) | IDE settings. | | <a id="mergerequestauthorjobtitle"></a>`jobTitle` | [`String`](#string) | Job title of the user. | | <a id="mergerequestauthorlinkedin"></a>`linkedin` | [`String`](#string) | LinkedIn profile name of the user. | | <a id="mergerequestauthorlocation"></a>`location` | [`String`](#string) | Location of the user. | @@ -18464,6 +18476,7 @@ A user participating in a merge request. | <a id="mergerequestparticipantgroupcount"></a>`groupCount` | [`Int`](#int) | Group count for the user. | | <a id="mergerequestparticipantgroupmemberships"></a>`groupMemberships` | [`GroupMemberConnection`](#groupmemberconnection) | Group memberships of the user. (see [Connections](#connections)) | | <a id="mergerequestparticipantid"></a>`id` | [`ID!`](#id) | ID of the user. | +| <a id="mergerequestparticipantide"></a>`ide` | [`Ide`](#ide) | IDE settings. | | <a id="mergerequestparticipantjobtitle"></a>`jobTitle` | [`String`](#string) | Job title of the user. | | <a id="mergerequestparticipantlinkedin"></a>`linkedin` | [`String`](#string) | LinkedIn profile name of the user. | | <a id="mergerequestparticipantlocation"></a>`location` | [`String`](#string) | Location of the user. | @@ -18778,6 +18791,7 @@ A user assigned to a merge request as a reviewer. | <a id="mergerequestreviewergroupcount"></a>`groupCount` | [`Int`](#int) | Group count for the user. | | <a id="mergerequestreviewergroupmemberships"></a>`groupMemberships` | [`GroupMemberConnection`](#groupmemberconnection) | Group memberships of the user. (see [Connections](#connections)) | | <a id="mergerequestreviewerid"></a>`id` | [`ID!`](#id) | ID of the user. | +| <a id="mergerequestrevieweride"></a>`ide` | [`Ide`](#ide) | IDE settings. | | <a id="mergerequestreviewerjobtitle"></a>`jobTitle` | [`String`](#string) | Job title of the user. | | <a id="mergerequestreviewerlinkedin"></a>`linkedin` | [`String`](#string) | LinkedIn profile name of the user. | | <a id="mergerequestreviewerlocation"></a>`location` | [`String`](#string) | Location of the user. | @@ -23355,6 +23369,7 @@ Core represention of a GitLab user. | <a id="usercoregroupcount"></a>`groupCount` | [`Int`](#int) | Group count for the user. | | <a id="usercoregroupmemberships"></a>`groupMemberships` | [`GroupMemberConnection`](#groupmemberconnection) | Group memberships of the user. (see [Connections](#connections)) | | <a id="usercoreid"></a>`id` | [`ID!`](#id) | ID of the user. | +| <a id="usercoreide"></a>`ide` | [`Ide`](#ide) | IDE settings. | | <a id="usercorejobtitle"></a>`jobTitle` | [`String`](#string) | Job title of the user. | | <a id="usercorelinkedin"></a>`linkedin` | [`String`](#string) | LinkedIn profile name of the user. | | <a id="usercorelocation"></a>`location` | [`String`](#string) | Location of the user. | @@ -28405,6 +28420,7 @@ Implementations: | <a id="usergroupcount"></a>`groupCount` | [`Int`](#int) | Group count for the user. | | <a id="usergroupmemberships"></a>`groupMemberships` | [`GroupMemberConnection`](#groupmemberconnection) | Group memberships of the user. (see [Connections](#connections)) | | <a id="userid"></a>`id` | [`ID!`](#id) | ID of the user. | +| <a id="useride"></a>`ide` | [`Ide`](#ide) | IDE settings. | | <a id="userjobtitle"></a>`jobTitle` | [`String`](#string) | Job title of the user. | | <a id="userlinkedin"></a>`linkedin` | [`String`](#string) | LinkedIn profile name of the user. | | <a id="userlocation"></a>`location` | [`String`](#string) | Location of the user. | diff --git a/spec/graphql/types/ide_type_spec.rb b/spec/graphql/types/ide_type_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..b0e43332fa89cbf8f763b7a04e12afcdbe71a93d --- /dev/null +++ b/spec/graphql/types/ide_type_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['Ide'], feature_category: :web_ide do + specify { expect(described_class.graphql_name).to eq('Ide') } + + it 'has the expected fields' do + expected_fields = %w[ + codeSuggestionsEnabled + ] + + expect(described_class).to have_graphql_fields(*expected_fields) + end +end diff --git a/spec/graphql/types/user_type_spec.rb b/spec/graphql/types/user_type_spec.rb index 7c280b9da426d451c4ec879c77ae27bba3fdb738..af0f8a86b6ca8433f4f4249c485b8edee46e59a3 100644 --- a/spec/graphql/types/user_type_spec.rb +++ b/spec/graphql/types/user_type_spec.rb @@ -56,6 +56,7 @@ jobTitle createdAt pronouns + ide ] expect(described_class).to include_graphql_fields(*expected_fields) @@ -78,13 +79,13 @@ let(:username) { requested_user.username } let(:query) do - %( + <<~GQL query { user(username: "#{username}") { name } } - ) + GQL end subject(:user_name) { GitlabSchema.execute(query, context: { current_user: current_user }).as_json.dig('data', 'user', 'name') } @@ -255,4 +256,40 @@ is_expected.to have_graphql_type(Types::Users::NamespaceCommitEmailType.connection_type) end end + + describe 'ide field' do + subject { described_class.fields['ide'] } + + it 'returns ide' do + is_expected.to have_graphql_type(Types::IdeType) + end + + context 'code suggestions enabled' do + let(:current_user) { create(:user) } + let(:query) do + <<~GQL + query { + currentUser { + ide { + codeSuggestionsEnabled + } + } + } + GQL + end + + subject(:code_suggestions_enabled) do + GitlabSchema.execute(query, context: { current_user: current_user }) + .as_json + .dig('data', 'currentUser', 'ide', 'codeSuggestionsEnabled') + end + + it 'returns code suggestions enabled' do + allow(current_user).to receive(:can?).with(:access_code_suggestions).and_return(true) + + expect(current_user).to receive(:can?).with(:access_code_suggestions).and_return(true) + expect(code_suggestions_enabled).to be true + end + end + end end diff --git a/spec/support/shared_examples/graphql/types/merge_request_interactions_type_shared_examples.rb b/spec/support/shared_examples/graphql/types/merge_request_interactions_type_shared_examples.rb index 03a3f02ae1dd5d58a146708e5b3d553d5b7a2093..c32e758d9213513ddcb262b1bb2938910da2e4a1 100644 --- a/spec/support/shared_examples/graphql/types/merge_request_interactions_type_shared_examples.rb +++ b/spec/support/shared_examples/graphql/types/merge_request_interactions_type_shared_examples.rb @@ -51,6 +51,7 @@ jobTitle createdAt pronouns + ide ] # TODO: 'workspaces' needs to be included, but only when this spec is run in EE context, to account for the