Commit ddfa9cb2 authored by Robert Speicher's avatar Robert Speicher

Merge branch 'master' of dev.gitlab.org:gitlab/gitlab-ee

parents 37452de8 e0a6a21a
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.
## 13.10.1 (2021-03-31)
### Security (1 change)
- Escape HTML on scoped labels tooltip.
## 13.10.0 (2021-03-22) ## 13.10.0 (2021-03-22)
### Removed (1 change) ### Removed (1 change)
...@@ -167,6 +174,13 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -167,6 +174,13 @@ Please view this file on the master branch, on stable branches it's out of date.
- Delete redirect files. !56169 - Delete redirect files. !56169
## 13.9.5 (2021-03-31)
### Security (1 change)
- Escape HTML on scoped labels tooltip.
## 13.9.4 (2021-03-17) ## 13.9.4 (2021-03-17)
- No changes. - No changes.
...@@ -337,6 +351,13 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -337,6 +351,13 @@ Please view this file on the master branch, on stable branches it's out of date.
- Review UI text - repo push rules settings. !52797 - Review UI text - repo push rules settings. !52797
## 13.8.7 (2021-03-31)
### Security (1 change)
- Escape HTML on scoped labels tooltip.
## 13.8.6 (2021-03-17) ## 13.8.6 (2021-03-17)
- No changes. - No changes.
......
...@@ -2,6 +2,28 @@ ...@@ -2,6 +2,28 @@
documentation](doc/development/changelog.md) for instructions on adding your own documentation](doc/development/changelog.md) for instructions on adding your own
entry. entry.
## 13.10.1 (2021-03-31)
### Security (6 changes)
- Leave pool repository on fork unlinking.
- Fixed XSS in merge requests sidebar.
- Fix arbitrary read/write in AsciiDoctor and Kroki gems.
- Prevent infinite loop when checking if collaboration is allowed.
- Disable arbitrary URI and file reads in JSON validator.
- Require POST request to trigger system hooks.
### Removed (1 change)
- Make HipChat project service do nothing. !57434
### Other (3 changes)
- Remove direct mimemagic dependency. !57387
- Refactor MimeMagic calls to new MimeType class. !57421
- Switch to using a fake mimemagic gem. !57443
## 13.10.0 (2021-03-22) ## 13.10.0 (2021-03-22)
### Security (3 changes) ### Security (3 changes)
...@@ -529,6 +551,28 @@ entry. ...@@ -529,6 +551,28 @@ entry.
- Convert mattermost alert to pajamas. !56556 - Convert mattermost alert to pajamas. !56556
## 13.9.5 (2021-03-31)
### Security (6 changes)
- Leave pool repository on fork unlinking.
- Fixed XSS in merge requests sidebar.
- Fix arbitrary read/write in AsciiDoctor and Kroki gems.
- Prevent infinite loop when checking if collaboration is allowed.
- Disable arbitrary URI and file reads in JSON validator.
- Require POST request to trigger system hooks.
### Removed (1 change)
- Make HipChat project service do nothing. !57434
### Other (3 changes)
- Remove direct mimemagic dependency. !57387
- Refactor MimeMagic calls to new MimeType class. !57421
- Switch to using a fake mimemagic gem. !57443
## 13.9.4 (2021-03-17) ## 13.9.4 (2021-03-17)
### Security (1 change) ### Security (1 change)
...@@ -1144,6 +1188,27 @@ entry. ...@@ -1144,6 +1188,27 @@ entry.
- Apply new GitLab UI for buttons in pipeline schedules. - Apply new GitLab UI for buttons in pipeline schedules.
## 13.8.7 (2021-03-31)
### Security (5 changes)
- Fixed XSS in merge requests sidebar.
- Leave pool repository on fork unlinking.
- Fix arbitrary read/write in AsciiDoctor and Kroki gems.
- Prevent infinite loop when checking if collaboration is allowed.
- Require POST request to trigger system hooks.
### Removed (1 change)
- Make HipChat project service do nothing. !57434
### Other (3 changes)
- Remove direct mimemagic dependency. !57387
- Refactor MimeMagic calls to new MimeType class. !57421
- Switch to using a fake mimemagic gem. !57443
## 13.8.6 (2021-03-17) ## 13.8.6 (2021-03-17)
### Security (1 change) ### Security (1 change)
......
...@@ -1350,8 +1350,8 @@ class MergeRequest < ApplicationRecord ...@@ -1350,8 +1350,8 @@ class MergeRequest < ApplicationRecord
has_no_commits? || branch_missing? || cannot_be_merged? has_no_commits? || branch_missing? || cannot_be_merged?
end end
def can_be_merged_by?(user) def can_be_merged_by?(user, skip_collaboration_check: false)
access = ::Gitlab::UserAccess.new(user, container: project) access = ::Gitlab::UserAccess.new(user, container: project, skip_collaboration_check: skip_collaboration_check)
access.can_update_branch?(target_branch) access.can_update_branch?(target_branch)
end end
......
...@@ -2711,7 +2711,7 @@ class Project < ApplicationRecord ...@@ -2711,7 +2711,7 @@ class Project < ApplicationRecord
# Issue for N+1: https://gitlab.com/gitlab-org/gitlab-foss/issues/49322 # Issue for N+1: https://gitlab.com/gitlab-org/gitlab-foss/issues/49322
Gitlab::GitalyClient.allow_n_plus_1_calls do Gitlab::GitalyClient.allow_n_plus_1_calls do
merge_requests_allowing_collaboration(branch_name).any? do |merge_request| merge_requests_allowing_collaboration(branch_name).any? do |merge_request|
merge_request.can_be_merged_by?(user) merge_request.can_be_merged_by?(user, skip_collaboration_check: true)
end end
end end
end end
......
...@@ -32,6 +32,8 @@ module Projects ...@@ -32,6 +32,8 @@ module Projects
if fork_network = @project.root_of_fork_network if fork_network = @project.root_of_fork_network
fork_network.update(root_project: nil, deleted_root_project_name: @project.full_name) fork_network.update(root_project: nil, deleted_root_project_name: @project.full_name)
end end
@project.leave_pool_repository
end end
# rubocop: disable Cop/InBatches # rubocop: disable Cop/InBatches
......
...@@ -138,7 +138,7 @@ ...@@ -138,7 +138,7 @@
= clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport') = clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport')
.gl-display-flex.gl-align-items-center.gl-justify-content-space-between.gl-mb-2.hide-collapsed .gl-display-flex.gl-align-items-center.gl-justify-content-space-between.gl-mb-2.hide-collapsed
%span.gl-overflow-hidden.gl-text-overflow-ellipsis.gl-white-space-nowrap %span.gl-overflow-hidden.gl-text-overflow-ellipsis.gl-white-space-nowrap
= _('Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}').html_safe % { source_branch_open: "<span class='gl-font-monospace' title='#{source_branch}'>".html_safe, source_branch_close: "</span>".html_safe, source_branch: source_branch } = _('Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}').html_safe % { source_branch_open: "<span class='gl-font-monospace' data-testid='ref-name' title='#{html_escape(source_branch)}'>".html_safe, source_branch_close: "</span>".html_safe, source_branch: html_escape(source_branch) }
= clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport') = clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport')
- if show_forwarding_email - if show_forwarding_email
......
---
title: Switch to using a fake mimemagic gem
merge_request: 57443
author:
type: other
---
title: Refactor MimeMagic calls to new MimeType class
merge_request: 57421
author:
type: other
---
title: Remove direct mimemagic dependency
merge_request: 57387
author:
type: other
---
title: Make HipChat project service do nothing
merge_request: 57434
author:
type: removed
# frozen_string_literal: true
# Ensure that locked attributes can not be changed using a counter.
# TODO: this can be removed once `asciidoctor` gem is > 2.0.12
# and https://github.com/asciidoctor/asciidoctor/issues/3939 is merged
module Asciidoctor
module DocumentPatch
def counter(name, seed = nil)
return @parent_document.counter(name, seed) if @parent_document # rubocop: disable Gitlab/ModuleWithInstanceVariables
unless attribute_locked? name
super
end
end
end
end
class Asciidoctor::Document
prepend Asciidoctor::DocumentPatch
end
...@@ -88,7 +88,7 @@ Example response: ...@@ -88,7 +88,7 @@ Example response:
## Test system hook ## Test system hook
```plaintext ```plaintext
GET /hooks/:id POST /hooks/:id
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
...@@ -98,7 +98,7 @@ GET /hooks/:id ...@@ -98,7 +98,7 @@ GET /hooks/:id
Example request: Example request:
```shell ```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/hooks/2" curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/hooks/1"
``` ```
Example response: Example response:
......
...@@ -5,6 +5,10 @@ module EE ...@@ -5,6 +5,10 @@ module EE
extend ActiveSupport::Concern extend ActiveSupport::Concern
prepended do prepended do
condition(:is_author) do
@user && @subject.author_id == @user.id
end
rule { can?(:read_issue) }.policy do rule { can?(:read_issue) }.policy do
enable :read_issuable_metric_image enable :read_issuable_metric_image
end end
...@@ -12,6 +16,15 @@ module EE ...@@ -12,6 +16,15 @@ module EE
rule { can?(:create_issue) & can?(:update_issue) }.policy do rule { can?(:create_issue) & can?(:update_issue) }.policy do
enable :upload_issuable_metric_image enable :upload_issuable_metric_image
end end
rule { is_author | can?(:create_issue) & can?(:update_issue) }.policy do
enable :destroy_issuable_metric_image
end
rule { ~is_project_member }.policy do
prevent :upload_issuable_metric_image
prevent :destroy_issuable_metric_image
end
end end
end end
end end
---
title: Fix permissions for modifying issue metric images
merge_request:
author:
type: security
...@@ -79,6 +79,9 @@ module EE ...@@ -79,6 +79,9 @@ module EE
end end
delete ':metric_image_id' do delete ':metric_image_id' do
issue = find_project_issue(params[:issue_iid]) issue = find_project_issue(params[:issue_iid])
authorize!(:destroy_issuable_metric_image, issue)
metric_image = issue.metric_images.find_by_id(params[:metric_image_id]) metric_image = issue.metric_images.find_by_id(params[:metric_image_id])
render_api_error!('Metric image not found', 404) unless metric_image render_api_error!('Metric image not found', 404) unless metric_image
...@@ -93,12 +96,6 @@ module EE ...@@ -93,12 +96,6 @@ module EE
end end
helpers do helpers do
include ::API::Helpers::Packages::BasicAuthHelpers
def project
authorized_user_project
end
def max_file_size_exceeded? def max_file_size_exceeded?
params[:file].size > ::IssuableMetricImage::MAX_FILE_SIZE params[:file].size > ::IssuableMetricImage::MAX_FILE_SIZE
end end
......
...@@ -10,12 +10,18 @@ module EE ...@@ -10,12 +10,18 @@ module EE
def data_attributes_for(text, parent, object, link_content: false, link_reference: false) def data_attributes_for(text, parent, object, link_content: false, link_reference: false)
return super unless object.scoped_label? return super unless object.scoped_label?
# Enabling HTML tooltips for scoped labels here but we do not need to do any additional # Enabling HTML tooltips for scoped labels here and additional escaping is done in `object_link_title`
# escaping because the label's tooltips are already stripped of dangerous HTML
super.merge!( super.merge!(
html: true html: true
) )
end end
override :object_link_title
def object_link_title(object, matches)
return super unless object.scoped_label?
ERB::Util.html_escape(super)
end
end end
end end
end end
......
...@@ -5,9 +5,10 @@ require 'spec_helper' ...@@ -5,9 +5,10 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::LabelReferenceFilter do RSpec.describe Banzai::Filter::LabelReferenceFilter do
include FilterSpecHelper include FilterSpecHelper
let(:project) { create(:project, :public, name: 'sample-project') } let(:project) { create(:project, :public, name: 'sample-project') }
let(:label) { create(:label, name: 'label', project: project) } let(:label) { create(:label, name: 'label', project: project) }
let(:scoped_label) { create(:label, name: 'key::value', project: project) } let(:scoped_description) { 'xss <script>alert("scriptAlert");</script> &<a>lt;svg id=&quot;svgId&quot;&gt;&lt;/svg&gt;' }
let(:scoped_label) { create(:label, name: 'key::value', project: project, description: scoped_description) }
context 'with scoped labels enabled' do context 'with scoped labels enabled' do
before do before do
...@@ -24,6 +25,10 @@ RSpec.describe Banzai::Filter::LabelReferenceFilter do ...@@ -24,6 +25,10 @@ RSpec.describe Banzai::Filter::LabelReferenceFilter do
it 'renders HTML tooltips' do it 'renders HTML tooltips' do
expect(doc.at_css('.gl-label-scoped a').attr('data-html')).to eq('true') expect(doc.at_css('.gl-label-scoped a').attr('data-html')).to eq('true')
end end
it "escapes HTML in the label's title" do
expect(doc.at_css('.gl-label-scoped a').attr('title')).to include('xss &lt;svg id="svgId"&gt;')
end
end end
context 'with a common label' do context 'with a common label' do
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe IssuablePolicy, models: true do
let(:non_member) { create(:user) }
let(:guest) { create(:user) }
let(:reporter) { create(:user) }
let(:guest_issue) { create(:issue, project: project, author: guest) }
let(:reporter_issue) { create(:issue, project: project, author: reporter) }
before do
project.add_guest(guest)
project.add_reporter(reporter)
end
def permissions(user, issue)
described_class.new(user, issue)
end
describe '#rules' do
context 'in a public project' do
let_it_be(:project) { create(:project, :public) }
let_it_be(:issue) { create(:issue, project: project) }
it 'disallows non-members from creating and deleting metric images' do
expect(permissions(non_member, issue)).to be_allowed(:read_issuable_metric_image)
expect(permissions(non_member, issue)).to be_disallowed(:upload_issuable_metric_image, :destroy_issuable_metric_image)
end
it 'allows guests to read, create metric images, and delete them in their own issues' do
expect(permissions(guest, issue)).to be_allowed(:read_issuable_metric_image)
expect(permissions(guest, issue)).to be_disallowed(:upload_issuable_metric_image, :destroy_issuable_metric_image)
expect(permissions(guest, guest_issue)).to be_allowed(:read_issuable_metric_image, :upload_issuable_metric_image, :destroy_issuable_metric_image)
end
it 'allows reporters to create and delete metric images' do
expect(permissions(reporter, issue)).to be_allowed(:read_issuable_metric_image, :upload_issuable_metric_image, :destroy_issuable_metric_image)
expect(permissions(reporter, reporter_issue)).to be_allowed(:read_issuable_metric_image, :upload_issuable_metric_image, :destroy_issuable_metric_image)
end
end
context 'in a private project' do
let_it_be(:project) { create(:project, :private) }
let_it_be(:issue) { create(:issue, project: project) }
it 'disallows non-members from creating and deleting metric images' do
expect(permissions(non_member, issue)).to be_disallowed(:read_issuable_metric_image, :upload_issuable_metric_image, :destroy_issuable_metric_image)
end
it 'allows guests to read metric images, and create + delete in their own issues' do
expect(permissions(guest, issue)).to be_allowed(:read_issuable_metric_image)
expect(permissions(guest, issue)).to be_disallowed(:upload_issuable_metric_image, :destroy_issuable_metric_image)
expect(permissions(guest, guest_issue)).to be_allowed(:read_issuable_metric_image, :upload_issuable_metric_image, :destroy_issuable_metric_image)
end
it 'allows reporters to create and delete metric images' do
expect(permissions(reporter, issue)).to be_allowed(:read_issuable_metric_image, :upload_issuable_metric_image, :destroy_issuable_metric_image)
expect(permissions(reporter, reporter_issue)).to be_allowed(:read_issuable_metric_image, :upload_issuable_metric_image, :destroy_issuable_metric_image)
end
end
end
end
...@@ -705,7 +705,7 @@ RSpec.describe API::Issues, :mailer do ...@@ -705,7 +705,7 @@ RSpec.describe API::Issues, :mailer do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
let_it_be(:project) do let_it_be(:project) do
create(:project, :private, creator_id: user.id, namespace: user.namespace) create(:project, :public, creator_id: user.id, namespace: user.namespace)
end end
let!(:image) { create(:issuable_metric_image, issue: issue) } let!(:image) { create(:issuable_metric_image, issue: issue) }
...@@ -722,6 +722,15 @@ RSpec.describe API::Issues, :mailer do ...@@ -722,6 +722,15 @@ RSpec.describe API::Issues, :mailer do
end end
shared_examples 'unauthorized_delete' do shared_examples 'unauthorized_delete' do
it 'cannot delete the metric image' do
subject
expect(response).to have_gitlab_http_status(:forbidden)
expect(image.reload).to eq(image)
end
end
shared_examples 'not_found' do
it 'cannot delete the metric image' do it 'cannot delete the metric image' do
subject subject
...@@ -734,9 +743,9 @@ RSpec.describe API::Issues, :mailer do ...@@ -734,9 +743,9 @@ RSpec.describe API::Issues, :mailer do
:not_member | false | false | :unauthorized_delete :not_member | false | false | :unauthorized_delete
:not_member | true | false | :unauthorized_delete :not_member | true | false | :unauthorized_delete
:not_member | true | true | :unauthorized_delete :not_member | true | true | :unauthorized_delete
:guest | false | true | :unauthorized_delete :guest | false | true | :not_found
:guest | false | false | :unauthorized_delete
:guest | true | false | :can_delete_metric_image :guest | true | false | :can_delete_metric_image
:guest | false | false | :can_delete_metric_image
:reporter | true | false | :can_delete_metric_image :reporter | true | false | :can_delete_metric_image
:reporter | false | false | :can_delete_metric_image :reporter | false | false | :can_delete_metric_image
end end
......
...@@ -47,7 +47,7 @@ module API ...@@ -47,7 +47,7 @@ module API
params do params do
requires :id, type: Integer, desc: 'The ID of the system hook' requires :id, type: Integer, desc: 'The ID of the system hook'
end end
get ":id" do post ":id" do
hook = SystemHook.find(params[:id]) hook = SystemHook.find(params[:id])
data = { data = {
event_name: "project_create", event_name: "project_create",
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
module Gitlab module Gitlab
module MarkdownCache module MarkdownCache
# Increment this number every time the renderer changes its output # Increment this number every time the renderer changes its output
CACHE_COMMONMARK_VERSION = 26 CACHE_COMMONMARK_VERSION = 27
CACHE_COMMONMARK_VERSION_START = 10 CACHE_COMMONMARK_VERSION_START = 10
BaseError = Class.new(StandardError) BaseError = Class.new(StandardError)
......
...@@ -11,10 +11,11 @@ module Gitlab ...@@ -11,10 +11,11 @@ module Gitlab
attr_reader :user, :push_ability attr_reader :user, :push_ability
attr_accessor :container attr_accessor :container
def initialize(user, container: nil, push_ability: :push_code) def initialize(user, container: nil, push_ability: :push_code, skip_collaboration_check: false)
@user = user @user = user
@container = container @container = container
@push_ability = push_ability @push_ability = push_ability
@skip_collaboration_check = skip_collaboration_check
end end
def can_do_action?(action) def can_do_action?(action)
...@@ -87,6 +88,8 @@ module Gitlab ...@@ -87,6 +88,8 @@ module Gitlab
private private
attr_reader :skip_collaboration_check
def can_push? def can_push?
user.can?(push_ability, container) user.can?(push_ability, container)
end end
...@@ -98,6 +101,8 @@ module Gitlab ...@@ -98,6 +101,8 @@ module Gitlab
end end
def branch_allows_collaboration_for?(ref) def branch_allows_collaboration_for?(ref)
return false if skip_collaboration_check
# Checking for an internal project or group to prevent an infinite loop: # Checking for an internal project or group to prevent an infinite loop:
# https://gitlab.com/gitlab-org/gitlab/issues/36805 # https://gitlab.com/gitlab-org/gitlab/issues/36805
(!project.internal? && project.branch_allows_collaboration?(user, ref)) (!project.internal? && project.branch_allows_collaboration?(user, ref))
......
...@@ -6,7 +6,7 @@ FactoryBot.define do ...@@ -6,7 +6,7 @@ FactoryBot.define do
state { :none } state { :none }
before(:create) do |pool| before(:create) do |pool|
pool.source_project = create(:project, :repository) pool.source_project ||= create(:project, :repository)
pool.source_project.update!(pool_repository: pool) pool.source_project.update!(pool_repository: pool)
end end
......
...@@ -111,4 +111,21 @@ RSpec.describe 'User views an open merge request' do ...@@ -111,4 +111,21 @@ RSpec.describe 'User views an open merge request' do
end end
end end
end end
context 'XSS source branch' do
let(:project) { create(:project, :public, :repository) }
let(:source_branch) { "&#39;&gt;&lt;iframe/srcdoc=&#39;&#39;&gt;&lt;/iframe&gt;" }
before do
project.repository.create_branch(source_branch, "master")
mr = create(:merge_request, source_project: project, target_project: project, source_branch: source_branch)
visit(merge_request_path(mr))
end
it 'encodes branch name' do
expect(find("[data-testid='ref-name']")[:title]).to eq(source_branch)
end
end
end end
...@@ -92,6 +92,15 @@ module Gitlab ...@@ -92,6 +92,15 @@ module Gitlab
expect(render(data[:input], context)).to include(data[:output]) expect(render(data[:input], context)).to include(data[:output])
end end
end end
it 'does not allow locked attributes to be overridden' do
input = <<~ADOC
{counter:max-include-depth:1234}
<|-- {max-include-depth}
ADOC
expect(render(input, {})).not_to include('1234')
end
end end
context "images" do context "images" do
...@@ -543,6 +552,40 @@ module Gitlab ...@@ -543,6 +552,40 @@ module Gitlab
expect(render(input, context)).to include(output.strip) expect(render(input, context)).to include(output.strip)
end end
it 'does not allow kroki-plantuml-include to be overridden' do
input = <<~ADOC
[plantuml, test="{counter:kroki-plantuml-include:/etc/passwd}", format="png"]
....
class BlockProcessor
BlockProcessor <|-- {counter:kroki-plantuml-include}
....
ADOC
output = <<~HTML
<div>
<div>
<a class=\"no-attachment-icon\" href=\"https://kroki.io/plantuml/png/eNpLzkksLlZwyslPzg4oyk9OLS7OL-LiQuUr2NTo6ipUJ-eX5pWkFlllF-VnZ-oW5CTmlZTm5uhm5iXnlKak1gIABQEb8A==\" target=\"_blank\" rel=\"noopener noreferrer\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Diagram\" class=\"lazy\" data-src=\"https://kroki.io/plantuml/png/eNpLzkksLlZwyslPzg4oyk9OLS7OL-LiQuUr2NTo6ipUJ-eX5pWkFlllF-VnZ-oW5CTmlZTm5uhm5iXnlKak1gIABQEb8A==\"></a>
</div>
</div>
HTML
expect(render(input, {})).to include(output.strip)
end
it 'does not allow kroki-server-url to be overridden' do
input = <<~ADOC
[plantuml, test="{counter:kroki-server-url:evilsite}", format="png"]
....
class BlockProcessor
BlockProcessor
....
ADOC
expect(render(input, {})).not_to include('evilsite')
end
end end
context 'with Kroki and BlockDiag (additional format) enabled' do context 'with Kroki and BlockDiag (additional format) enabled' do
......
...@@ -216,6 +216,15 @@ RSpec.describe Gitlab::UserAccess do ...@@ -216,6 +216,15 @@ RSpec.describe Gitlab::UserAccess do
expect(access.can_merge_to_branch?(@branch.name)).to be_falsey expect(access.can_merge_to_branch?(@branch.name)).to be_falsey
end end
end end
context 'when skip_collaboration_check is true' do
let(:access) { described_class.new(user, container: project, skip_collaboration_check: true) }
it 'does not call Project#branch_allows_collaboration?' do
expect(project).not_to receive(:branch_allows_collaboration?)
expect(access.can_push_to_branch?('master')).to be_falsey
end
end
end end
describe '#can_create_tag?' do describe '#can_create_tag?' do
......
...@@ -5319,6 +5319,64 @@ RSpec.describe Project, factory_default: :keep do ...@@ -5319,6 +5319,64 @@ RSpec.describe Project, factory_default: :keep do
end end
end end
describe '#branch_allows_collaboration?' do
context 'when there are open merge requests that have their source/target branches point to each other' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:developer) { create(:user) }
let_it_be(:reporter) { create(:user) }
let_it_be(:guest) { create(:user) }
before_all do
create(
:merge_request,
target_project: project,
target_branch: 'master',
source_project: project,
source_branch: 'merge-test',
allow_collaboration: true
)
create(
:merge_request,
target_project: project,
target_branch: 'merge-test',
source_project: project,
source_branch: 'master',
allow_collaboration: true
)
project.add_developer(developer)
project.add_reporter(reporter)
project.add_guest(guest)
end
shared_examples_for 'successful check' do
it 'does not go into an infinite loop' do
expect { project.branch_allows_collaboration?(user, 'master') }
.not_to raise_error
end
end
context 'when user is a developer' do
let(:user) { developer }
it_behaves_like 'successful check'
end
context 'when user is a reporter' do
let(:user) { reporter }
it_behaves_like 'successful check'
end
context 'when user is a guest' do
let(:user) { guest }
it_behaves_like 'successful check'
end
end
end
context 'with cross project merge requests' do context 'with cross project merge requests' do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:target_project) { create(:project, :repository) } let(:target_project) { create(:project, :repository) }
......
...@@ -103,15 +103,15 @@ RSpec.describe API::SystemHooks do ...@@ -103,15 +103,15 @@ RSpec.describe API::SystemHooks do
end end
end end
describe "GET /hooks/:id" do describe 'POST /hooks/:id' do
it "returns hook by id" do it "returns and trigger hook by id" do
get api("/hooks/#{hook.id}", admin) post api("/hooks/#{hook.id}", admin)
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:created)
expect(json_response['event_name']).to eq('project_create') expect(json_response['event_name']).to eq('project_create')
end end
it "returns 404 on failure" do it "returns 404 on failure" do
get api("/hooks/404", admin) post api("/hooks/404", admin)
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:not_found)
end end
end end
......
...@@ -403,7 +403,7 @@ RSpec.describe Projects::ForkService do ...@@ -403,7 +403,7 @@ RSpec.describe Projects::ForkService do
end end
context 'when forking with object pools' do context 'when forking with object pools' do
let(:fork_from_project) { create(:project, :public) } let(:fork_from_project) { create(:project, :repository, :public) }
let(:forker) { create(:user) } let(:forker) { create(:user) }
context 'when no pool exists' do context 'when no pool exists' do
......
...@@ -207,6 +207,17 @@ RSpec.describe Projects::UnlinkForkService, :use_clean_rails_memory_store_cachin ...@@ -207,6 +207,17 @@ RSpec.describe Projects::UnlinkForkService, :use_clean_rails_memory_store_cachin
end end
end end
context 'a project with pool repository' do
let(:project) { create(:project, :public, :repository) }
let!(:pool_repository) { create(:pool_repository, :ready, source_project: project) }
subject { described_class.new(project, user) }
it 'when unlinked leaves pool repository' do
expect { subject.execute }.to change { project.reload.has_pool_repository? }.from(true).to(false)
end
end
context 'when given project is not part of a fork network' do context 'when given project is not part of a fork network' do
let!(:project_without_forks) { create(:project, :public) } let!(:project_without_forks) { create(:project, :public) }
......
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