diff options
author | GitLab Release Tools Bot <delivery-team+release-tools@gitlab.com> | 2022-03-31 13:35:21 +0000 |
---|---|---|
committer | GitLab Release Tools Bot <delivery-team+release-tools@gitlab.com> | 2022-03-31 13:35:21 +0000 |
commit | 7bc34aad19503153d8d9b849006e59b43a1eda5b (patch) | |
tree | 45e48f5056d711d3f48a4866516599e7ed56d6a0 /spec | |
parent | 7bc3851c3276c365434ef23e3785102e5b01705a (diff) | |
parent | d51b185ed5091afd1b668fe8df0c57cd8f629ec0 (diff) | |
download | gitlab-ce-7bc34aad19503153d8d9b849006e59b43a1eda5b.tar.gz |
Merge remote-tracking branch 'dev/14-8-stable' into 14-8-stable
Diffstat (limited to 'spec')
49 files changed, 978 insertions, 134 deletions
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index c52223d4758..c46a12680a2 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -612,8 +612,8 @@ RSpec.describe Admin::UsersController do end context 'when the new password does not match the password confirmation' do - let(:password) { Gitlab::Password.test_default } - let(:password_confirmation) { "not" + Gitlab::Password.test_default } + let(:password) { 'some_password' } + let(:password_confirmation) { 'not_same_as_password' } it 'shows the edit page again' do update_password(user, password, password_confirmation) diff --git a/spec/controllers/projects/merge_requests/creations_controller_spec.rb b/spec/controllers/projects/merge_requests/creations_controller_spec.rb index 3c650988b4f..a061a14c7b1 100644 --- a/spec/controllers/projects/merge_requests/creations_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/creations_controller_spec.rb @@ -186,6 +186,7 @@ RSpec.describe Projects::MergeRequests::CreationsController do it 'fetches the commit if a user has access' do expect(Ability).to receive(:allowed?).with(user, :read_project, project) { true } + expect(Ability).to receive(:allowed?).with(user, :create_merge_request_in, project) { true }.at_least(:once) get :branch_to, params: { @@ -199,8 +200,25 @@ RSpec.describe Projects::MergeRequests::CreationsController do expect(response).to have_gitlab_http_status(:ok) end + it 'does not load the commit when the user cannot create_merge_request_in' do + expect(Ability).to receive(:allowed?).with(user, :read_project, project) { true } + expect(Ability).to receive(:allowed?).with(user, :create_merge_request_in, project) { false }.at_least(:once) + + get :branch_to, + params: { + namespace_id: fork_project.namespace, + project_id: fork_project, + target_project_id: project.id, + ref: 'master' + } + + expect(assigns(:commit)).to be_nil + expect(response).to have_gitlab_http_status(:ok) + end + it 'does not load the commit when the user cannot read the project' do expect(Ability).to receive(:allowed?).with(user, :read_project, project) { false } + expect(Ability).to receive(:allowed?).with(user, :create_merge_request_in, project) { true }.at_least(:once) get :branch_to, params: { diff --git a/spec/controllers/projects/mirrors_controller_spec.rb b/spec/controllers/projects/mirrors_controller_spec.rb index 7bc86d7c583..686effd799e 100644 --- a/spec/controllers/projects/mirrors_controller_spec.rb +++ b/spec/controllers/projects/mirrors_controller_spec.rb @@ -177,6 +177,7 @@ RSpec.describe Projects::MirrorsController do INVALID git@example.com:foo/bar.git ssh://git@example.com:foo/bar.git + ssh://127.0.0.1/foo/bar.git ].each do |url| it "returns an error with a 400 response for URL #{url.inspect}" do do_get(project, url) diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb index af34ae2f69b..caff7bcfc7b 100644 --- a/spec/controllers/registrations_controller_spec.rb +++ b/spec/controllers/registrations_controller_spec.rb @@ -521,7 +521,7 @@ RSpec.describe RegistrationsController do end it 'succeeds if password is confirmed' do - post :destroy, params: { password: Gitlab::Password.test_default } + post :destroy, params: { password: '12345678' } expect_success end @@ -562,7 +562,7 @@ RSpec.describe RegistrationsController do end it 'fails' do - delete :destroy, params: { password: Gitlab::Password.test_default } + delete :destroy, params: { password: '12345678' } expect_failure(s_('Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account')) end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 8764ac90af8..7566ec18fa4 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -5,7 +5,7 @@ FactoryBot.define do email { generate(:email) } name { generate(:name) } username { generate(:username) } - password { Gitlab::Password.test_default } + password { "12345678" } role { 'software_developer' } confirmed_at { Time.now } confirmation_token { nil } @@ -27,6 +27,10 @@ FactoryBot.define do after(:build) { |user, _| user.block! } end + trait :disallowed_password do + password { User::DISALLOWED_PASSWORDS.first } + end + trait :blocked_pending_approval do after(:build) { |user, _| user.block_pending_approval! } end diff --git a/spec/features/markdown/kroki_spec.rb b/spec/features/markdown/kroki_spec.rb new file mode 100644 index 00000000000..f02f5d44244 --- /dev/null +++ b/spec/features/markdown/kroki_spec.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'kroki rendering', :js do + let_it_be(:project) { create(:project, :public) } + + before do + stub_application_setting(kroki_enabled: true, kroki_url: 'http://localhost:8000') + end + + it 'shows kroki image' do + plain_text = 'This text length is ignored. ' * 300 + + description = <<~KROKI + #{plain_text} + ```plantuml + A -> A: T + ``` + KROKI + + issue = create(:issue, project: project, description: description) + + visit project_issue_path(project, issue) + + within('.description') do + expect(page).to have_css('img') + expect(page).not_to have_text 'Warning: Displaying this diagram might cause performance issues on this page.' + end + end + + it 'hides kroki image and shows warning alert when kroki source size is large' do + plantuml_text = 'A -> A: T ' * 300 + + description = <<~KROKI + ```plantuml + #{plantuml_text} + ``` + KROKI + + issue = create(:issue, project: project, description: description) + + visit project_issue_path(project, issue) + + within('.description') do + expect(page).not_to have_css('img') + expect(page).to have_text 'Warning: Displaying this diagram might cause performance issues on this page.' + + click_button 'Display' + + expect(page).to have_css('img') + expect(page).not_to have_text 'Warning: Displaying this diagram might cause performance issues on this page.' + end + end +end diff --git a/spec/features/password_reset_spec.rb b/spec/features/password_reset_spec.rb index 322ccc6a0c0..31b2b2d15aa 100644 --- a/spec/features/password_reset_spec.rb +++ b/spec/features/password_reset_spec.rb @@ -44,8 +44,8 @@ RSpec.describe 'Password reset' do visit(edit_user_password_path(reset_password_token: token)) - fill_in 'New password', with: "new" + Gitlab::Password.test_default - fill_in 'Confirm new password', with: "new" + Gitlab::Password.test_default + fill_in 'New password', with: 'hello1234' + fill_in 'Confirm new password', with: 'hello1234' click_button 'Change your password' diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index 34eb07d78f1..36657406303 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -29,7 +29,7 @@ RSpec.describe 'Profile account page', :js do it 'deletes user', :js, :sidekiq_might_not_need_inline do click_button 'Delete account' - fill_in 'password', with: Gitlab::Password.test_default + fill_in 'password', with: '12345678' page.within '.modal' do click_button 'Delete account' diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb index 898e2c2aa59..8e3f7a09eb0 100644 --- a/spec/features/profiles/password_spec.rb +++ b/spec/features/profiles/password_spec.rb @@ -39,7 +39,7 @@ RSpec.describe 'Profile > Password' do describe 'User puts the same passwords in the field and in the confirmation' do it 'shows a success message' do - fill_passwords(Gitlab::Password.test_default, Gitlab::Password.test_default) + fill_passwords('mypassword', 'mypassword') page.within('[data-testid="alert-info"]') do expect(page).to have_content('Password was successfully updated. Please sign in again.') @@ -79,7 +79,7 @@ RSpec.describe 'Profile > Password' do end context 'Change password' do - let(:new_password) { "new" + Gitlab::Password.test_default } + let(:new_password) { '22233344' } before do sign_in(user) @@ -170,8 +170,8 @@ RSpec.describe 'Profile > Password' do expect(current_path).to eq new_profile_password_path fill_in :user_password, with: user.password - fill_in :user_new_password, with: Gitlab::Password.test_default - fill_in :user_password_confirmation, with: Gitlab::Password.test_default + fill_in :user_new_password, with: '12345678' + fill_in :user_password_confirmation, with: '12345678' click_button 'Set new password' expect(current_path).to eq new_user_session_path diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb index 77194fd6ca1..d4cb9188fc1 100644 --- a/spec/features/projects/blobs/blob_show_spec.rb +++ b/spec/features/projects/blobs/blob_show_spec.rb @@ -948,6 +948,53 @@ RSpec.describe 'File blob', :js do end end end + + context 'openapi.yml' do + before do + file_name = 'openapi.yml' + + create_file(file_name, ' + swagger: \'2.0\' + info: + title: Classic API Resource Documentation + description: | + <div class="foo-bar" style="background-color: red;" data-foo-bar="baz"> + <h1>Swagger API documentation</h1> + </div> + version: production + basePath: /JSSResource/ + produces: + - application/xml + - application/json + consumes: + - application/xml + - application/json + security: + - basicAuth: [] + paths: + /accounts: + get: + responses: + \'200\': + description: No response was specified + tags: + - accounts + operationId: findAccounts + summary: Finds all accounts + ') + visit_blob(file_name, useUnsafeMarkdown: '1') + click_button('Display rendered file') + + wait_for_requests + end + + it 'removes `style`, `class`, and `data-*`` attributes from HTML' do + expect(page).to have_css('h1', text: 'Swagger API documentation') + expect(page).not_to have_css('.foo-bar') + expect(page).not_to have_css('[style="background-color: red;"]') + expect(page).not_to have_css('[data-foo-bar="baz"]') + end + end end context 'realtime pipelines' do diff --git a/spec/features/users/anonymous_sessions_spec.rb b/spec/features/users/anonymous_sessions_spec.rb index f9b23626397..6b21412ae3d 100644 --- a/spec/features/users/anonymous_sessions_spec.rb +++ b/spec/features/users/anonymous_sessions_spec.rb @@ -9,7 +9,7 @@ RSpec.describe 'Session TTLs', :clean_gitlab_redis_shared_state do visit new_user_session_path # The session key only gets created after a post fill_in 'user_login', with: 'non-existant@gitlab.org' - fill_in 'user_password', with: Gitlab::Password.test_default + fill_in 'user_password', with: '12345678' click_button 'Sign in' expect(page).to have_content('Invalid login or password') diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb index 2780549eea1..195026ca102 100644 --- a/spec/features/users/login_spec.rb +++ b/spec/features/users/login_spec.rb @@ -49,15 +49,15 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do expect(current_path).to eq edit_user_password_path expect(page).to have_content('Please create a password for your new account.') - fill_in 'user_password', with: Gitlab::Password.test_default - fill_in 'user_password_confirmation', with: Gitlab::Password.test_default + fill_in 'user_password', with: 'password' + fill_in 'user_password_confirmation', with: 'password' click_button 'Change your password' expect(current_path).to eq new_user_session_path expect(page).to have_content(I18n.t('devise.passwords.updated_not_active')) fill_in 'user_login', with: user.username - fill_in 'user_password', with: Gitlab::Password.test_default + fill_in 'user_password', with: 'password' click_button 'Sign in' expect_single_session_with_authenticated_ttl @@ -150,6 +150,27 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do end end + describe 'with a disallowed password' do + let(:user) { create(:user, :disallowed_password) } + + before do + expect(authentication_metrics) + .to increment(:user_unauthenticated_counter) + .and increment(:user_password_invalid_counter) + end + + it 'disallows login' do + gitlab_sign_in(user, password: user.password) + + expect(page).to have_content('Invalid login or password.') + end + + it 'does not update Devise trackable attributes' do + expect { gitlab_sign_in(user, password: user.password) } + .not_to change { User.ghost.reload.sign_in_count } + end + end + describe 'with the ghost user' do it 'disallows login' do expect(authentication_metrics) @@ -210,7 +231,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do end it 'does not allow sign-in if the user password is updated before entering a one-time code' do - user.update!(password: "new" + Gitlab::Password.test_default) + user.update!(password: 'new_password') enter_code(user.current_otp) @@ -447,7 +468,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do visit new_user_session_path fill_in 'user_login', with: user.email - fill_in 'user_password', with: Gitlab::Password.test_default + fill_in 'user_password', with: '12345678' click_button 'Sign in' expect(current_path).to eq(new_profile_password_path) @@ -456,7 +477,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do end context 'with invalid username and password' do - let(:user) { create(:user, password: "not" + Gitlab::Password.test_default) } + let(:user) { create(:user, password: 'not-the-default') } it 'blocks invalid login' do expect(authentication_metrics) @@ -767,7 +788,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do visit new_user_session_path fill_in 'user_login', with: user.email - fill_in 'user_password', with: Gitlab::Password.test_default + fill_in 'user_password', with: '12345678' click_button 'Sign in' @@ -788,7 +809,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do visit new_user_session_path fill_in 'user_login', with: user.email - fill_in 'user_password', with: Gitlab::Password.test_default + fill_in 'user_password', with: '12345678' click_button 'Sign in' @@ -809,7 +830,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do visit new_user_session_path fill_in 'user_login', with: user.email - fill_in 'user_password', with: Gitlab::Password.test_default + fill_in 'user_password', with: '12345678' click_button 'Sign in' @@ -844,7 +865,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do visit new_user_session_path fill_in 'user_login', with: user.email - fill_in 'user_password', with: Gitlab::Password.test_default + fill_in 'user_password', with: '12345678' click_button 'Sign in' fill_in 'user_otp_attempt', with: user.reload.current_otp @@ -870,7 +891,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do visit new_user_session_path fill_in 'user_login', with: user.email - fill_in 'user_password', with: Gitlab::Password.test_default + fill_in 'user_password', with: '12345678' click_button 'Sign in' expect_to_be_on_terms_page @@ -878,7 +899,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do expect(current_path).to eq(new_profile_password_path) - fill_in 'user_password', with: Gitlab::Password.test_default + fill_in 'user_password', with: '12345678' fill_in 'user_new_password', with: 'new password' fill_in 'user_password_confirmation', with: 'new password' click_button 'Set new password' diff --git a/spec/frontend/behaviors/components/diagram_performance_warning_spec.js b/spec/frontend/behaviors/components/diagram_performance_warning_spec.js new file mode 100644 index 00000000000..c58c2bc55a9 --- /dev/null +++ b/spec/frontend/behaviors/components/diagram_performance_warning_spec.js @@ -0,0 +1,40 @@ +import { GlAlert } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import DiagramPerformanceWarning from '~/behaviors/components/diagram_performance_warning.vue'; + +describe('DiagramPerformanceWarning component', () => { + let wrapper; + + const findAlert = () => wrapper.findComponent(GlAlert); + + beforeEach(() => { + wrapper = shallowMount(DiagramPerformanceWarning); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders warning alert with button', () => { + expect(findAlert().props()).toMatchObject({ + primaryButtonText: DiagramPerformanceWarning.i18n.buttonText, + variant: 'warning', + }); + }); + + it('renders warning message', () => { + expect(findAlert().text()).toBe(DiagramPerformanceWarning.i18n.bodyText); + }); + + it('emits event when closing alert', () => { + findAlert().vm.$emit('dismiss'); + + expect(wrapper.emitted('closeAlert')).toEqual([[]]); + }); + + it('emits event when accepting alert', () => { + findAlert().vm.$emit('primaryAction'); + + expect(wrapper.emitted('showImage')).toEqual([[]]); + }); +}); diff --git a/spec/graphql/resolvers/project_pipeline_statistics_resolver_spec.rb b/spec/graphql/resolvers/project_pipeline_statistics_resolver_spec.rb index ccc861baae5..66a5f0277fb 100644 --- a/spec/graphql/resolvers/project_pipeline_statistics_resolver_spec.rb +++ b/spec/graphql/resolvers/project_pipeline_statistics_resolver_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Resolvers::ProjectPipelineStatisticsResolver do let(:current_user) { reporter } - before_all do + before do project.add_guest(guest) project.add_reporter(reporter) end @@ -20,13 +20,8 @@ RSpec.describe Resolvers::ProjectPipelineStatisticsResolver do expect(described_class).to have_nullable_graphql_type(::Types::Ci::AnalyticsType) end - def resolve_statistics(project, args) - ctx = { current_user: current_user } - resolve(described_class, obj: project, args: args, ctx: ctx) - end - - describe '#resolve' do - it 'returns the pipelines statistics for a given project' do + shared_examples 'returns the pipelines statistics for a given project' do + it do result = resolve_statistics(project, {}) expect(result.keys).to contain_exactly( :week_pipelines_labels, @@ -42,14 +37,67 @@ RSpec.describe Resolvers::ProjectPipelineStatisticsResolver do :pipeline_times_values ) end + end + + shared_examples 'it returns nils' do + it do + result = resolve_statistics(project, {}) + + expect(result).to be_nil + end + end + + def resolve_statistics(project, args) + ctx = { current_user: current_user } + resolve(described_class, obj: project, args: args, ctx: ctx) + end + + describe '#resolve' do + it_behaves_like 'returns the pipelines statistics for a given project' context 'when the user does not have access to the CI/CD analytics data' do let(:current_user) { guest } - it 'returns nil' do - result = resolve_statistics(project, {}) + it_behaves_like 'it returns nils' + end + + context 'when the project is public' do + let_it_be(:project) { create(:project, :public) } + + context 'public pipelines are disabled' do + before do + project.update!(public_builds: false) + end + + context 'user is not a member' do + let(:current_user) { create(:user) } + + it_behaves_like 'it returns nils' + end + + context 'user is a guest' do + let(:current_user) { guest } + + it_behaves_like 'it returns nils' + end + + context 'user is a reporter or above' do + let(:current_user) { reporter } + + it_behaves_like 'returns the pipelines statistics for a given project' + end + end + + context 'public pipelines are enabled' do + before do + project.update!(public_builds: true) + end + + context 'user is not a member' do + let(:current_user) { create(:user) } - expect(result).to be_nil + it_behaves_like 'returns the pipelines statistics for a given project' + end end end end diff --git a/spec/initializers/rdoc_segfault_patch_spec.rb b/spec/initializers/rdoc_segfault_patch_spec.rb new file mode 100644 index 00000000000..f9630295052 --- /dev/null +++ b/spec/initializers/rdoc_segfault_patch_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +RSpec.describe 'RDoc segfault patch fix' do + describe 'RDoc::Markup::ToHtml' do + describe '#parseable?' do + it 'returns false' do + to_html = RDoc::Markup::ToHtml.new( nil) + + expect(to_html.parseable?('"def foo; end"')).to eq(false) + end + end + end + + describe 'RDoc::Markup::Verbatim' do + describe 'ruby?' do + it 'returns false' do + verbatim = RDoc::Markup::Verbatim.new('def foo; end') + verbatim.format = :ruby + + expect(verbatim.ruby?).to eq(false) + end + end + end +end diff --git a/spec/lib/banzai/filter/kroki_filter_spec.rb b/spec/lib/banzai/filter/kroki_filter_spec.rb index 57caba1d4d7..c9594ac702d 100644 --- a/spec/lib/banzai/filter/kroki_filter_spec.rb +++ b/spec/lib/banzai/filter/kroki_filter_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Banzai::Filter::KrokiFilter do stub_application_setting(kroki_enabled: true, kroki_url: "http://localhost:8000") doc = filter("<pre lang='nomnoml'><code>[Pirate|eyeCount: Int|raid();pillage()|\n [beard]--[parrot]\n [beard]-:>[foul mouth]\n]</code></pre>") - expect(doc.to_s).to eq '<img src="http://localhost:8000/nomnoml/svg/eNqLDsgsSixJrUmtTHXOL80rsVLwzCupKUrMTNHQtC7IzMlJTE_V0KzhUlCITkpNLEqJ1dWNLkgsKsoviUUSs7KLTssvzVHIzS8tyYjligUAMhEd0g==">' + expect(doc.to_s).to eq '<img class="js-render-kroki" src="http://localhost:8000/nomnoml/svg/eNqLDsgsSixJrUmtTHXOL80rsVLwzCupKUrMTNHQtC7IzMlJTE_V0KzhUlCITkpNLEqJ1dWNLkgsKsoviUUSs7KLTssvzVHIzS8tyYjligUAMhEd0g==">' end it 'replaces nomnoml pre tag with img tag if both kroki and plantuml are enabled' do @@ -19,7 +19,7 @@ RSpec.describe Banzai::Filter::KrokiFilter do plantuml_url: "http://localhost:8080") doc = filter("<pre lang='nomnoml'><code>[Pirate|eyeCount: Int|raid();pillage()|\n [beard]--[parrot]\n [beard]-:>[foul mouth]\n]</code></pre>") - expect(doc.to_s).to eq '<img src="http://localhost:8000/nomnoml/svg/eNqLDsgsSixJrUmtTHXOL80rsVLwzCupKUrMTNHQtC7IzMlJTE_V0KzhUlCITkpNLEqJ1dWNLkgsKsoviUUSs7KLTssvzVHIzS8tyYjligUAMhEd0g==">' + expect(doc.to_s).to eq '<img class="js-render-kroki" src="http://localhost:8000/nomnoml/svg/eNqLDsgsSixJrUmtTHXOL80rsVLwzCupKUrMTNHQtC7IzMlJTE_V0KzhUlCITkpNLEqJ1dWNLkgsKsoviUUSs7KLTssvzVHIzS8tyYjligUAMhEd0g==">' end it 'does not replace nomnoml pre tag with img tag if kroki is disabled' do @@ -38,4 +38,12 @@ RSpec.describe Banzai::Filter::KrokiFilter do expect(doc.to_s).to eq '<pre lang="plantuml"><code>Bob->Alice : hello</code></pre>' end + + it 'adds hidden attribute when content size is large' do + stub_application_setting(kroki_enabled: true, kroki_url: "http://localhost:8000") + text = '[Pirate|eyeCount: Int|raid();pillage()|\n [beard]--[parrot]\n [beard]-:>[foul mouth]\n]' * 25 + doc = filter("<pre lang='nomnoml'><code>#{text}</code></pre>") + + expect(doc.to_s).to eq '<img class="js-render-kroki" src="http://localhost:8000/nomnoml/svg/eNqLDsgsSixJrUmtTHXOL80rsVLwzCupKUrMTNHQtC7IzMlJTE_V0KyJyVNQiE5KTSxKidXVjS5ILCrKL4lFFrSyi07LL81RyM0vLckAysRGjxo8avCowaMGjxo8avCowaMGU8lgAE7mIdc=" hidden>' + end end diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb index aee4bd93207..16c958ec10b 100644 --- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb +++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb @@ -132,6 +132,12 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>') end + + it "escape sourcepos metadata to prevent XSS" do + result = filter('<pre data-sourcepos=""%22 href="x"></pre><base href=http://unsafe-website.com/><pre x=""><code></code></pre>') + + expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos=\'"%22 href="x"></pre><base href=http://unsafe-website.com/><pre x="\' class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code></code></pre><copy-code></copy-code></div>') + end end context "when Rouge lexing fails" do diff --git a/spec/lib/banzai/reference_redactor_spec.rb b/spec/lib/banzai/reference_redactor_spec.rb index 78cceedd0e5..59410fbce71 100644 --- a/spec/lib/banzai/reference_redactor_spec.rb +++ b/spec/lib/banzai/reference_redactor_spec.rb @@ -35,7 +35,7 @@ RSpec.describe Banzai::ReferenceRedactor do end context 'when data-original attribute provided' do - let(:original_content) { '<code>foo</code>' } + let(:original_content) { '<script>alert(1);</script>' } it 'replaces redacted reference with original content' do doc = Nokogiri::HTML.fragment("<a class='gfm' href='https://www.gitlab.com' data-reference-type='issue' data-original='#{original_content}'>bar</a>") diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 706344831b8..f5a74956174 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -87,7 +87,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do end context 'when IP is already banned' do - subject { gl_auth.find_for_git_client('username', Gitlab::Password.test_default, project: nil, ip: 'ip') } + subject { gl_auth.find_for_git_client('username', 'password', project: nil, ip: 'ip') } before do expect_next_instance_of(Gitlab::Auth::IpRateLimiter) do |rate_limiter| @@ -219,16 +219,16 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do end it 'recognizes master passwords' do - user = create(:user, password: Gitlab::Password.test_default) + user = create(:user, password: 'password') - expect(gl_auth.find_for_git_client(user.username, Gitlab::Password.test_default, project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities) + expect(gl_auth.find_for_git_client(user.username, 'password', project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities) end include_examples 'user login operation with unique ip limit' do - let(:user) { create(:user, password: Gitlab::Password.test_default) } + let(:user) { create(:user, password: 'password') } def operation - expect(gl_auth.find_for_git_client(user.username, Gitlab::Password.test_default, project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities) + expect(gl_auth.find_for_git_client(user.username, 'password', project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities) end end @@ -492,7 +492,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do :user, :blocked, username: 'normal_user', - password: Gitlab::Password.test_default + password: 'my-secret' ) expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip')) @@ -501,7 +501,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do context 'when 2fa is enabled globally' do let_it_be(:user) do - create(:user, username: 'normal_user', password: Gitlab::Password.test_default, otp_grace_period_started_at: 1.day.ago) + create(:user, username: 'normal_user', password: 'my-secret', otp_grace_period_started_at: 1.day.ago) end before do @@ -525,7 +525,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do context 'when 2fa is enabled personally' do let(:user) do - create(:user, :two_factor, username: 'normal_user', password: Gitlab::Password.test_default, otp_grace_period_started_at: 1.day.ago) + create(:user, :two_factor, username: 'normal_user', password: 'my-secret', otp_grace_period_started_at: 1.day.ago) end it 'fails' do @@ -538,7 +538,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do user = create( :user, username: 'normal_user', - password: Gitlab::Password.test_default + password: 'my-secret' ) expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip')) @@ -549,7 +549,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do user = create( :user, username: 'oauth2', - password: Gitlab::Password.test_default + password: 'my-secret' ) expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip')) @@ -624,7 +624,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do context 'when deploy token and user have the same username' do let(:username) { 'normal_user' } - let(:user) { create(:user, username: username, password: Gitlab::Password.test_default) } + let(:user) { create(:user, username: username, password: 'my-secret') } let(:deploy_token) { create(:deploy_token, username: username, read_registry: false, projects: [project]) } it 'succeeds for the token' do @@ -637,7 +637,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do it 'succeeds for the user' do auth_success = { actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities } - expect(gl_auth.find_for_git_client(username, Gitlab::Password.test_default, project: project, ip: 'ip')) + expect(gl_auth.find_for_git_client(username, 'my-secret', project: project, ip: 'ip')) .to have_attributes(auth_success) end end @@ -831,7 +831,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do end let(:username) { 'John' } # username isn't lowercase, test this - let(:password) { Gitlab::Password.test_default } + let(:password) { 'my-secret' } it "finds user by valid login/password" do expect(gl_auth.find_with_user_password(username, password)).to eql user @@ -956,13 +956,13 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do it "does not find user by using ldap as fallback to for authentication" do expect(Gitlab::Auth::Ldap::Authentication).to receive(:login).and_return(nil) - expect(gl_auth.find_with_user_password('ldap_user', Gitlab::Password.test_default)).to be_nil + expect(gl_auth.find_with_user_password('ldap_user', 'password')).to be_nil end it "find new user by using ldap as fallback to for authentication" do expect(Gitlab::Auth::Ldap::Authentication).to receive(:login).and_return(user) - expect(gl_auth.find_with_user_password('ldap_user', Gitlab::Password.test_default)).to eq(user) + expect(gl_auth.find_with_user_password('ldap_user', 'password')).to eq(user) end end diff --git a/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb b/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb index 8dd92c5b5fd..b59fc95a8cc 100644 --- a/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/artifact_spec.rb @@ -127,6 +127,12 @@ RSpec.describe Gitlab::Ci::Config::External::File::Artifact do let!(:metadata) { create(:ci_job_artifact, :metadata, job: generator_job) } context 'when file is empty' do + let(:params) { { artifact: 'secret_stuff/generated.yml', job: 'generator' } } + let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'secret_stuff', 'masked' => true }]) } + let(:context) do + Gitlab::Ci::Config::External::Context.new(parent_pipeline: parent_pipeline, variables: variables) + end + before do allow_next_instance_of(Gitlab::Ci::ArtifactFileReader) do |reader| allow(reader).to receive(:read).and_return('') @@ -134,7 +140,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Artifact do end let(:expected_error) do - 'File `generated.yml` is empty!' + 'File `xxxxxxxxxxxx/generated.yml` is empty!' end it_behaves_like 'is invalid' diff --git a/spec/lib/gitlab/ci/config/external/file/base_spec.rb b/spec/lib/gitlab/ci/config/external/file/base_spec.rb index 445edb253fd..536f48ecba6 100644 --- a/spec/lib/gitlab/ci/config/external/file/base_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/base_spec.rb @@ -3,7 +3,8 @@ require 'spec_helper' RSpec.describe Gitlab::Ci::Config::External::File::Base do - let(:context_params) { { sha: 'HEAD' } } + let(:variables) { } + let(:context_params) { { sha: 'HEAD', variables: variables } } let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) } let(:test_class) do @@ -76,7 +77,8 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base do end context 'when there are YAML syntax errors' do - let(:location) { 'some/file/config.yml' } + let(:location) { 'some/file/secret_file_name.yml' } + let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'secret_file_name', 'masked' => true }]) } before do allow_any_instance_of(test_class) @@ -85,7 +87,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base do it 'is not a valid file' do expect(subject).not_to be_valid - expect(subject.error_message).to match /does not have valid YAML syntax/ + expect(subject.error_message).to eq('Included file `some/file/xxxxxxxxxxxxxxxx.yml` does not have valid YAML syntax!') end end end diff --git a/spec/lib/gitlab/ci/config/external/file/local_spec.rb b/spec/lib/gitlab/ci/config/external/file/local_spec.rb index 3d1fc32a62d..61eb52a615b 100644 --- a/spec/lib/gitlab/ci/config/external/file/local_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/local_spec.rb @@ -7,6 +7,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do let_it_be(:user) { create(:user) } let(:sha) { '12345' } + let(:variables) { project.predefined_variables.to_runner_variables } let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) } let(:params) { { local: location } } let(:local_file) { described_class.new(params, context) } @@ -18,7 +19,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do sha: sha, user: user, parent_pipeline: parent_pipeline, - variables: project.predefined_variables.to_runner_variables + variables: variables } end @@ -66,7 +67,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do end end - context 'when is not a valid local path' do + context 'when it is not a valid local path' do let(:location) { '/lib/gitlab/ci/templates/non-existent-file.yml' } it 'returns false' do @@ -74,13 +75,23 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do end end - context 'when is not a yaml file' do + context 'when it is not a yaml file' do let(:location) { '/config/application.rb' } it 'returns false' do expect(local_file.valid?).to be_falsy end end + + context 'when it is an empty file' do + let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'secret', 'masked' => true }]) } + let(:location) { '/lib/gitlab/ci/templates/secret/existent-file.yml' } + + it 'returns false and adds an error message about an empty file' do + allow_any_instance_of(described_class).to receive(:fetch_local_content).and_return("") + expect(local_file.errors).to include("Local file `/lib/gitlab/ci/templates/xxxxxx/existent-file.yml` is empty!") + end + end end describe '#content' do @@ -116,10 +127,11 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do end describe '#error_message' do - let(:location) { '/lib/gitlab/ci/templates/non-existent-file.yml' } + let(:location) { '/lib/gitlab/ci/templates/secret_file.yml' } + let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'secret_file', 'masked' => true }]) } it 'returns an error message' do - expect(local_file.error_message).to eq("Local file `#{location}` does not exist!") + expect(local_file.error_message).to eq("Local file `/lib/gitlab/ci/templates/xxxxxxxxxxx.yml` does not exist!") end end diff --git a/spec/lib/gitlab/ci/config/external/file/project_spec.rb b/spec/lib/gitlab/ci/config/external/file/project_spec.rb index c53914c5772..74720c0a3ca 100644 --- a/spec/lib/gitlab/ci/config/external/file/project_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/project_spec.rb @@ -11,6 +11,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do let(:parent_pipeline) { double(:parent_pipeline) } let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) } let(:project_file) { described_class.new(params, context) } + let(:variables) { project.predefined_variables.to_runner_variables } let(:context_params) do { @@ -18,7 +19,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do sha: '12345', user: context_user, parent_pipeline: parent_pipeline, - variables: project.predefined_variables.to_runner_variables + variables: variables } end @@ -108,18 +109,19 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do context 'when an empty file is used' do let(:params) do - { project: project.full_path, file: '/file.yml' } + { project: project.full_path, file: '/secret_file.yml' } end + let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'secret_file', 'masked' => true }]) } let(:root_ref_sha) { project.repository.root_ref_sha } before do - stub_project_blob(root_ref_sha, '/file.yml') { '' } + stub_project_blob(root_ref_sha, '/secret_file.yml') { '' } end it 'returns false' do expect(project_file).not_to be_valid - expect(project_file.error_message).to include("Project `#{project.full_path}` file `/file.yml` is empty!") + expect(project_file.error_message).to include("Project `#{project.full_path}` file `/xxxxxxxxxxx.yml` is empty!") end end @@ -135,13 +137,15 @@ RSpec.describe Gitlab::Ci::Config::External::File::Project do end context 'when non-existing file is requested' do + let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'secret-invalid-file', 'masked' => true }]) } + let(:params) do - { project: project.full_path, file: '/invalid-file.yml' } + { project: project.full_path, file: '/secret-invalid-file.yml' } end it 'returns false' do expect(project_file).not_to be_valid - expect(project_file.error_message).to include("Project `#{project.full_path}` file `/invalid-file.yml` does not exist!") + expect(project_file.error_message).to include("Project `#{project.full_path}` file `/xxxxxxxxxxxxxxxxxxx.yml` does not exist!") end end diff --git a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb index ab60ac215ba..2613bfbfdcf 100644 --- a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb @@ -5,11 +5,12 @@ require 'spec_helper' RSpec.describe Gitlab::Ci::Config::External::File::Remote do include StubRequests - let(:context_params) { { sha: '12345' } } + let(:variables) {Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'secret_file', 'masked' => true }]) } + let(:context_params) { { sha: '12345', variables: variables } } let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) } let(:params) { { remote: location } } let(:remote_file) { described_class.new(params, context) } - let(:location) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' } + let(:location) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.secret_file.yml' } let(:remote_file_content) do <<~HEREDOC before_script: @@ -144,10 +145,10 @@ RSpec.describe Gitlab::Ci::Config::External::File::Remote do subject { remote_file.error_message } context 'when remote file location is not valid' do - let(:location) { 'not-valid://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' } + let(:location) { 'not-valid://gitlab.com/gitlab-org/gitlab-foss/blob/1234/?secret_file.yml' } it 'returns an error message describing invalid address' do - expect(subject).to match /does not have a valid address!/ + expect(subject).to eq('Remote file `not-valid://gitlab.com/gitlab-org/gitlab-foss/blob/1234/?xxxxxxxxxxx.yml` does not have a valid address!') end end @@ -157,7 +158,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Remote do end it 'returns error message about a timeout' do - expect(subject).to match /could not be fetched because of a timeout error!/ + expect(subject).to eq('Remote file `https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.xxxxxxxxxxx.yml` could not be fetched because of a timeout error!') end end @@ -167,7 +168,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Remote do end it 'returns error message about a HTTP error' do - expect(subject).to match /could not be fetched because of HTTP error!/ + expect(subject).to eq('Remote file `https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.xxxxxxxxxxx.yml` could not be fetched because of HTTP error!') end end @@ -177,7 +178,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Remote do end it 'returns error message about a timeout' do - expect(subject).to match /could not be fetched because of HTTP code `404` error!/ + expect(subject).to eq('Remote file `https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.xxxxxxxxxxx.yml` could not be fetched because of HTTP code `404` error!') end end diff --git a/spec/lib/gitlab/ci/config/external/file/template_spec.rb b/spec/lib/gitlab/ci/config/external/file/template_spec.rb index 75b22c1516c..66a06de3d28 100644 --- a/spec/lib/gitlab/ci/config/external/file/template_spec.rb +++ b/spec/lib/gitlab/ci/config/external/file/template_spec.rb @@ -54,11 +54,13 @@ RSpec.describe Gitlab::Ci::Config::External::File::Template do end context 'with invalid template name' do - let(:template) { 'Template.yml' } + let(:template) { 'SecretTemplate.yml' } + let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'SecretTemplate', 'masked' => true }]) } + let(:context_params) { { project: project, sha: '12345', user: user, variables: variables } } it 'returns false' do expect(template_file).not_to be_valid - expect(template_file.error_message).to include('Template file `Template.yml` is not a valid location!') + expect(template_file.error_message).to include('`xxxxxxxxxxxxxx.yml` is not a valid location!') end end diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb index f8754d7e124..f69feba5e59 100644 --- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb +++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb @@ -11,7 +11,8 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do let(:local_file) { '/lib/gitlab/ci/templates/non-existent-file.yml' } let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' } let(:template_file) { 'Auto-DevOps.gitlab-ci.yml' } - let(:context_params) { { project: project, sha: '123456', user: user, variables: project.predefined_variables } } + let(:variables) { project.predefined_variables } + let(:context_params) { { project: project, sha: '123456', user: user, variables: variables } } let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) } let(:file_content) do @@ -92,13 +93,16 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do end context 'when the key is a hash of file and remote' do + let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'secret-file', 'masked' => true }]) } + let(:local_file) { 'secret-file.yml' } + let(:remote_url) { 'https://gitlab.com/secret-file.yml' } let(:values) do { include: { 'local' => local_file, 'remote' => remote_url }, image: 'ruby:2.7' } end it 'returns ambigious specification error' do - expect { subject }.to raise_error(described_class::AmbigiousSpecificationError) + expect { subject }.to raise_error(described_class::AmbigiousSpecificationError, 'Include `{"local":"xxxxxxxxxxx.yml","remote":"https://gitlab.com/xxxxxxxxxxx.yml"}` needs to match exactly one accessor!') end end diff --git a/spec/lib/gitlab/error_tracking/processor/sanitize_error_message_processor_spec.rb b/spec/lib/gitlab/error_tracking/processor/sanitize_error_message_processor_spec.rb new file mode 100644 index 00000000000..b4173617a14 --- /dev/null +++ b/spec/lib/gitlab/error_tracking/processor/sanitize_error_message_processor_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::ErrorTracking::Processor::SanitizeErrorMessageProcessor, :sentry do + describe '.call' do + let(:exception) { StandardError.new('raw error') } + let(:event) { Raven::Event.from_exception(exception, raven_required_options) } + let(:result_hash) { described_class.call(event).to_hash } + let(:raven_required_options) do + { + configuration: Raven.configuration, + context: Raven.context, + breadcrumbs: Raven.breadcrumbs + } + end + + it 'cleans the exception message' do + expect(Gitlab::Sanitizers::ExceptionMessage).to receive(:clean).with('StandardError', 'raw error').and_return('cleaned') + + expect(result_hash[:exception][:values].first).to include( + type: 'StandardError', + value: 'cleaned' + ) + end + + context 'when event is invalid' do + let(:event) { instance_double('Raven::Event', to_hash: { invalid: true }) } + + it 'does nothing' do + extracted_exception = instance_double('Raven::SingleExceptionInterface', value: nil) + allow(described_class).to receive(:extract_exceptions_from).and_return([extracted_exception]) + + expect(Gitlab::Sanitizers::ExceptionMessage).not_to receive(:clean) + expect(result_hash).to eq(invalid: true) + end + end + end +end diff --git a/spec/lib/gitlab/error_tracking_spec.rb b/spec/lib/gitlab/error_tracking_spec.rb index a5d44963f4b..284b773ef24 100644 --- a/spec/lib/gitlab/error_tracking_spec.rb +++ b/spec/lib/gitlab/error_tracking_spec.rb @@ -301,5 +301,48 @@ RSpec.describe Gitlab::ErrorTracking do end end end + + context 'when processing invalid URI exceptions' do + let(:invalid_uri) { 'http://foo:bar' } + let(:sentry_exception_values) { sentry_event['exception']['values'] } + + context 'when the error is a URI::InvalidURIError' do + let(:exception) do + URI.parse(invalid_uri) + rescue URI::InvalidURIError => error + error + end + + it 'filters the URI from the error message' do + track_exception + + expect(sentry_exception_values).to include( + hash_including( + 'type' => 'URI::InvalidURIError', + 'value' => 'bad URI(is not URI?): [FILTERED]' + ) + ) + end + end + + context 'when the error is a Addressable::URI::InvalidURIError' do + let(:exception) do + Addressable::URI.parse(invalid_uri) + rescue Addressable::URI::InvalidURIError => error + error + end + + it 'filters the URI from the error message' do + track_exception + + expect(sentry_exception_values).to include( + hash_including( + 'type' => 'Addressable::URI::InvalidURIError', + 'value' => 'Invalid port number: [FILTERED]' + ) + ) + end + end + end end end diff --git a/spec/lib/gitlab/exception_log_formatter_spec.rb b/spec/lib/gitlab/exception_log_formatter_spec.rb index beeeeb2b64c..7dda56f0bf5 100644 --- a/spec/lib/gitlab/exception_log_formatter_spec.rb +++ b/spec/lib/gitlab/exception_log_formatter_spec.rb @@ -22,6 +22,14 @@ RSpec.describe Gitlab::ExceptionLogFormatter do expect(payload['exception.sql']).to be_nil end + it 'cleans the exception message' do + expect(Gitlab::Sanitizers::ExceptionMessage).to receive(:clean).with('RuntimeError', 'bad request').and_return('cleaned') + + described_class.format!(exception, payload) + + expect(payload['exception.message']).to eq('cleaned') + end + context 'when exception is ActiveRecord::StatementInvalid' do let(:exception) { ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1') } diff --git a/spec/lib/gitlab/import_export/members_mapper_spec.rb b/spec/lib/gitlab/import_export/members_mapper_spec.rb index 8d9bff9c610..87ca899a87d 100644 --- a/spec/lib/gitlab/import_export/members_mapper_spec.rb +++ b/spec/lib/gitlab/import_export/members_mapper_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Gitlab::ImportExport::MembersMapper do "notification_level" => 3, "created_at" => "2016-03-11T10:21:44.822Z", "updated_at" => "2016-03-11T10:21:44.822Z", - "created_by_id" => nil, + "created_by_id" => 1, "invite_email" => nil, "invite_token" => nil, "invite_accepted_at" => nil, @@ -38,10 +38,24 @@ RSpec.describe Gitlab::ImportExport::MembersMapper do "notification_level" => 3, "created_at" => "2016-03-11T10:21:44.822Z", "updated_at" => "2016-03-11T10:21:44.822Z", - "created_by_id" => 1, + "created_by_id" => 2, "invite_email" => 'invite@test.com', "invite_token" => 'token', "invite_accepted_at" => nil + }, + { + "id" => 3, + "access_level" => 40, + "source_id" => 14, + "source_type" => source_type, + "user_id" => nil, + "notification_level" => 3, + "created_at" => "2016-03-11T10:21:44.822Z", + "updated_at" => "2016-03-11T10:21:44.822Z", + "created_by_id" => nil, + "invite_email" => 'invite2@test.com', + "invite_token" => 'token', + "invite_accepted_at" => nil }] end @@ -68,12 +82,37 @@ RSpec.describe Gitlab::ImportExport::MembersMapper do expect(member_class.find_by_invite_email('invite@test.com')).not_to be_nil end - it 'removes old user_id from member_hash to avoid conflict with user key' do + it 'maps created_by_id to user on new instance' do + expect(member_class) + .to receive(:create) + .once + .with(hash_including('user_id' => user2.id, 'created_by_id' => nil)) + .and_call_original + expect(member_class) + .to receive(:create) + .once + .with(hash_including('invite_email' => 'invite@test.com', 'created_by_id' => nil)) + .and_call_original + expect(member_class) + .to receive(:create) + .once + .with(hash_including('invite_email' => 'invite2@test.com', 'created_by_id' => nil)) + .and_call_original + + members_mapper.map + end + + it 'replaced user_id with user_id from new instance' do + expect(member_class) + .to receive(:create) + .once + .with(hash_including('user_id' => user2.id)) + .and_call_original expect(member_class) .to receive(:create) - .twice - .with(hash_excluding('user_id')) - .and_call_original + .twice + .with(hash_excluding('user_id')) + .and_call_original members_mapper.map end @@ -99,7 +138,7 @@ RSpec.describe Gitlab::ImportExport::MembersMapper do end expect(logger).to receive(:info).with(hash_including(expected_log_params.call(user2.id))).once - expect(logger).to receive(:info).with(hash_including(expected_log_params.call(nil))).once + expect(logger).to receive(:info).with(hash_including(expected_log_params.call(nil))).twice members_mapper.map end diff --git a/spec/lib/gitlab/sanitizers/exception_message_spec.rb b/spec/lib/gitlab/sanitizers/exception_message_spec.rb new file mode 100644 index 00000000000..8b54b353235 --- /dev/null +++ b/spec/lib/gitlab/sanitizers/exception_message_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' +require 'rspec-parameterized' + +RSpec.describe Gitlab::Sanitizers::ExceptionMessage do + describe '.clean' do + let(:exception_name) { exception.class.name } + let(:exception_message) { exception.message } + + subject { described_class.clean(exception_name, exception_message) } + + context 'when error is a URI::InvalidURIError' do + let(:exception) do + URI.parse('http://foo:bar') + rescue URI::InvalidURIError => error + error + end + + it { is_expected.to eq('bad URI(is not URI?): [FILTERED]') } + end + + context 'when error is an Addressable::URI::InvalidURIError' do + using RSpec::Parameterized::TableSyntax + + let(:exception) do + Addressable::URI.parse(uri) + rescue Addressable::URI::InvalidURIError => error + error + end + + where(:uri, :result) do + 'http://foo:bar' | 'Invalid port number: [FILTERED]' + 'http://foo:%eb' | 'Invalid encoding in port' + 'ht%0atp://foo' | 'Invalid scheme format: [FILTERED]' + 'http:' | 'Absolute URI missing hierarchical segment: [FILTERED]' + '::http' | 'Cannot assemble URI string with ambiguous path: [FILTERED]' + 'http://foo bar' | 'Invalid character in host: [FILTERED]' + end + + with_them do + it { is_expected.to eq(result) } + end + end + + context 'with any other exception' do + let(:exception) { StandardError.new('Error message: http://foo@bar:baz@ex:ample.com') } + + it 'is not invoked and does nothing' do + is_expected.to eq('Error message: http://foo@bar:baz@ex:ample.com') + end + end + end +end diff --git a/spec/mailers/emails/profile_spec.rb b/spec/mailers/emails/profile_spec.rb index af77989dbbc..365ca892bb1 100644 --- a/spec/mailers/emails/profile_spec.rb +++ b/spec/mailers/emails/profile_spec.rb @@ -49,7 +49,7 @@ RSpec.describe Emails::Profile do describe 'for users that signed up, the email' do let(:example_site_path) { root_path } - let(:new_user) { create(:user, email: new_user_address, password: Gitlab::Password.test_default) } + let(:new_user) { create(:user, email: new_user_address, password: "securePassword") } subject { Notify.new_user_email(new_user.id) } diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index eb29db697a5..1a9832799d3 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -41,15 +41,25 @@ RSpec.describe Ci::Runner do context 'when runner is not allowed to pick untagged jobs' do context 'when runner does not have tags' do + let(:runner) { build(:ci_runner, tag_list: [], run_untagged: false) } + + it 'is not valid' do + expect(runner).to be_invalid + end + end + + context 'when runner has too many tags' do + let(:runner) { build(:ci_runner, tag_list: (1..::Ci::Runner::TAG_LIST_MAX_LENGTH + 1).map { |i| "tag#{i}" }, run_untagged: false) } + it 'is not valid' do - runner = build(:ci_runner, tag_list: [], run_untagged: false) expect(runner).to be_invalid end end context 'when runner has tags' do + let(:runner) { build(:ci_runner, tag_list: ['tag'], run_untagged: false) } + it 'is valid' do - runner = build(:ci_runner, tag_list: ['tag'], run_untagged: false) expect(runner).to be_valid end end diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb index a3d36058b74..bf69c7219a8 100644 --- a/spec/models/hooks/system_hook_spec.rb +++ b/spec/models/hooks/system_hook_spec.rb @@ -37,7 +37,7 @@ RSpec.describe SystemHook do let(:project) { create(:project, namespace: user.namespace) } let(:group) { create(:group) } let(:params) do - { name: 'John Doe', username: 'jduser', email: 'jg@example.com', password: Gitlab::Password.test_default } + { name: 'John Doe', username: 'jduser', email: 'jg@example.com', password: 'mydummypass' } end before do diff --git a/spec/models/integrations/asana_spec.rb b/spec/models/integrations/asana_spec.rb index b6602964182..43e876a4f47 100644 --- a/spec/models/integrations/asana_spec.rb +++ b/spec/models/integrations/asana_spec.rb @@ -20,11 +20,13 @@ RSpec.describe Integrations::Asana do let(:gid) { "123456789ABCD" } let(:asana_task) { double(::Asana::Resources::Task) } let(:asana_integration) { described_class.new } + let(:ref) { 'main' } + let(:restrict_to_branch) { nil } let(:data) do { object_kind: 'push', - ref: 'master', + ref: ref, user_name: user.name, commits: [ { @@ -40,16 +42,44 @@ RSpec.describe Integrations::Asana do project: project, project_id: project.id, api_key: 'verySecret', - restrict_to_branch: 'master' + restrict_to_branch: restrict_to_branch ) end subject(:execute_integration) { asana_integration.execute(data) } + context 'with restrict_to_branch' do + let(:restrict_to_branch) { 'feature-branch, main' } + let(:message) { 'fix #456789' } + + context 'when ref is in scope of restriced branches' do + let(:ref) { 'main' } + + it 'calls the Asana integration' do + expect(asana_task).to receive(:add_comment) + expect(asana_task).to receive(:update).with(completed: true) + expect(::Asana::Resources::Task).to receive(:find_by_id).with(anything, '456789').once.and_return(asana_task) + + execute_integration + end + end + + context 'when ref is not in scope of restricted branches' do + let(:ref) { 'mai' } + + it 'does not call the Asana integration' do + expect(asana_task).not_to receive(:add_comment) + expect(::Asana::Resources::Task).not_to receive(:find_by_id) + + execute_integration + end + end + end + context 'when creating a story' do let(:message) { "Message from commit. related to ##{gid}" } let(:expected_message) do - "#{user.name} pushed to branch master of #{project.full_name} ( https://gitlab.com/ ): #{message}" + "#{user.name} pushed to branch main of #{project.full_name} ( https://gitlab.com/ ): #{message}" end it 'calls Asana integration to create a story' do diff --git a/spec/models/releases/link_spec.rb b/spec/models/releases/link_spec.rb index 4dc1e53d59e..74ef38f482b 100644 --- a/spec/models/releases/link_spec.rb +++ b/spec/models/releases/link_spec.rb @@ -113,6 +113,17 @@ RSpec.describe Releases::Link do end end + describe 'when filepath is greater than max length' do + let!(:invalid_link) { build(:release_link, filepath: 'x' * (Releases::Link::FILEPATH_MAX_LENGTH + 1), release: release) } + + it 'will not execute regex' do + invalid_link.filepath_format_valid? + + expect(invalid_link.errors[:filepath].size).to eq(1) + expect(invalid_link.errors[:filepath].first).to start_with("is too long") + end + end + describe 'FILEPATH_REGEX with table' do using RSpec::Parameterized::TableSyntax diff --git a/spec/models/ssh_host_key_spec.rb b/spec/models/ssh_host_key_spec.rb index 4d729d5585f..4b756846598 100644 --- a/spec/models/ssh_host_key_spec.rb +++ b/spec/models/ssh_host_key_spec.rb @@ -4,7 +4,9 @@ require 'spec_helper' RSpec.describe SshHostKey do using RSpec::Parameterized::TableSyntax + include ReactiveCachingHelpers + include StubRequests let(:key1) do 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC3UpyF2iLqy1d63M6k3jH1vuEnq/NWtE+o' \ @@ -35,6 +37,7 @@ RSpec.describe SshHostKey do let(:extra) { known_hosts + "foo\nbar\n" } let(:reversed) { known_hosts.lines.reverse.join } + let(:url) { 'ssh://example.com:2222' } let(:compare_host_keys) { nil } def stub_ssh_keyscan(args, status: true, stdout: "", stderr: "") @@ -50,7 +53,7 @@ RSpec.describe SshHostKey do let(:project) { build(:project) } - subject(:ssh_host_key) { described_class.new(project: project, url: 'ssh://example.com:2222', compare_host_keys: compare_host_keys) } + subject(:ssh_host_key) { described_class.new(project: project, url: url, compare_host_keys: compare_host_keys) } describe '.primary_key' do it 'returns a symbol' do @@ -191,5 +194,45 @@ RSpec.describe SshHostKey do is_expected.to eq(error: 'Failed to detect SSH host keys') end end + + context 'DNS rebinding protection enabled' do + before do + stub_application_setting(dns_rebinding_protection_enabled: true) + end + + it 'sends an address as well as hostname to ssh-keyscan' do + stub_dns(url, ip_address: '1.2.3.4') + + stdin = stub_ssh_keyscan(%w[-T 5 -p 2222 -f-]) + + cache + + expect(stdin.string).to eq("1.2.3.4 example.com\n") + end + end + end + + describe 'URL validation' do + let(:url) { 'ssh://127.0.0.1' } + + context 'when local requests are not allowed' do + before do + stub_application_setting(allow_local_requests_from_web_hooks_and_services: false) + end + + it 'forbids scanning localhost' do + expect { ssh_host_key }.to raise_error(/Invalid URL/) + end + end + + context 'when local requests are allowed' do + before do + stub_application_setting(allow_local_requests_from_web_hooks_and_services: true) + end + + it 'permits scanning localhost' do + expect(ssh_host_key.url.to_s).to eq('ssh://127.0.0.1:22') + end + end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index e4f25c79e53..cd711757bf1 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1696,9 +1696,9 @@ RSpec.describe User do describe '#generate_password' do it 'does not generate password by default' do - user = create(:user, password: Gitlab::Password.test_default) + user = create(:user, password: 'abcdefghe') - expect(user.password).to eq(Gitlab::Password.test_default) + expect(user.password).to eq('abcdefghe') end end @@ -5623,6 +5623,36 @@ RSpec.describe User do end end + describe '#valid_password?' do + subject { user.valid_password?(password) } + + context 'user with password not in disallowed list' do + let(:user) { create(:user) } + let(:password) { user.password } + + it { is_expected.to be_truthy } + + context 'using a wrong password' do + let(:password) { 'WRONG PASSWORD' } + + it { is_expected.to be_falsey } + end + end + + context 'user with disallowed password' do + let(:user) { create(:user, :disallowed_password) } + let(:password) { user.password } + + it { is_expected.to be_falsey } + + context 'using a wrong password' do + let(:password) { 'WRONG PASSWORD' } + + it { is_expected.to be_falsey } + end + end + end + describe '#password_expired?' do let(:user) { build(:user, password_expires_at: password_expires_at) } diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index 793b1fffd5f..7cd4191f6fc 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -81,25 +81,62 @@ RSpec.describe ProjectPolicy do context 'merge requests feature' do let(:current_user) { owner } + let(:mr_permissions) do + [:create_merge_request_from, :read_merge_request, :update_merge_request, + :admin_merge_request, :create_merge_request_in] + end it 'disallows all permissions when the feature is disabled' do project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED) - mr_permissions = [:create_merge_request_from, :read_merge_request, - :update_merge_request, :admin_merge_request, - :create_merge_request_in] - expect_disallowed(*mr_permissions) end + + context 'for a guest in a private project' do + let(:current_user) { guest } + let(:project) { private_project } + + it 'disallows the guest from all merge request permissions' do + expect_disallowed(*mr_permissions) + end + end end - context 'for a guest in a private project' do - let(:current_user) { guest } - let(:project) { private_project } + context 'creating_merge_request_in' do + context 'when project is public' do + let(:project) { public_project } + + context 'when the current_user is guest' do + let(:current_user) { guest } - it 'disallows the guest from reading the merge request and merge request iid' do - expect_disallowed(:read_merge_request) - expect_disallowed(:read_merge_request_iid) + it { is_expected.to be_allowed(:create_merge_request_in) } + end + end + + context 'when project is internal' do + let(:project) { internal_project } + + context 'when the current_user is guest' do + let(:current_user) { guest } + + it { is_expected.to be_allowed(:create_merge_request_in) } + end + end + + context 'when project is private' do + let(:project) { private_project } + + context 'when the current_user is guest' do + let(:current_user) { guest } + + it { is_expected.not_to be_allowed(:create_merge_request_in) } + end + + context 'when the current_user is reporter or above' do + let(:current_user) { reporter } + + it { is_expected.to be_allowed(:create_merge_request_in) } + end end end @@ -1316,6 +1353,110 @@ RSpec.describe ProjectPolicy do end end + describe 'read_ci_cd_analytics' do + context 'public project' do + let(:project) { create(:project, :public, :analytics_enabled) } + let(:current_user) { create(:user) } + + context 'when public pipelines are disabled for the project' do + before do + project.update!(public_builds: false) + end + + context 'project member' do + %w(guest reporter developer maintainer).each do |role| + context role do + before do + project.add_user(current_user, role.to_sym) + end + + if role == 'guest' + it { is_expected.to be_disallowed(:read_ci_cd_analytics) } + else + it { is_expected.to be_allowed(:read_ci_cd_analytics) } + end + end + end + end + + context 'non member' do + let(:current_user) { non_member } + + it { is_expected.to be_disallowed(:read_ci_cd_analytics) } + end + + context 'anonymous' do + let(:current_user) { anonymous } + + it { is_expected.to be_disallowed(:read_ci_cd_analytics) } + end + end + + context 'when public pipelines are enabled for the project' do + before do + project.update!(public_builds: true) + end + + context 'project member' do + %w(guest reporter developer maintainer).each do |role| + context role do + before do + project.add_user(current_user, role.to_sym) + end + + it { is_expected.to be_allowed(:read_ci_cd_analytics) } + end + end + end + + context 'non member' do + let(:current_user) { non_member } + + it { is_expected.to be_allowed(:read_ci_cd_analytics) } + end + + context 'anonymous' do + let(:current_user) { anonymous } + + it { is_expected.to be_allowed(:read_ci_cd_analytics) } + end + end + end + + context 'private project' do + let(:project) { create(:project, :private, :analytics_enabled) } + let(:current_user) { create(:user) } + + context 'project member' do + %w(guest reporter developer maintainer).each do |role| + context role do + before do + project.add_user(current_user, role.to_sym) + end + + if role == 'guest' + it { is_expected.to be_disallowed(:read_ci_cd_analytics) } + else + it { is_expected.to be_allowed(:read_ci_cd_analytics) } + end + end + end + end + + context 'non member' do + let(:current_user) { non_member } + + it { is_expected.to be_disallowed(:read_ci_cd_analytics) } + end + + context 'anonymous' do + let(:current_user) { anonymous } + + it { is_expected.to be_disallowed(:read_ci_cd_analytics) } + end + end + end + it_behaves_like 'Self-managed Core resource access tokens' describe 'operations feature' do diff --git a/spec/requests/api/ci/runner/runners_post_spec.rb b/spec/requests/api/ci/runner/runners_post_spec.rb index 5eb5d3977a3..af2c1df0b58 100644 --- a/spec/requests/api/ci/runner/runners_post_spec.rb +++ b/spec/requests/api/ci/runner/runners_post_spec.rb @@ -130,7 +130,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do } end - let_it_be(:new_runner) { create(:ci_runner) } + let_it_be(:new_runner) { build(:ci_runner) } it 'uses active value in registration' do expect_next_instance_of(::Ci::RegisterRunnerService) do |service| @@ -183,6 +183,54 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do expect(response).to have_gitlab_http_status(:created) expect(::Ci::Runner.last.ip_address).to eq('123.111.123.111') end + + context 'when tags parameter is provided' do + def request + post api('/runners'), params: { + token: registration_token, + tag_list: tag_list + } + end + + context 'with number of tags above limit' do + let(:tag_list) { (1..::Ci::Runner::TAG_LIST_MAX_LENGTH + 1).map { |i| "tag#{i}" } } + + it 'uses tag_list value in registration and returns error' do + expect_next_instance_of(::Ci::RegisterRunnerService) do |service| + expected_params = { tag_list: tag_list }.stringify_keys + + expect(service).to receive(:execute) + .once + .with(registration_token, a_hash_including(expected_params)) + .and_call_original + end + + request + + expect(response).to have_gitlab_http_status(:bad_request) + expect(json_response.dig('message', 'tags_list')).to contain_exactly("Too many tags specified. Please limit the number of tags to #{::Ci::Runner::TAG_LIST_MAX_LENGTH}") + end + end + + context 'with number of tags below limit' do + let(:tag_list) { (1..20).map { |i| "tag#{i}" } } + + it 'uses tag_list value in registration and successfully creates runner' do + expect_next_instance_of(::Ci::RegisterRunnerService) do |service| + expected_params = { tag_list: tag_list }.stringify_keys + + expect(service).to receive(:execute) + .once + .with(registration_token, a_hash_including(expected_params)) + .and_call_original + end + + request + + expect(response).to have_gitlab_http_status(:created) + end + end + end end end end diff --git a/spec/requests/api/ci/runners_spec.rb b/spec/requests/api/ci/runners_spec.rb index 336ce70d8d2..c0adf5c71cb 100644 --- a/spec/requests/api/ci/runners_spec.rb +++ b/spec/requests/api/ci/runners_spec.rb @@ -396,6 +396,19 @@ RSpec.describe API::Ci::Runners do expect(shared_runner.reload.tag_list).to include('ruby2.1', 'pgsql', 'mysql') end + it 'unrelated runner attribute on an existing runner with too many tags' do + # This test ensures that it is possible to update any attribute on a runner that currently fails the + # validation that ensures that there aren't too many tags associated with a runner + existing_invalid_shared_runner = build(:ci_runner, :instance, tag_list: (1..::Ci::Runner::TAG_LIST_MAX_LENGTH + 1).map { |i| "tag#{i}" } ) + existing_invalid_shared_runner.save!(validate: false) + + active = existing_invalid_shared_runner.active + update_runner(existing_invalid_shared_runner.id, admin, paused: active) + + expect(response).to have_gitlab_http_status(:ok) + expect(existing_invalid_shared_runner.reload.active).to eq(!active) + end + it 'runner untagged flag' do # Ensure tag list is non-empty before setting untagged to false. update_runner(shared_runner.id, admin, tag_list: ['ruby2.1', 'pgsql', 'mysql']) diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 985e07bf174..54095ca80ff 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -1046,7 +1046,7 @@ RSpec.describe API::Users do post api('/users', admin), params: { email: 'invalid email', - password: Gitlab::Password.test_default, + password: 'password', name: 'test' } expect(response).to have_gitlab_http_status(:bad_request) @@ -1112,7 +1112,7 @@ RSpec.describe API::Users do post api('/users', admin), params: { email: 'test@example.com', - password: Gitlab::Password.test_default, + password: 'password', username: 'test', name: 'foo' } @@ -1124,7 +1124,7 @@ RSpec.describe API::Users do params: { name: 'foo', email: 'test@example.com', - password: Gitlab::Password.test_default, + password: 'password', username: 'foo' } end.to change { User.count }.by(0) @@ -1138,7 +1138,7 @@ RSpec.describe API::Users do params: { name: 'foo', email: 'foo@example.com', - password: Gitlab::Password.test_default, + password: 'password', username: 'test' } end.to change { User.count }.by(0) @@ -1152,7 +1152,7 @@ RSpec.describe API::Users do params: { name: 'foo', email: 'foo@example.com', - password: Gitlab::Password.test_default, + password: 'password', username: 'TEST' } end.to change { User.count }.by(0) @@ -1497,8 +1497,8 @@ RSpec.describe API::Users do context "with existing user" do before do - post api("/users", admin), params: { email: 'test@example.com', password: Gitlab::Password.test_default, username: 'test', name: 'test' } - post api("/users", admin), params: { email: 'foo@bar.com', password: Gitlab::Password.test_default, username: 'john', name: 'john' } + post api("/users", admin), params: { email: 'test@example.com', password: 'password', username: 'test', name: 'test' } + post api("/users", admin), params: { email: 'foo@bar.com', password: 'password', username: 'john', name: 'john' } @user = User.all.last end diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 340ed7bde53..0d24eb9ee2a 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -319,7 +319,7 @@ RSpec.describe 'Git HTTP requests' do context 'when user is using credentials with special characters' do context 'with password with special characters' do before do - user.update!(password: Gitlab::Password.test_default) + user.update!(password: 'RKszEwéC5kFnû∆f243fycGu§Gh9ftDj!U') end it 'allows clones' do @@ -1688,7 +1688,7 @@ RSpec.describe 'Git HTTP requests' do context 'when user is using credentials with special characters' do context 'with password with special characters' do before do - user.update!(password: Gitlab::Password.test_default) + user.update!(password: 'RKszEwéC5kFnû∆f243fycGu§Gh9ftDj!U') end it 'allows clones' do diff --git a/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb b/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb index e62a94b6df8..a920b90b97d 100644 --- a/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb +++ b/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb @@ -53,6 +53,24 @@ RSpec.describe Ci::CreatePipelineService do end context 'when failed to create the pipeline' do + context 'when errors are raised and masked variables are involved' do + let_it_be(:variable) { create(:ci_variable, project: project, key: 'GL_TOKEN', value: 'test_value', masked: true) } + + let(:config) do + <<~YAML + include: + - local: $GL_TOKEN/gitlab-ci.txt + YAML + end + + it 'contains errors and masks variables' do + error_message = "Included file `xxxxxxxxxx/gitlab-ci.txt` does not have YAML extension!" + expect(pipeline.yaml_errors).to eq(error_message) + expect(pipeline.error_messages.map(&:content)).to contain_exactly(error_message) + expect(pipeline.errors.full_messages).to contain_exactly(error_message) + end + end + context 'when warnings are raised' do let(:config) do <<~YAML diff --git a/spec/services/users/create_service_spec.rb b/spec/services/users/create_service_spec.rb index ab9da82e91c..74340bac055 100644 --- a/spec/services/users/create_service_spec.rb +++ b/spec/services/users/create_service_spec.rb @@ -12,7 +12,7 @@ RSpec.describe Users::CreateService do context 'when required parameters are provided' do let(:params) do - { name: 'John Doe', username: 'jduser', email: email, password: Gitlab::Password.test_default } + { name: 'John Doe', username: 'jduser', email: email, password: 'mydummypass' } end it 'returns a persisted user' do @@ -82,13 +82,13 @@ RSpec.describe Users::CreateService do context 'when force_random_password parameter is true' do let(:params) do - { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: Gitlab::Password.test_default, force_random_password: true } + { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', force_random_password: true } end it 'generates random password' do user = service.execute - expect(user.password).not_to eq Gitlab::Password.test_default + expect(user.password).not_to eq 'mydummypass' expect(user.password).to be_present end end @@ -99,7 +99,7 @@ RSpec.describe Users::CreateService do name: 'John Doe', username: 'jduser', email: 'jd@example.com', - password: Gitlab::Password.test_default, + password: 'mydummypass', password_automatically_set: true } end @@ -121,7 +121,7 @@ RSpec.describe Users::CreateService do context 'when skip_confirmation parameter is true' do let(:params) do - { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: Gitlab::Password.test_default, skip_confirmation: true } + { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', skip_confirmation: true } end it 'confirms the user' do @@ -131,7 +131,7 @@ RSpec.describe Users::CreateService do context 'when reset_password parameter is true' do let(:params) do - { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: Gitlab::Password.test_default, reset_password: true } + { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', reset_password: true } end it 'resets password even if a password parameter is given' do @@ -152,7 +152,7 @@ RSpec.describe Users::CreateService do context 'with nil user' do let(:params) do - { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: Gitlab::Password.test_default, skip_confirmation: true } + { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', skip_confirmation: true } end let(:service) { described_class.new(nil, params) } diff --git a/spec/support/helpers/login_helpers.rb b/spec/support/helpers/login_helpers.rb index c0734bae375..7666d71f13c 100644 --- a/spec/support/helpers/login_helpers.rb +++ b/spec/support/helpers/login_helpers.rb @@ -91,11 +91,12 @@ module LoginHelpers # user - User instance to login with # remember - Whether or not to check "Remember me" (default: false) # two_factor_auth - If two-factor authentication is enabled (default: false) - def gitlab_sign_in_with(user, remember: false, two_factor_auth: false) + # password - password to attempt to login with + def gitlab_sign_in_with(user, remember: false, two_factor_auth: false, password: nil) visit new_user_session_path fill_in "user_login", with: user.email - fill_in "user_password", with: Gitlab::Password.test_default + fill_in "user_password", with: (password || "12345678") check 'user_remember_me' if remember click_button "Sign in" diff --git a/spec/support/shared_contexts/policies/project_policy_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_shared_context.rb index 3641edc845a..a78953e8199 100644 --- a/spec/support/shared_contexts/policies/project_policy_shared_context.rb +++ b/spec/support/shared_contexts/policies/project_policy_shared_context.rb @@ -15,7 +15,7 @@ RSpec.shared_context 'ProjectPolicy context' do let(:base_guest_permissions) do %i[ - award_emoji create_issue create_merge_request_in create_note + award_emoji create_issue create_note create_project read_issue_board read_issue read_issue_iid read_issue_link read_label read_planning_hierarchy read_issue_board_list read_milestone read_note read_project read_project_for_iids read_project_member read_release read_snippet @@ -26,12 +26,12 @@ RSpec.shared_context 'ProjectPolicy context' do let(:base_reporter_permissions) do %i[ admin_issue admin_issue_link admin_label admin_issue_board_list - create_snippet create_incident daily_statistics download_code + create_snippet create_incident daily_statistics create_merge_request_in download_code download_wiki_code fork_project metrics_dashboard read_build read_commit_status read_confidential_issues read_container_image read_deployment read_environment read_merge_request read_metrics_dashboard_annotation read_pipeline read_prometheus - read_sentry_issue update_issue + read_sentry_issue update_issue create_merge_request_in ] end @@ -66,7 +66,7 @@ RSpec.shared_context 'ProjectPolicy context' do let(:public_permissions) do %i[ - build_download_code build_read_container_image download_code + build_download_code build_read_container_image create_merge_request_in download_code download_wiki_code fork_project read_commit_status read_container_image read_pipeline read_release ] diff --git a/spec/support/shared_examples/policies/project_policy_shared_examples.rb b/spec/support/shared_examples/policies/project_policy_shared_examples.rb index a4243db6bc9..63e4d458ad4 100644 --- a/spec/support/shared_examples/policies/project_policy_shared_examples.rb +++ b/spec/support/shared_examples/policies/project_policy_shared_examples.rb @@ -107,6 +107,19 @@ RSpec.shared_examples 'deploy token does not get confused with user' do end RSpec.shared_examples 'project policies as guest' do + context 'abilities for public projects' do + let(:project) { public_project } + let(:current_user) { guest } + + it do + expect_allowed(*guest_permissions) + expect_allowed(*public_permissions) + expect_disallowed(*developer_permissions) + expect_disallowed(*maintainer_permissions) + expect_disallowed(*owner_permissions) + end + end + context 'abilities for non-public projects' do let(:project) { private_project } let(:current_user) { guest } diff --git a/spec/tasks/gitlab/password_rake_spec.rb b/spec/tasks/gitlab/password_rake_spec.rb index ec18d713351..65bba836024 100644 --- a/spec/tasks/gitlab/password_rake_spec.rb +++ b/spec/tasks/gitlab/password_rake_spec.rb @@ -3,7 +3,7 @@ require 'rake_helper' RSpec.describe 'gitlab:password rake tasks', :silence_stdout do - let_it_be(:user_1) { create(:user, username: 'foobar', password: Gitlab::Password.test_default) } + let_it_be(:user_1) { create(:user, username: 'foobar', password: 'initial_password') } def stub_username(username) allow(Gitlab::TaskHelpers).to receive(:prompt).with('Enter username: ').and_return(username) @@ -19,14 +19,14 @@ RSpec.describe 'gitlab:password rake tasks', :silence_stdout do Rake.application.rake_require 'tasks/gitlab/password' stub_username('foobar') - stub_password(Gitlab::Password.test_default) + stub_password('secretpassword') end describe ':reset' do context 'when all inputs are correct' do it 'updates the password properly' do run_rake_task('gitlab:password:reset', user_1.username) - expect(user_1.reload.valid_password?(Gitlab::Password.test_default)).to eq(true) + expect(user_1.reload.valid_password?('secretpassword')).to eq(true) end end @@ -55,7 +55,7 @@ RSpec.describe 'gitlab:password rake tasks', :silence_stdout do context 'when passwords do not match' do before do - stub_password(Gitlab::Password.test_default, "different" + Gitlab::Password.test_default) + stub_password('randompassword', 'differentpassword') end it 'aborts with an error' do |