2020-01-01 13:55:28 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-11-03 12:29:30 +05:30
|
|
|
require 'spec_helper'
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
describe Gitlab::ImportExport::ProjectRelationFactory do
|
|
|
|
let(:group) { create(:group) }
|
|
|
|
let(:project) { create(:project, :repository, group: group) }
|
2016-11-03 12:29:30 +05:30
|
|
|
let(:members_mapper) { double('members_mapper').as_null_object }
|
2019-12-21 20:55:43 +05:30
|
|
|
let(:merge_requests_mapping) { {} }
|
2017-08-17 22:00:37 +05:30
|
|
|
let(:user) { create(:admin) }
|
2018-06-03 19:52:53 +05:30
|
|
|
let(:excluded_keys) { [] }
|
2016-11-03 12:29:30 +05:30
|
|
|
let(:created_object) do
|
|
|
|
described_class.create(relation_sym: relation_sym,
|
|
|
|
relation_hash: relation_hash,
|
2020-03-13 15:44:24 +05:30
|
|
|
object_builder: Gitlab::ImportExport::GroupProjectObjectBuilder,
|
2016-11-03 12:29:30 +05:30
|
|
|
members_mapper: members_mapper,
|
2019-12-21 20:55:43 +05:30
|
|
|
merge_requests_mapping: merge_requests_mapping,
|
2016-11-03 12:29:30 +05:30
|
|
|
user: user,
|
2020-03-13 15:44:24 +05:30
|
|
|
importable: project,
|
2018-06-03 19:52:53 +05:30
|
|
|
excluded_keys: excluded_keys)
|
2016-11-03 12:29:30 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
context 'hook object' do
|
|
|
|
let(:relation_sym) { :hooks }
|
|
|
|
let(:id) { 999 }
|
|
|
|
let(:service_id) { 99 }
|
|
|
|
let(:original_project_id) { 8 }
|
|
|
|
let(:token) { 'secret' }
|
|
|
|
|
|
|
|
let(:relation_hash) do
|
|
|
|
{
|
|
|
|
'id' => id,
|
|
|
|
'url' => 'https://example.json',
|
|
|
|
'project_id' => original_project_id,
|
|
|
|
'created_at' => '2016-08-12T09:41:03.462Z',
|
|
|
|
'updated_at' => '2016-08-12T09:41:03.462Z',
|
|
|
|
'service_id' => service_id,
|
|
|
|
'push_events' => true,
|
|
|
|
'issues_events' => false,
|
2018-03-27 19:54:05 +05:30
|
|
|
'confidential_issues_events' => false,
|
2016-11-03 12:29:30 +05:30
|
|
|
'merge_requests_events' => true,
|
|
|
|
'tag_push_events' => false,
|
|
|
|
'note_events' => true,
|
|
|
|
'enable_ssl_verification' => true,
|
2017-09-10 17:25:29 +05:30
|
|
|
'job_events' => false,
|
2016-11-03 12:29:30 +05:30
|
|
|
'wiki_page_events' => true,
|
|
|
|
'token' => token
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not have the original ID' do
|
|
|
|
expect(created_object.id).not_to eq(id)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not have the original service_id' do
|
|
|
|
expect(created_object.service_id).not_to eq(service_id)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not have the original project_id' do
|
|
|
|
expect(created_object.project_id).not_to eq(original_project_id)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'has the new project_id' do
|
2020-03-13 15:44:24 +05:30
|
|
|
expect(created_object.project_id).to eql(project.id)
|
2016-11-03 12:29:30 +05:30
|
|
|
end
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
it 'has a nil token' do
|
|
|
|
expect(created_object.token).to eq(nil)
|
2016-11-03 12:29:30 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
context 'original service exists' do
|
2017-08-17 22:00:37 +05:30
|
|
|
let(:service_id) { create(:service, project: project).id }
|
2016-11-03 12:29:30 +05:30
|
|
|
|
|
|
|
it 'does not have the original service_id' do
|
|
|
|
expect(created_object.service_id).not_to eq(service_id)
|
|
|
|
end
|
|
|
|
end
|
2018-06-03 19:52:53 +05:30
|
|
|
|
|
|
|
context 'excluded attributes' do
|
|
|
|
let(:excluded_keys) { %w[url] }
|
|
|
|
|
|
|
|
it 'are removed from the imported object' do
|
|
|
|
expect(created_object.url).to be_nil
|
|
|
|
end
|
|
|
|
end
|
2016-11-03 12:29:30 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
# Mocks an ActiveRecordish object with the dodgy columns
|
|
|
|
class FooModel
|
|
|
|
include ActiveModel::Model
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
def initialize(params = {})
|
2016-11-03 12:29:30 +05:30
|
|
|
params.each { |key, value| send("#{key}=", value) }
|
|
|
|
end
|
|
|
|
|
|
|
|
def values
|
|
|
|
instance_variables.map { |ivar| instance_variable_get(ivar) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
context 'merge_request object' do
|
|
|
|
let(:relation_sym) { :merge_requests }
|
|
|
|
|
|
|
|
let(:exported_member) do
|
|
|
|
{
|
|
|
|
"id" => 111,
|
|
|
|
"access_level" => 30,
|
|
|
|
"source_id" => 1,
|
|
|
|
"source_type" => "Project",
|
|
|
|
"user_id" => 3,
|
|
|
|
"notification_level" => 3,
|
|
|
|
"created_at" => "2016-11-18T09:29:42.634Z",
|
|
|
|
"updated_at" => "2016-11-18T09:29:42.634Z",
|
|
|
|
"user" => {
|
|
|
|
"id" => user.id,
|
|
|
|
"email" => user.email,
|
|
|
|
"username" => user.username
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:members_mapper) do
|
|
|
|
Gitlab::ImportExport::MembersMapper.new(
|
|
|
|
exported_members: [exported_member],
|
|
|
|
user: user,
|
|
|
|
importable: project)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:relation_hash) do
|
|
|
|
{
|
|
|
|
'id' => 27,
|
|
|
|
'target_branch' => "feature",
|
|
|
|
'source_branch' => "feature_conflict",
|
|
|
|
'source_project_id' => project.id,
|
|
|
|
'target_project_id' => project.id,
|
|
|
|
'author_id' => user.id,
|
|
|
|
'assignee_id' => user.id,
|
|
|
|
'updated_by_id' => user.id,
|
|
|
|
'title' => "MR1",
|
|
|
|
'created_at' => "2016-06-14T15:02:36.568Z",
|
|
|
|
'updated_at' => "2016-06-14T15:02:56.815Z",
|
|
|
|
'state' => "opened",
|
|
|
|
'merge_status' => "unchecked",
|
|
|
|
'description' => "Description",
|
|
|
|
'position' => 0,
|
|
|
|
'source_branch_sha' => "ABCD",
|
|
|
|
'target_branch_sha' => "DCBA",
|
|
|
|
'merge_when_pipeline_succeeds' => true
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'has preloaded author' do
|
|
|
|
expect(created_object.author).to equal(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'has preloaded updated_by' do
|
|
|
|
expect(created_object.updated_by).to equal(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'has preloaded source project' do
|
|
|
|
expect(created_object.source_project).to equal(project)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'has preloaded target project' do
|
|
|
|
expect(created_object.source_project).to equal(project)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'label object' do
|
|
|
|
let(:relation_sym) { :labels }
|
|
|
|
let(:relation_hash) do
|
|
|
|
{
|
|
|
|
"id": 3,
|
|
|
|
"title": "test3",
|
|
|
|
"color": "#428bca",
|
|
|
|
"group_id": project.group.id,
|
|
|
|
"created_at": "2016-07-22T08:55:44.161Z",
|
|
|
|
"updated_at": "2016-07-22T08:55:44.161Z",
|
|
|
|
"template": false,
|
|
|
|
"description": "",
|
|
|
|
"project_id": project.id,
|
|
|
|
"type": "GroupLabel"
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'has preloaded project' do
|
|
|
|
expect(created_object.project).to equal(project)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'has preloaded group' do
|
|
|
|
expect(created_object.group).to equal(project.group)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-11-03 12:29:30 +05:30
|
|
|
# `project_id`, `described_class.USER_REFERENCES`, noteable_id, target_id, and some project IDs are already
|
|
|
|
# re-assigned by described_class.
|
|
|
|
context 'Potentially hazardous foreign keys' do
|
|
|
|
let(:relation_sym) { :hazardous_foo_model }
|
|
|
|
let(:relation_hash) do
|
|
|
|
{
|
|
|
|
'service_id' => 99,
|
|
|
|
'moved_to_id' => 99,
|
|
|
|
'namespace_id' => 99,
|
|
|
|
'ci_id' => 99,
|
|
|
|
'random_project_id' => 99,
|
|
|
|
'random_id' => 99,
|
|
|
|
'milestone_id' => 99,
|
|
|
|
'project_id' => 99,
|
2017-09-10 17:25:29 +05:30
|
|
|
'user_id' => 99
|
2016-11-03 12:29:30 +05:30
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
class HazardousFooModel < FooModel
|
|
|
|
attr_accessor :service_id, :moved_to_id, :namespace_id, :ci_id, :random_project_id, :random_id, :milestone_id, :project_id
|
|
|
|
end
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
before do
|
|
|
|
allow(HazardousFooModel).to receive(:reflect_on_association).and_return(nil)
|
|
|
|
end
|
|
|
|
|
2016-11-03 12:29:30 +05:30
|
|
|
it 'does not preserve any foreign key IDs' do
|
|
|
|
expect(created_object.values).not_to include(99)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
context 'overrided model with pluralized name' do
|
|
|
|
let(:relation_sym) { :metrics }
|
|
|
|
|
|
|
|
let(:relation_hash) do
|
|
|
|
{
|
|
|
|
'id' => 99,
|
|
|
|
'merge_request_id' => 99,
|
|
|
|
'merged_at' => Time.now,
|
|
|
|
'merged_by_id' => 99,
|
|
|
|
'latest_closed_at' => nil,
|
|
|
|
'latest_closed_by_id' => nil
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not raise errors' do
|
|
|
|
expect { created_object }.not_to raise_error
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-11-03 12:29:30 +05:30
|
|
|
context 'Project references' do
|
|
|
|
let(:relation_sym) { :project_foo_model }
|
|
|
|
let(:relation_hash) do
|
2020-03-13 15:44:24 +05:30
|
|
|
Gitlab::ImportExport::ProjectRelationFactory::PROJECT_REFERENCES.map { |ref| { ref => 99 } }.inject(:merge)
|
2016-11-03 12:29:30 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
class ProjectFooModel < FooModel
|
2020-03-13 15:44:24 +05:30
|
|
|
attr_accessor(*Gitlab::ImportExport::ProjectRelationFactory::PROJECT_REFERENCES)
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
allow(ProjectFooModel).to receive(:reflect_on_association).and_return(nil)
|
2016-11-03 12:29:30 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not preserve any project foreign key IDs' do
|
|
|
|
expect(created_object.values).not_to include(99)
|
|
|
|
end
|
|
|
|
end
|
2017-08-17 22:00:37 +05:30
|
|
|
|
|
|
|
context 'Notes user references' do
|
|
|
|
let(:relation_sym) { :notes }
|
|
|
|
let(:new_user) { create(:user) }
|
|
|
|
let(:exported_member) do
|
|
|
|
{
|
|
|
|
"id" => 111,
|
|
|
|
"access_level" => 30,
|
|
|
|
"source_id" => 1,
|
|
|
|
"source_type" => "Project",
|
|
|
|
"user_id" => 3,
|
|
|
|
"notification_level" => 3,
|
|
|
|
"created_at" => "2016-11-18T09:29:42.634Z",
|
|
|
|
"updated_at" => "2016-11-18T09:29:42.634Z",
|
|
|
|
"user" => {
|
|
|
|
"id" => 999,
|
|
|
|
"email" => new_user.email,
|
|
|
|
"username" => new_user.username
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:relation_hash) do
|
|
|
|
{
|
|
|
|
"id" => 4947,
|
|
|
|
"note" => "merged",
|
|
|
|
"noteable_type" => "MergeRequest",
|
|
|
|
"author_id" => 999,
|
|
|
|
"created_at" => "2016-11-18T09:29:42.634Z",
|
|
|
|
"updated_at" => "2016-11-18T09:29:42.634Z",
|
|
|
|
"project_id" => 1,
|
|
|
|
"attachment" => {
|
|
|
|
"url" => nil
|
|
|
|
},
|
|
|
|
"noteable_id" => 377,
|
|
|
|
"system" => true,
|
|
|
|
"author" => {
|
|
|
|
"name" => "Administrator"
|
|
|
|
},
|
2018-12-05 23:21:45 +05:30
|
|
|
"events" => []
|
2017-08-17 22:00:37 +05:30
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:members_mapper) do
|
|
|
|
Gitlab::ImportExport::MembersMapper.new(
|
|
|
|
exported_members: [exported_member],
|
|
|
|
user: user,
|
2020-01-01 13:55:28 +05:30
|
|
|
importable: project)
|
2017-08-17 22:00:37 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'maps the right author to the imported note' do
|
|
|
|
expect(created_object.author).to eq(new_user)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'encrypted attributes' do
|
|
|
|
let(:relation_sym) { 'Ci::Variable' }
|
|
|
|
let(:relation_hash) do
|
|
|
|
create(:ci_variable).as_json
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'has no value for the encrypted attribute' do
|
|
|
|
expect(created_object.value).to be_nil
|
|
|
|
end
|
|
|
|
end
|
2016-11-03 12:29:30 +05:30
|
|
|
end
|