Commit aefea581 authored by Valery Sizov's avatar Valery Sizov

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ee into ce_upstream

parents 85201751 4c2d4315
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
## 8.13.1
- Fix Elasticsearch::Transport::Transport::Errors::BadRequest when ES is enabled. #21036
- Hides multiple board actions if user doesnt have permissions
## 8.13.0 (2016-10-22) ## 8.13.0 (2016-10-22)
- Cache the last usage data to avoid unicorn timeouts - Cache the last usage data to avoid unicorn timeouts
......
...@@ -8,6 +8,9 @@ module ProtectedBranchAccess ...@@ -8,6 +8,9 @@ module ProtectedBranchAccess
scope: :protected_branch, scope: :protected_branch,
unless: Proc.new { |access_level| access_level.user_id? || access_level.group_id? }, unless: Proc.new { |access_level| access_level.user_id? || access_level.group_id? },
conditions: -> { where(user_id: nil, group_id: nil) } conditions: -> { where(user_id: nil, group_id: nil) }
scope :master, -> { where(access_level: Gitlab::Access::MASTER) }
scope :developer, -> { where(access_level: Gitlab::Access::DEVELOPER) }
end end
def type def type
......
class DiffNote < Note class DiffNote < Note
# Elastic search configuration (it does not support STI properly)
document_type 'note'
index_name [Rails.application.class.parent_name.downcase, Rails.env].join('-')
include Elastic::NotesSearch
include NoteOnDiff include NoteOnDiff
serialize :original_position, Gitlab::Diff::Position serialize :original_position, Gitlab::Diff::Position
......
class LegacyDiffNote < Note class LegacyDiffNote < Note
# Elastic search configuration (it does not support STI properly)
document_type 'note'
index_name [Rails.application.class.parent_name.downcase, Rails.env].join('-')
include Elastic::NotesSearch
include NoteOnDiff include NoteOnDiff
serialize :st_diff serialize :st_diff
......
...@@ -58,6 +58,7 @@ class ProjectPolicy < BasePolicy ...@@ -58,6 +58,7 @@ class ProjectPolicy < BasePolicy
can! :update_issue can! :update_issue
can! :admin_issue can! :admin_issue
can! :admin_label can! :admin_label
can! :admin_board
can! :admin_list can! :admin_list
can! :read_commit_status can! :read_commit_status
can! :read_build can! :read_build
......
...@@ -12,6 +12,7 @@ module ProtectedBranches ...@@ -12,6 +12,7 @@ module ProtectedBranches
protected_branch.transaction do protected_branch.transaction do
delete_redundant_access_levels delete_redundant_access_levels
delete_redundant_ee_access_levels
case @developers_can_push case @developers_can_push
when true when true
...@@ -43,5 +44,26 @@ module ProtectedBranches ...@@ -43,5 +44,26 @@ module ProtectedBranches
@protected_branch.push_access_levels.destroy_all @protected_branch.push_access_levels.destroy_all
end end
end end
# If a protected branch can have more than one access level (EE), only
# remove the relevant access levels. If we don't do this, we'll have a
# failed validation.
def delete_redundant_ee_access_levels
case @developers_can_merge
when true
@protected_branch.merge_access_levels.developer.destroy_all
when false
@protected_branch.merge_access_levels.developer.destroy_all
@protected_branch.merge_access_levels.master.destroy_all
end
case @developers_can_push
when true
@protected_branch.push_access_levels.developer.destroy_all
when false
@protected_branch.push_access_levels.developer.destroy_all
@protected_branch.push_access_levels.master.destroy_all
end
end
end end
end end
...@@ -23,39 +23,41 @@ ...@@ -23,39 +23,41 @@
{{ board.name }} {{ board.name }}
.dropdown-loading{ "v-if" => "loading" } .dropdown-loading{ "v-if" => "loading" }
= icon("spin spinner") = icon("spin spinner")
%board-selector-form{ "inline-template" => true, - if can?(current_user, :admin_board, @project)
"v-if" => "currentPage === 'edit'", %board-selector-form{ "inline-template" => true,
"type" => "edit", "v-if" => "currentPage === 'edit'",
":current-board.sync" => "currentBoard", "type" => "edit",
":current-page.sync" => "currentPage", ":current-board.sync" => "currentBoard",
":reload.sync" => "reload" } ":current-page.sync" => "currentPage",
= render "projects/boards/components/form" ":reload.sync" => "reload" }
%board-selector-form{ "inline-template" => true, = render "projects/boards/components/form"
"v-if" => "currentPage === 'new'", %board-selector-form{ "inline-template" => true,
"type" => "new", "v-if" => "currentPage === 'new'",
":current-page.sync" => "currentPage", "type" => "new",
":reload.sync" => "reload" } ":current-page.sync" => "currentPage",
= render "projects/boards/components/form" ":reload.sync" => "reload" }
.dropdown-content.board-selector-page-two{ "v-if" => "currentPage === 'delete'" } = render "projects/boards/components/form"
%p .dropdown-content.board-selector-page-two{ "v-if" => "currentPage === 'delete'" }
Are you sure you want to delete this board? %p
.board-delete-btns.clearfix Are you sure you want to delete this board?
= link_to "", .board-delete-btns.clearfix
class: "btn btn-danger pull-left", = link_to "",
method: :delete, class: "btn btn-danger pull-left",
":href" => "'#{namespace_project_boards_path(@project.namespace, @project)}/' + currentBoard.id" do method: :delete,
Delete ":href" => "'#{namespace_project_boards_path(@project.namespace, @project)}/' + currentBoard.id" do
%button.btn.btn-default.pull-right{ type: "button", Delete
"@click.stop.prevent" => "currentPage = ''" } %button.btn.btn-default.pull-right{ type: "button",
Cancel "@click.stop.prevent" => "currentPage = ''" }
.dropdown-footer{ "v-if" => "currentPage === ''" } Cancel
%ul.dropdown-footer-list - if can?(current_user, :admin_board, @project)
%li .dropdown-footer{ "v-if" => "currentPage === ''" }
%a{ "href" => "#", "@click.stop.prevent" => "showPage('new')" } %ul.dropdown-footer-list
Create new board %li
%li %a{ "href" => "#", "@click.stop.prevent" => "showPage('new')" }
%a{ "href" => "#", "@click.stop.prevent" => "showPage('edit')" } Create new board
Edit board name %li
%li{ "v-if" => "showDelete" } %a{ "href" => "#", "@click.stop.prevent" => "showPage('edit')" }
%a.text-danger{ "href" => "#", "@click.stop.prevent" => "showPage('delete')" } Edit board name
Delete board %li{ "v-if" => "showDelete" }
%a.text-danger{ "href" => "#", "@click.stop.prevent" => "showPage('delete')" }
Delete board
...@@ -10,136 +10,155 @@ describe 'Multiple Issue Boards', feature: true, js: true do ...@@ -10,136 +10,155 @@ describe 'Multiple Issue Boards', feature: true, js: true do
let!(:board) { create(:board, project: project) } let!(:board) { create(:board, project: project) }
let!(:board2) { create(:board, project: project) } let!(:board2) { create(:board, project: project) }
before do context 'authorized user' do
project.team << [user, :master] before do
project.team << [user, :master]
login_as(user) login_as(user)
visit namespace_project_boards_path(project.namespace, project) visit namespace_project_boards_path(project.namespace, project)
wait_for_vue_resource wait_for_vue_resource
end end
it 'shows current board name' do it 'shows current board name' do
page.within('.boards-switcher') do page.within('.boards-switcher') do
expect(page).to have_content(board.name) expect(page).to have_content(board.name)
end
end end
end
it 'shows a list of boards' do it 'shows a list of boards' do
click_button board.name click_button board.name
page.within('.boards-title-holder .dropdown-menu') do page.within('.boards-title-holder .dropdown-menu') do
expect(page).to have_content(board.name) expect(page).to have_content(board.name)
expect(page).to have_content(board2.name) expect(page).to have_content(board2.name)
end
end end
end
it 'switches current board' do it 'switches current board' do
click_button board.name click_button board.name
page.within('.boards-title-holder .dropdown-menu') do page.within('.boards-title-holder .dropdown-menu') do
click_link board2.name click_link board2.name
end end
wait_for_vue_resource wait_for_vue_resource
page.within('.boards-switcher') do page.within('.boards-switcher') do
expect(page).to have_content(board2.name) expect(page).to have_content(board2.name)
end
end end
end
it 'creates new board' do it 'creates new board' do
click_button board.name click_button board.name
page.within('.boards-title-holder .dropdown-menu') do page.within('.boards-title-holder .dropdown-menu') do
click_link 'Edit board name' click_link 'Edit board name'
fill_in 'board-new-name', with: 'Testing' fill_in 'board-new-name', with: 'Testing'
click_button 'Save' click_button 'Save'
end end
wait_for_vue_resource wait_for_vue_resource
page.within('.boards-title-holder .dropdown-menu') do page.within('.boards-title-holder .dropdown-menu') do
expect(page).to have_content('Testing') expect(page).to have_content('Testing')
end
end end
end
it 'edits board name' do it 'edits board name' do
click_button board.name click_button board.name
page.within('.boards-title-holder .dropdown-menu') do page.within('.boards-title-holder .dropdown-menu') do
click_link 'Edit board name' click_link 'Edit board name'
fill_in 'board-new-name', with: 'Testing' fill_in 'board-new-name', with: 'Testing'
click_button 'Save' click_button 'Save'
end end
wait_for_vue_resource wait_for_vue_resource
page.within('.boards-title-holder .dropdown-menu') do page.within('.boards-title-holder .dropdown-menu') do
expect(page).to have_content('Testing') expect(page).to have_content('Testing')
end
end end
end
it 'deletes board' do it 'deletes board' do
click_button board.name click_button board.name
wait_for_vue_resource wait_for_vue_resource
page.within('.boards-title-holder .dropdown-menu') do page.within('.boards-title-holder .dropdown-menu') do
click_link 'Delete board' click_link 'Delete board'
page.within('.dropdown-title') do page.within('.dropdown-title') do
expect(page).to have_content('Delete board') expect(page).to have_content('Delete board')
end
click_link 'Delete'
end end
click_link 'Delete' click_button board2.name
page.within('.boards-title-holder .dropdown-menu') do
expect(page).not_to have_content(board.name)
expect(page).to have_content(board2.name)
end
end end
click_button board2.name it 'adds a list to the none default board' do
click_button board.name
page.within('.boards-title-holder .dropdown-menu') do page.within('.boards-title-holder .dropdown-menu') do
expect(page).not_to have_content(board.name) click_link board2.name
expect(page).to have_content(board2.name) end
end
end
it 'adds a list to the none default board' do wait_for_vue_resource
click_button board.name
page.within('.boards-title-holder .dropdown-menu') do page.within('.boards-switcher') do
click_link board2.name expect(page).to have_content(board2.name)
end end
wait_for_vue_resource click_button 'Create new list'
page.within('.boards-switcher') do wait_for_ajax
expect(page).to have_content(board2.name)
end
click_button 'Create new list' page.within '.dropdown-menu-issues-board-new' do
click_link planning.title
end
wait_for_ajax wait_for_vue_resource
page.within '.dropdown-menu-issues-board-new' do expect(page).to have_selector('.board', count: 3)
click_link planning.title
end
wait_for_vue_resource click_button board2.name
page.within('.boards-title-holder .dropdown-menu') do
click_link board.name
end
expect(page).to have_selector('.board', count: 3) wait_for_vue_resource
click_button board2.name expect(page).to have_selector('.board', count: 2)
end
end
page.within('.boards-title-holder .dropdown-menu') do context 'unauthorized user' do
click_link board.name before do
visit namespace_project_boards_path(project.namespace, project)
wait_for_vue_resource
end end
wait_for_vue_resource it 'does not show action links' do
click_button board.name
expect(page).to have_selector('.board', count: 2) page.within('.boards-title-holder .dropdown-menu') do
expect(page).not_to have_content('Create new board')
expect(page).not_to have_content('Edit board name')
expect(page).not_to have_content('Delete board')
end
end
end end
end end
...@@ -29,6 +29,24 @@ describe Note, elastic: true do ...@@ -29,6 +29,24 @@ describe Note, elastic: true do
expect(described_class.elastic_search('term', options: options).total_count).to eq(1) expect(described_class.elastic_search('term', options: options).total_count).to eq(1)
end end
it "indexes && searches diff notes" do
notes = []
Sidekiq::Testing.inline! do
notes << create(:diff_note_on_merge_request, note: "term")
notes << create(:diff_note_on_commit, note: "term")
notes << create(:legacy_diff_note_on_merge_request, note: "term")
notes << create(:legacy_diff_note_on_commit, note: "term")
Gitlab::Elastic::Helper.refresh_index
end
project_ids = notes.map { |note| note.noteable.project.id }
options = { project_ids: project_ids }
expect(described_class.elastic_search('term', options: options).total_count).to eq(4)
end
it "returns json with all needed elements" do it "returns json with all needed elements" do
note = create :note note = create :note
......
...@@ -163,6 +163,19 @@ describe API::API, api: true do ...@@ -163,6 +163,19 @@ describe API::API, api: true do
expect(json_response['developers_can_merge']).to eq(true) expect(json_response['developers_can_merge']).to eq(true)
end end
end end
context "when no one can push" do
let(:protected_branch) { create(:protected_branch, :no_one_can_push, project: project, name: 'protected_branch') }
it "updates 'developers_can_push' without removing the 'no_one' access level" do
put api("/projects/#{project.id}/repository/branches/#{protected_branch.name}/protect", user),
developers_can_push: true, developers_can_merge: true
expect(response).to have_http_status(200)
expect(json_response['name']).to eq(protected_branch.name)
expect(protected_branch.reload.push_access_levels.pluck(:access_level)).to include(Gitlab::Access::NO_ACCESS)
end
end
end end
context "multiple API calls" do context "multiple API calls" do
......
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