diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-01 18:29:25 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-01 18:29:36 +0000 |
commit | cf599b3cb9210c48820e7d88c4393303aa28826e (patch) | |
tree | 1a5af24f92aec8d50ae770eb251fe4c29f944b9d | |
parent | 165c4fb3de28c1b03b1d3a5e05b8962b73eea228 (diff) | |
download | gitlab-ce-cf599b3cb9210c48820e7d88c4393303aa28826e.tar.gz |
Add latest changes from gitlab-org/security/gitlab@15-8-stable-ee
-rw-r--r-- | app/assets/javascripts/work_items/components/item_title.vue | 6 | ||||
-rw-r--r-- | app/models/integration.rb | 2 | ||||
-rw-r--r-- | app/services/resource_access_tokens/create_service.rb | 2 | ||||
-rw-r--r-- | doc/development/integrations/index.md | 9 | ||||
-rw-r--r-- | spec/frontend/work_items/components/item_title_spec.js | 24 | ||||
-rw-r--r-- | spec/models/integration_spec.rb | 9 | ||||
-rw-r--r-- | spec/services/resource_access_tokens/create_service_spec.rb | 51 |
7 files changed, 72 insertions, 31 deletions
diff --git a/app/assets/javascripts/work_items/components/item_title.vue b/app/assets/javascripts/work_items/components/item_title.vue index b2c8b7ae1db..3d49bb9cf10 100644 --- a/app/assets/javascripts/work_items/components/item_title.vue +++ b/app/assets/javascripts/work_items/components/item_title.vue @@ -29,6 +29,11 @@ export default { handleSubmit() { this.$refs.titleEl.blur(); }, + handlePaste(e) { + e.preventDefault(); + const text = e.clipboardData.getData('text'); + this.$refs.titleEl.innerText = text; + }, }, }; </script> @@ -48,6 +53,7 @@ export default { :contenteditable="!disabled" class="gl-px-4 gl-py-3 gl-ml-n4 gl-border gl-border-white gl-rounded-base gl-display-block" :class="{ 'gl-hover-border-gray-200 gl-pseudo-placeholder': !disabled }" + @paste="handlePaste" @blur="handleBlur" @keyup="handleInput" @keydown.enter.exact="handleSubmit" diff --git a/app/models/integration.rb b/app/models/integration.rb index 54eeab10360..4e5c90bffa1 100644 --- a/app/models/integration.rb +++ b/app/models/integration.rb @@ -510,7 +510,7 @@ class Integration < ApplicationRecord end def api_field_names - fields.reject { _1[:type] == 'password' }.pluck(:name) + fields.reject { _1[:type] == 'password' || _1[:name] == 'webhook' }.pluck(:name) end def form_fields diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb index c6948536053..f6fe23b4555 100644 --- a/app/services/resource_access_tokens/create_service.rb +++ b/app/services/resource_access_tokens/create_service.rb @@ -125,7 +125,7 @@ module ResourceAccessTokens def do_not_allow_owner_access_level_for_project_bot?(access_level) resource.is_a?(Project) && - access_level == Gitlab::Access::OWNER && + access_level.to_i == Gitlab::Access::OWNER && !current_user.can?(:manage_owners, resource) end end diff --git a/doc/development/integrations/index.md b/doc/development/integrations/index.md index 9fd8fb7eb61..ceb64ba2bb7 100644 --- a/doc/development/integrations/index.md +++ b/doc/development/integrations/index.md @@ -249,6 +249,15 @@ To expose the integration in the [REST API](../../api/integrations.md): You can also refer to our [REST API style guide](../api_styleguide.md). +Sensitive fields are not exposed over the API. Sensitive fields are those fields that contain any of the following in their name: + +- `key` +- `passphrase` +- `password` +- `secret` +- `token` +- `webhook` + #### GraphQL API Integrations use the `Types::Projects::ServiceType` type by default, diff --git a/spec/frontend/work_items/components/item_title_spec.js b/spec/frontend/work_items/components/item_title_spec.js index 13e04ef6671..6361f8dafc4 100644 --- a/spec/frontend/work_items/components/item_title_spec.js +++ b/spec/frontend/work_items/components/item_title_spec.js @@ -1,8 +1,7 @@ import { shallowMount } from '@vue/test-utils'; +import { escape } from 'lodash'; import ItemTitle from '~/work_items/components/item_title.vue'; -jest.mock('lodash/escape', () => jest.fn((fn) => fn)); - const createComponent = ({ title = 'Sample title', disabled = false } = {}) => shallowMount(ItemTitle, { propsData: { @@ -51,4 +50,25 @@ describe('ItemTitle', () => { expect(wrapper.emitted(eventName)).toBeDefined(); }); + + it('renders only the text content from clipboard', async () => { + const htmlContent = '<strong>bold text</strong>'; + const buildClipboardData = (data = {}) => ({ + clipboardData: { + getData(mimeType) { + return data[mimeType]; + }, + types: Object.keys(data), + }, + }); + + findInputEl().trigger( + 'paste', + buildClipboardData({ + html: htmlContent, + text: htmlContent, + }), + ); + expect(findInputEl().element.innerHTML).toBe(escape(htmlContent)); + }); }); diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb index 9b3250e3c08..3c6f9ad7fea 100644 --- a/spec/models/integration_spec.rb +++ b/spec/models/integration_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Integration do +RSpec.describe Integration, feature_category: :integrations do using RSpec::Parameterized::TableSyntax let_it_be(:group) { create(:group) } @@ -854,6 +854,7 @@ RSpec.describe Integration do { name: 'api_key', type: 'password' }, { name: 'password', type: 'password' }, { name: 'password_field', type: 'password' }, + { name: 'webhook' }, { name: 'some_safe_field' }, { name: 'safe_field' }, { name: 'url' }, @@ -881,6 +882,7 @@ RSpec.describe Integration do field :api_key, type: 'password' field :password, type: 'password' field :password_field, type: 'password' + field :webhook field :some_safe_field field :safe_field field :url @@ -1090,6 +1092,8 @@ RSpec.describe Integration do field :bar, type: 'password' field :password + field :webhook + field :with_help, help: -> { 'help' } field :select, type: 'select' field :boolean, type: 'checkbox' @@ -1140,7 +1144,7 @@ RSpec.describe Integration do it 'registers fields in the fields list' do expect(integration.fields.pluck(:name)).to match_array %w[ - foo foo_p foo_dt bar password with_help select boolean + foo foo_p foo_dt bar password with_help select boolean webhook ] expect(integration.api_field_names).to match_array %w[ @@ -1155,6 +1159,7 @@ RSpec.describe Integration do have_attributes(name: 'foo_dt', type: 'text'), have_attributes(name: 'bar', type: 'password'), have_attributes(name: 'password', type: 'password'), + have_attributes(name: 'webhook', type: 'text'), have_attributes(name: 'with_help', help: 'help'), have_attributes(name: 'select', type: 'select'), have_attributes(name: 'boolean', type: 'checkbox') diff --git a/spec/services/resource_access_tokens/create_service_spec.rb b/spec/services/resource_access_tokens/create_service_spec.rb index 442232920f9..a8c8d41ca09 100644 --- a/spec/services/resource_access_tokens/create_service_spec.rb +++ b/spec/services/resource_access_tokens/create_service_spec.rb @@ -27,6 +27,13 @@ RSpec.describe ResourceAccessTokens::CreateService do end end + shared_examples 'correct error message' do + it 'returns correct error message' do + expect(subject.error?).to be true + expect(subject.errors).to include(error_message) + end + end + shared_examples 'allows creation of bot with valid params' do it { expect { subject }.to change { User.count }.by(1) } @@ -200,16 +207,11 @@ RSpec.describe ResourceAccessTokens::CreateService do end context 'when invalid scope is passed' do + let(:error_message) { 'Scopes can only contain available scopes' } let_it_be(:params) { { scopes: [:invalid_scope] } } it_behaves_like 'token creation fails' - - it 'returns the scope error message' do - response = subject - - expect(response.error?).to be true - expect(response.errors).to include("Scopes can only contain available scopes") - end + it_behaves_like 'correct error message' end end @@ -217,6 +219,7 @@ RSpec.describe ResourceAccessTokens::CreateService do let_it_be(:bot_user) { create(:user, :project_bot) } let(:unpersisted_member) { build(:project_member, source: resource, user: bot_user) } + let(:error_message) { 'Could not provision maintainer access to project access token' } before do allow_next_instance_of(ResourceAccessTokens::CreateService) do |service| @@ -226,13 +229,7 @@ RSpec.describe ResourceAccessTokens::CreateService do end it_behaves_like 'token creation fails' - - it 'returns the provisioning error message' do - response = subject - - expect(response.error?).to be true - expect(response.errors).to include("Could not provision maintainer access to project access token") - end + it_behaves_like 'correct error message' end end @@ -246,14 +243,10 @@ RSpec.describe ResourceAccessTokens::CreateService do end shared_examples 'when user does not have permission to create a resource bot' do - it_behaves_like 'token creation fails' - - it 'returns the permission error message' do - response = subject + let(:error_message) { "User does not have permission to create #{resource_type} access token" } - expect(response.error?).to be true - expect(response.errors).to include("User does not have permission to create #{resource_type} access token") - end + it_behaves_like 'token creation fails' + it_behaves_like 'correct error message' end context 'when resource is a project' do @@ -273,11 +266,19 @@ RSpec.describe ResourceAccessTokens::CreateService do let_it_be(:params) { { access_level: Gitlab::Access::OWNER } } context 'when the executor is a MAINTAINER' do - it 'does not add the bot user with the specified access level in the resource' do - response = subject + let(:error_message) { 'Could not provision owner access to project access token' } - expect(response.error?).to be true - expect(response.errors).to include('Could not provision owner access to project access token') + context 'with OWNER access_level, in integer format' do + it_behaves_like 'token creation fails' + it_behaves_like 'correct error message' + end + + context 'with OWNER access_level, in string format' do + let(:error_message) { 'Could not provision owner access to project access token' } + let_it_be(:params) { { access_level: Gitlab::Access::OWNER.to_s } } + + it_behaves_like 'token creation fails' + it_behaves_like 'correct error message' end end |