diff options
author | Rémy Coutable <remy@rymai.me> | 2016-03-16 12:16:49 +0300 |
---|---|---|
committer | Rémy Coutable <remy@rymai.me> | 2016-03-16 12:16:49 +0300 |
commit | cacd3373ff7d5f3c8cc5774527e2474f9a28fc92 (patch) | |
tree | 58e4426905d64660d8c04020514a86bdb4306264 | |
parent | 1e8bf60f40426de9cc6671a42019237688a848ac (diff) | |
parent | 374037b8a326b82a7787b2e29da820aa9c4390b3 (diff) |
Merge remote-tracking branch 'origin/master' into 8-6-stable
25 files changed, 163 insertions, 43 deletions
diff --git a/CHANGELOG b/CHANGELOG index 7f076f70c7c..fcf659c07f9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,7 @@ v 8.6.0 (unreleased) setup. A password can be provided during setup (see installation docs), or GitLab will ask the user to create a new one upon first visit. - Fix issue when pushing to projects ending in .wiki + - Add support for wiki with UTF-8 page names (Hiroyuki Sato) - Don't load all of GitLab in mail_room - Update `omniauth-saml` to 1.5.0 to allow for custom response attributes to be set - Memoize @group in Admin::GroupsController (Yatish Mehta) @@ -39,6 +40,10 @@ v 8.6.0 (unreleased) - Add ability to show archived projects on dashboard, explore and group pages - Move group activity to separate page - Continue parameters are checked to ensure redirection goes to the same instance + - User deletion is now done in the background so the request can not time out + +v 8.5.7 + - Bump Git version requirement to 2.7.3 v 8.5.6 - Obtain a lease before querying LDAP @@ -58,7 +58,9 @@ gem "gitlab_git", '~> 9.0' gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: "omniauth-ldap" # Git Wiki -gem 'gollum-lib', '~> 4.1.0' +# Required manually in config/initializers/gollum.rb to control load order +gem 'gollum-lib', '~> 4.1.0', require: false +gem 'gollum-rugged_adapter', '~> 0.4.2', require: false # Language detection gem "github-linguist", "~> 4.7.0", require: "linguist" diff --git a/Gemfile.lock b/Gemfile.lock index f4f5649eb75..669bfcf4d6b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -381,6 +381,9 @@ GEM rouge (~> 1.9) sanitize (~> 2.1.0) stringex (~> 2.5.1) + gollum-rugged_adapter (0.4.2) + mime-types (>= 1.15) + rugged (~> 0.24.0, >= 0.21.3) gon (6.0.1) actionpack (>= 3.0) json @@ -703,7 +706,7 @@ GEM rubyntlm (0.5.2) rubypants (0.2.0) rufus-scheduler (3.1.10) - rugged (0.24.0b13) + rugged (0.24.0) safe_yaml (1.0.4) sanitize (2.1.0) nokogiri (>= 1.4.4) @@ -941,6 +944,7 @@ DEPENDENCIES gitlab_meta (= 7.0) gitlab_omniauth-ldap (~> 1.2.1) gollum-lib (~> 4.1.0) + gollum-rugged_adapter (~> 0.4.2) gon (~> 6.0.1) grape (~> 0.13.0) grape-entity (~> 0.4.2) diff --git a/README.md b/README.md index 3ec1d4a776c..208427fcf8c 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ GitLab is a Ruby on Rails application that runs on the following software: - Ubuntu/Debian/CentOS/RHEL - Ruby (MRI) 2.1 -- Git 1.7.10+ +- Git 2.7.3+ - Redis 2.8+ - MySQL or PostgreSQL diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 5b647fc6176..309da34da07 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -161,9 +161,8 @@ .dropdown-menu-user-full-name { display: block; - margin-bottom: 2px; font-weight: 600; - line-height: 1; + line-height: 16px; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; @@ -171,7 +170,7 @@ .dropdown-menu-user-username { display: block; - line-height: 1; + line-height: 16px; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; diff --git a/app/controllers/admin/abuse_reports_controller.rb b/app/controllers/admin/abuse_reports_controller.rb index 2463cfa87be..e9b0972bdd8 100644 --- a/app/controllers/admin/abuse_reports_controller.rb +++ b/app/controllers/admin/abuse_reports_controller.rb @@ -6,7 +6,7 @@ class Admin::AbuseReportsController < Admin::ApplicationController def destroy abuse_report = AbuseReport.find(params[:id]) - abuse_report.remove_user if params[:remove_user] + abuse_report.remove_user(deleted_by: current_user) if params[:remove_user] abuse_report.destroy render nothing: true diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 87f4fb455b8..3063d299b1a 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -119,10 +119,10 @@ class Admin::UsersController < Admin::ApplicationController end def destroy - DeleteUserService.new(current_user).execute(user) + DeleteUserWorker.perform_async(current_user.id, user.id) respond_to do |format| - format.html { redirect_to admin_users_path } + format.html { redirect_to admin_users_path, notice: "The user is being deleted." } format.json { head :ok } end end diff --git a/app/models/abuse_report.rb b/app/models/abuse_report.rb index cc59aa4e911..b61f5123127 100644 --- a/app/models/abuse_report.rb +++ b/app/models/abuse_report.rb @@ -19,9 +19,9 @@ class AbuseReport < ActiveRecord::Base validates :message, presence: true validates :user_id, uniqueness: { message: 'has already been reported' } - def remove_user + def remove_user(deleted_by:) user.block - user.destroy + DeleteUserWorker.perform_async(deleted_by.id, user.id, delete_solo_owned_groups: true) end def notify diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index c96e6f0b8ea..59b1b86d1fb 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -2,7 +2,7 @@ class ProjectWiki include Gitlab::ShellAdapter MARKUPS = { - 'Markdown' => :md, + 'Markdown' => :markdown, 'RDoc' => :rdoc, 'AsciiDoc' => :asciidoc } unless defined?(MARKUPS) @@ -47,7 +47,7 @@ class ProjectWiki def wiki @wiki ||= begin Gollum::Wiki.new(path_to_repo) - rescue Gollum::NoSuchPathError + rescue Rugged::OSError create_repo! end end @@ -90,7 +90,7 @@ class ProjectWiki def create_page(title, content, format = :markdown, message = nil) commit = commit_details(:created, message, title) - wiki.write_page(title, format, content, commit) + wiki.write_page(title, format.to_sym, content, commit) update_project_activity rescue Gollum::DuplicatePageError => e @@ -101,7 +101,7 @@ class ProjectWiki def update_page(page, content, format = :markdown, message = nil) commit = commit_details(:updated, message, page.title) - wiki.update_page(page, page.name, format, content, commit) + wiki.update_page(page, page.name, format.to_sym, content, commit) update_project_activity end diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index dbd70dc5a44..526760779a4 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -62,7 +62,7 @@ class WikiPage # The raw content of this page. def content @attributes[:content] ||= if @page - @page.raw_data + @page.text_data end end diff --git a/app/services/delete_user_service.rb b/app/services/delete_user_service.rb index 173e50c9206..ce79287e35a 100644 --- a/app/services/delete_user_service.rb +++ b/app/services/delete_user_service.rb @@ -5,18 +5,22 @@ class DeleteUserService @current_user = current_user end - def execute(user) - if user.solo_owned_groups.present? + def execute(user, options = {}) + if !options[:delete_solo_owned_groups] && user.solo_owned_groups.present? user.errors[:base] << 'You must transfer ownership or delete groups before you can remove user' - user - else - user.personal_projects.each do |project| - # Skip repository removal because we remove directory with namespace - # that contain all this repositories - ::Projects::DestroyService.new(project, current_user, skip_repo: true).pending_delete! - end + return user + end + + user.solo_owned_groups.each do |group| + DestroyGroupService.new(group, current_user).execute + end - user.destroy + user.personal_projects.each do |project| + # Skip repository removal because we remove directory with namespace + # that contain all this repositories + ::Projects::DestroyService.new(project, current_user, skip_repo: true).pending_delete! end + + user.destroy end end diff --git a/app/services/destroy_group_service.rb b/app/services/destroy_group_service.rb index 9189de390a2..3c42ac61be4 100644 --- a/app/services/destroy_group_service.rb +++ b/app/services/destroy_group_service.rb @@ -6,12 +6,12 @@ class DestroyGroupService end def execute - @group.projects.each do |project| + group.projects.each do |project| # Skip repository removal because we remove directory with namespace # that contain all this repositories ::Projects::DestroyService.new(project, current_user, skip_repo: true).pending_delete! end - @group.destroy + group.destroy end end diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml index 42a3c2c3f02..3eb0db276b2 100644 --- a/app/views/shared/issuable/_filter.html.haml +++ b/app/views/shared/issuable/_filter.html.haml @@ -16,7 +16,7 @@ - if params[:assignee_id] = hidden_field_tag(:assignee_id, params[:assignee_id]) = dropdown_tag("Assignee", options: { toggle_class: "js-user-search js-filter-submit js-assignee-search", title: "Filter by assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee", - placeholder: "Search assignee", data: { any_user: "Any Author", first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: (@project.id if @project), selected: params[:assignee_id], field_name: "assignee_id" } }) + placeholder: "Search assignee", data: { any_user: "Any Assignee", first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: (@project.id if @project), selected: params[:assignee_id], field_name: "assignee_id" } }) .filter-item.inline.milestone-filter - if params[:milestone_title] diff --git a/app/workers/delete_user_worker.rb b/app/workers/delete_user_worker.rb new file mode 100644 index 00000000000..6ff361e4d80 --- /dev/null +++ b/app/workers/delete_user_worker.rb @@ -0,0 +1,10 @@ +class DeleteUserWorker + include Sidekiq::Worker + + def perform(current_user_id, delete_user_id, options = {}) + delete_user = User.find(delete_user_id) + current_user = User.find(current_user_id) + + DeleteUserService.new(current_user).execute(delete_user, options.symbolize_keys) + end +end diff --git a/config/initializers/gollum.rb b/config/initializers/gollum.rb new file mode 100644 index 00000000000..703f24f93b2 --- /dev/null +++ b/config/initializers/gollum.rb @@ -0,0 +1,13 @@ +module Gollum + GIT_ADAPTER = "rugged" +end +require "gollum-lib" + +module Gollum + class Committer + # Patch for UTF-8 path + def method_missing(name, *args) + index.send(name, *args) + end + end +end diff --git a/doc/install/installation.md b/doc/install/installation.md index 4f011397269..362b27350cc 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -76,7 +76,7 @@ Make sure you have the right version of Git installed # Install Git sudo apt-get install -y git-core - # Make sure Git is version 1.7.10 or higher, for example 1.7.12 or 2.0.0 + # Make sure Git is version 2.7.3 or higher git --version Is the system packaged Git too old? Remove it and compile from source. diff --git a/features/support/capybara.rb b/features/support/capybara.rb index f33379f76c9..fe9e39cf509 100644 --- a/features/support/capybara.rb +++ b/features/support/capybara.rb @@ -9,7 +9,7 @@ Capybara.register_driver :poltergeist do |app| Capybara::Poltergeist::Driver.new(app, js_errors: true, timeout: timeout, window_size: [1366, 768]) end -Capybara.default_wait_time = timeout +Capybara.default_max_wait_time = timeout Capybara.ignore_hidden_elements = false unless ENV['CI'] || ENV['CI_SERVER'] diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb index d0f6ba23ab4..d0815fc7eea 100644 --- a/lib/gitlab/diff/parser.rb +++ b/lib/gitlab/diff/parser.rb @@ -4,6 +4,8 @@ module Gitlab include Enumerable def parse(lines) + return [] if lines.blank? + @lines = lines line_obj_index = 0 line_old = 1 diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 581ab26db79..27ed57efe55 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -913,7 +913,7 @@ namespace :gitlab do end def check_git_version - required_version = Gitlab::VersionInfo.new(1, 7, 10) + required_version = Gitlab::VersionInfo.new(2, 7, 3) current_version = Gitlab::VersionInfo.parse(run(%W(#{Gitlab.config.git.bin_path} --version))) puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\"" diff --git a/spec/lib/gitlab/diff/parser_spec.rb b/spec/lib/gitlab/diff/parser_spec.rb index f576c39284e..cdff063a9ed 100644 --- a/spec/lib/gitlab/diff/parser_spec.rb +++ b/spec/lib/gitlab/diff/parser_spec.rb @@ -90,4 +90,9 @@ eos end end end + + context 'when lines is empty' do + it { expect(parser.parse([])).to eq([]) } + it { expect(parser.parse(nil)).to eq([]) } + end end diff --git a/spec/models/abuse_report_spec.rb b/spec/models/abuse_report_spec.rb index 4799bbaa57c..ac12ab6c757 100644 --- a/spec/models/abuse_report_spec.rb +++ b/spec/models/abuse_report_spec.rb @@ -13,7 +13,8 @@ require 'rails_helper' RSpec.describe AbuseReport, type: :model do - subject { create(:abuse_report) } + subject { create(:abuse_report) } + let(:user) { create(:user) } it { expect(subject).to be_valid } @@ -31,17 +32,14 @@ RSpec.describe AbuseReport, type: :model do describe '#remove_user' do it 'blocks the user' do - report = build(:abuse_report) - - allow(report.user).to receive(:destroy) - - expect { report.remove_user }.to change { report.user.blocked? }.to(true) + expect { subject.remove_user(deleted_by: user) }.to change { subject.user.blocked? }.to(true) end - it 'removes the user' do - report = build(:abuse_report) + it 'lets a worker delete the user' do + expect(DeleteUserWorker).to receive(:perform_async).with(user.id, subject.user.id, + delete_solo_owned_groups: true) - expect { report.remove_user }.to change { User.count }.by(-1) + subject.remove_user(deleted_by: user) end end diff --git a/spec/services/delete_user_service_spec.rb b/spec/services/delete_user_service_spec.rb new file mode 100644 index 00000000000..a65938fa03b --- /dev/null +++ b/spec/services/delete_user_service_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +describe DeleteUserService, services: true do + describe "Deletes a user and all their personal projects" do + let!(:user) { create(:user) } + let!(:current_user) { create(:user) } + let!(:namespace) { create(:namespace, owner: user) } + let!(:project) { create(:project, namespace: namespace) } + + context 'no options are given' do + it 'deletes the user' do + DeleteUserService.new(current_user).execute(user) + + expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) + end + + it 'will delete the project in the near future' do + expect_any_instance_of(Projects::DestroyService).to receive(:pending_delete!).once + + DeleteUserService.new(current_user).execute(user) + end + end + + context "solo owned groups present" do + let(:solo_owned) { create(:group) } + let(:member) { create(:group_member) } + let(:user) { member.user } + + before do + solo_owned.group_members = [member] + DeleteUserService.new(current_user).execute(user) + end + + it 'does not delete the user' do + expect(User.find(user.id)).to eq user + end + end + + context "deletions with solo owned groups" do + let(:solo_owned) { create(:group) } + let(:member) { create(:group_member) } + let(:user) { member.user } + + before do + solo_owned.group_members = [member] + DeleteUserService.new(current_user).execute(user, delete_solo_owned_groups: true) + end + + it 'deletes solo owned groups' do + expect { Project.find(solo_owned.id) }.to raise_error(ActiveRecord::RecordNotFound) + end + + it 'deletes the user' do + expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound) + end + end + end +end diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index 65d59e6813c..e1f90e17cce 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -10,7 +10,7 @@ Capybara.register_driver :poltergeist do |app| Capybara::Poltergeist::Driver.new(app, js_errors: true, timeout: timeout, window_size: [1366, 768]) end -Capybara.default_wait_time = timeout +Capybara.default_max_wait_time = timeout Capybara.ignore_hidden_elements = true unless ENV['CI'] || ENV['CI_SERVER'] diff --git a/spec/support/wait_for_ajax.rb b/spec/support/wait_for_ajax.rb index 692d219e9f1..b90fc112671 100644 --- a/spec/support/wait_for_ajax.rb +++ b/spec/support/wait_for_ajax.rb @@ -1,6 +1,6 @@ module WaitForAjax def wait_for_ajax - Timeout.timeout(Capybara.default_wait_time) do + Timeout.timeout(Capybara.default_max_wait_time) do loop until finished_all_ajax_requests? end end diff --git a/spec/workers/delete_user_worker_spec.rb b/spec/workers/delete_user_worker_spec.rb new file mode 100644 index 00000000000..14c56521280 --- /dev/null +++ b/spec/workers/delete_user_worker_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe DeleteUserWorker do + let!(:user) { create(:user) } + let!(:current_user) { create(:user) } + + it "calls the DeleteUserWorker with the params it was given" do + expect_any_instance_of(DeleteUserService).to receive(:execute). + with(user, {}) + + DeleteUserWorker.new.perform(current_user.id, user.id) + end + + it "uses symbolized keys" do + expect_any_instance_of(DeleteUserService).to receive(:execute). + with(user, test: "test") + + DeleteUserWorker.new.perform(current_user.id, user.id, "test" => "test") + end +end |