diff --git a/lib/import_export.rb b/lib/import_export.rb index f86600253db..6a32d686f13 100644 --- a/lib/import_export.rb +++ b/lib/import_export.rb @@ -5,6 +5,7 @@ require "import_export/base_exporter" require "import_export/category_structure_exporter" require "import_export/category_exporter" require "import_export/topic_exporter" +require "import_export/group_exporter" require "json" module ImportExport @@ -26,4 +27,8 @@ module ImportExport ImportExport::TopicExporter.new(topic_ids).perform.save_to_file(filename) end + def self.export_groups(include_users, filename = nil) + ImportExport::GroupExporter.new(include_users).perform.save_to_file(filename) + end + end diff --git a/lib/import_export/base_exporter.rb b/lib/import_export/base_exporter.rb index ec0bd2b4284..f53b38025fa 100644 --- a/lib/import_export/base_exporter.rb +++ b/lib/import_export/base_exporter.rb @@ -8,9 +8,11 @@ module ImportExport :auto_close_hours, :parent_category_id, :auto_close_based_on_last_post, :topic_template, :all_topics_wiki, :permissions_params] - GROUP_ATTRS = [ :id, :name, :created_at, :mentionable_level, :messageable_level, :visibility_level, - :automatic_membership_email_domains, :automatic_membership_retroactive, - :primary_group, :title, :grant_trust_level, :incoming_email] + GROUP_ATTRS = [:id, :name, :created_at, :automatic_membership_email_domains, :primary_group, + :title, :grant_trust_level, :incoming_email, :bio_raw, :allow_membership_requests, + :full_name, :default_notification_level, :visibility_level, :public_exit, + :public_admission, :membership_request_template, :messageable_level, :mentionable_level, + :members_visibility_level, :publish_read_state] USER_ATTRS = [:id, :email, :username, :name, :created_at, :trust_level, :active, :last_emailed_at] @@ -39,6 +41,26 @@ module ImportExport self end + def export_groups(group_names) + data = [] + groups = Group.all + groups = groups.where(name: group_names) if group_names.present? + + groups.find_each do |group| + attrs = GROUP_ATTRS.inject({}) { |h, a| h[a] = group.public_send(a); h } + attrs[:user_ids] = group.users.pluck(:id) + data << attrs + end + + data + end + + def export_groups! + @export_data[:groups] = export_groups([]) + + self + end + def export_category_groups groups = [] group_names = [] @@ -53,13 +75,7 @@ module ImportExport group_names.uniq! return [] if group_names.empty? - Group.where(name: group_names).find_each do |group| - attrs = GROUP_ATTRS.inject({}) { |h, a| h[a] = group.public_send(a); h } - attrs[:user_ids] = group.users.pluck(:id) - groups << attrs - end - - groups + export_groups(group_names) end def export_category_groups! diff --git a/lib/import_export/group_exporter.rb b/lib/import_export/group_exporter.rb new file mode 100644 index 00000000000..893320cfbbb --- /dev/null +++ b/lib/import_export/group_exporter.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module ImportExport + class GroupExporter < BaseExporter + + def initialize(include_group_users = false) + @include_group_users = include_group_users + + @export_data = { + groups: [] + } + @export_data[:users] = [] if @include_group_users + end + + def perform + puts "Exporting all user groups...", "" + export_groups! + export_group_users! if @include_group_users + + self + end + + def default_filename_prefix + "groups-export" + end + + end +end diff --git a/lib/tasks/export.rake b/lib/tasks/export.rake index ab1b9138eb8..1e58a3f9a86 100644 --- a/lib/tasks/export.rake +++ b/lib/tasks/export.rake @@ -16,3 +16,11 @@ task 'export:category_structure', [:include_group_users, :file_name] => [:enviro ImportExport.export_category_structure(args[:include_group_users], args[:file_name]) puts "", "Done", "" end + +desc 'Export all user groups' +task 'export:groups', [:include_group_users, :file_name] => [:environment] do |_, args| + require "import_export" + + ImportExport.export_groups(args[:include_group_users], args[:file_name]) + puts "", "Done", "" +end diff --git a/spec/fixtures/json/import-export.json b/spec/fixtures/json/import-export.json index aaf292a1c22..f991e7f2c40 100644 --- a/spec/fixtures/json/import-export.json +++ b/spec/fixtures/json/import-export.json @@ -1,7 +1,7 @@ { "groups":[ - {"id":41,"name":"custom_group","created_at":"2017-10-26T15:33:46.328Z","mentionable_level":0,"messageable_level":0,"visibility_level":0,"automatic_membership_email_domains":"","automatic_membership_retroactive":false,"primary_group":false,"title":null,"grant_trust_level":null,"incoming_email":null,"user_ids":[1]}, - {"id":42,"name":"custom_group_import","created_at":"2017-10-26T15:33:46.328Z","mentionable_level":0,"messageable_level":0,"visibility_level":0,"automatic_membership_email_domains":"","automatic_membership_retroactive":false,"primary_group":false,"title":null,"grant_trust_level":null,"incoming_email":null,"user_ids":[2]} + {"id":41,"name":"custom_group","created_at":"2017-10-26T15:33:46.328Z","automatic_membership_email_domains":"","primary_group":false,"title":null,"grant_trust_level":null,"incoming_email":null,"bio_raw":"This is a custom group","allow_membership_requests":false,"full_name":"Custom Group","default_notification_level":3,"visibility_level":0,"public_exit":false,"public_admission":false,"membership_request_template":"","messageable_level":0,"mentionable_level":0,"members_visibility_level":0,"publish_read_state":false,"user_ids":[1]}, + {"id":42,"name":"custom_group_import","created_at":"2017-10-26T15:33:46.328Z","automatic_membership_email_domains":"","primary_group":false,"title":null,"grant_trust_level":null,"incoming_email":null,"bio_raw":"This is a custom group import","allow_membership_requests":false,"full_name":"Custom Group Import","default_notification_level":3,"visibility_level":0,"public_exit":false,"public_admission":false,"membership_request_template":"","messageable_level":0,"mentionable_level":0,"members_visibility_level":0,"publish_read_state":false,"user_ids":[2]} ], "categories":[ {"id":8,"name":"Custom Category","color":"0088CC","created_at":"2017-10-26T15:32:44.083Z","user_id":1,"slug":"custom-category","description":null,"text_color":"FFFFFF","auto_close_hours":null,"parent_category_id":3,"auto_close_based_on_last_post":false,"topic_template":"","all_topics_wiki":false,"permissions_params":{"custom_group":1,"everyone":2}}, diff --git a/spec/import_export/group_exporter_spec.rb b/spec/import_export/group_exporter_spec.rb new file mode 100644 index 00000000000..1e2deb929c6 --- /dev/null +++ b/spec/import_export/group_exporter_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require "rails_helper" +require "import_export/group_exporter" + +describe ImportExport::GroupExporter do + + before do + STDOUT.stubs(:write) + end + + it 'exports all the groups' do + group = Fabricate(:group) + user = Fabricate(:user) + group_user = Fabricate(:group_user, group: group, user: user) + data = ImportExport::GroupExporter.new.perform.export_data + + expect(data[:groups].map { |g| g[:id] }).to include(group.id) + expect(data[:users].blank?).to eq(true) + end + + it 'exports all the groups with users' do + group = Fabricate(:group) + user = Fabricate(:user) + group_user = Fabricate(:group_user, group: group, user: user) + data = ImportExport::GroupExporter.new(true).perform.export_data + + expect(data[:groups].map { |g| g[:id] }).to include(group.id) + expect(data[:users].map { |u| u[:id] }).to include(user.id) + end + +end diff --git a/spec/import_export/importer_spec.rb b/spec/import_export/importer_spec.rb index ea659e1191e..6065448996a 100644 --- a/spec/import_export/importer_spec.rb +++ b/spec/import_export/importer_spec.rb @@ -84,6 +84,20 @@ describe ImportExport::Importer do .and change { User.count }.by(2) end + it 'groups' do + data = import_data.dup + data[:categories] = nil + data[:topics] = nil + data[:users] = nil + + expect { + import(data) + }.to change { Category.count }.by(0) + .and change { Group.count }.by(2) + .and change { Topic.count }.by(0) + .and change { User.count }.by(0) + end + it 'all' do expect { import(import_data)