From 7b855b75f2699f3189610886d8b2acf7912bf7ef Mon Sep 17 00:00:00 2001
From: James Lopez <james@jameslopez.es>
Date: Fri, 11 Mar 2016 12:55:50 +0100
Subject: [PATCH] project members import stuff

---
 .../projects/import_export/members_mapper.rb  | 47 ++++++++++++++++++-
 .../projects/import_export/project_factory.rb |  2 +-
 .../import_export/project_tree_restorer.rb    |  5 +-
 .../import_export/members_mapper_spec.rb      | 42 +++++++++++++++++
 4 files changed, 91 insertions(+), 5 deletions(-)
 create mode 100644 spec/services/projects/import_export/members_mapper_spec.rb

diff --git a/app/services/projects/import_export/members_mapper.rb b/app/services/projects/import_export/members_mapper.rb
index ebb50c30b84..56abc131b16 100644
--- a/app/services/projects/import_export/members_mapper.rb
+++ b/app/services/projects/import_export/members_mapper.rb
@@ -6,12 +6,55 @@ module Projects
         new(*args).map
       end
 
-      def initialize(exported_members:)
+      def initialize(exported_members:, user:, project_id:)
         @exported_members = exported_members
+        @user = user
+        @project_id = project_id
       end
 
       def map
-        #TODO
+        @project_member_map ||= project_member_map
+      end
+
+      private
+
+      def project_member_map
+        @project_member_map = Hash.new(default_project_member)
+        @exported_members.each do |member|
+          existing_user = User.where(find_project_user_query(member)).first
+          assign_member(existing_user, member) if existing_user
+        end
+        @project_member_map
+      end
+
+      def assign_member(existing_user, member)
+        member['user'] = existing_user
+        project_member = ProjectMember.new(member_hash(member))
+        @project_member_map[member['id']] = project_member if project_member.save
+      end
+
+      def member_hash(member)
+        member.except('id').merge(source_id: @project_id)
+      end
+
+      def default_project_member
+        @default_project_member ||=
+          begin
+            default_member = ProjectMember.new(default_project_member_hash)
+            default_member if default_member.save
+          end
+      end
+
+      def default_project_member_hash
+        { user: @user, access_level: ProjectMember::MASTER, source_id: @project_id }
+      end
+
+      def find_project_user_query(member)
+        user_arel[:username].eq(member['user']['username']).or(user_arel[:email].eq(member['user']['email']))
+      end
+
+      def user_arel
+        @user_arel ||= User.arel_table
       end
     end
   end
diff --git a/app/services/projects/import_export/project_factory.rb b/app/services/projects/import_export/project_factory.rb
index 825907df537..1ca0cfb8673 100644
--- a/app/services/projects/import_export/project_factory.rb
+++ b/app/services/projects/import_export/project_factory.rb
@@ -3,7 +3,7 @@ module Projects
     module ProjectFactory
       extend self
 
-      def create(project_params:, user:, members_map:)
+      def create(project_params:, user:)
         project = Project.new(project_params.except('id'))
         project.creator = user
         check_namespace(project_params['namespace_id'], project, user)
diff --git a/app/services/projects/import_export/project_tree_restorer.rb b/app/services/projects/import_export/project_tree_restorer.rb
index 64ac3a534e2..87b78197cd6 100644
--- a/app/services/projects/import_export/project_tree_restorer.rb
+++ b/app/services/projects/import_export/project_tree_restorer.rb
@@ -17,7 +17,8 @@ module Projects
       private
 
       def members_map
-        @members ||= Projects::ImportExport::MembersMapper.map(exported_members: @tree_hash.delete('project_members'))
+        @members ||= Projects::ImportExport::MembersMapper.map(
+          exported_members: @tree_hash.delete('project_members'), user: @user, project_id: project.id)
       end
 
       def create_relations
@@ -35,7 +36,7 @@ module Projects
       def create_project
         project_params = @tree_hash.reject { |_key, value| value.is_a?(Array) }
         project = Projects::ImportExport::ProjectFactory.create(
-          project_params: project_params, user: @user, members_map: members_map)
+          project_params: project_params, user: @user)
         project.save
         project
       end
diff --git a/spec/services/projects/import_export/members_mapper_spec.rb b/spec/services/projects/import_export/members_mapper_spec.rb
new file mode 100644
index 00000000000..431626d5e78
--- /dev/null
+++ b/spec/services/projects/import_export/members_mapper_spec.rb
@@ -0,0 +1,42 @@
+require 'spec_helper'
+
+describe Projects::ImportExport::MembersMapper, services: true do
+  describe :map do
+
+    let(:user) { create(:user) }
+    let(:project) { create(:project, :public, name: 'searchable_project') }
+    let(:user2) { create(:user) }
+    let(:exported_members) { [
+      {
+        "id" => 2,
+        "access_level" => 40,
+        "source_id" => 14,
+        "source_type" => "Project",
+        "user_id" => 19,
+        "notification_level" => 3,
+        "created_at" => "2016-03-11T10:21:44.822Z",
+        "updated_at" => "2016-03-11T10:21:44.822Z",
+        "created_by_id" => nil,
+        "invite_email" => nil,
+        "invite_token" => nil,
+        "invite_accepted_at" => nil,
+        "user" => { "email" => user2.email, "username" => user2.username } }] }
+
+    let(:members_mapper) do
+      Projects::ImportExport::MembersMapper.new(
+        exported_members: exported_members, user: user, project_id: project.id)
+    end
+
+    it 'maps a project member' do
+      expect(project_member_map_id(user2.id)).to eq(user2.id)
+    end
+
+    it 'defaults to importer project member if it does not exist' do
+      expect(project_member_map_id(-1)).to eq(user.id)
+    end
+  end
+
+  def project_member_map_id(id)
+    members_mapper.map[id]['id']
+  end
+end
-- 
GitLab