diff options
23 files changed, 222 insertions, 80 deletions
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue index c3ca147e850..3aca38399fb 100644 --- a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue +++ b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue @@ -52,6 +52,7 @@ export default { </strong> <changed-file-icon :file="activeFile" + class="ml-0" /> <div class="ml-auto"> <button diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue index 10c78a80302..ee0e72cd05f 100644 --- a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue +++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue @@ -120,10 +120,6 @@ export default { :css-classes="iconClass" /> </div> - <component - :is="actionComponent" - :path="file.path" - /> </div> </div> </div> diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue index b5eaaf054e7..0e445a29de4 100644 --- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue +++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue @@ -114,6 +114,8 @@ export default { }, beforeDestroy() { eventHub.$off('mr.discussion.updated', this.checkStatus); + this.pollingInterval.destroy(); + this.deploymentsInterval.destroy(); }, methods: { createService(store) { diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 838527aaa41..fb2808edf47 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -12,6 +12,7 @@ class ApplicationController < ActionController::Base include WorkhorseHelper include EnforcesTwoFactorAuthentication include WithPerformanceBar + include InvalidUTF8ErrorHandler before_action :authenticate_sessionless_user! before_action :authenticate_user! diff --git a/app/controllers/concerns/invalid_utf8_error_handler.rb b/app/controllers/concerns/invalid_utf8_error_handler.rb new file mode 100644 index 00000000000..a7ea0d00a43 --- /dev/null +++ b/app/controllers/concerns/invalid_utf8_error_handler.rb @@ -0,0 +1,25 @@ +module InvalidUTF8ErrorHandler + extend ActiveSupport::Concern + + included do + rescue_from ArgumentError, with: :handle_invalid_utf8 + end + + private + + def handle_invalid_utf8(error) + if error.message == "invalid byte sequence in UTF-8" + render_412 + else + raise(error) + end + end + + def render_412 + respond_to do |format| + format.html { render "errors/precondition_failed", layout: "errors", status: 412 } + format.js { render json: { error: 'Invalid UTF-8' }, status: :precondition_failed, content_type: 'application/json' } + format.any { head :precondition_failed } + end + end +end diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml index 3764e86dd8b..7dced0942f5 100644 --- a/app/views/devise/shared/_tabs_ldap.html.haml +++ b/app/views/devise/shared/_tabs_ldap.html.haml @@ -10,4 +10,4 @@ = link_to 'Standard', '#login-pane', class: 'nav-link qa-standard-tab', 'data-toggle' => 'tab' - if allow_signup? %li.nav-item - = link_to 'Register', '#register-pane', class: 'nav-link', 'data-toggle' => 'tab' + = link_to 'Register', '#register-pane', class: 'nav-link qa-register-tab', 'data-toggle' => 'tab' diff --git a/app/views/errors/precondition_failed.html.haml b/app/views/errors/precondition_failed.html.haml new file mode 100644 index 00000000000..aa3869f33a9 --- /dev/null +++ b/app/views/errors/precondition_failed.html.haml @@ -0,0 +1,8 @@ +- content_for(:title, 'Encoding Error') +%img{ :alt => "GitLab Logo", :src => image_path('logo.svg') } + %h1 + 412 +.container + %h3 Precondition failed + %hr + %p Page can't be loaded because of invalid parameters. diff --git a/changelogs/unreleased/enable-force-write-auth-keys-restore.yml b/changelogs/unreleased/enable-force-write-auth-keys-restore.yml new file mode 100644 index 00000000000..f6c83cc7950 --- /dev/null +++ b/changelogs/unreleased/enable-force-write-auth-keys-restore.yml @@ -0,0 +1,5 @@ +--- +title: Enable the ability to use the force env for rebuilding authorized_keys during a restore +merge_request: 21896 +author: +type: fixed diff --git a/changelogs/unreleased/fa-handle_invalid_utf8_errors.yml b/changelogs/unreleased/fa-handle_invalid_utf8_errors.yml new file mode 100644 index 00000000000..9cae193d858 --- /dev/null +++ b/changelogs/unreleased/fa-handle_invalid_utf8_errors.yml @@ -0,0 +1,5 @@ +--- +title: Render 412 when invalid UTF-8 parameters are passed to controller +merge_request: +author: +type: other diff --git a/changelogs/unreleased/osw-clean-up-phase-for-diff-files-removal.yml b/changelogs/unreleased/osw-clean-up-phase-for-diff-files-removal.yml new file mode 100644 index 00000000000..03189d934a7 --- /dev/null +++ b/changelogs/unreleased/osw-clean-up-phase-for-diff-files-removal.yml @@ -0,0 +1,5 @@ +--- +title: Add clean-up phase for ScheduleDiffFilesDeletion migration +merge_request: 21734 +author: +type: other diff --git a/db/post_migrate/20180913051323_consume_remaining_diff_files_deletion_jobs.rb b/db/post_migrate/20180913051323_consume_remaining_diff_files_deletion_jobs.rb new file mode 100644 index 00000000000..ed9422a3894 --- /dev/null +++ b/db/post_migrate/20180913051323_consume_remaining_diff_files_deletion_jobs.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class ConsumeRemainingDiffFilesDeletionJobs < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + MIGRATION = 'ScheduleDiffFilesDeletion'.freeze + TMP_INDEX = 'tmp_partial_diff_id_with_files_index'.freeze + + def up + # Perform any ongoing background migration that might still be scheduled. + Gitlab::BackgroundMigration.steal(MIGRATION) + + remove_concurrent_index_by_name(:merge_request_diffs, TMP_INDEX) + end + + def down + add_concurrent_index(:merge_request_diffs, :id, where: "(state NOT IN ('without_files', 'empty'))", name: TMP_INDEX) + end +end diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 1d29f6d4e43..98fce7efb0b 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -523,7 +523,7 @@ more of the following options: - `BACKUP=timestamp_of_backup` - Required if more than one backup exists. Read what the [backup timestamp is about](#backup-timestamp). -- `force=yes` - Does not ask if the authorized_keys file should get regenerated and assumes 'yes' for warning that database tables will be removed. +- `force=yes` - Does not ask if the authorized_keys file should get regenerated and assumes 'yes' for warning that database tables will be removed, enabling the "Write to authorized_keys file" setting, and updating LDAP providers. If you are restoring into directories that are mountpoints you will need to make sure these directories are empty before attempting a restore. Otherwise GitLab diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake index 4fcbbbf8c9d..0ebc6f00793 100644 --- a/lib/tasks/gitlab/shell.rake +++ b/lib/tasks/gitlab/shell.rake @@ -92,9 +92,11 @@ namespace :gitlab do def setup warn_user_is_not_gitlab + ensure_write_to_authorized_keys_is_enabled + unless ENV['force'] == 'yes' - puts "This will rebuild an authorized_keys file." - puts "You will lose any data stored in authorized_keys file." + puts "This task will now rebuild the authorized_keys file." + puts "You will lose any data stored in the authorized_keys file." ask_to_continue puts "" end @@ -118,4 +120,44 @@ namespace :gitlab do puts "Quitting...".color(:red) exit 1 end + + def ensure_write_to_authorized_keys_is_enabled + return if Gitlab::CurrentSettings.current_application_settings.authorized_keys_enabled + + puts authorized_keys_is_disabled_warning + + unless ENV['force'] == 'yes' + puts 'Do you want to permanently enable the "Write to authorized_keys file" setting now?' + ask_to_continue + end + + puts 'Enabling the "Write to authorized_keys file" setting...' + Gitlab::CurrentSettings.current_application_settings.update!(authorized_keys_enabled: true) + + puts 'Successfully enabled "Write to authorized_keys file"!' + puts '' + end + + def authorized_keys_is_disabled_warning + <<-MSG.strip_heredoc + WARNING + + The "Write to authorized_keys file" setting is disabled, which prevents + the file from being rebuilt! + + It should be enabled for most GitLab installations. Large installations + may wish to disable it as part of speeding up SSH operations. + + See https://docs.gitlab.com/ee/administration/operations/fast_ssh_key_lookup.html + + If you did not intentionally disable this option in Admin Area > Settings, + then you may have been affected by the 9.3.0 bug in which the new setting + was disabled by default. + + https://gitlab.com/gitlab-org/gitlab-ee/issues/2738 + + It was reverted in 9.3.1 and fixed in 9.3.3, however, if Settings were + saved while the setting was unchecked, then it is still disabled. + MSG + end end diff --git a/qa/qa/factory/resource/user.rb b/qa/qa/factory/resource/user.rb index eac2a873bd5..34b52223b2d 100644 --- a/qa/qa/factory/resource/user.rb +++ b/qa/qa/factory/resource/user.rb @@ -37,7 +37,10 @@ module QA product(:password) { |factory| factory.password } def fabricate! - Page::Menu::Main.perform { |main| main.sign_out } + # Don't try to log-out if we're not logged-in + if Page::Menu::Main.act { has_personal_area?(wait: 0) } + Page::Menu::Main.perform { |main| main.sign_out } + end if credentials_given? Page::Main::Login.perform do |login| diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index 30e35bf7abb..a87536671c6 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -76,6 +76,10 @@ module QA find_element(name).set(content) end + def has_element?(name) + has_css?(element_selector_css(name)) + end + def within_element(name) page.within(element_selector_css(name)) do yield diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb index e9e49964e63..89542b49d0e 100644 --- a/qa/qa/page/main/login.rb +++ b/qa/qa/page/main/login.rb @@ -23,6 +23,7 @@ module QA view 'app/views/devise/shared/_tabs_ldap.html.haml' do element :ldap_tab element :standard_tab + element :register_tab end view 'app/views/devise/shared/_tabs_normal.html.haml' do @@ -35,7 +36,7 @@ module QA # we need to wait for the instance to start. That said, in some cases # we are already logged-in so we check both cases here. wait(max: 500) do - page.has_css?('.login-page') || + has_css?('.login-page') || Page::Menu::Main.act { has_personal_area?(wait: 0) } end end @@ -78,12 +79,28 @@ module QA '/users/sign_in' end + def has_sign_in_tab? + has_element?(:sign_in_tab) + end + + def has_ldap_tab? + has_element?(:ldap_tab) + end + + def has_standard_tab? + has_element?(:standard_tab) + end + def sign_in_tab? - page.has_button?('Sign in') + has_css?(".active", text: 'Sign in') end def ldap_tab? - page.has_link?('LDAP') + has_css?(".active", text: 'LDAP') + end + + def standard_tab? + has_css?(".active", text: 'Standard') end def switch_to_sign_in_tab @@ -113,8 +130,8 @@ module QA end def sign_in_using_gitlab_credentials(user) - switch_to_sign_in_tab unless sign_in_tab? - switch_to_standard_tab if ldap_tab? + switch_to_sign_in_tab if has_sign_in_tab? + switch_to_standard_tab if has_standard_tab? fill_element :login_field, user.username fill_element :password_field, user.password @@ -122,7 +139,7 @@ module QA end def set_initial_password_if_present - return unless page.has_content?('Change your password') + return unless has_content?('Change your password') fill_element :password_field, Runtime::User.password fill_element :password_confirmation, Runtime::User.password diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb new file mode 100644 index 00000000000..478a5cb9c4c --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module QA + shared_examples 'registration and login' do + it 'user registers and logs in' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + + Factory::Resource::User.fabricate! + + # TODO, since `Signed in successfully` message was removed + # this is the only way to tell if user is signed in correctly. + # + Page::Menu::Main.perform do |menu| + expect(menu).to have_personal_area + end + end + end + + context :manage do + describe 'standard' do + it_behaves_like 'registration and login' + end + end + + context :manage, :orchestrated, :ldap do + describe 'while LDAP is enabled' do + it_behaves_like 'registration and login' + end + end +end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index fbf116e533b..7202cee04ea 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -694,4 +694,38 @@ describe ApplicationController do expect(response).to have_gitlab_http_status(403) end end + + context 'when invalid UTF-8 parameters are received' do + controller(described_class) do + def index + params[:text].split(' ') + + render json: :ok + end + end + + before do + sign_in user + end + + context 'html' do + it 'renders 412' do + get :index, text: "hi \255" + + expect(response).to have_gitlab_http_status(412) + expect(response).to render_template :precondition_failed + end + end + + context 'js' do + it 'renders 412' do + get :index, text: "hi \255", format: :js + + json_response = JSON.parse(response.body) + + expect(response).to have_gitlab_http_status(412) + expect(json_response['error']).to eq('Invalid UTF-8') + end + end + end end diff --git a/spec/features/projects/tree/create_directory_spec.rb b/spec/features/projects/tree/create_directory_spec.rb index 9e58280b868..2cb2a23b7be 100644 --- a/spec/features/projects/tree/create_directory_spec.rb +++ b/spec/features/projects/tree/create_directory_spec.rb @@ -43,7 +43,7 @@ describe 'Multi-file editor new directory', :js do find('.js-ide-commit-mode').click find('.multi-file-commit-list-item').hover - first('.multi-file-discard-btn .btn').click + click_button 'Stage' fill_in('commit-message', with: 'commit message ide') diff --git a/spec/features/projects/tree/create_file_spec.rb b/spec/features/projects/tree/create_file_spec.rb index a04d3566a7e..9f5524da8e9 100644 --- a/spec/features/projects/tree/create_file_spec.rb +++ b/spec/features/projects/tree/create_file_spec.rb @@ -35,7 +35,7 @@ describe 'Multi-file editor new file', :js do find('.js-ide-commit-mode').click find('.multi-file-commit-list-item').hover - first('.multi-file-discard-btn .btn').click + click_button 'Stage' fill_in('commit-message', with: 'commit message ide') diff --git a/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js b/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js index b45ae5bbb0f..bf48d7bfdad 100644 --- a/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js +++ b/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js @@ -33,10 +33,6 @@ describe('Multi-file editor commit sidebar list item', () => { expect(vm.$el.querySelector('.multi-file-commit-list-path').textContent).toContain(f.path); }); - it('renders actionn button', () => { - expect(vm.$el.querySelector('.multi-file-discard-btn')).not.toBeNull(); - }); - it('opens a closed file in the editor when clicking the file path', done => { spyOn(vm, 'openPendingTab').and.callThrough(); spyOn(router, 'push'); diff --git a/spec/javascripts/ide/components/repo_commit_section_spec.js b/spec/javascripts/ide/components/repo_commit_section_spec.js index d09ccd7ac34..6c726c1e154 100644 --- a/spec/javascripts/ide/components/repo_commit_section_spec.js +++ b/spec/javascripts/ide/components/repo_commit_section_spec.js @@ -103,65 +103,6 @@ describe('RepoCommitSection', () => { }); }); - it('adds changed files into staged files', done => { - vm.$el.querySelector('.multi-file-discard-btn .btn').click(); - vm - .$nextTick() - .then(() => vm.$el.querySelector('.multi-file-discard-btn .btn').click()) - .then(vm.$nextTick) - .then(() => { - expect(vm.$el.querySelector('.ide-commit-list-container').textContent).toContain( - 'There are no unstaged changes', - ); - }) - .then(done) - .catch(done.fail); - }); - - it('stages a single file', done => { - vm.$el.querySelector('.multi-file-discard-btn .btn').click(); - - Vue.nextTick(() => { - expect( - vm.$el - .querySelector('.ide-commit-list-container') - .querySelectorAll('.multi-file-commit-list > li').length, - ).toBe(1); - - done(); - }); - }); - - it('discards a single file', done => { - vm.$el.querySelector('.multi-file-commit-list li:first-child .js-modal-primary-action').click(); - - Vue.nextTick(() => { - expect(vm.$el.querySelector('.ide-commit-list-container').textContent).not.toContain('file1'); - expect( - vm.$el - .querySelector('.ide-commit-list-container') - .querySelectorAll('.multi-file-commit-list > li').length, - ).toBe(1); - - done(); - }); - }); - - it('unstages a single file', done => { - vm.$el - .querySelectorAll('.multi-file-discard-btn')[2] - .querySelector('.btn') - .click(); - - Vue.nextTick(() => { - expect( - vm.$el.querySelectorAll('.ide-commit-list-container')[1].querySelectorAll('li').length, - ).toBe(1); - - done(); - }); - }); - describe('mounted', () => { it('opens last opened file', () => { expect(store.state.openFiles.length).toBe(1); diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js index 6342ea00436..6ac7138743b 100644 --- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js +++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js @@ -27,6 +27,10 @@ describe('mrWidgetOptions', () => { }); }); + afterEach(() => { + vm.$destroy(); + }); + describe('data', () => { it('should instantiate Store and Service', () => { expect(vm.mr).toBeDefined(); |