diff options
17 files changed, 198 insertions, 59 deletions
diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb index 3da44b9b888..306afb65f10 100644 --- a/app/controllers/confirmations_controller.rb +++ b/app/controllers/confirmations_controller.rb @@ -14,12 +14,8 @@ class ConfirmationsController < Devise::ConfirmationsController if signed_in?(resource_name) after_sign_in_path_for(resource) else - sign_in(resource) - if signed_in?(resource_name) - after_sign_in_path_for(resource) - else - new_session_path(resource_name) - end + flash[:notice] += " Please sign in." + new_session_path(resource_name) end end end diff --git a/app/models/project.rb b/app/models/project.rb index 1630975b0d3..cd35601d76b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -121,8 +121,6 @@ class Project < ActiveRecord::Base # Merge Requests for target project should be removed with it has_many :merge_requests, dependent: :destroy, foreign_key: 'target_project_id' - # Merge requests from source project should be kept when source project was removed - has_many :fork_merge_requests, foreign_key: 'source_project_id', class_name: 'MergeRequest' has_many :issues, dependent: :destroy has_many :labels, dependent: :destroy, class_name: 'ProjectLabel' has_many :services, dependent: :destroy diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb index 70e25956dc7..5a53b973059 100644 --- a/app/services/merge_requests/base_service.rb +++ b/app/services/merge_requests/base_service.rb @@ -38,15 +38,13 @@ module MergeRequests private - def merge_requests_for(branch) - origin_merge_requests = @project.origin_merge_requests - .opened.where(source_branch: branch).to_a - - fork_merge_requests = @project.fork_merge_requests - .opened.where(source_branch: branch).to_a - - (origin_merge_requests + fork_merge_requests) - .uniq.select(&:source_project) + # Returns all origin and fork merge requests from `@project` satisfying passed arguments. + def merge_requests_for(source_branch, mr_states: [:opened]) + MergeRequest + .with_state(mr_states) + .where(source_branch: source_branch, source_project_id: @project.id) + .preload(:source_project) # we don't need a #includes since we're just preloading for the #select + .select(&:source_project) end def pipeline_merge_requests(pipeline) diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb index 51d5d7563fc..b4bfb0e5e8c 100644 --- a/app/services/merge_requests/refresh_service.rb +++ b/app/services/merge_requests/refresh_service.rb @@ -42,7 +42,7 @@ module MergeRequests commit_ids.include?(merge_request.diff_head_sha) end - merge_requests.uniq.select(&:source_project).each do |merge_request| + filter_merge_requests(merge_requests).each do |merge_request| MergeRequests::PostMergeService. new(merge_request.target_project, @current_user). execute(merge_request) @@ -58,10 +58,13 @@ module MergeRequests def reload_merge_requests merge_requests = @project.merge_requests.opened. by_source_or_target_branch(@branch_name).to_a - merge_requests += fork_merge_requests - merge_requests = filter_merge_requests(merge_requests) - merge_requests.each do |merge_request| + # Fork merge requests + merge_requests += MergeRequest.opened + .where(source_branch: @branch_name, source_project: @project) + .where.not(target_project: @project).to_a + + filter_merge_requests(merge_requests).each do |merge_request| if merge_request.source_branch == @branch_name || force_push? merge_request.reload_diff else @@ -175,16 +178,7 @@ module MergeRequests end def merge_requests_for_source_branch - @source_merge_requests ||= begin - merge_requests = @project.origin_merge_requests.opened.where(source_branch: @branch_name).to_a - merge_requests += fork_merge_requests - filter_merge_requests(merge_requests) - end - end - - def fork_merge_requests - @fork_merge_requests ||= @project.fork_merge_requests.opened. - where(source_branch: @branch_name).to_a + @source_merge_requests ||= merge_requests_for(@branch_name) end def branch_added? diff --git a/changelogs/unreleased/disable-autologin-on-email-confirmation-links.yml b/changelogs/unreleased/disable-autologin-on-email-confirmation-links.yml new file mode 100644 index 00000000000..6dd0d748001 --- /dev/null +++ b/changelogs/unreleased/disable-autologin-on-email-confirmation-links.yml @@ -0,0 +1,4 @@ +--- +title: Disable automatic login after clicking email confirmation links +merge_request: 7472 +author: diff --git a/changelogs/unreleased/zj-requeue-pending-delete.yml b/changelogs/unreleased/zj-requeue-pending-delete.yml new file mode 100644 index 00000000000..464c5948f8c --- /dev/null +++ b/changelogs/unreleased/zj-requeue-pending-delete.yml @@ -0,0 +1,4 @@ +--- +title: Requeue pending deletion projects +merge_request: +author: diff --git a/db/post_migrate/20170104150317_requeue_pending_delete_projects.rb b/db/post_migrate/20170104150317_requeue_pending_delete_projects.rb new file mode 100644 index 00000000000..f399950bd5e --- /dev/null +++ b/db/post_migrate/20170104150317_requeue_pending_delete_projects.rb @@ -0,0 +1,49 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class RequeuePendingDeleteProjects < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + admin = User.find_by(admin: true) + return unless admin + + @offset = 0 + + loop do + ids = pending_delete_batch + + break if ids.rows.count.zero? + + args = ids.map { |id| [id['id'], admin.id, {}] } + + Sidekiq::Client.push_bulk('class' => "ProjectDestroyWorker", 'args' => args) + + @offset += 1 + end + end + + def down + # noop + end + + private + + def pending_delete_batch + connection.exec_query(find_batch) + end + + BATCH_SIZE = 5000 + + def find_batch + projects = Arel::Table.new(:projects) + projects.project(projects[:id]). + where(projects[:pending_delete].eq(true)). + where(projects[:namespace_id].not_eq(nil)). + skip(@offset * BATCH_SIZE). + take(BATCH_SIZE). + to_sql + end +end diff --git a/doc/user/permissions.md b/doc/user/permissions.md index 5ada8748d85..678fc3ffd1f 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -19,10 +19,12 @@ The following table depicts the various user permission levels in a project. | Action | Guest | Reporter | Developer | Master | Owner | |---------------------------------------|---------|------------|-------------|----------|--------| | Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ | +| Create confidential issue | ✓ | ✓ | ✓ | ✓ | ✓ | +| View confidential issues | (✓) [^1] | ✓ | ✓ | ✓ | ✓ | | Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ | -| See a list of builds | ✓ [^1] | ✓ | ✓ | ✓ | ✓ | -| See a build log | ✓ [^1] | ✓ | ✓ | ✓ | ✓ | -| Download and browse build artifacts | ✓ [^1] | ✓ | ✓ | ✓ | ✓ | +| See a list of builds | ✓ [^2] | ✓ | ✓ | ✓ | ✓ | +| See a build log | ✓ [^2] | ✓ | ✓ | ✓ | ✓ | +| Download and browse build artifacts | ✓ [^2] | ✓ | ✓ | ✓ | ✓ | | View wiki pages | ✓ | ✓ | ✓ | ✓ | ✓ | | Pull project code | | ✓ | ✓ | ✓ | ✓ | | Download project | | ✓ | ✓ | ✓ | ✓ | @@ -63,11 +65,8 @@ The following table depicts the various user permission levels in a project. | Switch visibility level | | | | | ✓ | | Transfer project to another namespace | | | | | ✓ | | Remove project | | | | | ✓ | -| Force push to protected branches [^2] | | | | | | -| Remove protected branches [^2] | | | | | | - -[^1]: If **Public pipelines** is enabled in **Project Settings > CI/CD Pipelines** -[^2]: Not allowed for Guest, Reporter, Developer, Master, or Owner +| Force push to protected branches [^3] | | | | | | +| Remove protected branches [^3] | | | | | | ## Group @@ -156,17 +155,20 @@ users: | Run CI build | | ✓ | ✓ | ✓ | | Clone source and LFS from current project | | ✓ | ✓ | ✓ | | Clone source and LFS from public projects | | ✓ | ✓ | ✓ | -| Clone source and LFS from internal projects | | ✓ [^3] | ✓ [^3] | ✓ | -| Clone source and LFS from private projects | | ✓ [^4] | ✓ [^4] | ✓ [^4] | +| Clone source and LFS from internal projects | | ✓ [^4] | ✓ [^4] | ✓ | +| Clone source and LFS from private projects | | ✓ [^5] | ✓ [^5] | ✓ [^5] | | Push source and LFS | | | | | | Pull container images from current project | | ✓ | ✓ | ✓ | | Pull container images from public projects | | ✓ | ✓ | ✓ | -| Pull container images from internal projects| | ✓ [^3] | ✓ [^3] | ✓ | -| Pull container images from private projects | | ✓ [^4] | ✓ [^4] | ✓ [^4] | +| Pull container images from internal projects| | ✓ [^4] | ✓ [^4] | ✓ | +| Pull container images from private projects | | ✓ [^5] | ✓ [^5] | ✓ [^5] | | Push container images to current project | | ✓ | ✓ | ✓ | | Push container images to other projects | | | | | -[^3]: Only if user is not external one. -[^4]: Only if user is a member of the project. +[^1]: Guest users can only view the confidential issues they created themselves +[^2]: If **Public pipelines** is enabled in **Project Settings > CI/CD Pipelines** +[^3]: Not allowed for Guest, Reporter, Developer, Master, or Owner +[^4]: Only if user is not external one. +[^5]: Only if user is a member of the project. [ce-18994]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18994 [new-mod]: project/new_ci_build_permissions_model.md diff --git a/doc/user/project/issues/confidential_issues.md b/doc/user/project/issues/confidential_issues.md new file mode 100644 index 00000000000..1760b182114 --- /dev/null +++ b/doc/user/project/issues/confidential_issues.md @@ -0,0 +1,68 @@ +# Confidential issues + +> [Introduced][ce-3282] in GitLab 8.6. + +Confidential issues are issues visible only to members of a project with +[sufficient permissions](#permissions-and-access-to-confidential-issues). +Confidential issues can be used by open source projects and companies alike to +keep security vulnerabilities private or prevent surprises from leaking out. + +## Making an issue confidential + +You can make an issue confidential either by creating a new issue or editing +an existing one. + +When you create a new issue, a checkbox right below the text area is available +to mark the issue as confidential. Check that box and hit the **Submit issue** +button to create the issue. For existing issues, edit them, check the +confidential checkbox and hit **Save changes**. + +![Creating a new confidential issue](img/confidential_issues_create.png) + +## Making an issue non-confidential + +To make an issue non-confidential, all you have to do is edit it and unmark +the confidential checkbox. Once you save the issue, it will gain the default +visibility level you have chosen for your project. + +Every change from regular to confidential and vice versa, is indicated by a +system note in the issue's comments. + +![Confidential issues system notes](img/confidential_issues_system_notes.png) + +## Indications of a confidential issue + +>**Note:** If you don't have [enough permissions](#permissions-and-access-to-confidential-issues), +you won't be able to see the confidential issues at all. + +There are a few things that visually separate a confidential issue from a +regular one. In the issues index page view, you can see the eye-slash icon +next to the issues that are marked as confidential. + +![Confidential issues index page](img/confidential_issues_index_page.png) + +--- + +Likewise, while inside the issue, you can see the eye-slash icon right next to +the issue number, but there is also an indicator in the comment area that the +issue you are commenting on is confidential. + +![Confidential issue page](img/confidential_issues_issue_page.png) + +## Permissions and access to confidential issues + +There are two kinds of level access for confidential issues. The general rule +is that confidential issues are visible only to members of a project with at +least [Reporter access][permissions]. However, a guest user can also create +confidential issues, but can only view the ones that they created themselves. + +Confidential issues are also hidden in search results for unprivileged users. +For example, here's what a user with Master and Guest access sees in the +project's search results respectively. + +| Master access | Guest access | +| :-----------: | :----------: | +| ![Confidential issues search master](img/confidential_issues_search_master.png) | ![Confidential issues search guest](img/confidential_issues_search_guest.png) | + +[permissions]: ../../permissions.md#project +[ce-3282]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3282 diff --git a/doc/user/project/issues/img/confidential_issues_create.png b/doc/user/project/issues/img/confidential_issues_create.png Binary files differnew file mode 100644 index 00000000000..4e6be3cc431 --- /dev/null +++ b/doc/user/project/issues/img/confidential_issues_create.png diff --git a/doc/user/project/issues/img/confidential_issues_index_page.png b/doc/user/project/issues/img/confidential_issues_index_page.png Binary files differnew file mode 100644 index 00000000000..042461e2451 --- /dev/null +++ b/doc/user/project/issues/img/confidential_issues_index_page.png diff --git a/doc/user/project/issues/img/confidential_issues_issue_page.png b/doc/user/project/issues/img/confidential_issues_issue_page.png Binary files differnew file mode 100644 index 00000000000..b3568e9303a --- /dev/null +++ b/doc/user/project/issues/img/confidential_issues_issue_page.png diff --git a/doc/user/project/issues/img/confidential_issues_search_guest.png b/doc/user/project/issues/img/confidential_issues_search_guest.png Binary files differnew file mode 100644 index 00000000000..1af3d04d507 --- /dev/null +++ b/doc/user/project/issues/img/confidential_issues_search_guest.png diff --git a/doc/user/project/issues/img/confidential_issues_search_master.png b/doc/user/project/issues/img/confidential_issues_search_master.png Binary files differnew file mode 100644 index 00000000000..b2edeb6094a --- /dev/null +++ b/doc/user/project/issues/img/confidential_issues_search_master.png diff --git a/doc/user/project/issues/img/confidential_issues_system_notes.png b/doc/user/project/issues/img/confidential_issues_system_notes.png Binary files differnew file mode 100644 index 00000000000..4005f9350f7 --- /dev/null +++ b/doc/user/project/issues/img/confidential_issues_system_notes.png diff --git a/doc/workflow/README.md b/doc/workflow/README.md index b317bd79ded..a56ae75fe69 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -7,6 +7,9 @@ - [Feature branch workflow](workflow.md) - [GitLab Flow](gitlab_flow.md) - [Groups](groups.md) +- Issues - The GitLab Issue Tracker is an advanced and complete tool for + tracking the evolution of a new idea or the process of solving a problem. + - [Confidential issues](../user/project/issues/confidential_issues.md) - [Issue Board](../user/project/issue_board.md) - [Keyboard shortcuts](shortcuts.md) - [File finder](file_finder.md) diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 00d0e20f47c..314ea670a71 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -106,23 +106,46 @@ describe MergeRequests::RefreshService, services: true do context 'push to fork repo source branch' do let(:refresh_service) { service.new(@fork_project, @user) } - before do - allow(refresh_service).to receive(:execute_hooks) - refresh_service.execute(@oldrev, @newrev, 'refs/heads/master') - reload_mrs - end - it 'executes hooks with update action' do - expect(refresh_service).to have_received(:execute_hooks). - with(@fork_merge_request, 'update', @oldrev) + context 'open fork merge request' do + before do + allow(refresh_service).to receive(:execute_hooks) + refresh_service.execute(@oldrev, @newrev, 'refs/heads/master') + reload_mrs + end + + it 'executes hooks with update action' do + expect(refresh_service).to have_received(:execute_hooks). + with(@fork_merge_request, 'update', @oldrev) + end + + it { expect(@merge_request.notes).to be_empty } + it { expect(@merge_request).to be_open } + it { expect(@fork_merge_request.notes.last.note).to include('added 28 commits') } + it { expect(@fork_merge_request).to be_open } + it { expect(@build_failed_todo).to be_pending } + it { expect(@fork_build_failed_todo).to be_pending } end - it { expect(@merge_request.notes).to be_empty } - it { expect(@merge_request).to be_open } - it { expect(@fork_merge_request.notes.last.note).to include('added 28 commits') } - it { expect(@fork_merge_request).to be_open } - it { expect(@build_failed_todo).to be_pending } - it { expect(@fork_build_failed_todo).to be_pending } + context 'closed fork merge request' do + before do + @fork_merge_request.close! + allow(refresh_service).to receive(:execute_hooks) + refresh_service.execute(@oldrev, @newrev, 'refs/heads/master') + reload_mrs + end + + it 'do not execute hooks with update action' do + expect(refresh_service).not_to have_received(:execute_hooks) + end + + it { expect(@merge_request.notes).to be_empty } + it { expect(@merge_request).to be_open } + it { expect(@fork_merge_request.notes).to be_empty } + it { expect(@fork_merge_request).to be_closed } + it { expect(@build_failed_todo).to be_pending } + it { expect(@fork_build_failed_todo).to be_pending } + end end context 'push to fork repo target branch' do |