1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
# frozen_string_literal: true
module Groups
module ImportExport
class ImportService
attr_reader :current_user, :group, :shared
def initialize(group:, user:)
@group = group
@current_user = user
@user_role = user_role
@shared = Gitlab::ImportExport::Shared.new(@group)
@logger = Gitlab::Import::Logger.build
end
def async_execute
group_import_state = GroupImportState.safe_find_or_create_by!(group: group, user: current_user)
jid = GroupImportWorker.with_status.perform_async(current_user.id, group.id)
if jid.present?
group_import_state.update!(jid: jid)
else
group_import_state.fail_op('Failed to schedule import job')
false
end
end
def execute
Gitlab::Tracking.event(self.class.name, 'create', label: 'import_group_from_file')
if valid_user_permissions? && import_file && valid_import_file? && restorers.all?(&:restore)
notify_success
Gitlab::Tracking.event(
self.class.name,
'create',
label: 'import_access_level',
user: current_user,
extra: { user_role: user_role, import_type: 'import_group_from_file' }
)
group
else
notify_error!
end
ensure
remove_base_tmp_dir
remove_import_file
end
private
def user_role
# rubocop:disable CodeReuse/ActiveRecord, Style/MultilineTernaryOperator
access_level = group.parent ?
current_user&.group_members&.find_by(source_id: group.parent&.id)&.access_level :
Gitlab::Access::OWNER
Gitlab::Access.human_access(access_level)
# rubocop:enable CodeReuse/ActiveRecord, Style/MultilineTernaryOperator
end
def import_file
@import_file ||= Gitlab::ImportExport::FileImporter.import(
importable: group,
archive_file: nil,
shared: shared
)
end
def restorers
[tree_restorer]
end
def tree_restorer
@tree_restorer ||=
Gitlab::ImportExport::Group::TreeRestorer.new(
user: current_user,
shared: shared,
group: group
)
end
def remove_import_file
upload = group.import_export_upload
return unless upload&.import_file&.file
upload.remove_import_file!
upload.save!
end
def valid_user_permissions?
if current_user.can?(:admin_group, group)
true
else
shared.error(::Gitlab::ImportExport::Error.permission_error(current_user, group))
false
end
end
def valid_import_file?
return true if File.exist?(File.join(shared.export_path, 'tree/groups/_all.ndjson'))
shared.error(::Gitlab::ImportExport::Error.incompatible_import_file_error)
false
end
def notify_success
@logger.info(
group_id: group.id,
group_name: group.name,
message: 'Group Import/Export: Import succeeded'
)
end
def notify_error
@logger.error(
group_id: group.id,
group_name: group.name,
message: "Group Import/Export: Errors occurred, see '#{Gitlab::ErrorTracking::Logger.file_name}' for details"
)
end
def notify_error!
notify_error
raise Gitlab::ImportExport::Error, shared.errors.to_sentence
end
def remove_base_tmp_dir
FileUtils.rm_rf(shared.base_path)
end
end
end
end
Groups::ImportExport::ImportService.prepend_mod_with('Groups::ImportExport::ImportService')
|