Commit cacd3373 authored by Rémy Coutable's avatar Rémy Coutable

Merge remote-tracking branch 'origin/master' into 8-6-stable

parents 1e8bf60f 374037b8
...@@ -10,6 +10,7 @@ v 8.6.0 (unreleased) ...@@ -10,6 +10,7 @@ v 8.6.0 (unreleased)
setup. A password can be provided during setup (see installation docs), or 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. GitLab will ask the user to create a new one upon first visit.
- Fix issue when pushing to projects ending in .wiki - 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 - 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 - Update `omniauth-saml` to 1.5.0 to allow for custom response attributes to be set
- Memoize @group in Admin::GroupsController (Yatish Mehta) - Memoize @group in Admin::GroupsController (Yatish Mehta)
...@@ -39,6 +40,10 @@ v 8.6.0 (unreleased) ...@@ -39,6 +40,10 @@ v 8.6.0 (unreleased)
- Add ability to show archived projects on dashboard, explore and group pages - Add ability to show archived projects on dashboard, explore and group pages
- Move group activity to separate page - Move group activity to separate page
- Continue parameters are checked to ensure redirection goes to the same instance - 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 v 8.5.6
- Obtain a lease before querying LDAP - Obtain a lease before querying LDAP
......
...@@ -58,7 +58,9 @@ gem "gitlab_git", '~> 9.0' ...@@ -58,7 +58,9 @@ gem "gitlab_git", '~> 9.0'
gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: "omniauth-ldap" gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: "omniauth-ldap"
# Git Wiki # 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 # Language detection
gem "github-linguist", "~> 4.7.0", require: "linguist" gem "github-linguist", "~> 4.7.0", require: "linguist"
......
...@@ -381,6 +381,9 @@ GEM ...@@ -381,6 +381,9 @@ GEM
rouge (~> 1.9) rouge (~> 1.9)
sanitize (~> 2.1.0) sanitize (~> 2.1.0)
stringex (~> 2.5.1) 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) gon (6.0.1)
actionpack (>= 3.0) actionpack (>= 3.0)
json json
...@@ -703,7 +706,7 @@ GEM ...@@ -703,7 +706,7 @@ GEM
rubyntlm (0.5.2) rubyntlm (0.5.2)
rubypants (0.2.0) rubypants (0.2.0)
rufus-scheduler (3.1.10) rufus-scheduler (3.1.10)
rugged (0.24.0b13) rugged (0.24.0)
safe_yaml (1.0.4) safe_yaml (1.0.4)
sanitize (2.1.0) sanitize (2.1.0)
nokogiri (>= 1.4.4) nokogiri (>= 1.4.4)
...@@ -941,6 +944,7 @@ DEPENDENCIES ...@@ -941,6 +944,7 @@ DEPENDENCIES
gitlab_meta (= 7.0) gitlab_meta (= 7.0)
gitlab_omniauth-ldap (~> 1.2.1) gitlab_omniauth-ldap (~> 1.2.1)
gollum-lib (~> 4.1.0) gollum-lib (~> 4.1.0)
gollum-rugged_adapter (~> 0.4.2)
gon (~> 6.0.1) gon (~> 6.0.1)
grape (~> 0.13.0) grape (~> 0.13.0)
grape-entity (~> 0.4.2) grape-entity (~> 0.4.2)
......
...@@ -68,7 +68,7 @@ GitLab is a Ruby on Rails application that runs on the following software: ...@@ -68,7 +68,7 @@ GitLab is a Ruby on Rails application that runs on the following software:
- Ubuntu/Debian/CentOS/RHEL - Ubuntu/Debian/CentOS/RHEL
- Ruby (MRI) 2.1 - Ruby (MRI) 2.1
- Git 1.7.10+ - Git 2.7.3+
- Redis 2.8+ - Redis 2.8+
- MySQL or PostgreSQL - MySQL or PostgreSQL
......
...@@ -161,9 +161,8 @@ ...@@ -161,9 +161,8 @@
.dropdown-menu-user-full-name { .dropdown-menu-user-full-name {
display: block; display: block;
margin-bottom: 2px;
font-weight: 600; font-weight: 600;
line-height: 1; line-height: 16px;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
...@@ -171,7 +170,7 @@ ...@@ -171,7 +170,7 @@
.dropdown-menu-user-username { .dropdown-menu-user-username {
display: block; display: block;
line-height: 1; line-height: 16px;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
......
...@@ -6,7 +6,7 @@ class Admin::AbuseReportsController < Admin::ApplicationController ...@@ -6,7 +6,7 @@ class Admin::AbuseReportsController < Admin::ApplicationController
def destroy def destroy
abuse_report = AbuseReport.find(params[:id]) 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 abuse_report.destroy
render nothing: true render nothing: true
......
...@@ -119,10 +119,10 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -119,10 +119,10 @@ class Admin::UsersController < Admin::ApplicationController
end end
def destroy def destroy
DeleteUserService.new(current_user).execute(user) DeleteUserWorker.perform_async(current_user.id, user.id)
respond_to do |format| 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 } format.json { head :ok }
end end
end end
......
...@@ -19,9 +19,9 @@ class AbuseReport < ActiveRecord::Base ...@@ -19,9 +19,9 @@ class AbuseReport < ActiveRecord::Base
validates :message, presence: true validates :message, presence: true
validates :user_id, uniqueness: { message: 'has already been reported' } validates :user_id, uniqueness: { message: 'has already been reported' }
def remove_user def remove_user(deleted_by:)
user.block user.block
user.destroy DeleteUserWorker.perform_async(deleted_by.id, user.id, delete_solo_owned_groups: true)
end end
def notify def notify
......
...@@ -2,7 +2,7 @@ class ProjectWiki ...@@ -2,7 +2,7 @@ class ProjectWiki
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
MARKUPS = { MARKUPS = {
'Markdown' => :md, 'Markdown' => :markdown,
'RDoc' => :rdoc, 'RDoc' => :rdoc,
'AsciiDoc' => :asciidoc 'AsciiDoc' => :asciidoc
} unless defined?(MARKUPS) } unless defined?(MARKUPS)
...@@ -47,7 +47,7 @@ class ProjectWiki ...@@ -47,7 +47,7 @@ class ProjectWiki
def wiki def wiki
@wiki ||= begin @wiki ||= begin
Gollum::Wiki.new(path_to_repo) Gollum::Wiki.new(path_to_repo)
rescue Gollum::NoSuchPathError rescue Rugged::OSError
create_repo! create_repo!
end end
end end
...@@ -90,7 +90,7 @@ class ProjectWiki ...@@ -90,7 +90,7 @@ class ProjectWiki
def create_page(title, content, format = :markdown, message = nil) def create_page(title, content, format = :markdown, message = nil)
commit = commit_details(:created, message, title) 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 update_project_activity
rescue Gollum::DuplicatePageError => e rescue Gollum::DuplicatePageError => e
...@@ -101,7 +101,7 @@ class ProjectWiki ...@@ -101,7 +101,7 @@ class ProjectWiki
def update_page(page, content, format = :markdown, message = nil) def update_page(page, content, format = :markdown, message = nil)
commit = commit_details(:updated, message, page.title) 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 update_project_activity
end end
......
...@@ -62,7 +62,7 @@ class WikiPage ...@@ -62,7 +62,7 @@ class WikiPage
# The raw content of this page. # The raw content of this page.
def content def content
@attributes[:content] ||= if @page @attributes[:content] ||= if @page
@page.raw_data @page.text_data
end end
end end
......
...@@ -5,18 +5,22 @@ class DeleteUserService ...@@ -5,18 +5,22 @@ class DeleteUserService
@current_user = current_user @current_user = current_user
end end
def execute(user) def execute(user, options = {})
if user.solo_owned_groups.present? 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.errors[:base] << 'You must transfer ownership or delete groups before you can remove user'
user return user
else end
user.personal_projects.each do |project|
# Skip repository removal because we remove directory with namespace user.solo_owned_groups.each do |group|
# that contain all this repositories DestroyGroupService.new(group, current_user).execute
::Projects::DestroyService.new(project, current_user, skip_repo: true).pending_delete! end
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 end
user.destroy
end end
end end
...@@ -6,12 +6,12 @@ class DestroyGroupService ...@@ -6,12 +6,12 @@ class DestroyGroupService
end end
def execute def execute
@group.projects.each do |project| group.projects.each do |project|
# Skip repository removal because we remove directory with namespace # Skip repository removal because we remove directory with namespace
# that contain all this repositories # that contain all this repositories
::Projects::DestroyService.new(project, current_user, skip_repo: true).pending_delete! ::Projects::DestroyService.new(project, current_user, skip_repo: true).pending_delete!
end end
@group.destroy group.destroy
end end
end end
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
- if params[:assignee_id] - if params[:assignee_id]
= hidden_field_tag(:assignee_id, 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", = 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 .filter-item.inline.milestone-filter
- if params[:milestone_title] - if params[:milestone_title]
......
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
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
...@@ -76,7 +76,7 @@ Make sure you have the right version of Git installed ...@@ -76,7 +76,7 @@ Make sure you have the right version of Git installed
# Install Git # Install Git
sudo apt-get install -y git-core 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 git --version
Is the system packaged Git too old? Remove it and compile from source. Is the system packaged Git too old? Remove it and compile from source.
......
...@@ -9,7 +9,7 @@ Capybara.register_driver :poltergeist do |app| ...@@ -9,7 +9,7 @@ Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, js_errors: true, timeout: timeout, window_size: [1366, 768]) Capybara::Poltergeist::Driver.new(app, js_errors: true, timeout: timeout, window_size: [1366, 768])
end end
Capybara.default_wait_time = timeout Capybara.default_max_wait_time = timeout
Capybara.ignore_hidden_elements = false Capybara.ignore_hidden_elements = false
unless ENV['CI'] || ENV['CI_SERVER'] unless ENV['CI'] || ENV['CI_SERVER']
......
...@@ -4,6 +4,8 @@ module Gitlab ...@@ -4,6 +4,8 @@ module Gitlab
include Enumerable include Enumerable
def parse(lines) def parse(lines)
return [] if lines.blank?
@lines = lines @lines = lines
line_obj_index = 0 line_obj_index = 0
line_old = 1 line_old = 1
......
...@@ -913,7 +913,7 @@ namespace :gitlab do ...@@ -913,7 +913,7 @@ namespace :gitlab do
end end
def check_git_version 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))) current_version = Gitlab::VersionInfo.parse(run(%W(#{Gitlab.config.git.bin_path} --version)))
puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\"" puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\""
......
...@@ -90,4 +90,9 @@ eos ...@@ -90,4 +90,9 @@ eos
end end
end end
end end
context 'when lines is empty' do
it { expect(parser.parse([])).to eq([]) }
it { expect(parser.parse(nil)).to eq([]) }
end
end end
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe AbuseReport, type: :model do RSpec.describe AbuseReport, type: :model do
subject { create(:abuse_report) } subject { create(:abuse_report) }
let(:user) { create(:user) }
it { expect(subject).to be_valid } it { expect(subject).to be_valid }
...@@ -31,17 +32,14 @@ RSpec.describe AbuseReport, type: :model do ...@@ -31,17 +32,14 @@ RSpec.describe AbuseReport, type: :model do
describe '#remove_user' do describe '#remove_user' do
it 'blocks the user' do it 'blocks the user' do
report = build(:abuse_report) expect { subject.remove_user(deleted_by: user) }.to change { subject.user.blocked? }.to(true)
allow(report.user).to receive(:destroy)
expect { report.remove_user }.to change { report.user.blocked? }.to(true)
end end
it 'removes the user' do it 'lets a worker delete the user' do
report = build(:abuse_report) 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
end end
......
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
...@@ -10,7 +10,7 @@ Capybara.register_driver :poltergeist do |app| ...@@ -10,7 +10,7 @@ Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, js_errors: true, timeout: timeout, window_size: [1366, 768]) Capybara::Poltergeist::Driver.new(app, js_errors: true, timeout: timeout, window_size: [1366, 768])
end end
Capybara.default_wait_time = timeout Capybara.default_max_wait_time = timeout
Capybara.ignore_hidden_elements = true Capybara.ignore_hidden_elements = true
unless ENV['CI'] || ENV['CI_SERVER'] unless ENV['CI'] || ENV['CI_SERVER']
......
module WaitForAjax module WaitForAjax
def wait_for_ajax 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? loop until finished_all_ajax_requests?
end end
end end
......
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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment