Commit 1eabd9dfecad735a4e59884c568b27d27932517f

Authored by Marin Jankovski
2 parents 3682a082 358426d6

Merge branch 'master' into relative_links_in_documentation

CHANGELOG
... ... @@ -12,6 +12,7 @@ v 6.2.0
12 12 - Update logic for validates_merge_request for tree of MR (Andrew Kumanyaev)
13 13 - Rake tasks for web hooks management (Jonhnny Weslley)
14 14 - Extended User API to expose admin and can_create_group for user creation/updating (Boyan Tabakov)
  15 + - API: Remove group
15 16  
16 17 v 6.1.0
17 18 - Project specific IDs for issues, mr, milestones
... ...
app/assets/stylesheets/sections/tree.scss
... ... @@ -65,11 +65,6 @@
65 65  
66 66 .tree_author {
67 67 padding-right: 8px;
68   -
69   - img.avatar {
70   - margin-top: 0;
71   - width: 16px;
72   - }
73 68 }
74 69  
75 70 .tree_commit {
... ...
app/controllers/projects/milestones_controller.rb
... ... @@ -14,7 +14,7 @@ class Projects::MilestonesController < Projects::ApplicationController
14 14 @milestones = case params[:f]
15 15 when 'all'; @project.milestones.order("state, due_date DESC")
16 16 when 'closed'; @project.milestones.closed.order("due_date DESC")
17   - else @project.milestones.active.order("due_date DESC")
  17 + else @project.milestones.active.order("due_date ASC")
18 18 end
19 19  
20 20 @milestones = @milestones.includes(:project)
... ...
app/models/merge_request.rb
... ... @@ -222,7 +222,11 @@ class MergeRequest < ActiveRecord::Base
222 222  
223 223 def mr_and_commit_notes
224 224 commit_ids = commits.map(&:id)
225   - Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
  225 + project.notes.where(
  226 + "(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))",
  227 + mr_id: id,
  228 + commit_ids: commit_ids
  229 + )
226 230 end
227 231  
228 232 # Returns the raw diff for this merge request
... ...
app/models/project.rb
... ... @@ -53,6 +53,7 @@ class Project < ActiveRecord::Base
53 53 has_many :services, dependent: :destroy
54 54 has_many :events, dependent: :destroy
55 55 has_many :merge_requests, dependent: :destroy, foreign_key: "target_project_id"
  56 + has_many :fork_merge_requests,dependent: :destroy, foreign_key: "source_project_id", class_name: MergeRequest
56 57 has_many :issues, dependent: :destroy, order: "state DESC, created_at DESC"
57 58 has_many :milestones, dependent: :destroy
58 59 has_many :notes, dependent: :destroy
... ... @@ -312,8 +313,11 @@ class Project < ActiveRecord::Base
312 313 branch_name = ref.gsub("refs/heads/", "")
313 314 c_ids = self.repository.commits_between(oldrev, newrev).map(&:id)
314 315  
315   - # Update code for merge requests
  316 + # Update code for merge requests into project between project branches
316 317 mrs = self.merge_requests.opened.by_branch(branch_name).all
  318 + # Update code for merge requests between project and project fork
  319 + mrs += self.fork_merge_requests.opened.by_branch(branch_name).all
  320 +
317 321 mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }
318 322  
319 323 # Close merge requests
... ...
app/services/system_hooks_service.rb
... ... @@ -36,7 +36,8 @@ class SystemHooksService
36 36 when User
37 37 data.merge!({
38 38 name: model.name,
39   - email: model.email
  39 + email: model.email,
  40 + user_id: model.id
40 41 })
41 42 when UsersProject
42 43 data.merge!({
... ...
app/views/admin/hooks/_data_ex.html.erb
... ... @@ -52,7 +52,8 @@
52 52 "created_at": "2012-07-21T07:44:07Z",
53 53 "email": "js@gitlabhq.com",
54 54 "event_name": "user_create",
55   - "name": "John Smith"
  55 + "name": "John Smith",
  56 + "user_id": 41
56 57 }
57 58  
58 59 6. User removed:
... ... @@ -60,7 +61,8 @@
60 61 "created_at": "2012-07-21T07:44:07Z",
61 62 "email": "js@gitlabhq.com",
62 63 "event_name": "user_destroy",
63   - "name": "John Smith"
  64 + "name": "John Smith",
  65 + "user_id": 41
64 66 }
65 67  
66 68 eos
... ...
app/views/admin/hooks/index.html.haml
1   -.alert.alert-info
2   - %span
3   - Post-receive hooks for binding events.
4   - %br
5   - Read more about system hooks
6   - %strong #{link_to "here", help_system_hooks_path, class: "vlink"}
  1 +%h3.page-title
  2 + System Hooks
  3 +
  4 +%p.light
  5 + #{link_to "System hooks ", help_system_hooks_path, class: "vlink"} can be
  6 + used for binding events when GitLab creates a User or Project.
  7 +
  8 +%hr
  9 +
7 10  
8 11 = form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-inline' } do |f|
9 12 -if @hook.errors.any?
... ...
app/views/projects/tree/_tree_commit_column.html.haml
1   -%span.tree_author= commit_author_link(commit, avatar: true)
  1 +%span.tree_author= commit_author_link(commit, avatar: true, size: 16)
2 2 = link_to_gfm truncate(commit.title, length: 80), project_commit_path(@project, commit.id), class: "tree-commit-link"
... ...
doc/api/groups.md
... ... @@ -57,6 +57,19 @@ Parameters:
57 57 + `project_id` (required) - The ID of a project
58 58  
59 59  
  60 +## Remove group
  61 +
  62 +Removes group with all projects inside.
  63 +
  64 +```
  65 +DELETE /groups/:id
  66 +```
  67 +
  68 +Parameters:
  69 +
  70 ++ `id` (required) - The ID of a user group
  71 +
  72 +
60 73 ## Group members
61 74  
62 75  
... ...
doc/api/merge_requests.md
... ... @@ -20,6 +20,8 @@ Parameters:
20 20 "project_id":3,
21 21 "title":"test1",
22 22 "state":"opened",
  23 + "upvotes":0,
  24 + "downvotes":0,
23 25 "author":{
24 26 "id":1,
25 27 "username": "admin",
... ... @@ -62,6 +64,8 @@ Parameters:
62 64 "project_id":3,
63 65 "title":"test1",
64 66 "state":"merged",
  67 + "upvotes":0,
  68 + "downvotes":0,
65 69 "author":{
66 70 "id":1,
67 71 "username": "admin",
... ... @@ -106,6 +110,8 @@ Parameters:
106 110 "project_id":3,
107 111 "title":"test1",
108 112 "state":"opened",
  113 + "upvotes":0,
  114 + "downvotes":0,
109 115 "author":{
110 116 "id":1,
111 117 "username": "admin",
... ... @@ -152,6 +158,8 @@ Parameters:
152 158 "project_id":3,
153 159 "title":"test1",
154 160 "state":"opened",
  161 + "upvotes":0,
  162 + "downvotes":0,
155 163 "author":{
156 164 "id":1,
157 165 "username": "admin",
... ...
doc/update/5.1-to-5.2.md
... ... @@ -7,7 +7,7 @@ It's useful to make a backup just in case things go south:
7 7  
8 8 ```bash
9 9 cd /home/git/gitlab
10   -sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
  10 +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
11 11 ```
12 12  
13 13 ### 1. Stop server
... ... @@ -95,5 +95,5 @@ Follow the [`upgrade guide from 5.0 to 5.1`](5.0-to-5.1.md), except for the data
95 95  
96 96 ```bash
97 97 cd /home/git/gitlab
98   -sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
  98 +sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
99 99 ```
... ...
doc/update/5.2-to-5.3.md
... ... @@ -7,7 +7,7 @@ It's useful to make a backup just in case things go south:
7 7  
8 8 ```bash
9 9 cd /home/git/gitlab
10   -sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
  10 +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
11 11 ```
12 12  
13 13 ### 1. Stop server
... ... @@ -78,5 +78,5 @@ Follow the [`upgrade guide from 5.1 to 5.2`](5.1-to-5.2.md), except for the data
78 78  
79 79 ```bash
80 80 cd /home/git/gitlab
81   -sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
  81 +sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
82 82 ```
... ...
doc/update/5.3-to-5.4.md
... ... @@ -7,7 +7,7 @@ It's useful to make a backup just in case things go south:
7 7  
8 8 ```bash
9 9 cd /home/git/gitlab
10   -sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
  10 +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
11 11 ```
12 12  
13 13 ### 1. Stop server
... ... @@ -86,5 +86,5 @@ Follow the [`upgrade guide from 5.2 to 5.3`](5.2-to-5.3.md), except for the data
86 86  
87 87 ```bash
88 88 cd /home/git/gitlab
89   -sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
  89 +sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
90 90 ```
... ...
doc/update/5.4-to-6.0.md
... ... @@ -24,7 +24,7 @@ It's useful to make a backup just in case things go south:
24 24  
25 25 ```bash
26 26 cd /home/git/gitlab
27   -sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
  27 +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
28 28 ```
29 29  
30 30 ### 1. Stop server
... ...
doc/update/6.0-to-6.1.md
... ... @@ -16,7 +16,7 @@ It's useful to make a backup just in case things go south:
16 16  
17 17 ```bash
18 18 cd /home/git/gitlab
19   -sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
  19 +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
20 20 ```
21 21  
22 22 ### 1. Stop server
... ... @@ -99,5 +99,5 @@ Follow the [`upgrade guide from 5.4 to 6.0`](5.4-to-6.0.md), except for the data
99 99  
100 100 ```bash
101 101 cd /home/git/gitlab
102   -sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
  102 +sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
103 103 ```
... ...
doc/update/6.1-to-6.2.md
... ... @@ -9,7 +9,7 @@ It's useful to make a backup just in case things go south:
9 9  
10 10 ```bash
11 11 cd /home/git/gitlab
12   -sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
  12 +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
13 13 ```
14 14  
15 15 ### 1. Stop server
... ... @@ -96,5 +96,5 @@ Follow the [`upgrade guide from 6.0 to 6.1`](6.0-to-6.1.md), except for the data
96 96  
97 97 ```bash
98 98 cd /home/git/gitlab
99   -sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
  99 +sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
100 100 ```
... ...
lib/api/entities.rb
... ... @@ -112,7 +112,7 @@ module API
112 112 end
113 113  
114 114 class MergeRequest < Grape::Entity
115   - expose :id, :target_branch, :source_branch, :title, :state
  115 + expose :id, :target_branch, :source_branch, :title, :state, :upvotes, :downvotes
116 116 expose :target_project_id, as: :project_id
117 117 expose :author, :assignee, using: Entities::UserBasic
118 118 end
... ...
lib/api/groups.rb
... ... @@ -7,12 +7,14 @@ module API
7 7 helpers do
8 8 def find_group(id)
9 9 group = Group.find(id)
10   - if current_user.admin or current_user.groups.include? group
  10 +
  11 + if can?(current_user, :read_group, group)
11 12 group
12 13 else
13 14 render_api_error!("403 Forbidden - #{current_user.username} lacks sufficient access to #{group.name}", 403)
14 15 end
15 16 end
  17 +
16 18 def validate_access_level?(level)
17 19 Gitlab::Access.options_with_owner.values.include? level.to_i
18 20 end
... ... @@ -64,6 +66,19 @@ module API
64 66 present group, with: Entities::GroupDetail
65 67 end
66 68  
  69 +
  70 + # Remove group
  71 + #
  72 + # Parameters:
  73 + # id (required) - The ID of a group
  74 + # Example Request:
  75 + # DELETE /groups/:id
  76 + delete ":id" do
  77 + group = find_group(params[:id])
  78 + authorize! :manage_group, group
  79 + group.destroy
  80 + end
  81 +
67 82 # Transfer a project to the Group namespace
68 83 #
69 84 # Parameters:
... ... @@ -132,7 +147,6 @@ module API
132 147 member.destroy
133 148 end
134 149 end
135   -
136 150 end
137 151 end
138 152 end
... ...
lib/api/internal.rb
... ... @@ -35,6 +35,7 @@ module API
35 35 user = key.user
36 36  
37 37 return false if user.blocked?
  38 + return false if user.ldap_user? && Gitlab::LDAP::User.blocked?(user.extern_uid)
38 39  
39 40 action = case git_cmd
40 41 when *DOWNLOAD_COMMANDS
... ...
lib/gitlab/ldap/user.rb
... ... @@ -71,6 +71,16 @@ module Gitlab
71 71 find_by_uid(ldap_user.dn) if ldap_user
72 72 end
73 73  
  74 + # Check LDAP user existance by dn. User in git over ssh check
  75 + #
  76 + # It covers 2 cases:
  77 + # * when ldap account was removed
  78 + # * when ldap account was deactivated by change of OU membership in 'dn'
  79 + def blocked?(dn)
  80 + ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
  81 + ldap.connection.search(base: dn, size: 1).blank?
  82 + end
  83 +
74 84 private
75 85  
76 86 def find_by_uid(uid)
... ...
lib/support/init.d/gitlab
... ... @@ -151,7 +151,7 @@ stop() {
151 151 exit_if_not_running
152 152 # If the Unicorn web server is running, tell it to stop;
153 153 if [ "$web_status" = "0" ]; then
154   - kill -QUIT "$wpid" &
  154 + kill -QUIT "$wpid"
155 155 echo "Stopping the GitLab Unicorn web server..."
156 156 stopping=true
157 157 else
... ... @@ -160,7 +160,7 @@ stop() {
160 160 # And do the same thing for the Sidekiq.
161 161 if [ "$sidekiq_status" = "0" ]; then
162 162 printf "Stopping Sidekiq job dispatcher."
163   - RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop &
  163 + RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop
164 164 stopping=true
165 165 else
166 166 echo "The Sidekiq was not running, must have run out of breath."
... ...
lib/tasks/gitlab/check.rake
... ... @@ -392,14 +392,20 @@ namespace :gitlab do
392 392 hook_file = "update"
393 393 gitlab_shell_hooks_path = Gitlab.config.gitlab_shell.hooks_path
394 394 gitlab_shell_hook_file = File.join(gitlab_shell_hooks_path, hook_file)
395   - gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user
396 395  
397   - unless File.exists?(gitlab_shell_hook_file)
398   - puts "can't check because of previous errors".magenta
399   - return
  396 + if File.exists?(gitlab_shell_hook_file)
  397 + puts "yes".green
  398 + else
  399 + puts "no".red
  400 + puts "Could not find #{gitlab_shell_hook_file}"
  401 + try_fixing_it(
  402 + 'Check the hooks_path in config/gitlab.yml',
  403 + 'Check your gitlab-shell installation'
  404 + )
  405 + for_more_information(
  406 + see_installation_guide_section "GitLab Shell"
  407 + )
400 408 end
401   -
402   - puts "yes".green
403 409 end
404 410  
405 411 def check_repo_base_exists
... ...
spec/models/merge_request_spec.rb
... ... @@ -49,8 +49,8 @@ describe MergeRequest do
49 49  
50 50 before do
51 51 merge_request.stub(:commits) { [merge_request.source_project.repository.commit] }
52   - create(:note, commit_id: merge_request.commits.first.id, noteable_type: 'Commit')
53   - create(:note, noteable: merge_request)
  52 + create(:note, commit_id: merge_request.commits.first.id, noteable_type: 'Commit', project: merge_request.project)
  53 + create(:note, noteable: merge_request, project: merge_request.project)
54 54 end
55 55  
56 56 it "should include notes for commits" do
... ...
spec/requests/api/groups_spec.rb
... ... @@ -106,6 +106,44 @@ describe API::API do
106 106 end
107 107 end
108 108  
  109 + describe "DELETE /groups/:id" do
  110 + context "when authenticated as user" do
  111 + it "should remove group" do
  112 + delete api("/groups/#{group1.id}", user1)
  113 + response.status.should == 200
  114 + end
  115 +
  116 + it "should not remove a group if not an owner" do
  117 + user3 = create(:user)
  118 + group1.add_user(user3, Gitlab::Access::MASTER)
  119 + delete api("/groups/#{group1.id}", user3)
  120 + response.status.should == 403
  121 + end
  122 +
  123 + it "should not remove a non existing group" do
  124 + delete api("/groups/1328", user1)
  125 + response.status.should == 404
  126 + end
  127 +
  128 + it "should not remove a group not attached to user1" do
  129 + delete api("/groups/#{group2.id}", user1)
  130 + response.status.should == 403
  131 + end
  132 + end
  133 +
  134 + context "when authenticated as admin" do
  135 + it "should remove any existing group" do
  136 + delete api("/groups/#{group2.id}", admin)
  137 + response.status.should == 200
  138 + end
  139 +
  140 + it "should not remove a non existing group" do
  141 + delete api("/groups/1328", admin)
  142 + response.status.should == 404
  143 + end
  144 + end
  145 + end
  146 +
109 147 describe "POST /groups/:id/projects/:project_id" do
110 148 let(:project) { create(:project) }
111 149 before(:each) do
... ...
spec/services/system_hooks_service_spec.rb
... ... @@ -5,37 +5,29 @@ describe SystemHooksService do
5 5 let (:project) { create :project }
6 6 let (:users_project) { create :users_project }
7 7  
8   - context 'it should build event data' do
9   - it 'should build event data for user' do
10   - SystemHooksService.build_event_data(user, :create).should include(:event_name, :name, :created_at, :email)
11   - end
12   -
13   - it 'should build event data for project' do
14   - SystemHooksService.build_event_data(project, :create).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email)
15   - end
16   -
17   - it 'should build event data for users project' do
18   - SystemHooksService.build_event_data(users_project, :create).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access)
19   - end
  8 + context 'event data' do
  9 + it { event_data(user, :create).should include(:event_name, :name, :created_at, :email, :user_id) }
  10 + it { event_data(user, :destroy).should include(:event_name, :name, :created_at, :email, :user_id) }
  11 + it { event_data(project, :create).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email) }
  12 + it { event_data(project, :destroy).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email) }
  13 + it { event_data(users_project, :create).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access) }
  14 + it { event_data(users_project, :destroy).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access) }
