Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
db2275b561
commit
0a977c1034
|
@ -71,23 +71,9 @@ class MergeRequest < ApplicationRecord
|
|||
belongs_to :latest_merge_request_diff, class_name: 'MergeRequestDiff'
|
||||
manual_inverse_association :latest_merge_request_diff, :merge_request
|
||||
|
||||
# method overriden in EE
|
||||
def suggested_reviewer_users
|
||||
return User.none unless predictions && predictions.suggested_reviewers.is_a?(Hash)
|
||||
|
||||
usernames = Array.wrap(suggested_reviewers["reviewers"])
|
||||
return User.none if usernames.empty?
|
||||
|
||||
# Preserve the orginal order of suggested usernames
|
||||
join_sql = MergeRequest.sanitize_sql_array(
|
||||
[
|
||||
'JOIN UNNEST(ARRAY[?]::varchar[]) WITH ORDINALITY AS t(username, ord) USING(username)',
|
||||
usernames
|
||||
]
|
||||
)
|
||||
|
||||
project.authorized_users.active
|
||||
.joins(Arel.sql(join_sql))
|
||||
.order('t.ord')
|
||||
User.none
|
||||
end
|
||||
|
||||
# This is the same as latest_merge_request_diff unless:
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class PreparePartialTrigramIndexesForIssuesAttempt2 < Gitlab::Database::Migration[2.0]
|
||||
TITLE_INDEX_NAME = 'index_issues_on_title_trigram_non_latin'
|
||||
DESCRIPTION_INDEX_NAME = 'index_issues_on_description_trigram_non_latin'
|
||||
|
||||
def up
|
||||
prepare_async_index :issues, :title,
|
||||
name: TITLE_INDEX_NAME,
|
||||
using: :gin, opclass: { description: :gin_trgm_ops },
|
||||
where: "title NOT SIMILAR TO '[\\u0000-\\u02FF\\u1E00-\\u1EFF\\u2070-\\u218F]*' " \
|
||||
"OR description NOT SIMILAR TO '[\\u0000-\\u02FF\\u1E00-\\u1EFF\\u2070-\\u218F]*'"
|
||||
|
||||
prepare_async_index :issues, :description,
|
||||
name: DESCRIPTION_INDEX_NAME,
|
||||
using: :gin, opclass: { description: :gin_trgm_ops },
|
||||
where: "title NOT SIMILAR TO '[\\u0000-\\u02FF\\u1E00-\\u1EFF\\u2070-\\u218F]*' " \
|
||||
"OR description NOT SIMILAR TO '[\\u0000-\\u02FF\\u1E00-\\u1EFF\\u2070-\\u218F]*'"
|
||||
end
|
||||
|
||||
def down
|
||||
unprepare_async_index_by_name :issues, DESCRIPTION_INDEX_NAME
|
||||
unprepare_async_index_by_name :issues, TITLE_INDEX_NAME
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
0ad92f76e14b2e9286b2f77f32c00dba8ae29b64035f79641451edfdc725c92a
|
|
@ -40,7 +40,7 @@ module API
|
|||
params do
|
||||
requires :name, type: String, desc: 'The name of the environment to be created'
|
||||
optional :external_url, type: String, desc: 'URL on which this deployment is viewable'
|
||||
optional :slug, absence: { message: "is automatically generated and cannot be changed" }
|
||||
optional :slug, absence: { message: "is automatically generated and cannot be changed" }, documentation: { hidden: true }
|
||||
optional :tier, type: String, values: Environment.tiers.keys, desc: 'The tier of the environment to be created'
|
||||
end
|
||||
post ':id/environments' do
|
||||
|
@ -64,7 +64,7 @@ module API
|
|||
# TODO: disallow renaming via the API https://gitlab.com/gitlab-org/gitlab/-/issues/338897
|
||||
optional :name, type: String, desc: 'DEPRECATED: Renaming environment can lead to errors, this will be removed in 15.0'
|
||||
optional :external_url, type: String, desc: 'The new URL on which this deployment is viewable'
|
||||
optional :slug, absence: { message: "is automatically generated and cannot be changed" }
|
||||
optional :slug, absence: { message: "is automatically generated and cannot be changed" }, documentation: { hidden: true }
|
||||
optional :tier, type: String, values: Environment.tiers.keys, desc: 'The tier of the environment to be created'
|
||||
end
|
||||
put ':id/environments/:environment_id' do
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
|
||||
# A dumb middleware that returns a Go HTML document if the go-get=1 query string
|
||||
# is used irrespective if the namespace/project exists
|
||||
#
|
||||
# In order to prevent the project from being exposed,
|
||||
# auth failure (401 & 403) is regarded as not found (404)
|
||||
module Gitlab
|
||||
module Middleware
|
||||
class Go
|
||||
|
@ -24,16 +21,15 @@ module Gitlab
|
|||
rescue Gitlab::Auth::IpBlacklisted
|
||||
Gitlab::AuthLogger.error(
|
||||
message: 'Rack_Attack',
|
||||
status: 403,
|
||||
env: :blocklist,
|
||||
remote_ip: request.ip,
|
||||
request_method: request.request_method,
|
||||
path: request.fullpath
|
||||
)
|
||||
Rack::Response.new('', 404).finish
|
||||
Rack::Response.new('', 403).finish
|
||||
rescue Gitlab::Auth::MissingPersonalAccessTokenError
|
||||
Rack::Response.new('', 404).finish
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
Rack::Response.new('', 404).finish
|
||||
Rack::Response.new('', 401).finish
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -104,6 +100,7 @@ module Gitlab
|
|||
|
||||
# We find all potential project paths out of the path segments
|
||||
path_segments = path.split('/')
|
||||
simple_project_path = path_segments.first(2).join('/')
|
||||
|
||||
project_paths = []
|
||||
begin
|
||||
|
@ -113,18 +110,28 @@ module Gitlab
|
|||
|
||||
# We see if a project exists with any of these potential paths
|
||||
project = project_for_paths(project_paths, request)
|
||||
# If a project is found and the user has access, we return the full project path
|
||||
[project.full_path, project.default_branch]
|
||||
|
||||
if project
|
||||
# If a project is found and the user has access, we return the full project path
|
||||
[project.full_path, project.default_branch]
|
||||
else
|
||||
# If not, we return the first two components as if it were a simple `namespace/project` path,
|
||||
# so that we don't reveal the existence of a nested project the user doesn't have access to.
|
||||
# This means that for an unauthenticated request to `group/subgroup/project/subpackage`
|
||||
# for a private `group/subgroup/project` with subpackage path `subpackage`, GitLab will respond
|
||||
# as if the user is looking for project `group/subgroup`, with subpackage path `project/subpackage`.
|
||||
# Since `go get` doesn't authenticate by default, this means that
|
||||
# `go get gitlab.com/group/subgroup/project/subpackage` will not work for private projects.
|
||||
# `go get gitlab.com/group/subgroup/project.git/subpackage` will work, since Go is smart enough
|
||||
# to figure that out. `import 'gitlab.com/...'` behaves the same as `go get`.
|
||||
[simple_project_path, 'master']
|
||||
end
|
||||
end
|
||||
|
||||
def project_for_paths(paths, request)
|
||||
project = Project.where_full_path_in(paths).first
|
||||
|
||||
raise ActiveRecord::RecordNotFound unless project
|
||||
|
||||
unless authentication_result(request, project).can_perform_action_on_project?(:read_project, project)
|
||||
raise Gitlab::Auth::MissingPersonalAccessTokenError
|
||||
end
|
||||
return unless authentication_result(request, project).can_perform_action_on_project?(:read_project, project)
|
||||
|
||||
project
|
||||
end
|
||||
|
|
|
@ -32,7 +32,7 @@ RSpec.describe Gitlab::Middleware::Go do
|
|||
|
||||
shared_examples 'go-get=1' do |enabled_protocol:|
|
||||
context 'with simple 2-segment project path' do
|
||||
let!(:project) { create(:project, :public, :repository) }
|
||||
let!(:project) { create(:project, :private, :repository) }
|
||||
|
||||
context 'with subpackages' do
|
||||
let(:path) { "#{project.full_path}/subpackage" }
|
||||
|
@ -51,16 +51,6 @@ RSpec.describe Gitlab::Middleware::Go do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with nonexistent path' do
|
||||
let(:path) { 'nonexistent-group/nonexistent-project' }
|
||||
|
||||
it 'responses not found' do
|
||||
status_code, _headers, body = go
|
||||
expect(status_code).to eq(404)
|
||||
expect(body).to match_array([''])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a nested project path' do
|
||||
let(:group) { create(:group, :nested) }
|
||||
let!(:project) { create(:project, :public, :repository, namespace: group) }
|
||||
|
@ -78,10 +68,8 @@ RSpec.describe Gitlab::Middleware::Go do
|
|||
end
|
||||
|
||||
shared_examples 'unauthorized' do
|
||||
it 'returns unauthorized' do
|
||||
status_code, _headers, body = go
|
||||
expect(status_code).to eq(404)
|
||||
expect(body).to match_array([''])
|
||||
it 'returns the 2-segment group path' do
|
||||
expect_response_with_path(go, enabled_protocol, group.full_path, project.default_branch)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -153,7 +141,7 @@ RSpec.describe Gitlab::Middleware::Go do
|
|||
expect(Gitlab::Auth).to receive(:find_for_git_client).and_raise(Gitlab::Auth::IpBlacklisted)
|
||||
response = go
|
||||
|
||||
expect(response[0]).to eq(404)
|
||||
expect(response[0]).to eq(403)
|
||||
expect(response[1]['Content-Length']).to be_nil
|
||||
expect(response[2]).to eq([''])
|
||||
end
|
||||
|
@ -170,7 +158,7 @@ RSpec.describe Gitlab::Middleware::Go do
|
|||
expect(Gitlab::Auth).to receive(:find_for_git_client).and_raise(Gitlab::Auth::MissingPersonalAccessTokenError)
|
||||
response = go
|
||||
|
||||
expect(response[0]).to eq(404)
|
||||
expect(response[0]).to eq(401)
|
||||
expect(response[1]['Content-Length']).to be_nil
|
||||
expect(response[2]).to eq([''])
|
||||
end
|
||||
|
|
|
@ -5416,82 +5416,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
|
|||
|
||||
subject(:suggested_reviewer_users) { merge_request.suggested_reviewer_users }
|
||||
|
||||
shared_examples 'blank suggestions' do
|
||||
it 'returns an empty relation' do
|
||||
expect(suggested_reviewer_users).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when predictions is nil' do
|
||||
it_behaves_like 'blank suggestions'
|
||||
end
|
||||
|
||||
context 'when predictions is not nil' do
|
||||
before do
|
||||
merge_request.build_predictions
|
||||
end
|
||||
|
||||
context 'when predictions is a non hash' do
|
||||
before do
|
||||
merge_request.build_predictions
|
||||
merge_request.predictions.suggested_reviewers = 1
|
||||
end
|
||||
|
||||
it_behaves_like 'blank suggestions'
|
||||
end
|
||||
|
||||
context 'when predictions is an empty hash' do
|
||||
before do
|
||||
merge_request.predictions.suggested_reviewers = {}
|
||||
end
|
||||
|
||||
it_behaves_like 'blank suggestions'
|
||||
end
|
||||
|
||||
context 'when suggests a user who is not a member' do
|
||||
let_it_be(:non_member) { create(:user) }
|
||||
|
||||
before do
|
||||
merge_request.predictions.suggested_reviewers = { 'reviewers' => [non_member.username] }
|
||||
end
|
||||
|
||||
it_behaves_like 'blank suggestions'
|
||||
end
|
||||
|
||||
context 'when suggests users who are members' do
|
||||
let_it_be(:first_member) { create(:user) }
|
||||
let_it_be(:second_member) { create(:user) }
|
||||
|
||||
before_all do
|
||||
project.add_developer(first_member)
|
||||
project.add_developer(second_member)
|
||||
end
|
||||
|
||||
before do
|
||||
merge_request.predictions.suggested_reviewers = {
|
||||
'reviewers' => [
|
||||
second_member.username,
|
||||
first_member.username
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
context 'when a user is inactive' do
|
||||
before do
|
||||
second_member.deactivate
|
||||
end
|
||||
|
||||
it 'returns only active users' do
|
||||
expect(suggested_reviewer_users).to eq([first_member])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when all users are active' do
|
||||
it 'returns users in correct suggested order' do
|
||||
expect(suggested_reviewer_users).to eq([second_member, first_member])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
it { is_expected.to be_empty }
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue