diff --git a/app/assets/javascripts/admin/controllers/admin-logs-screened-emails.js.es6 b/app/assets/javascripts/admin/controllers/admin-logs-screened-emails.js.es6
index 2b4bd0e29cd..745a172d2ec 100644
--- a/app/assets/javascripts/admin/controllers/admin-logs-screened-emails.js.es6
+++ b/app/assets/javascripts/admin/controllers/admin-logs-screened-emails.js.es6
@@ -1,3 +1,5 @@
+import { outputExportResult } from 'admin/lib/export-result';
+
export default Ember.ArrayController.extend(Discourse.Presence, {
loading: false,
@@ -7,12 +9,16 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
// feeling lazy
window.location.reload();
});
+ },
+
+ exportScreenedEmailList: function(subject) {
+ Discourse.ExportCsv.exportScreenedEmailList().then(outputExportResult);
}
},
show: function() {
var self = this;
- this.set('loading', true);
+ self.set('loading', true);
Discourse.ScreenedEmail.findAll().then(function(result) {
self.set('model', result);
self.set('loading', false);
diff --git a/app/assets/javascripts/admin/controllers/admin-logs-screened-ip-addresses.js.es6 b/app/assets/javascripts/admin/controllers/admin-logs-screened-ip-addresses.js.es6
index 414461edacb..b06c74d04ea 100644
--- a/app/assets/javascripts/admin/controllers/admin-logs-screened-ip-addresses.js.es6
+++ b/app/assets/javascripts/admin/controllers/admin-logs-screened-ip-addresses.js.es6
@@ -1,10 +1,12 @@
+import { outputExportResult } from 'admin/lib/export-result';
+
export default Ember.ArrayController.extend(Discourse.Presence, {
loading: false,
itemController: 'admin-log-screened-ip-address',
show: function() {
var self = this;
- this.set('loading', true);
+ self.set('loading', true);
Discourse.ScreenedIpAddress.findAll().then(function(result) {
self.set('model', result);
self.set('loading', false);
@@ -34,6 +36,10 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
});
}
});
+ },
+
+ exportScreenedIpList: function(subject) {
+ Discourse.ExportCsv.exportScreenedIpList().then(outputExportResult);
}
}
});
diff --git a/app/assets/javascripts/admin/controllers/admin-logs-screened-urls.js.es6 b/app/assets/javascripts/admin/controllers/admin-logs-screened-urls.js.es6
index 92cb40e4962..49637494c82 100644
--- a/app/assets/javascripts/admin/controllers/admin-logs-screened-urls.js.es6
+++ b/app/assets/javascripts/admin/controllers/admin-logs-screened-urls.js.es6
@@ -1,12 +1,20 @@
+import { outputExportResult } from 'admin/lib/export-result';
+
export default Ember.ArrayController.extend(Discourse.Presence, {
loading: false,
show: function() {
var self = this;
- this.set('loading', true);
+ self.set('loading', true);
Discourse.ScreenedUrl.findAll().then(function(result) {
self.set('model', result);
self.set('loading', false);
});
+ },
+
+ actions: {
+ exportScreenedUrlList: function(subject) {
+ Discourse.ExportCsv.exportScreenedUrlList().then(outputExportResult);
+ }
}
});
diff --git a/app/assets/javascripts/admin/controllers/admin-logs-staff-action-logs.js.es6 b/app/assets/javascripts/admin/controllers/admin-logs-staff-action-logs.js.es6
index 76df4a3b60d..9d043749316 100644
--- a/app/assets/javascripts/admin/controllers/admin-logs-staff-action-logs.js.es6
+++ b/app/assets/javascripts/admin/controllers/admin-logs-staff-action-logs.js.es6
@@ -6,6 +6,8 @@
@namespace Discourse
@module Discourse
**/
+import { outputExportResult } from 'admin/lib/export-result';
+
export default Ember.ArrayController.extend(Discourse.Presence, {
loading: false,
filters: {},
@@ -60,6 +62,10 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
filterBySubject: function(subject) {
this.set('filters.subject', subject);
+ },
+
+ exportStaffActionLogs: function(subject) {
+ Discourse.ExportCsv.exportStaffActionLogs().then(outputExportResult);
}
}
});
diff --git a/app/assets/javascripts/admin/lib/export-result.js.es6 b/app/assets/javascripts/admin/lib/export-result.js.es6
new file mode 100644
index 00000000000..da1058d5640
--- /dev/null
+++ b/app/assets/javascripts/admin/lib/export-result.js.es6
@@ -0,0 +1,7 @@
+export function outputExportResult(result) {
+ if (result.success) {
+ bootbox.alert(I18n.t("admin.export_csv.success"));
+ } else {
+ bootbox.alert(I18n.t("admin.export_csv.failed"));
+ }
+}
diff --git a/app/assets/javascripts/admin/models/export_csv.js b/app/assets/javascripts/admin/models/export_csv.js
index b747cd449be..082ddeb0014 100644
--- a/app/assets/javascripts/admin/models/export_csv.js
+++ b/app/assets/javascripts/admin/models/export_csv.js
@@ -15,15 +15,42 @@ Discourse.ExportCsv.reopenClass({
@method export_user_list
**/
exportUserList: function() {
- return Discourse.ajax("/admin/export_csv/users.json");
+ return Discourse.ajax("/admin/export_csv/export_entity.json", {data: {entity: 'user'}});
},
/**
- Exports screened IPs list
+ Exports staff action logs
- @method export_screened_ips_list
+ @method export_staff_action_logs
**/
- exportScreenedIpsList: function() {
- return Discourse.ajax("/admin/export_csv/screened_ips.json");
+ exportStaffActionLogs: function() {
+ return Discourse.ajax("/admin/export_csv/export_entity.json", {data: {entity: 'staff_action'}});
+ },
+
+ /**
+ Exports screened email list
+
+ @method export_screened_email_list
+ **/
+ exportScreenedEmailList: function() {
+ return Discourse.ajax("/admin/export_csv/export_entity.json", {data: {entity: 'screened_email'}});
+ },
+
+ /**
+ Exports screened IP list
+
+ @method export_screened_ip_list
+ **/
+ exportScreenedIpList: function() {
+ return Discourse.ajax("/admin/export_csv/export_entity.json", {data: {entity: 'screened_ip'}});
+ },
+
+ /**
+ Exports screened URL list
+
+ @method export_screened_url_list
+ **/
+ exportScreenedUrlList: function() {
+ return Discourse.ajax("/admin/export_csv/export_entity.json", {data: {entity: 'screened_url'}});
}
});
diff --git a/app/assets/javascripts/admin/routes/admin-logs.js.es6 b/app/assets/javascripts/admin/routes/admin-logs.js.es6
deleted file mode 100644
index a16a9f1a6bf..00000000000
--- a/app/assets/javascripts/admin/routes/admin-logs.js.es6
+++ /dev/null
@@ -1,15 +0,0 @@
-export default Discourse.Route.extend({
-
- actions: {
- exportScreenedIps: function() {
- Discourse.ExportCsv.exportScreenedIpsList().then(function(result) {
- if (result.success) {
- bootbox.alert(I18n.t("admin.export_csv.success"));
- } else {
- bootbox.alert(I18n.t("admin.export_csv.failed"));
- }
- });
- }
- }
-
-});
diff --git a/app/assets/javascripts/admin/templates/logs.hbs b/app/assets/javascripts/admin/templates/logs.hbs
index 0e4f8b4a61a..c85bb02d7cb 100644
--- a/app/assets/javascripts/admin/templates/logs.hbs
+++ b/app/assets/javascripts/admin/templates/logs.hbs
@@ -8,9 +8,6 @@
{{i18n 'admin.logs.logster.title'}}
-
-
-
diff --git a/app/assets/javascripts/admin/templates/logs/screened_emails.hbs b/app/assets/javascripts/admin/templates/logs/screened_emails.hbs
index 3a426459a49..f231c391943 100644
--- a/app/assets/javascripts/admin/templates/logs/screened_emails.hbs
+++ b/app/assets/javascripts/admin/templates/logs/screened_emails.hbs
@@ -1,4 +1,8 @@
-
{{i18n 'admin.logs.screened_emails.description'}}
+
+ {{i18n 'admin.logs.screened_emails.description'}}
+
+
+
{{#loading-spinner condition=loading}}
{{#if model.length}}
diff --git a/app/assets/javascripts/admin/templates/logs/screened_ip_addresses.hbs b/app/assets/javascripts/admin/templates/logs/screened_ip_addresses.hbs
index f26fc2b0c8b..c1b27eb88fb 100644
--- a/app/assets/javascripts/admin/templates/logs/screened_ip_addresses.hbs
+++ b/app/assets/javascripts/admin/templates/logs/screened_ip_addresses.hbs
@@ -1,5 +1,8 @@
{{i18n 'admin.logs.screened_ips.description'}}
-
+
+
+
+
{{screened-ip-address-form action="recordAdded"}}
diff --git a/app/assets/javascripts/admin/templates/logs/screened_urls.hbs b/app/assets/javascripts/admin/templates/logs/screened_urls.hbs
index ded1bba2472..701909ff564 100644
--- a/app/assets/javascripts/admin/templates/logs/screened_urls.hbs
+++ b/app/assets/javascripts/admin/templates/logs/screened_urls.hbs
@@ -1,4 +1,8 @@
-
{{i18n 'admin.logs.screened_urls.description'}}
+
+ {{i18n 'admin.logs.screened_urls.description'}}
+
+
+
{{#loading-spinner condition=loading}}
{{#if model.length}}
diff --git a/app/assets/javascripts/admin/templates/logs/staff_action_logs.hbs b/app/assets/javascripts/admin/templates/logs/staff_action_logs.hbs
index 66fa817fd01..10ae1750533 100644
--- a/app/assets/javascripts/admin/templates/logs/staff_action_logs.hbs
+++ b/app/assets/javascripts/admin/templates/logs/staff_action_logs.hbs
@@ -28,6 +28,11 @@
{{/if}}
+
+
+
+
+
{{i18n 'admin.logs.staff_actions.instructions'}}
diff --git a/app/assets/javascripts/admin/templates/users_list.hbs b/app/assets/javascripts/admin/templates/users_list.hbs
index 9f857dec436..14032b4e203 100644
--- a/app/assets/javascripts/admin/templates/users_list.hbs
+++ b/app/assets/javascripts/admin/templates/users_list.hbs
@@ -13,7 +13,7 @@
-
+
diff --git a/app/assets/javascripts/main_include_admin.js b/app/assets/javascripts/main_include_admin.js
index 2cd37f1596c..00050ed3d9c 100644
--- a/app/assets/javascripts/main_include_admin.js
+++ b/app/assets/javascripts/main_include_admin.js
@@ -1,4 +1,5 @@
//= require list-view
+//= require admin/lib/export-result
//= require admin/models/user-field
//= require admin/controllers/admin-email-skipped
//= require admin/controllers/change-site-customization-details
diff --git a/app/controllers/admin/export_csv_controller.rb b/app/controllers/admin/export_csv_controller.rb
index 2a5d53a00f6..0ab4aefe068 100644
--- a/app/controllers/admin/export_csv_controller.rb
+++ b/app/controllers/admin/export_csv_controller.rb
@@ -2,15 +2,10 @@ class Admin::ExportCsvController < Admin::AdminController
skip_before_filter :check_xhr, only: [:show]
- def export_user_list
+ def export_entity
+ params.require(:entity)
# export csv file in a background thread
- Jobs.enqueue(:export_csv_file, entity: 'user', user_id: current_user.id)
- render json: success_json
- end
-
- def export_screened_ips_list
- # export csv file in a background thread
- Jobs.enqueue(:export_csv_file, entity: 'screened_ips', user_id: current_user.id)
+ Jobs.enqueue(:export_csv_file, entity: params[:entity], user_id: current_user.id)
render json: success_json
end
diff --git a/app/jobs/regular/export_csv_file.rb b/app/jobs/regular/export_csv_file.rb
index 926aee562d7..f8c2a2f79f9 100644
--- a/app/jobs/regular/export_csv_file.rb
+++ b/app/jobs/regular/export_csv_file.rb
@@ -4,10 +4,14 @@ require_dependency 'system_message'
module Jobs
class ExportCsvFile < Jobs::Base
- CSV_USER_ATTRS = ['id','name','username','email','title','created_at','trust_level','active','admin','moderator','ip_address']
- CSV_USER_STATS = ['topics_entered','posts_read_count','time_read','topic_count','post_count','likes_given','likes_received']
- CSV_USER_SSO_ATTRS = ['external_id','external_email', 'external_username', 'external_name', 'external_avatar_url']
- SCREENED_IP_ATTRS = ['ip_address','action_type','match_count','last_match_at','created_at']
+ HEADER_ATTRS_FOR = {}
+ HEADER_ATTRS_FOR['user'] = ['id','name','username','email','title','created_at','trust_level','active','admin','moderator','ip_address']
+ HEADER_ATTRS_FOR['user_stats'] = ['topics_entered','posts_read_count','time_read','topic_count','post_count','likes_given','likes_received']
+ HEADER_ATTRS_FOR['user_sso'] = ['external_id','external_email', 'external_username', 'external_name', 'external_avatar_url']
+ HEADER_ATTRS_FOR['staff_action'] = ['staff_user','action','subject','created_at','details', 'context']
+ HEADER_ATTRS_FOR['screened_email'] = ['email','action','match_count','last_match_at','created_at','ip_address']
+ HEADER_ATTRS_FOR['screened_ip'] = ['ip_address','action','match_count','last_match_at','created_at']
+ HEADER_ATTRS_FOR['screened_url'] = ['domain','action','match_count','last_match_at','created_at']
sidekiq_options retry: false
attr_accessor :current_user
@@ -20,14 +24,12 @@ module Jobs
entity = args[:entity]
@current_user = User.find_by(id: args[:user_id])
-
+ export_method = "#{entity}_export".to_sym
data =
- if entity == 'user'
- user_export
- elsif entity == 'screened_ips'
- screened_ips_export
+ if respond_to?(export_method)
+ send(export_method)
else
- raise Discourse::InvalidParameters.new(:entity) if entity.blank?
+ raise Discourse::InvalidParameters.new(:entity)
end
if data && data.length > 0
@@ -50,21 +52,41 @@ module Jobs
end
end
+ def staff_action_export
+ staff_action_data = UserHistory.order('id DESC').to_a
+ staff_action_data.map do |staff_action|
+ get_staff_action_fields(staff_action)
+ end
+ end
- def screened_ips_export
- screened_ips_data = ScreenedIpAddress.order('id desc').to_a
- screened_ips_data.map do |screened_ip|
+ def screened_email_export
+ screened_email_data = ScreenedEmail.order('last_match_at desc').to_a
+ screened_email_data.map do |screened_email|
+ get_screened_email_fields(screened_email)
+ end
+ end
+
+ def screened_ip_export
+ screened_ip_data = ScreenedIpAddress.order('id desc').to_a
+ screened_ip_data.map do |screened_ip|
get_screened_ip_fields(screened_ip)
end
end
+ def screened_url_export
+ screened_url_data = ScreenedUrl.select("domain, sum(match_count) as match_count, max(last_match_at) as last_match_at, min(created_at) as created_at").group(:domain).order('last_match_at DESC').to_a
+ screened_url_data.map do |screened_url|
+ get_screened_url_fields(screened_url)
+ end
+ end
+
def get_header(entity)
case entity
when 'user'
- header_array = CSV_USER_ATTRS + CSV_USER_STATS
+ header_array = HEADER_ATTRS_FOR['user'] + HEADER_ATTRS_FOR['user_stats']
if SiteSetting.enable_sso
- header_array.concat(CSV_USER_SSO_ATTRS)
+ header_array.concat(HEADER_ATTRS_FOR['user_sso'])
end
user_custom_fields = UserField.all
if user_custom_fields.present?
@@ -73,9 +95,9 @@ module Jobs
end
end
header_array.push("group_names")
- when 'screened_ips'
- header_array = SCREENED_IP_ATTRS
- end
+ else
+ header_array = HEADER_ATTRS_FOR[entity]
+ end
header_array
end
@@ -94,17 +116,17 @@ module Jobs
def get_user_fields(user)
user_array = []
- CSV_USER_ATTRS.each do |attr|
+ HEADER_ATTRS_FOR['user'].each do |attr|
user_array.push(user.attributes[attr])
end
- CSV_USER_STATS.each do |stat|
+ HEADER_ATTRS_FOR['user_stats'].each do |stat|
user_array.push(user.user_stat.attributes[stat])
end
if SiteSetting.enable_sso
sso = user.single_sign_on_record
- CSV_USER_SSO_ATTRS.each do |stat|
+ HEADER_ATTRS_FOR['user_sso'].each do |stat|
field = sso.attributes[stat] if sso
user_array.push(field)
end
@@ -119,16 +141,78 @@ module Jobs
user_array
end
+ def get_staff_action_fields(staff_action)
+ staff_action_array = []
+
+ HEADER_ATTRS_FOR['staff_action'].each do |attr|
+ data =
+ if attr == 'action'
+ UserHistory.actions.key(staff_action.attributes[attr]).to_s
+ elsif attr == 'staff_user'
+ user = User.find_by(id: staff_action.attributes['acting_user_id'])
+ user.username if !user.nil?
+ else
+ staff_action.attributes[attr]
+ end
+
+ staff_action_array.push(data)
+ end
+
+ staff_action_array
+ end
+
+ def get_screened_email_fields(screened_email)
+ screened_email_array = []
+
+ HEADER_ATTRS_FOR['screened_email'].each do |attr|
+ data =
+ if attr == 'action'
+ ScreenedEmail.actions.key(screened_email.attributes['action_type']).to_s
+ else
+ screened_email.attributes[attr]
+ end
+
+ screened_email_array.push(data)
+ end
+
+ screened_email_array
+ end
+
def get_screened_ip_fields(screened_ip)
screened_ip_array = []
- SCREENED_IP_ATTRS.each do |attr|
- screened_ip_array.push(screened_ip.attributes[attr])
+ HEADER_ATTRS_FOR['screened_ip'].each do |attr|
+ data =
+ if attr == 'action'
+ ScreenedIpAddress.actions.key(screened_ip.attributes['action_type']).to_s
+ else
+ screened_ip.attributes[attr]
+ end
+
+ screened_ip_array.push(data)
end
screened_ip_array
end
+ def get_screened_url_fields(screened_url)
+ screened_url_array = []
+
+ HEADER_ATTRS_FOR['screened_url'].each do |attr|
+ data =
+ if attr == 'action'
+ action = ScreenedUrl.actions.key(screened_url.attributes['action_type']).to_s
+ action = "do nothing" if action.blank?
+ else
+ screened_url.attributes[attr]
+ end
+
+ screened_url_array.push(data)
+ end
+
+ screened_url_array
+ end
+
def set_file_path
@file_name = "export_#{SecureRandom.hex(4)}.csv"
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index b0f2ecf3a7c..c3290d52f61 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -1688,13 +1688,15 @@ en:
confirm: "Are your sure you want to rollback the database to the previous working state?"
export_csv:
- users:
- title: "Export full user list in CSV format."
- screened_ips:
- title: "Export full screened IPs list in CSV format."
success: "Export initiated, you will be notified shortly with progress."
failed: "Export failed. Please check the logs."
button_text: "Export"
+ button_title:
+ user: "Export full user list in CSV format."
+ staff_action: "Export full staff action log in CSV format."
+ screened_email: "Export full screened email list in CSV format."
+ screened_ip: "Export full screened IP list in CSV format."
+ screened_url: "Export full screened URL list in CSV format."
customize:
title: "Customize"
diff --git a/config/routes.rb b/config/routes.rb
index 4c716ed7222..7846e50830a 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -164,8 +164,7 @@ Discourse::Application.routes.draw do
resources :export_csv, constraints: AdminConstraint.new do
collection do
- get "users" => "export_csv#export_user_list"
- get "screened_ips" => "export_csv#export_screened_ips_list"
+ get "export_entity" => "export_csv#export_entity"
end
member do
get "" => "export_csv#show", constraints: { id: /[^\/]+/ }