+<%= f.submit class: "btn btn-primary" %>
\ No newline at end of file
diff --git a/app/views/admin/moderator_actions/index.html.erb b/app/views/admin/moderator_actions/index.html.erb
index 8fb35db2e..f7f101cfc 100644
--- a/app/views/admin/moderator_actions/index.html.erb
+++ b/app/views/admin/moderator_actions/index.html.erb
@@ -8,7 +8,7 @@
<%= paginate @moderator_actions %>
-
+
ID
diff --git a/app/views/admin/users/_data_export.html.erb b/app/views/admin/users/_data_export.html.erb
new file mode 100644
index 000000000..d0153d9fe
--- /dev/null
+++ b/app/views/admin/users/_data_export.html.erb
@@ -0,0 +1,21 @@
+
+
+
Data Export
+
+
+
+
+ You can export a user's data here. Currently we only support exporting a user's posts and comments.
+
+
+ You have the option of exporting to your admin account to send to the user, or exporting to the user directly.
+
+
+ Exporting the data to your admin account will send it to your default admin email (<%= SiteConfig.email_addresses[:default] %>), and exporting to the user will send it to their email (<%= @user.email %>).
+
+
+ <%= button_to "Export to Admin", export_data_admin_user_path(@user.id), data: { confirm: "Are you sure you want to export this user's content to the ADMIN?" }, class: "crayons-btn", params: { send_to_admin: true }, style: "margin-right: 8px;" %>
+ <%= button_to "Export to User", export_data_admin_user_path(@user.id), data: { confirm: "Are you sure you want to export this user's content to the USER?" }, class: "crayons-btn", params: { send_to_admin: false } %>
+
Removing a social account identity can solve certain sign in issues, for example:
@@ -92,7 +93,7 @@
Destructive Actions
-
+
diff --git a/app/workers/export_content_worker.rb b/app/workers/export_content_worker.rb
index 95293d60a..5cf385f5f 100644
--- a/app/workers/export_content_worker.rb
+++ b/app/workers/export_content_worker.rb
@@ -3,9 +3,9 @@ class ExportContentWorker
sidekiq_options queue: :medium_priority, retry: 10, lock: :until_executed
- def perform(user_id)
+ def perform(user_id, email)
user = User.find_by(id: user_id)
- Exporter::Service.new(user).export(send_email: true) if user
+ Exporter::Service.new(user).export(email) if user
end
end
diff --git a/config/routes.rb b/config/routes.rb
index c0e63ca1e..b76cdb175 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -103,6 +103,7 @@ Rails.application.routes.draw do
resources :users, only: %i[index show edit update] do
member do
post "banish"
+ post "export_data"
post "full_delete"
patch "user_status"
post "merge"
diff --git a/spec/mailers/notify_mailer_spec.rb b/spec/mailers/notify_mailer_spec.rb
index b90bbbd64..f0da96db0 100644
--- a/spec/mailers/notify_mailer_spec.rb
+++ b/spec/mailers/notify_mailer_spec.rb
@@ -403,7 +403,7 @@ RSpec.describe NotifyMailer, type: :mailer do
end
describe "#export_email" do
- let(:email) { described_class.with(user: user, attachment: "attachment").export_email }
+ let(:email) { described_class.with(email: user.email, attachment: "attachment").export_email }
it "renders proper subject" do
expect(email.subject).to include("export of your content is ready")
@@ -431,12 +431,6 @@ RSpec.describe NotifyMailer, type: :mailer do
it "includes the tracking pixel" do
expect(email.html_part.body).to include("open.gif")
end
-
- it "includes UTM params" do
- expect(email.html_part.body).to include(CGI.escape("utm_medium=email"))
- expect(email.html_part.body).to include(CGI.escape("utm_source=notify_mailer"))
- expect(email.html_part.body).to include(CGI.escape("utm_campaign=export_email"))
- end
end
describe "#tag_moderator_confirmation_email" do
diff --git a/spec/refinements/string_to_boolean_spec.rb b/spec/refinements/string_to_boolean_spec.rb
new file mode 100644
index 000000000..4d6fae4ca
--- /dev/null
+++ b/spec/refinements/string_to_boolean_spec.rb
@@ -0,0 +1,10 @@
+require "rails_helper"
+
+RSpec.describe StringToBoolean, type: :refinement do
+ describe "#to_boolean" do
+ using described_class
+ it "converts a string to a boolean" do
+ expect("true".to_boolean).to be true
+ end
+ end
+end
diff --git a/spec/requests/admin/users_spec.rb b/spec/requests/admin/users_spec.rb
index 77a3ade19..b79823b67 100644
--- a/spec/requests/admin/users_spec.rb
+++ b/spec/requests/admin/users_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe "admin/users", type: :request do
sign_in(admin)
end
- describe "GETS /admin/users" do
+ describe "GET /admin/users" do
it "renders to appropriate page" do
get "/admin/users"
expect(response.body).to include(user.username)
@@ -149,4 +149,12 @@ RSpec.describe "admin/users", type: :request do
end.to change { user.reload.access_locked? }.from(true).to(false)
end
end
+
+ describe "POST admin/users/:id/export_data" do
+ it "redirects properly to the user edit page" do
+ sign_in admin
+ post export_data_admin_user_path(user), params: { send_to_admin: "true" }
+ expect(response).to redirect_to edit_admin_user_path(user)
+ end
+ end
end
diff --git a/spec/services/exporter/service_spec.rb b/spec/services/exporter/service_spec.rb
index 6e2581fa2..488cdb232 100644
--- a/spec/services/exporter/service_spec.rb
+++ b/spec/services/exporter/service_spec.rb
@@ -47,14 +47,14 @@ RSpec.describe Exporter::Service, type: :service do
describe "#export" do
it "exports a zip file with files" do
service = valid_instance(article.user)
- zipped_exports = service.export
+ zipped_exports = service.export(article.user.email)
exports = extract_zipped_exports(zipped_exports)
expect(exports.keys).to eq(["articles.json", "comments.json"])
end
it "passes configuration to an exporter" do
service = valid_instance(article.user)
- zipped_exports = service.export(config: { articles: { slug: article.slug } })
+ zipped_exports = service.export(article.user.email, config: { articles: { slug: article.slug } })
exports = extract_zipped_exports(zipped_exports)
expect(exports.length).to eq(described_class::EXPORTERS.size)
end
@@ -64,20 +64,26 @@ RSpec.describe Exporter::Service, type: :service do
config = double
allow(config).to receive(:fetch).with(:articles, {}).and_return(slug: article.slug)
allow(config).to receive(:fetch).with(:comments, {}).and_return({})
- service.export(config: config)
+ service.export(article.user.email, config: config)
expect(config).to have_received(:fetch).with(:articles, {})
end
context "when emailing the user" do
it "delivers one email" do
service = valid_instance(article.user)
- service.export(send_email: true)
+ service.export(article.user.email)
expect(ActionMailer::Base.deliveries.count).to eq(1)
end
+ it "delivers one email to the user's email" do
+ service = valid_instance(article.user)
+ service.export(article.user.email)
+ expect(ActionMailer::Base.deliveries.last.to.first).to eq article.user.email
+ end
+
it "delivers an email with the export" do
service = valid_instance(article.user)
- zipped_export = service.export(send_email: true)
+ zipped_export = service.export(article.user.email)
attachment = ActionMailer::Base.deliveries.last.attachments[0].decoded
exports = extract_zipped_exports(zipped_export)
@@ -85,16 +91,26 @@ RSpec.describe Exporter::Service, type: :service do
end
end
+ context "when emailing an admin" do
+ it "delivers one email to the default admin email" do
+ admin_email = "admin@example.com"
+ allow(SiteConfig).to receive(:email_addresses).and_return({ default: admin_email })
+ service = valid_instance(article.user)
+ service.export(admin_email)
+ expect(ActionMailer::Base.deliveries.last.to.first).to eq admin_email
+ end
+ end
+
it "sets the requested flag as false" do
service = valid_instance(article.user)
- service.export
+ service.export(article.user.email)
expect(user.export_requested).to be(false)
end
it "sets the exported at datetime as the current one" do
Timecop.freeze(Time.current) do
service = valid_instance(article.user)
- service.export
+ service.export(article.user.email)
expect(user.exported_at).to eq(Time.current)
end
end
diff --git a/spec/workers/export_content_worker_spec.rb b/spec/workers/export_content_worker_spec.rb
index 7d6d20e2a..0f49d1c01 100644
--- a/spec/workers/export_content_worker_spec.rb
+++ b/spec/workers/export_content_worker_spec.rb
@@ -15,12 +15,12 @@ RSpec.describe ExportContentWorker, type: :worker do
end
it "calls the service" do
- worker.perform(user.id)
+ worker.perform(user.id, user.email)
expect(exporter_service).to have_received(:export).once
end
it "doesn't call the service if non existent user ID is given" do
- worker.perform(9999)
+ worker.perform(9999, user.email)
expect(exporter_service).not_to have_received(:export)
end
end