20 15 end
21 16  
22   - context 'it should build event names' do
23   - it 'should build event names for user' do
24   - SystemHooksService.build_event_name(user, :create).should eq "user_create"
25   -
26   - SystemHooksService.build_event_name(user, :destroy).should eq "user_destroy"
27   - end
28   -
29   - it 'should build event names for project' do
30   - SystemHooksService.build_event_name(project, :create).should eq "project_create"
31   -
32   - SystemHooksService.build_event_name(project, :destroy).should eq "project_destroy"
33   - end
  17 + context 'event names' do
  18 + it { event_name(user, :create).should eq "user_create" }
  19 + it { event_name(user, :destroy).should eq "user_destroy" }
  20 + it { event_name(project, :create).should eq "project_create" }
  21 + it { event_name(project, :destroy).should eq "project_destroy" }
  22 + it { event_name(users_project, :create).should eq "user_add_to_team" }
  23 + it { event_name(users_project, :destroy).should eq "user_remove_from_team" }
  24 + end
34 25  
35   - it 'should build event names for users project' do
36   - SystemHooksService.build_event_name(users_project, :create).should eq "user_add_to_team"
  26 + def event_data(*args)
  27 + SystemHooksService.build_event_data(*args)
  28 + end
37 29  
38   - SystemHooksService.build_event_name(users_project, :destroy).should eq "user_remove_from_team"
39   - end
  30 + def event_name(*args)
  31 + SystemHooksService.build_event_name(*args)
40 32 end
41 33 end
... ...