Update upstream source from tag 'upstream/13.9.5+ds1'
Update to upstream version '13.9.5+ds1'
with Debian dir 71eb89d788
This commit is contained in:
commit
9adaa9b51a
44 changed files with 437 additions and 532 deletions
22
CHANGELOG.md
22
CHANGELOG.md
|
@ -2,6 +2,28 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 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)
|
||||
|
||||
### Security (1 change)
|
||||
|
|
|
@ -1 +1 @@
|
|||
13.9.4
|
||||
13.9.5
|
8
Gemfile
8
Gemfile
|
@ -235,9 +235,6 @@ gem 'redis-rails', '~> 5.0.2'
|
|||
# Discord integration
|
||||
gem 'discordrb-webhooks-blackst0ne', '~> 3.3', require: false
|
||||
|
||||
# HipChat integration
|
||||
gem 'hipchat', '~> 1.5.0'
|
||||
|
||||
# Jira integration
|
||||
gem 'jira-ruby', '~> 2.1.4'
|
||||
gem 'atlassian-jwt', '~> 0.2.0'
|
||||
|
@ -274,7 +271,10 @@ gem 'licensee', '~> 9.14.1'
|
|||
gem 'charlock_holmes', '~> 0.7.7'
|
||||
|
||||
# Detect mime content type from content
|
||||
gem 'mimemagic', '~> 0.3.2'
|
||||
gem 'ruby-magic-static', '~> 0.3.4'
|
||||
|
||||
# Fake version of the gem to trick bundler
|
||||
gem 'mimemagic', '0.3.7', path: 'vendor/shims/mimemagic', require: false
|
||||
|
||||
# Faster blank
|
||||
gem 'fast_blank'
|
||||
|
|
14
Gemfile.lock
14
Gemfile.lock
|
@ -1,3 +1,8 @@
|
|||
PATH
|
||||
remote: vendor/shims/mimemagic
|
||||
specs:
|
||||
mimemagic (0.3.7)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
|
@ -574,9 +579,6 @@ GEM
|
|||
railties (>= 5.0)
|
||||
heapy (0.2.0)
|
||||
thor
|
||||
hipchat (1.5.2)
|
||||
httparty
|
||||
mimemagic
|
||||
html-pipeline (2.13.2)
|
||||
activesupport (>= 2)
|
||||
nokogiri (>= 1.4)
|
||||
|
@ -711,7 +713,6 @@ GEM
|
|||
mime-types (3.3.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2020.0512)
|
||||
mimemagic (0.3.5)
|
||||
mini_histogram (0.3.1)
|
||||
mini_magick (4.10.1)
|
||||
mini_mime (1.0.2)
|
||||
|
@ -1068,6 +1069,7 @@ GEM
|
|||
i18n
|
||||
ruby-fogbugz (0.2.1)
|
||||
crack (~> 0.4)
|
||||
ruby-magic-static (0.3.4)
|
||||
ruby-prof (1.3.1)
|
||||
ruby-progressbar (1.11.0)
|
||||
ruby-saml (1.7.2)
|
||||
|
@ -1404,7 +1406,6 @@ DEPENDENCIES
|
|||
hashie
|
||||
hashie-forbidden_attributes
|
||||
health_check (~> 3.0)
|
||||
hipchat (~> 1.5.0)
|
||||
html-pipeline (~> 2.13.2)
|
||||
html2text
|
||||
httparty (~> 0.16.4)
|
||||
|
@ -1433,7 +1434,7 @@ DEPENDENCIES
|
|||
marginalia (~> 1.10.0)
|
||||
memory_profiler (~> 0.9)
|
||||
method_source (~> 1.0)
|
||||
mimemagic (~> 0.3.2)
|
||||
mimemagic (= 0.3.7)!
|
||||
mini_magick (~> 4.10.1)
|
||||
minitest (~> 5.11.0)
|
||||
multi_json (~> 1.14.1)
|
||||
|
@ -1505,6 +1506,7 @@ DEPENDENCIES
|
|||
rspec_junit_formatter
|
||||
rspec_profiling (~> 0.0.6)
|
||||
ruby-fogbugz (~> 0.2.1)
|
||||
ruby-magic-static (~> 0.3.4)
|
||||
ruby-prof (~> 1.3.0)
|
||||
ruby-progressbar (~> 1.10)
|
||||
ruby_parser (~> 3.15)
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
13.9.4
|
||||
13.9.5
|
|
@ -226,10 +226,10 @@ class Projects::JobsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def raw_trace_content_disposition(raw_data)
|
||||
mime_type = MimeMagic.by_magic(raw_data)
|
||||
mime_type = Gitlab::Utils::MimeType.from_string(raw_data)
|
||||
|
||||
# if mime_type is nil can also represent 'text/plain'
|
||||
return 'inline' if mime_type.nil? || mime_type.type == 'text/plain'
|
||||
return 'inline' if mime_type.nil? || mime_type == 'text/plain'
|
||||
|
||||
'attachment'
|
||||
end
|
||||
|
|
|
@ -1289,8 +1289,8 @@ class MergeRequest < ApplicationRecord
|
|||
has_no_commits? || branch_missing? || cannot_be_merged?
|
||||
end
|
||||
|
||||
def can_be_merged_by?(user)
|
||||
access = ::Gitlab::UserAccess.new(user, container: project)
|
||||
def can_be_merged_by?(user, skip_collaboration_check: false)
|
||||
access = ::Gitlab::UserAccess.new(user, container: project, skip_collaboration_check: skip_collaboration_check)
|
||||
access.can_update_branch?(target_branch)
|
||||
end
|
||||
|
||||
|
|
|
@ -2666,7 +2666,7 @@ class Project < ApplicationRecord
|
|||
# Issue for N+1: https://gitlab.com/gitlab-org/gitlab-foss/issues/49322
|
||||
Gitlab::GitalyClient.allow_n_plus_1_calls do
|
||||
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
|
||||
|
|
|
@ -52,12 +52,8 @@ class HipchatService < Service
|
|||
end
|
||||
|
||||
def execute(data)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
|
||||
message = create_message(data)
|
||||
return unless message.present?
|
||||
|
||||
gate[room].send('GitLab', message, message_options(data)) # rubocop:disable GitlabSecurity/PublicSend
|
||||
# We removed the hipchat gem due to https://gitlab.com/gitlab-org/gitlab/-/issues/325851#note_537143149
|
||||
# HipChat is unusable anyway, so do nothing in this method
|
||||
end
|
||||
|
||||
def test(data)
|
||||
|
@ -72,71 +68,14 @@ class HipchatService < Service
|
|||
|
||||
private
|
||||
|
||||
def gate
|
||||
options = { api_version: api_version.presence || 'v2' }
|
||||
options[:server_url] = server unless server.blank?
|
||||
@gate ||= HipChat::Client.new(token, options)
|
||||
end
|
||||
|
||||
def message_options(data = nil)
|
||||
{ notify: notify.present? && Gitlab::Utils.to_boolean(notify), color: message_color(data) }
|
||||
end
|
||||
|
||||
def create_message(data)
|
||||
object_kind = data[:object_kind]
|
||||
|
||||
case object_kind
|
||||
when "push", "tag_push"
|
||||
create_push_message(data)
|
||||
when "issue"
|
||||
create_issue_message(data) unless update?(data)
|
||||
when "merge_request"
|
||||
create_merge_request_message(data) unless update?(data)
|
||||
when "note"
|
||||
create_note_message(data)
|
||||
when "pipeline"
|
||||
create_pipeline_message(data) if should_pipeline_be_notified?(data)
|
||||
end
|
||||
end
|
||||
|
||||
def render_line(text)
|
||||
markdown(text.lines.first.chomp, pipeline: :single_line) if text
|
||||
end
|
||||
|
||||
def create_push_message(push)
|
||||
ref_type = Gitlab::Git.tag_ref?(push[:ref]) ? 'tag' : 'branch'
|
||||
ref = Gitlab::Git.ref_name(push[:ref])
|
||||
|
||||
before = push[:before]
|
||||
after = push[:after]
|
||||
|
||||
message = []
|
||||
message << "#{push[:user_name]} "
|
||||
|
||||
if Gitlab::Git.blank_ref?(before)
|
||||
message << "pushed new #{ref_type} <a href=\""\
|
||||
"#{project_url}/commits/#{CGI.escape(ref)}\">#{ref}</a>"\
|
||||
" to #{project_link}\n"
|
||||
elsif Gitlab::Git.blank_ref?(after)
|
||||
message << "removed #{ref_type} <b>#{ref}</b> from <a href=\"#{project.web_url}\">#{project_name}</a> \n"
|
||||
else
|
||||
message << "pushed to #{ref_type} <a href=\""\
|
||||
"#{project.web_url}/commits/#{CGI.escape(ref)}\">#{ref}</a> "
|
||||
message << "of <a href=\"#{project.web_url}\">#{project.full_name.gsub!(/\s/, '')}</a> "
|
||||
message << "(<a href=\"#{project.web_url}/compare/#{before}...#{after}\">Compare changes</a>)"
|
||||
|
||||
push[:commits].take(MAX_COMMITS).each do |commit|
|
||||
message << "<br /> - #{render_line(commit[:message])} (<a href=\"#{commit[:url]}\">#{commit[:id][0..5]}</a>)"
|
||||
end
|
||||
|
||||
if push[:commits].count > MAX_COMMITS
|
||||
message << "<br />... #{push[:commits].count - MAX_COMMITS} more commits"
|
||||
end
|
||||
end
|
||||
|
||||
message.join
|
||||
end
|
||||
|
||||
def markdown(text, options = {})
|
||||
return "" unless text
|
||||
|
||||
|
@ -155,109 +94,10 @@ class HipchatService < Service
|
|||
sanitized_html.truncate(200, separator: ' ', omission: '...')
|
||||
end
|
||||
|
||||
def create_issue_message(data)
|
||||
user_name = data[:user][:name]
|
||||
|
||||
obj_attr = data[:object_attributes]
|
||||
obj_attr = HashWithIndifferentAccess.new(obj_attr)
|
||||
title = render_line(obj_attr[:title])
|
||||
state = Issue.available_states.key(obj_attr[:state_id])
|
||||
issue_iid = obj_attr[:iid]
|
||||
issue_url = obj_attr[:url]
|
||||
description = obj_attr[:description]
|
||||
|
||||
issue_link = "<a href=\"#{issue_url}\">issue ##{issue_iid}</a>"
|
||||
|
||||
message = ["#{user_name} #{state} #{issue_link} in #{project_link}: <b>#{title}</b>"]
|
||||
message << "<pre>#{markdown(description)}</pre>"
|
||||
|
||||
message.join
|
||||
end
|
||||
|
||||
def create_merge_request_message(data)
|
||||
user_name = data[:user][:name]
|
||||
|
||||
obj_attr = data[:object_attributes]
|
||||
obj_attr = HashWithIndifferentAccess.new(obj_attr)
|
||||
merge_request_id = obj_attr[:iid]
|
||||
state = obj_attr[:state]
|
||||
description = obj_attr[:description]
|
||||
title = render_line(obj_attr[:title])
|
||||
|
||||
merge_request_url = "#{project_url}/-/merge_requests/#{merge_request_id}"
|
||||
merge_request_link = "<a href=\"#{merge_request_url}\">merge request !#{merge_request_id}</a>"
|
||||
message = ["#{user_name} #{state} #{merge_request_link} in " \
|
||||
"#{project_link}: <b>#{title}</b>"]
|
||||
|
||||
message << "<pre>#{markdown(description)}</pre>"
|
||||
message.join
|
||||
end
|
||||
|
||||
def format_title(title)
|
||||
"<b>#{render_line(title)}</b>"
|
||||
end
|
||||
|
||||
def create_note_message(data)
|
||||
data = HashWithIndifferentAccess.new(data)
|
||||
user_name = data[:user][:name]
|
||||
|
||||
obj_attr = HashWithIndifferentAccess.new(data[:object_attributes])
|
||||
note = obj_attr[:note]
|
||||
note_url = obj_attr[:url]
|
||||
noteable_type = obj_attr[:noteable_type]
|
||||
commit_id = nil
|
||||
|
||||
case noteable_type
|
||||
when "Commit"
|
||||
commit_attr = HashWithIndifferentAccess.new(data[:commit])
|
||||
commit_id = commit_attr[:id]
|
||||
subject_desc = commit_id
|
||||
subject_desc = Commit.truncate_sha(subject_desc)
|
||||
subject_type = "commit"
|
||||
title = format_title(commit_attr[:message])
|
||||
when "Issue"
|
||||
subj_attr = HashWithIndifferentAccess.new(data[:issue])
|
||||
subject_id = subj_attr[:iid]
|
||||
subject_desc = "##{subject_id}"
|
||||
subject_type = "issue"
|
||||
title = format_title(subj_attr[:title])
|
||||
when "MergeRequest"
|
||||
subj_attr = HashWithIndifferentAccess.new(data[:merge_request])
|
||||
subject_id = subj_attr[:iid]
|
||||
subject_desc = "!#{subject_id}"
|
||||
subject_type = "merge request"
|
||||
title = format_title(subj_attr[:title])
|
||||
when "Snippet"
|
||||
subj_attr = HashWithIndifferentAccess.new(data[:snippet])
|
||||
subject_id = subj_attr[:id]
|
||||
subject_desc = "##{subject_id}"
|
||||
subject_type = "snippet"
|
||||
title = format_title(subj_attr[:title])
|
||||
end
|
||||
|
||||
subject_html = "<a href=\"#{note_url}\">#{subject_type} #{subject_desc}</a>"
|
||||
message = ["#{user_name} commented on #{subject_html} in #{project_link}: "]
|
||||
message << title
|
||||
|
||||
message << "<pre>#{markdown(note, ref: commit_id)}</pre>"
|
||||
message.join
|
||||
end
|
||||
|
||||
def create_pipeline_message(data)
|
||||
pipeline_attributes = data[:object_attributes]
|
||||
pipeline_id = pipeline_attributes[:id]
|
||||
ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch'
|
||||
ref = pipeline_attributes[:ref]
|
||||
user_name = (data[:user] && data[:user][:name]) || 'API'
|
||||
status = pipeline_attributes[:status]
|
||||
duration = pipeline_attributes[:duration]
|
||||
|
||||
branch_link = "<a href=\"#{project_url}/-/commits/#{CGI.escape(ref)}\">#{ref}</a>"
|
||||
pipeline_url = "<a href=\"#{project_url}/-/pipelines/#{pipeline_id}\">##{pipeline_id}</a>"
|
||||
|
||||
"#{project_link}: Pipeline #{pipeline_url} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status(status)} in #{duration} second(s)"
|
||||
end
|
||||
|
||||
def message_color(data)
|
||||
pipeline_status_color(data) || color || 'yellow'
|
||||
end
|
||||
|
@ -309,5 +149,3 @@ class HipchatService < Service
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
HipchatService.prepend_if_ee('EE::HipchatService')
|
||||
|
|
|
@ -32,6 +32,8 @@ module Projects
|
|||
if fork_network = @project.root_of_fork_network
|
||||
fork_network.update(root_project: nil, deleted_root_project_name: @project.full_name)
|
||||
end
|
||||
|
||||
@project.leave_pool_repository
|
||||
end
|
||||
|
||||
# rubocop: disable Cop/InBatches
|
||||
|
|
|
@ -43,7 +43,7 @@ module ContentTypeWhitelist
|
|||
def mime_magic_content_type(path)
|
||||
if path
|
||||
File.open(path) do |file|
|
||||
MimeMagic.by_magic(file).try(:type) || 'invalid/invalid'
|
||||
Gitlab::Utils::MimeType.from_io(file) || 'invalid/invalid'
|
||||
end
|
||||
end
|
||||
rescue Errno::ENOENT
|
||||
|
|
|
@ -143,7 +143,7 @@
|
|||
= clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport')
|
||||
.sidebar-mr-source-branch.hide-collapsed
|
||||
%span
|
||||
= _('Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}').html_safe % { source_branch_open: "<cite class='ref-name' title='#{source_branch}'>".html_safe, source_branch_close: "</cite>".html_safe, source_branch: source_branch }
|
||||
= _('Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}').html_safe % { source_branch_open: "<cite class='ref-name' title='#{html_escape(source_branch)}'>".html_safe, source_branch_close: "</cite>".html_safe, source_branch: html_escape(source_branch) }
|
||||
= clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport')
|
||||
|
||||
- if show_forwarding_email
|
||||
|
|
20
config/initializers/asciidoctor_patch.rb
Normal file
20
config/initializers/asciidoctor_patch.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
# 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
|
|
@ -1,15 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
# This monkey patches the HTTParty used in https://github.com/hipchat/hipchat-rb.
|
||||
module HipChat
|
||||
class Client
|
||||
connection_adapter ::Gitlab::HTTPConnectionAdapter
|
||||
end
|
||||
|
||||
class Room
|
||||
connection_adapter ::Gitlab::HTTPConnectionAdapter
|
||||
end
|
||||
|
||||
class User
|
||||
connection_adapter ::Gitlab::HTTPConnectionAdapter
|
||||
end
|
||||
end
|
28
config/initializers/json_validator_patch.rb
Normal file
28
config/initializers/json_validator_patch.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# This patches https://github.com/ruby-json-schema/json-schema/blob/765e6d8fdbfdaca1a42fa743f4621e757f9f6a03/lib/json-schema/validator.rb
|
||||
# to address https://github.com/ruby-json-schema/json-schema/issues/148.
|
||||
require 'json-schema'
|
||||
|
||||
module JSON
|
||||
class Validator
|
||||
def initialize_data(data)
|
||||
if @options[:parse_data]
|
||||
if @options[:json]
|
||||
data = self.class.parse(data)
|
||||
elsif @options[:uri]
|
||||
json_uri = Util::URI.normalized_uri(data)
|
||||
data = self.class.parse(custom_open(json_uri))
|
||||
elsif data.is_a?(String)
|
||||
begin
|
||||
data = self.class.parse(data)
|
||||
rescue JSON::Schema::JsonParseError
|
||||
# Silently discard the error - use the data as-is
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
JSON::Schema.stringify(data)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -88,7 +88,7 @@ Example response:
|
|||
## Test system hook
|
||||
|
||||
```plaintext
|
||||
GET /hooks/:id
|
||||
POST /hooks/:id
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|
@ -98,7 +98,7 @@ GET /hooks/:id
|
|||
Example request:
|
||||
|
||||
```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:
|
||||
|
|
|
@ -4,7 +4,12 @@ group: Ecosystem
|
|||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Atlassian HipChat
|
||||
# Atlassian HipChat (Deprecated) **(FREE)**
|
||||
|
||||
As of [GitLab
|
||||
13.11](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57434), the
|
||||
HipChat integration will not send any notifications to HipChat. This
|
||||
integration is also deprecated.
|
||||
|
||||
GitLab provides a way to send HipChat notifications upon a number of events,
|
||||
such as when a user pushes code, creates a branch or tag, adds a comment, and
|
||||
|
|
|
@ -47,7 +47,7 @@ module API
|
|||
params do
|
||||
requires :id, type: Integer, desc: 'The ID of the system hook'
|
||||
end
|
||||
get ":id" do
|
||||
post ":id" do
|
||||
hook = SystemHook.find(params[:id])
|
||||
data = {
|
||||
event_name: "project_create",
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
module Gitlab
|
||||
module MarkdownCache
|
||||
# Increment this number every time the renderer changes its output
|
||||
CACHE_COMMONMARK_VERSION = 26
|
||||
CACHE_COMMONMARK_VERSION = 27
|
||||
CACHE_COMMONMARK_VERSION_START = 10
|
||||
|
||||
BaseError = Class.new(StandardError)
|
||||
|
|
|
@ -11,10 +11,11 @@ module Gitlab
|
|||
attr_reader :user, :push_ability
|
||||
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
|
||||
@container = container
|
||||
@push_ability = push_ability
|
||||
@skip_collaboration_check = skip_collaboration_check
|
||||
end
|
||||
|
||||
def can_do_action?(action)
|
||||
|
@ -87,6 +88,8 @@ module Gitlab
|
|||
|
||||
private
|
||||
|
||||
attr_reader :skip_collaboration_check
|
||||
|
||||
def can_push?
|
||||
user.can?(push_ability, container)
|
||||
end
|
||||
|
@ -98,6 +101,8 @@ module Gitlab
|
|||
end
|
||||
|
||||
def branch_allows_collaboration_for?(ref)
|
||||
return false if skip_collaboration_check
|
||||
|
||||
# Checking for an internal project or group to prevent an infinite loop:
|
||||
# https://gitlab.com/gitlab-org/gitlab/issues/36805
|
||||
(!project.internal? && project.branch_allows_collaboration?(user, ref))
|
||||
|
|
25
lib/gitlab/utils/mime_type.rb
Normal file
25
lib/gitlab/utils/mime_type.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
require 'magic'
|
||||
|
||||
# This wraps calls to a gem which support mime type detection.
|
||||
# We use the `ruby-magic` gem instead of `mimemagic` due to licensing issues
|
||||
module Gitlab
|
||||
module Utils
|
||||
class MimeType
|
||||
class << self
|
||||
def from_io(io)
|
||||
return unless io.is_a?(IO) || io.is_a?(StringIO)
|
||||
|
||||
mime_type = File.magic(io, Magic::MIME_TYPE)
|
||||
mime_type == 'inode/x-empty' ? nil : mime_type
|
||||
end
|
||||
|
||||
def from_string(string)
|
||||
return unless string.is_a?(String)
|
||||
|
||||
string.type
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,7 +6,7 @@ FactoryBot.define do
|
|||
state { :none }
|
||||
|
||||
before(:create) do |pool|
|
||||
pool.source_project = create(:project, :repository)
|
||||
pool.source_project ||= create(:project, :repository)
|
||||
pool.source_project.update!(pool_repository: pool)
|
||||
end
|
||||
|
||||
|
|
|
@ -111,4 +111,21 @@ RSpec.describe 'User views an open merge request' do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'XSS source branch' do
|
||||
let(:project) { create(:project, :public, :repository) }
|
||||
let(:source_branch) { "'><iframe/srcdoc=''></iframe>" }
|
||||
|
||||
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('cite.ref-name')[:title]).to eq(source_branch)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
BIN
spec/fixtures/rails_sample.bmp
vendored
Normal file
BIN
spec/fixtures/rails_sample.bmp
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 348 KiB |
BIN
spec/fixtures/rails_sample.png
vendored
Normal file
BIN
spec/fixtures/rails_sample.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 84 KiB |
BIN
spec/fixtures/rails_sample.tif
vendored
Normal file
BIN
spec/fixtures/rails_sample.tif
vendored
Normal file
Binary file not shown.
BIN
spec/fixtures/sample.ico
vendored
Normal file
BIN
spec/fixtures/sample.ico
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
39
spec/initializers/json_validator_patch_spec.rb
Normal file
39
spec/initializers/json_validator_patch_spec.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require 'rspec-parameterized'
|
||||
|
||||
RSpec.describe 'JSON validator patch' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:schema) { '{"format": "string"}' }
|
||||
|
||||
subject { JSON::Validator.validate(schema, data) }
|
||||
|
||||
context 'with invalid JSON' do
|
||||
where(:data) do
|
||||
[
|
||||
'https://example.com',
|
||||
'/tmp/test.txt'
|
||||
]
|
||||
end
|
||||
|
||||
with_them do
|
||||
it 'does not attempt to open a file or URI' do
|
||||
allow(File).to receive(:read).and_call_original
|
||||
allow(URI).to receive(:open).and_call_original
|
||||
expect(File).not_to receive(:read).with(data)
|
||||
expect(URI).not_to receive(:open).with(data)
|
||||
expect(subject).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with valid JSON' do
|
||||
let(:data) { %({ 'somekey': 'value' }) }
|
||||
|
||||
it 'validates successfully' do
|
||||
expect(subject).to be true
|
||||
end
|
||||
end
|
||||
end
|
|
@ -92,6 +92,15 @@ module Gitlab
|
|||
expect(render(data[:input], context)).to include(data[:output])
|
||||
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
|
||||
|
||||
context "images" do
|
||||
|
@ -543,6 +552,40 @@ module Gitlab
|
|||
|
||||
expect(render(input, context)).to include(output.strip)
|
||||
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
|
||||
|
||||
context 'with Kroki and BlockDiag (additional format) enabled' do
|
||||
|
|
|
@ -216,6 +216,15 @@ RSpec.describe Gitlab::UserAccess do
|
|||
expect(access.can_merge_to_branch?(@branch.name)).to be_falsey
|
||||
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
|
||||
|
||||
describe '#can_create_tag?' do
|
||||
|
|
57
spec/lib/gitlab/utils/mime_type_spec.rb
Normal file
57
spec/lib/gitlab/utils/mime_type_spec.rb
Normal file
|
@ -0,0 +1,57 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "fast_spec_helper"
|
||||
require "rspec/parameterized"
|
||||
|
||||
RSpec.describe Gitlab::Utils::MimeType do
|
||||
describe ".from_io" do
|
||||
subject { described_class.from_io(io) }
|
||||
|
||||
context "input isn't an IO" do
|
||||
let(:io) { "test" }
|
||||
|
||||
it "returns nil" do
|
||||
expect(subject).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context "input is a file" do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:fixture, :mime_type) do
|
||||
"banana_sample.gif" | "image/gif"
|
||||
"rails_sample.jpg" | "image/jpeg"
|
||||
"rails_sample.png" | "image/png"
|
||||
"rails_sample.bmp" | "image/bmp"
|
||||
"rails_sample.tif" | "image/tiff"
|
||||
"sample.ico" | "image/vnd.microsoft.icon"
|
||||
"blockquote_fence_before.md" | "text/plain"
|
||||
"csv_empty.csv" | "application/x-empty"
|
||||
end
|
||||
|
||||
with_them do
|
||||
let(:io) { File.open(File.join(__dir__, "../../../fixtures", fixture)) }
|
||||
|
||||
it { is_expected.to eq(mime_type) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ".from_string" do
|
||||
subject { described_class.from_string(str) }
|
||||
|
||||
context "input isn't a string" do
|
||||
let(:str) { nil }
|
||||
|
||||
it "returns nil" do
|
||||
expect(subject).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context "input is a string" do
|
||||
let(:str) { "plain text" }
|
||||
|
||||
it { is_expected.to eq('text/plain') }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -49,307 +49,8 @@ RSpec.describe HipchatService do
|
|||
WebMock.stub_request(:post, api_url)
|
||||
end
|
||||
|
||||
it 'tests and return errors' do
|
||||
allow(hipchat).to receive(:execute).and_raise(StandardError, 'no such room')
|
||||
result = hipchat.test(push_sample_data)
|
||||
|
||||
expect(result[:success]).to be_falsey
|
||||
expect(result[:result].to_s).to eq('no such room')
|
||||
end
|
||||
|
||||
it 'uses v1 if version is provided' do
|
||||
allow(hipchat).to receive(:api_version).and_return('v1')
|
||||
expect(HipChat::Client).to receive(:new).with(
|
||||
token,
|
||||
api_version: 'v1',
|
||||
server_url: server_url
|
||||
).and_return(double(:hipchat_service).as_null_object)
|
||||
hipchat.execute(push_sample_data)
|
||||
end
|
||||
|
||||
it 'uses v2 as the version when nothing is provided' do
|
||||
allow(hipchat).to receive(:api_version).and_return('')
|
||||
expect(HipChat::Client).to receive(:new).with(
|
||||
token,
|
||||
api_version: 'v2',
|
||||
server_url: server_url
|
||||
).and_return(double(:hipchat_service).as_null_object)
|
||||
hipchat.execute(push_sample_data)
|
||||
end
|
||||
|
||||
context 'push events' do
|
||||
it "calls Hipchat API for push events" do
|
||||
hipchat.execute(push_sample_data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, api_url).once
|
||||
end
|
||||
|
||||
it "creates a push message" do
|
||||
message = hipchat.send(:create_push_message, push_sample_data)
|
||||
|
||||
push_sample_data[:object_attributes]
|
||||
branch = push_sample_data[:ref].gsub('refs/heads/', '')
|
||||
expect(message).to include("#{user.name} pushed to branch " \
|
||||
"<a href=\"#{project.web_url}/commits/#{branch}\">#{branch}</a> of " \
|
||||
"<a href=\"#{project.web_url}\">#{project_name}</a>")
|
||||
end
|
||||
end
|
||||
|
||||
context 'tag_push events' do
|
||||
let(:push_sample_data) do
|
||||
Gitlab::DataBuilder::Push.build(
|
||||
project: project,
|
||||
user: user,
|
||||
oldrev: Gitlab::Git::BLANK_SHA,
|
||||
newrev: '1' * 40,
|
||||
ref: 'refs/tags/test')
|
||||
end
|
||||
|
||||
it "calls Hipchat API for tag push events" do
|
||||
hipchat.execute(push_sample_data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, api_url).once
|
||||
end
|
||||
|
||||
it "creates a tag push message" do
|
||||
message = hipchat.send(:create_push_message, push_sample_data)
|
||||
|
||||
push_sample_data[:object_attributes]
|
||||
expect(message).to eq("#{user.name} pushed new tag " \
|
||||
"<a href=\"#{project.web_url}/commits/test\">test</a> to " \
|
||||
"<a href=\"#{project.web_url}\">#{project_name}</a>\n")
|
||||
end
|
||||
end
|
||||
|
||||
context 'issue events' do
|
||||
let(:issue) { create(:issue, title: 'Awesome issue', description: '**please** fix') }
|
||||
let(:issue_service) { Issues::CreateService.new(project, user) }
|
||||
let(:issues_sample_data) { issue_service.hook_data(issue, 'open') }
|
||||
|
||||
it "calls Hipchat API for issue events" do
|
||||
hipchat.execute(issues_sample_data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, api_url).once
|
||||
end
|
||||
|
||||
it "creates an issue message" do
|
||||
message = hipchat.send(:create_issue_message, issues_sample_data)
|
||||
|
||||
obj_attr = issues_sample_data[:object_attributes]
|
||||
expect(message).to eq("#{user.name} opened " \
|
||||
"<a href=\"#{obj_attr[:url]}\">issue ##{obj_attr["iid"]}</a> in " \
|
||||
"<a href=\"#{project.web_url}\">#{project_name}</a>: " \
|
||||
"<b>Awesome issue</b>" \
|
||||
"<pre><strong>please</strong> fix</pre>")
|
||||
end
|
||||
end
|
||||
|
||||
context 'merge request events' do
|
||||
let(:merge_request) { create(:merge_request, description: '**please** fix', title: 'Awesome merge request', target_project: project, source_project: project) }
|
||||
let(:merge_service) { MergeRequests::CreateService.new(project, user) }
|
||||
let(:merge_sample_data) { merge_service.hook_data(merge_request, 'open') }
|
||||
|
||||
it "calls Hipchat API for merge requests events" do
|
||||
hipchat.execute(merge_sample_data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, api_url).once
|
||||
end
|
||||
|
||||
it "creates a merge request message" do
|
||||
message = hipchat.send(:create_merge_request_message,
|
||||
merge_sample_data)
|
||||
|
||||
obj_attr = merge_sample_data[:object_attributes]
|
||||
expect(message).to eq("#{user.name} opened " \
|
||||
"<a href=\"#{obj_attr[:url]}\">merge request !#{obj_attr["iid"]}</a> in " \
|
||||
"<a href=\"#{project.web_url}\">#{project_name}</a>: " \
|
||||
"<b>Awesome merge request</b>" \
|
||||
"<pre><strong>please</strong> fix</pre>")
|
||||
end
|
||||
end
|
||||
|
||||
context "Note events" do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :repository, creator: user) }
|
||||
|
||||
context 'when commit comment event triggered' do
|
||||
let(:commit_note) do
|
||||
create(:note_on_commit, author: user, project: project,
|
||||
commit_id: project.repository.commit.id,
|
||||
note: 'a comment on a commit')
|
||||
end
|
||||
|
||||
it "calls Hipchat API for commit comment events" do
|
||||
data = Gitlab::DataBuilder::Note.build(commit_note, user)
|
||||
hipchat.execute(data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, api_url).once
|
||||
|
||||
message = hipchat.send(:create_message, data)
|
||||
|
||||
obj_attr = data[:object_attributes]
|
||||
commit_id = Commit.truncate_sha(data[:commit][:id])
|
||||
title = hipchat.send(:format_title, data[:commit][:message])
|
||||
|
||||
expect(message).to eq("#{user.name} commented on " \
|
||||
"<a href=\"#{obj_attr[:url]}\">commit #{commit_id}</a> in " \
|
||||
"<a href=\"#{project.web_url}\">#{project_name}</a>: " \
|
||||
"#{title}" \
|
||||
"<pre>a comment on a commit</pre>")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when merge request comment event triggered' do
|
||||
let(:merge_request) do
|
||||
create(:merge_request, source_project: project,
|
||||
target_project: project)
|
||||
end
|
||||
|
||||
let(:merge_request_note) do
|
||||
create(:note_on_merge_request, noteable: merge_request,
|
||||
project: project,
|
||||
note: "merge request **note**")
|
||||
end
|
||||
|
||||
it "calls Hipchat API for merge request comment events" do
|
||||
data = Gitlab::DataBuilder::Note.build(merge_request_note, user)
|
||||
hipchat.execute(data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, api_url).once
|
||||
|
||||
message = hipchat.send(:create_message, data)
|
||||
|
||||
obj_attr = data[:object_attributes]
|
||||
merge_id = data[:merge_request]['iid']
|
||||
title = data[:merge_request]['title']
|
||||
|
||||
expect(message).to eq("#{user.name} commented on " \
|
||||
"<a href=\"#{obj_attr[:url]}\">merge request !#{merge_id}</a> in " \
|
||||
"<a href=\"#{project.web_url}\">#{project_name}</a>: " \
|
||||
"<b>#{title}</b>" \
|
||||
"<pre>merge request <strong>note</strong></pre>")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when issue comment event triggered' do
|
||||
let(:issue) { create(:issue, project: project) }
|
||||
let(:issue_note) do
|
||||
create(:note_on_issue, noteable: issue, project: project,
|
||||
note: "issue **note**")
|
||||
end
|
||||
|
||||
it "calls Hipchat API for issue comment events" do
|
||||
data = Gitlab::DataBuilder::Note.build(issue_note, user)
|
||||
hipchat.execute(data)
|
||||
|
||||
message = hipchat.send(:create_message, data)
|
||||
|
||||
obj_attr = data[:object_attributes]
|
||||
issue_id = data[:issue]['iid']
|
||||
title = data[:issue]['title']
|
||||
|
||||
expect(message).to eq("#{user.name} commented on " \
|
||||
"<a href=\"#{obj_attr[:url]}\">issue ##{issue_id}</a> in " \
|
||||
"<a href=\"#{project.web_url}\">#{project_name}</a>: " \
|
||||
"<b>#{title}</b>" \
|
||||
"<pre>issue <strong>note</strong></pre>")
|
||||
end
|
||||
|
||||
context 'with confidential issue' do
|
||||
before do
|
||||
issue.update!(confidential: true)
|
||||
end
|
||||
|
||||
it 'calls Hipchat API with issue comment' do
|
||||
data = Gitlab::DataBuilder::Note.build(issue_note, user)
|
||||
hipchat.execute(data)
|
||||
|
||||
message = hipchat.send(:create_message, data)
|
||||
|
||||
expect(message).to include("<pre>issue <strong>note</strong></pre>")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when snippet comment event triggered' do
|
||||
let(:snippet) { create(:project_snippet, project: project) }
|
||||
let(:snippet_note) do
|
||||
create(:note_on_project_snippet, noteable: snippet,
|
||||
project: project,
|
||||
note: "snippet note")
|
||||
end
|
||||
|
||||
it "calls Hipchat API for snippet comment events" do
|
||||
data = Gitlab::DataBuilder::Note.build(snippet_note, user)
|
||||
hipchat.execute(data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, api_url).once
|
||||
|
||||
message = hipchat.send(:create_message, data)
|
||||
|
||||
obj_attr = data[:object_attributes]
|
||||
snippet_id = data[:snippet]['id']
|
||||
title = data[:snippet]['title']
|
||||
|
||||
expect(message).to eq("#{user.name} commented on " \
|
||||
"<a href=\"#{obj_attr[:url]}\">snippet ##{snippet_id}</a> in " \
|
||||
"<a href=\"#{project.web_url}\">#{project_name}</a>: " \
|
||||
"<b>#{title}</b>" \
|
||||
"<pre>snippet note</pre>")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'pipeline events' do
|
||||
let(:pipeline) { create(:ci_empty_pipeline, user: project.owner) }
|
||||
let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
|
||||
|
||||
context 'for failed' do
|
||||
before do
|
||||
pipeline.drop
|
||||
end
|
||||
|
||||
it "calls Hipchat API" do
|
||||
hipchat.execute(data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, api_url).once
|
||||
end
|
||||
|
||||
it "creates a build message" do
|
||||
message = hipchat.__send__(:create_pipeline_message, data)
|
||||
|
||||
project_url = project.web_url
|
||||
project_name = project.full_name.gsub(/\s/, '')
|
||||
pipeline_attributes = data[:object_attributes]
|
||||
ref = pipeline_attributes[:ref]
|
||||
ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch'
|
||||
duration = pipeline_attributes[:duration]
|
||||
user_name = data[:user][:name]
|
||||
|
||||
expect(message).to eq("<a href=\"#{project_url}\">#{project_name}</a>: " \
|
||||
"Pipeline <a href=\"#{project_url}/-/pipelines/#{pipeline.id}\">##{pipeline.id}</a> " \
|
||||
"of <a href=\"#{project_url}/-/commits/#{ref}\">#{ref}</a> #{ref_type} " \
|
||||
"by #{user_name} failed in #{duration} second(s)")
|
||||
end
|
||||
end
|
||||
|
||||
context 'for succeeded' do
|
||||
before do
|
||||
pipeline.succeed
|
||||
end
|
||||
|
||||
it "calls Hipchat API" do
|
||||
hipchat.notify_only_broken_pipelines = false
|
||||
hipchat.execute(data)
|
||||
expect(WebMock).to have_requested(:post, api_url).once
|
||||
end
|
||||
|
||||
it "notifies only broken" do
|
||||
hipchat.notify_only_broken_pipelines = true
|
||||
hipchat.execute(data)
|
||||
expect(WebMock).not_to have_requested(:post, api_url).once
|
||||
end
|
||||
end
|
||||
it 'does nothing' do
|
||||
expect { hipchat.execute(push_sample_data) }.not_to raise_error
|
||||
end
|
||||
|
||||
describe "#message_options" do
|
||||
|
@ -388,22 +89,4 @@ RSpec.describe HipchatService do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with UrlBlocker' do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :repository) }
|
||||
let(:hipchat) { create(:hipchat_service, project: project, properties: { room: 'test' }) }
|
||||
let(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
|
||||
|
||||
describe '#execute' do
|
||||
before do
|
||||
hipchat.server = 'http://localhost:9123'
|
||||
end
|
||||
|
||||
it 'raises UrlBlocker for localhost' do
|
||||
expect(Gitlab::UrlBlocker).to receive(:validate!).and_call_original
|
||||
expect { hipchat.execute(push_sample_data) }.to raise_error(Gitlab::HTTP::BlockedUrlError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5211,6 +5211,64 @@ RSpec.describe Project, factory_default: :keep do
|
|||
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
|
||||
let(:user) { create(:user) }
|
||||
let(:target_project) { create(:project, :repository) }
|
||||
|
|
|
@ -103,15 +103,15 @@ RSpec.describe API::SystemHooks do
|
|||
end
|
||||
end
|
||||
|
||||
describe "GET /hooks/:id" do
|
||||
it "returns hook by id" do
|
||||
get api("/hooks/#{hook.id}", admin)
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
describe 'POST /hooks/:id' do
|
||||
it "returns and trigger hook by id" do
|
||||
post api("/hooks/#{hook.id}", admin)
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
expect(json_response['event_name']).to eq('project_create')
|
||||
end
|
||||
|
||||
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)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -403,7 +403,7 @@ RSpec.describe Projects::ForkService do
|
|||
end
|
||||
|
||||
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) }
|
||||
|
||||
context 'when no pool exists' do
|
||||
|
|
|
@ -207,6 +207,17 @@ RSpec.describe Projects::UnlinkForkService, :use_clean_rails_memory_store_cachin
|
|||
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
|
||||
let!(:project_without_forks) { create(:project, :public) }
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ end
|
|||
# @param mime_type [String] mime type to forcibly detect.
|
||||
RSpec.shared_context 'force content type detection to mime_type' do
|
||||
before do
|
||||
magic_mime_obj = MimeMagic.new(mime_type)
|
||||
allow(MimeMagic).to receive(:by_magic).with(anything).and_return(magic_mime_obj)
|
||||
allow(Gitlab::Utils::MimeType).to receive(:from_io).and_return(mime_type)
|
||||
end
|
||||
end
|
||||
|
|
6
vendor/shims/mimemagic/Gemfile
vendored
Normal file
6
vendor/shims/mimemagic/Gemfile
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
# Specify your gem's dependencies in mimemagic.gemspec
|
||||
gemspec
|
||||
|
||||
gem "rake", "~> 12.0"
|
21
vendor/shims/mimemagic/LICENSE.txt
vendored
Normal file
21
vendor/shims/mimemagic/LICENSE.txt
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 GitLab B.V.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
1
vendor/shims/mimemagic/README.md
vendored
Normal file
1
vendor/shims/mimemagic/README.md
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
This is a fake gem to prevent mimemagic from being included into GitLab.
|
2
vendor/shims/mimemagic/Rakefile
vendored
Normal file
2
vendor/shims/mimemagic/Rakefile
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
require "bundler/gem_tasks"
|
||||
task :default => :spec
|
6
vendor/shims/mimemagic/lib/mimemagic.rb
vendored
Normal file
6
vendor/shims/mimemagic/lib/mimemagic.rb
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
require "mimemagic/version"
|
||||
|
||||
module MimeMagic
|
||||
class Error < StandardError; end
|
||||
raise Error, 'This gem should never be required'
|
||||
end
|
3
vendor/shims/mimemagic/lib/mimemagic/version.rb
vendored
Normal file
3
vendor/shims/mimemagic/lib/mimemagic/version.rb
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
module MimeMagic
|
||||
VERSION = "0.3.7"
|
||||
end
|
18
vendor/shims/mimemagic/mimemagic.gemspec
vendored
Normal file
18
vendor/shims/mimemagic/mimemagic.gemspec
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
require_relative 'lib/mimemagic/version'
|
||||
|
||||
Gem::Specification.new do |spec|
|
||||
spec.name = "mimemagic"
|
||||
spec.version = MimeMagic::VERSION
|
||||
spec.authors = ["Marc Shaw"]
|
||||
spec.email = ["mshaw@gitlab.com"]
|
||||
|
||||
spec.summary = %q{MimeMagic shim}
|
||||
spec.description = %q{A shim for mimemagic}
|
||||
spec.homepage = "https://gitlab.com/gitlab-org/gitlab/-/tree/master/vendor/shims/mimemagic"
|
||||
spec.license = "MIT"
|
||||
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
||||
|
||||
spec.files = %w[lib/mimemagic.rb lib/mimemagic/version.rb]
|
||||
|
||||
spec.require_paths = ["lib"]
|
||||
end
|
Loading…
Reference in a new issue