New upstream version 12.10.2
This commit is contained in:
parent
33be1af3d8
commit
d76068268a
14 changed files with 337 additions and 52 deletions
|
@ -1,5 +1,12 @@
|
||||||
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.
|
||||||
|
|
||||||
|
## 12.10.1 (2020-04-24)
|
||||||
|
|
||||||
|
### Changed (1 change)
|
||||||
|
|
||||||
|
- Move project deploy tokens section back to Repository settings. !29280
|
||||||
|
|
||||||
|
|
||||||
## 12.10.0 (2020-04-22)
|
## 12.10.0 (2020-04-22)
|
||||||
|
|
||||||
### Fixed (6 changes, 1 of them is from the community)
|
### Fixed (6 changes, 1 of them is from the community)
|
||||||
|
|
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -2,6 +2,20 @@
|
||||||
documentation](doc/development/changelog.md) for instructions on adding your own
|
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||||
entry.
|
entry.
|
||||||
|
|
||||||
|
## 12.10.2 (2020-04-30)
|
||||||
|
|
||||||
|
### Security (8 changes)
|
||||||
|
|
||||||
|
- Ensure MR diff exists before codeowner check.
|
||||||
|
- Apply CODEOWNERS validations to web requests.
|
||||||
|
- Prevent unauthorized access to default branch.
|
||||||
|
- Do not return private project ID without permission.
|
||||||
|
- Fix doorkeeper CVE-2020-10187.
|
||||||
|
- Change GitHub service integration token input to password.
|
||||||
|
- Return only safe urls for mirrors.
|
||||||
|
- Validate workhorse 'rewritten_fields' and properly use them during multipart uploads.
|
||||||
|
|
||||||
|
|
||||||
## 12.10.1 (2020-04-24)
|
## 12.10.1 (2020-04-24)
|
||||||
|
|
||||||
### Fixed (5 changes)
|
### Fixed (5 changes)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
12.10.1
|
12.10.2
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
12.10.1
|
12.10.2
|
||||||
|
|
|
@ -5,6 +5,13 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
|
||||||
|
|
||||||
layout 'profile'
|
layout 'profile'
|
||||||
|
|
||||||
|
def index
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { render "errors/not_found", layout: "errors", status: :not_found }
|
||||||
|
format.json { render json: "", status: :not_found }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
if params[:token_id].present?
|
if params[:token_id].present?
|
||||||
current_resource_owner.oauth_authorized_tokens.find(params[:token_id]).revoke
|
current_resource_owner.oauth_authorized_tokens.find(params[:token_id]).revoke
|
||||||
|
|
|
@ -624,6 +624,7 @@ module ProjectsHelper
|
||||||
|
|
||||||
def find_file_path
|
def find_file_path
|
||||||
return unless @project && !@project.empty_repo?
|
return unless @project && !@project.empty_repo?
|
||||||
|
return unless can?(current_user, :download_code, @project)
|
||||||
|
|
||||||
ref = @ref || @project.repository.root_ref
|
ref = @ref || @project.repository.root_ref
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
class RemoteMirrorEntity < Grape::Entity
|
class RemoteMirrorEntity < Grape::Entity
|
||||||
expose :id
|
expose :id
|
||||||
expose :url
|
expose :safe_url, as: :url
|
||||||
expose :enabled
|
expose :enabled
|
||||||
|
|
||||||
expose :auth_method
|
expose :auth_method
|
||||||
|
|
|
@ -43,11 +43,13 @@ module Gitlab
|
||||||
raise "unexpected field: #{field.inspect}" unless parsed_field.count == 1
|
raise "unexpected field: #{field.inspect}" unless parsed_field.count == 1
|
||||||
|
|
||||||
key, value = parsed_field.first
|
key, value = parsed_field.first
|
||||||
if value.nil?
|
if value.nil? # we have a top level param, eg. field = 'foo' and not 'foo[bar]'
|
||||||
value = open_file(@request.params, key)
|
raise "invalid field: #{field.inspect}" if field != key
|
||||||
|
|
||||||
|
value = open_file(@request.params, key, tmp_path.presence)
|
||||||
@open_files << value
|
@open_files << value
|
||||||
else
|
else
|
||||||
value = decorate_params_value(value, @request.params[key])
|
value = decorate_params_value(value, @request.params[key], tmp_path.presence)
|
||||||
end
|
end
|
||||||
|
|
||||||
update_param(key, value)
|
update_param(key, value)
|
||||||
|
@ -59,7 +61,7 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
# This function calls itself recursively
|
# This function calls itself recursively
|
||||||
def decorate_params_value(path_hash, value_hash)
|
def decorate_params_value(path_hash, value_hash, path_override = nil)
|
||||||
unless path_hash.is_a?(Hash) && path_hash.count == 1
|
unless path_hash.is_a?(Hash) && path_hash.count == 1
|
||||||
raise "invalid path: #{path_hash.inspect}"
|
raise "invalid path: #{path_hash.inspect}"
|
||||||
end
|
end
|
||||||
|
@ -72,19 +74,19 @@ module Gitlab
|
||||||
|
|
||||||
case path_value
|
case path_value
|
||||||
when nil
|
when nil
|
||||||
value_hash[path_key] = open_file(value_hash.dig(path_key), '')
|
value_hash[path_key] = open_file(value_hash.dig(path_key), '', path_override)
|
||||||
@open_files << value_hash[path_key]
|
@open_files << value_hash[path_key]
|
||||||
value_hash
|
value_hash
|
||||||
when Hash
|
when Hash
|
||||||
decorate_params_value(path_value, value_hash[path_key])
|
decorate_params_value(path_value, value_hash[path_key], path_override)
|
||||||
value_hash
|
value_hash
|
||||||
else
|
else
|
||||||
raise "unexpected path value: #{path_value.inspect}"
|
raise "unexpected path value: #{path_value.inspect}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def open_file(params, key)
|
def open_file(params, key, path_override = nil)
|
||||||
::UploadedFile.from_params(params, key, allowed_paths)
|
::UploadedFile.from_params(params, key, allowed_paths, path_override)
|
||||||
end
|
end
|
||||||
|
|
||||||
# update_params ensures that both rails controllers and rack middleware can find
|
# update_params ensures that both rails controllers and rack middleware can find
|
||||||
|
|
|
@ -42,13 +42,14 @@ class UploadedFile
|
||||||
@remote_id = remote_id
|
@remote_id = remote_id
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.from_params(params, field, upload_paths)
|
def self.from_params(params, field, upload_paths, path_override = nil)
|
||||||
path = params["#{field}.path"]
|
path = path_override || params["#{field}.path"]
|
||||||
remote_id = params["#{field}.remote_id"]
|
remote_id = params["#{field}.remote_id"]
|
||||||
return if path.blank? && remote_id.blank?
|
return if path.blank? && remote_id.blank?
|
||||||
|
|
||||||
|
if remote_id.present? # don't use file_path if remote_id is set
|
||||||
file_path = nil
|
file_path = nil
|
||||||
if path.present?
|
elsif path.present?
|
||||||
file_path = File.realpath(path)
|
file_path = File.realpath(path)
|
||||||
|
|
||||||
paths = Array(upload_paths) << Dir.tmpdir
|
paths = Array(upload_paths) << Dir.tmpdir
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Oauth::AuthorizedApplicationsController do
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
let(:guest) { create(:user) }
|
||||||
|
let(:application) { create(:oauth_application, owner: guest) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_in(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'GET #index' do
|
||||||
|
it 'responds with 404' do
|
||||||
|
get :index
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(:not_found)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -277,11 +277,16 @@ describe ApplicationHelper do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when @project is set' do
|
context 'when @project is set' do
|
||||||
it 'includes all possible body data elements and associates the project elements with project' do
|
let_it_be(:project) { create(:project, :repository) }
|
||||||
project = create(:project)
|
let_it_be(:user) { create(:user) }
|
||||||
|
|
||||||
|
before do
|
||||||
assign(:project, project)
|
assign(:project, project)
|
||||||
|
allow(helper).to receive(:current_user).and_return(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes all possible body data elements and associates the project elements with project' do
|
||||||
|
expect(helper).to receive(:can?).with(nil, :download_code, project)
|
||||||
expect(helper.body_data).to eq(
|
expect(helper.body_data).to eq(
|
||||||
{
|
{
|
||||||
page: 'application',
|
page: 'application',
|
||||||
|
@ -302,12 +307,11 @@ describe ApplicationHelper do
|
||||||
|
|
||||||
context 'when params[:id] is present and the issue exsits and action_name is show' do
|
context 'when params[:id] is present and the issue exsits and action_name is show' do
|
||||||
it 'sets all project and id elements correctly related to the issue' do
|
it 'sets all project and id elements correctly related to the issue' do
|
||||||
issue = create(:issue)
|
issue = create(:issue, project: project)
|
||||||
stub_controller_method(:action_name, 'show')
|
stub_controller_method(:action_name, 'show')
|
||||||
stub_controller_method(:params, { id: issue.id })
|
stub_controller_method(:params, { id: issue.id })
|
||||||
|
|
||||||
assign(:project, issue.project)
|
expect(helper).to receive(:can?).with(nil, :download_code, project).and_return(false)
|
||||||
|
|
||||||
expect(helper.body_data).to eq(
|
expect(helper.body_data).to eq(
|
||||||
{
|
{
|
||||||
page: 'projects:issues:show',
|
page: 'projects:issues:show',
|
||||||
|
@ -322,6 +326,15 @@ describe ApplicationHelper do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when current_user has download_code permission' do
|
||||||
|
it 'returns find_file with the default branch' do
|
||||||
|
allow(helper).to receive(:current_user).and_return(user)
|
||||||
|
|
||||||
|
expect(helper).to receive(:can?).with(user, :download_code, project).and_return(true)
|
||||||
|
expect(helper.body_data[:find_file]).to end_with(project.default_branch)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def stub_controller_method(method_name, value)
|
def stub_controller_method(method_name, value)
|
||||||
|
|
|
@ -7,11 +7,11 @@ require 'tempfile'
|
||||||
describe Gitlab::Middleware::Multipart do
|
describe Gitlab::Middleware::Multipart do
|
||||||
include_context 'multipart middleware context'
|
include_context 'multipart middleware context'
|
||||||
|
|
||||||
shared_examples_for 'multipart upload files' do
|
RSpec.shared_examples_for 'multipart upload files' do
|
||||||
it 'opens top-level files' do
|
it 'opens top-level files' do
|
||||||
Tempfile.open('top-level') do |tempfile|
|
Tempfile.open('top-level') do |tempfile|
|
||||||
rewritten = { 'file' => tempfile.path }
|
rewritten = { 'file' => tempfile.path }
|
||||||
in_params = { 'file.name' => original_filename, 'file.path' => tempfile.path, 'file.remote_id' => remote_id }
|
in_params = { 'file.name' => original_filename, 'file.path' => file_path, 'file.remote_id' => remote_id, 'file.size' => file_size }
|
||||||
env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
|
env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
|
||||||
|
|
||||||
expect_uploaded_file(tempfile, %w(file))
|
expect_uploaded_file(tempfile, %w(file))
|
||||||
|
@ -22,8 +22,8 @@ describe Gitlab::Middleware::Multipart do
|
||||||
|
|
||||||
it 'opens files one level deep' do
|
it 'opens files one level deep' do
|
||||||
Tempfile.open('one-level') do |tempfile|
|
Tempfile.open('one-level') do |tempfile|
|
||||||
in_params = { 'user' => { 'avatar' => { '.name' => original_filename, '.path' => tempfile.path, '.remote_id' => remote_id } } }
|
|
||||||
rewritten = { 'user[avatar]' => tempfile.path }
|
rewritten = { 'user[avatar]' => tempfile.path }
|
||||||
|
in_params = { 'user' => { 'avatar' => { '.name' => original_filename, '.path' => file_path, '.remote_id' => remote_id, '.size' => file_size } } }
|
||||||
env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
|
env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
|
||||||
|
|
||||||
expect_uploaded_file(tempfile, %w(user avatar))
|
expect_uploaded_file(tempfile, %w(user avatar))
|
||||||
|
@ -34,7 +34,7 @@ describe Gitlab::Middleware::Multipart do
|
||||||
|
|
||||||
it 'opens files two levels deep' do
|
it 'opens files two levels deep' do
|
||||||
Tempfile.open('two-levels') do |tempfile|
|
Tempfile.open('two-levels') do |tempfile|
|
||||||
in_params = { 'project' => { 'milestone' => { 'themesong' => { '.name' => original_filename, '.path' => tempfile.path, '.remote_id' => remote_id } } } }
|
in_params = { 'project' => { 'milestone' => { 'themesong' => { '.name' => original_filename, '.path' => file_path, '.remote_id' => remote_id, '.size' => file_size } } } }
|
||||||
rewritten = { 'project[milestone][themesong]' => tempfile.path }
|
rewritten = { 'project[milestone][themesong]' => tempfile.path }
|
||||||
env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
|
env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
|
||||||
|
|
||||||
|
@ -44,13 +44,61 @@ describe Gitlab::Middleware::Multipart do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def expect_uploaded_file(tempfile, path, remote: false)
|
def expect_uploaded_file(tempfile, path)
|
||||||
expect(app).to receive(:call) do |env|
|
expect(app).to receive(:call) do |env|
|
||||||
file = get_params(env).dig(*path)
|
file = get_params(env).dig(*path)
|
||||||
expect(file).to be_a(::UploadedFile)
|
expect(file).to be_a(::UploadedFile)
|
||||||
expect(file.path).to eq(tempfile.path)
|
|
||||||
expect(file.original_filename).to eq(original_filename)
|
expect(file.original_filename).to eq(original_filename)
|
||||||
|
|
||||||
|
if remote_id
|
||||||
expect(file.remote_id).to eq(remote_id)
|
expect(file.remote_id).to eq(remote_id)
|
||||||
|
expect(file.path).to be_nil
|
||||||
|
else
|
||||||
|
expect(file.path).to eq(File.realpath(tempfile.path))
|
||||||
|
expect(file.remote_id).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
RSpec.shared_examples_for 'handling CI artifact upload' do
|
||||||
|
it 'uploads both file and metadata' do
|
||||||
|
Tempfile.open('file') do |file|
|
||||||
|
Tempfile.open('metadata') do |metadata|
|
||||||
|
rewritten = { 'file' => file.path, 'metadata' => metadata.path }
|
||||||
|
in_params = { 'file.name' => 'file.txt', 'file.path' => file_path, 'file.remote_id' => file_remote_id, 'file.size' => file_size, 'metadata.name' => 'metadata.gz' }
|
||||||
|
env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
|
||||||
|
|
||||||
|
with_expected_uploaded_artifact_files(file, metadata) do |uploaded_file, uploaded_metadata|
|
||||||
|
expect(uploaded_file).to be_a(::UploadedFile)
|
||||||
|
expect(uploaded_file.original_filename).to eq('file.txt')
|
||||||
|
|
||||||
|
if file_remote_id
|
||||||
|
expect(uploaded_file.remote_id).to eq(file_remote_id)
|
||||||
|
expect(uploaded_file.size).to eq(file_size)
|
||||||
|
expect(uploaded_file.path).to be_nil
|
||||||
|
else
|
||||||
|
expect(uploaded_file.path).to eq(File.realpath(file.path))
|
||||||
|
expect(uploaded_file.remote_id).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(uploaded_metadata).to be_a(::UploadedFile)
|
||||||
|
expect(uploaded_metadata.original_filename).to eq('metadata.gz')
|
||||||
|
expect(uploaded_metadata.path).to eq(File.realpath(metadata.path))
|
||||||
|
expect(uploaded_metadata.remote_id).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
middleware.call(env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_expected_uploaded_artifact_files(file, metadata)
|
||||||
|
expect(app).to receive(:call) do |env|
|
||||||
|
file = get_params(env).dig('file')
|
||||||
|
metadata = get_params(env).dig('metadata')
|
||||||
|
|
||||||
|
yield file, metadata
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -67,18 +115,65 @@ describe Gitlab::Middleware::Multipart do
|
||||||
expect { middleware.call(env) }.to raise_error(JWT::InvalidIssuerError)
|
expect { middleware.call(env) }.to raise_error(JWT::InvalidIssuerError)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with invalid rewritten field' do
|
||||||
|
invalid_field_names = [
|
||||||
|
'[file]',
|
||||||
|
';file',
|
||||||
|
'file]',
|
||||||
|
';file]',
|
||||||
|
'file]]',
|
||||||
|
'file;;'
|
||||||
|
]
|
||||||
|
|
||||||
|
invalid_field_names.each do |invalid_field_name|
|
||||||
|
it "rejects invalid rewritten field name #{invalid_field_name}" do
|
||||||
|
env = post_env({ invalid_field_name => nil }, {}, Gitlab::Workhorse.secret, 'gitlab-workhorse')
|
||||||
|
|
||||||
|
expect { middleware.call(env) }.to raise_error(RuntimeError, "invalid field: \"#{invalid_field_name}\"")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'with remote file' do
|
context 'with remote file' do
|
||||||
let(:remote_id) { 'someid' }
|
let(:remote_id) { 'someid' }
|
||||||
|
let(:file_size) { 300 }
|
||||||
|
let(:file_path) { '' }
|
||||||
|
|
||||||
|
it_behaves_like 'multipart upload files'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with remote file and a file path set' do
|
||||||
|
let(:remote_id) { 'someid' }
|
||||||
|
let(:file_size) { 300 }
|
||||||
|
let(:file_path) { 'not_a_valid_file_path' } # file path will come from the rewritten_fields
|
||||||
|
|
||||||
it_behaves_like 'multipart upload files'
|
it_behaves_like 'multipart upload files'
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with local file' do
|
context 'with local file' do
|
||||||
let(:remote_id) { nil }
|
let(:remote_id) { nil }
|
||||||
|
let(:file_size) { nil }
|
||||||
|
let(:file_path) { 'not_a_valid_file_path' } # file path will come from the rewritten_fields
|
||||||
|
|
||||||
it_behaves_like 'multipart upload files'
|
it_behaves_like 'multipart upload files'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with remote CI artifact upload' do
|
||||||
|
let(:file_remote_id) { 'someid' }
|
||||||
|
let(:file_size) { 300 }
|
||||||
|
let(:file_path) { 'not_a_valid_file_path' } # file path will come from the rewritten_fields
|
||||||
|
|
||||||
|
it_behaves_like 'handling CI artifact upload'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with local CI artifact upload' do
|
||||||
|
let(:file_remote_id) { nil }
|
||||||
|
let(:file_size) { nil }
|
||||||
|
let(:file_path) { 'not_a_valid_file_path' } # file path will come from the rewritten_fields
|
||||||
|
|
||||||
|
it_behaves_like 'handling CI artifact upload'
|
||||||
|
end
|
||||||
|
|
||||||
it 'allows files in uploads/tmp directory' do
|
it 'allows files in uploads/tmp directory' do
|
||||||
with_tmp_dir('public/uploads/tmp') do |dir, env|
|
with_tmp_dir('public/uploads/tmp') do |dir, env|
|
||||||
expect(app).to receive(:call) do |env|
|
expect(app).to receive(:call) do |env|
|
||||||
|
|
|
@ -4,7 +4,7 @@ require 'spec_helper'
|
||||||
|
|
||||||
describe UploadedFile do
|
describe UploadedFile do
|
||||||
let(:temp_dir) { Dir.tmpdir }
|
let(:temp_dir) { Dir.tmpdir }
|
||||||
let(:temp_file) { Tempfile.new("test", temp_dir) }
|
let(:temp_file) { Tempfile.new(%w[test test], temp_dir) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
FileUtils.touch(temp_file)
|
FileUtils.touch(temp_file)
|
||||||
|
@ -16,13 +16,14 @@ describe UploadedFile do
|
||||||
|
|
||||||
describe ".from_params" do
|
describe ".from_params" do
|
||||||
let(:upload_path) { nil }
|
let(:upload_path) { nil }
|
||||||
|
let(:file_path_override) { nil }
|
||||||
|
|
||||||
after do
|
after do
|
||||||
FileUtils.rm_r(upload_path) if upload_path
|
FileUtils.rm_r(upload_path) if upload_path
|
||||||
end
|
end
|
||||||
|
|
||||||
subject do
|
subject do
|
||||||
described_class.from_params(params, :file, upload_path)
|
described_class.from_params(params, :file, upload_path, file_path_override)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when valid file is specified' do
|
context 'when valid file is specified' do
|
||||||
|
@ -31,9 +32,7 @@ describe UploadedFile do
|
||||||
{ 'file.path' => temp_file.path }
|
{ 'file.path' => temp_file.path }
|
||||||
end
|
end
|
||||||
|
|
||||||
it "succeeds" do
|
it { is_expected.not_to be_nil }
|
||||||
is_expected.not_to be_nil
|
|
||||||
end
|
|
||||||
|
|
||||||
it "generates filename from path" do
|
it "generates filename from path" do
|
||||||
expect(subject.original_filename).to eq(::File.basename(temp_file.path))
|
expect(subject.original_filename).to eq(::File.basename(temp_file.path))
|
||||||
|
@ -41,23 +40,26 @@ describe UploadedFile do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'all parameters are specified' do
|
context 'all parameters are specified' do
|
||||||
let(:params) do
|
RSpec.shared_context 'filepath override' do
|
||||||
{ 'file.path' => temp_file.path,
|
let(:temp_file_override) { Tempfile.new(%w[override override], temp_dir) }
|
||||||
'file.name' => 'dir/my file&.txt',
|
let(:file_path_override) { temp_file_override.path }
|
||||||
'file.type' => 'my/type',
|
|
||||||
'file.sha256' => 'sha256',
|
before do
|
||||||
'file.remote_id' => 'remote_id' }
|
FileUtils.touch(temp_file_override)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "succeeds" do
|
after do
|
||||||
is_expected.not_to be_nil
|
FileUtils.rm_f(temp_file_override)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "generates filename from path" do
|
RSpec.shared_examples 'using the file path' do |filename:, content_type:, sha256:, path_suffix:|
|
||||||
expect(subject.original_filename).to eq('my_file_.txt')
|
it 'sets properly the attributes' do
|
||||||
expect(subject.content_type).to eq('my/type')
|
expect(subject.original_filename).to eq(filename)
|
||||||
expect(subject.sha256).to eq('sha256')
|
expect(subject.content_type).to eq(content_type)
|
||||||
expect(subject.remote_id).to eq('remote_id')
|
expect(subject.sha256).to eq(sha256)
|
||||||
|
expect(subject.remote_id).to be_nil
|
||||||
|
expect(subject.path).to end_with(path_suffix)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'handles a blank path' do
|
it 'handles a blank path' do
|
||||||
|
@ -70,6 +72,123 @@ describe UploadedFile do
|
||||||
.not_to raise_error
|
.not_to raise_error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
RSpec.shared_examples 'using the remote id' do |filename:, content_type:, sha256:, size:, remote_id:|
|
||||||
|
it 'sets properly the attributes' do
|
||||||
|
expect(subject.original_filename).to eq(filename)
|
||||||
|
expect(subject.content_type).to eq('application/octet-stream')
|
||||||
|
expect(subject.sha256).to eq('sha256')
|
||||||
|
expect(subject.path).to be_nil
|
||||||
|
expect(subject.size).to eq(123456)
|
||||||
|
expect(subject.remote_id).to eq('1234567890')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a filepath' do
|
||||||
|
let(:params) do
|
||||||
|
{ 'file.path' => temp_file.path,
|
||||||
|
'file.name' => 'dir/my file&.txt',
|
||||||
|
'file.type' => 'my/type',
|
||||||
|
'file.sha256' => 'sha256' }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.not_to be_nil }
|
||||||
|
|
||||||
|
it_behaves_like 'using the file path',
|
||||||
|
filename: 'my_file_.txt',
|
||||||
|
content_type: 'my/type',
|
||||||
|
sha256: 'sha256',
|
||||||
|
path_suffix: 'test'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a filepath override' do
|
||||||
|
include_context 'filepath override'
|
||||||
|
|
||||||
|
let(:params) do
|
||||||
|
{ 'file.path' => temp_file.path,
|
||||||
|
'file.name' => 'dir/my file&.txt',
|
||||||
|
'file.type' => 'my/type',
|
||||||
|
'file.sha256' => 'sha256' }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.not_to be_nil }
|
||||||
|
|
||||||
|
it_behaves_like 'using the file path',
|
||||||
|
filename: 'my_file_.txt',
|
||||||
|
content_type: 'my/type',
|
||||||
|
sha256: 'sha256',
|
||||||
|
path_suffix: 'override'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a remote id' do
|
||||||
|
let(:params) do
|
||||||
|
{
|
||||||
|
'file.name' => 'dir/my file&.txt',
|
||||||
|
'file.sha256' => 'sha256',
|
||||||
|
'file.remote_url' => 'http://localhost/file',
|
||||||
|
'file.remote_id' => '1234567890',
|
||||||
|
'file.etag' => 'etag1234567890',
|
||||||
|
'file.size' => '123456'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.not_to be_nil }
|
||||||
|
|
||||||
|
it_behaves_like 'using the remote id',
|
||||||
|
filename: 'my_file_.txt',
|
||||||
|
content_type: 'application/octet-stream',
|
||||||
|
sha256: 'sha256',
|
||||||
|
size: 123456,
|
||||||
|
remote_id: '1234567890'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a path and a remote id' do
|
||||||
|
let(:params) do
|
||||||
|
{
|
||||||
|
'file.path' => temp_file.path,
|
||||||
|
'file.name' => 'dir/my file&.txt',
|
||||||
|
'file.sha256' => 'sha256',
|
||||||
|
'file.remote_url' => 'http://localhost/file',
|
||||||
|
'file.remote_id' => '1234567890',
|
||||||
|
'file.etag' => 'etag1234567890',
|
||||||
|
'file.size' => '123456'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.not_to be_nil }
|
||||||
|
|
||||||
|
it_behaves_like 'using the remote id',
|
||||||
|
filename: 'my_file_.txt',
|
||||||
|
content_type: 'application/octet-stream',
|
||||||
|
sha256: 'sha256',
|
||||||
|
size: 123456,
|
||||||
|
remote_id: '1234567890'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a path override and a remote id' do
|
||||||
|
include_context 'filepath override'
|
||||||
|
|
||||||
|
let(:params) do
|
||||||
|
{
|
||||||
|
'file.name' => 'dir/my file&.txt',
|
||||||
|
'file.sha256' => 'sha256',
|
||||||
|
'file.remote_url' => 'http://localhost/file',
|
||||||
|
'file.remote_id' => '1234567890',
|
||||||
|
'file.etag' => 'etag1234567890',
|
||||||
|
'file.size' => '123456'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.not_to be_nil }
|
||||||
|
|
||||||
|
it_behaves_like 'using the remote id',
|
||||||
|
filename: 'my_file_.txt',
|
||||||
|
content_type: 'application/octet-stream',
|
||||||
|
sha256: 'sha256',
|
||||||
|
size: 123456,
|
||||||
|
remote_id: '1234567890'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when no params are specified' do
|
context 'when no params are specified' do
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe RemoteMirrorEntity do
|
describe RemoteMirrorEntity do
|
||||||
let(:project) { create(:project, :repository, :remote_mirror) }
|
let(:project) { create(:project, :repository, :remote_mirror, url: "https://test:password@gitlab.com") }
|
||||||
let(:remote_mirror) { project.remote_mirrors.first }
|
let(:remote_mirror) { project.remote_mirrors.first }
|
||||||
let(:entity) { described_class.new(remote_mirror) }
|
let(:entity) { described_class.new(remote_mirror) }
|
||||||
|
|
||||||
|
@ -15,4 +15,9 @@ describe RemoteMirrorEntity do
|
||||||
:ssh_known_hosts, :ssh_public_key, :ssh_known_hosts_fingerprints
|
:ssh_known_hosts, :ssh_public_key, :ssh_known_hosts_fingerprints
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'does not expose password information' do
|
||||||
|
expect(subject[:url]).not_to include('password')
|
||||||
|
expect(subject[:url]).to eq(remote_mirror.safe_url)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue