summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-03-01 18:29:25 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-01 18:29:36 +0000
commitcf599b3cb9210c48820e7d88c4393303aa28826e (patch)
tree1a5af24f92aec8d50ae770eb251fe4c29f944b9d
parent165c4fb3de28c1b03b1d3a5e05b8962b73eea228 (diff)
downloadgitlab-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.vue6
-rw-r--r--app/models/integration.rb2
-rw-r--r--app/services/resource_access_tokens/create_service.rb2
-rw-r--r--doc/development/integrations/index.md9
-rw-r--r--spec/frontend/work_items/components/item_title_spec.js24
-rw-r--r--spec/models/integration_spec.rb9
-rw-r--r--spec/services/resource_access_tokens/create_service_spec.rb51
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