2014-08-09 06:28:57 -04:00
require 'csv'
require_dependency 'system_message'
module Jobs
class ExportCsvFile < Jobs :: Base
2015-01-19 08:51:53 -05:00
include ActionView :: Helpers :: NumberHelper
2014-12-06 23:15:22 -05:00
HEADER_ATTRS_FOR = { }
2014-12-29 06:58:33 -05:00
HEADER_ATTRS_FOR [ 'user_archive' ] = [ 'topic_title' , 'category' , 'sub_category' , 'is_pm' , 'post' , 'like_count' , 'reply_count' , 'url' , 'created_at' ]
2015-07-15 01:58:02 -04:00
HEADER_ATTRS_FOR [ 'user_list' ] = [ 'id' , 'name' , 'username' , 'email' , 'title' , 'created_at' , 'last_seen_at' , 'last_posted_at' , 'last_emailed_at' , 'trust_level' , 'approved' , 'suspended_at' , 'suspended_till' , 'blocked' , 'active' , 'admin' , 'moderator' , 'ip_address' ]
2014-12-06 23:15:22 -05:00
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' ]
2015-09-15 16:45:01 -04:00
HEADER_ATTRS_FOR [ 'report' ] = [ 'date' , 'value' ]
2014-11-19 12:09:23 -05:00
2014-08-09 06:28:57 -04:00
sidekiq_options retry : false
attr_accessor :current_user
def execute ( args )
2015-01-14 11:00:51 -05:00
@entity = args [ :entity ]
2015-09-15 16:45:01 -04:00
@extra = HashWithIndifferentAccess . new ( args [ :args ] ) if args [ :args ]
2015-01-14 11:00:51 -05:00
@file_name = @entity
2014-08-09 06:28:57 -04:00
@current_user = User . find_by ( id : args [ :user_id ] )
2015-01-14 11:00:51 -05:00
export_method = " #{ @entity } _export " . to_sym
2014-11-25 17:43:17 -05:00
data =
2014-12-06 23:15:22 -05:00
if respond_to? ( export_method )
send ( export_method )
2014-11-25 17:43:17 -05:00
else
2014-12-06 23:15:22 -05:00
raise Discourse :: InvalidParameters . new ( :entity )
2014-11-25 17:43:17 -05:00
end
2014-08-09 06:28:57 -04:00
if data && data . length > 0
set_file_path
2015-01-14 11:00:51 -05:00
write_csv_file ( data )
2014-08-09 06:28:57 -04:00
end
2014-12-29 06:58:33 -05:00
ensure
2014-08-09 06:28:57 -04:00
notify_user
end
2014-12-22 11:17:04 -05:00
def user_archive_export
2014-12-29 06:58:33 -05:00
user_archive_data = Post . includes ( :topic = > :category ) . where ( user_id : @current_user . id ) . select ( 'topic_id' , 'post_number' , 'raw' , 'like_count' , 'reply_count' , 'created_at' ) . order ( 'created_at' ) . with_deleted . to_a
2014-12-22 11:17:04 -05:00
user_archive_data . map do | user_archive |
get_user_archive_fields ( user_archive )
end
end
2015-01-02 01:59:05 -05:00
def user_list_export
2014-11-25 17:43:17 -05:00
query = :: AdminUserIndexQuery . new
user_data = query . find_users_query . to_a
user_data . map do | user |
group_names = get_group_names ( user ) . join ( ';' )
2015-01-02 01:59:05 -05:00
user_array = get_user_list_fields ( user )
2014-11-25 17:43:17 -05:00
user_array . push ( group_names ) if group_names != ''
user_array
end
end
2014-12-06 23:15:22 -05:00
def staff_action_export
2015-01-02 00:33:14 -05:00
if @current_user . admin?
staff_action_data = UserHistory . only_staff_actions . order ( 'id DESC' ) . to_a
else
# moderator
staff_action_data = UserHistory . where ( admin_only : false ) . only_staff_actions . order ( 'id DESC' ) . to_a
end
2014-12-06 23:15:22 -05:00
staff_action_data . map do | staff_action |
get_staff_action_fields ( staff_action )
end
end
2014-11-25 17:43:17 -05:00
2014-12-06 23:15:22 -05:00
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 |
2014-11-25 17:43:17 -05:00
get_screened_ip_fields ( screened_ip )
end
end
2014-12-06 23:15:22 -05:00
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
2015-09-15 16:45:01 -04:00
def report_export
@extra [ :start_date ] = @extra [ :start_date ] . to_date if @extra [ :start_date ] . is_a? ( String )
@extra [ :end_date ] = @extra [ :end_date ] . to_date if @extra [ :end_date ] . is_a? ( String )
@extra [ :category_id ] = @extra [ :category_id ] . to_i if @extra [ :category_id ]
r = Report . find ( @extra [ :name ] , @extra )
r . data . map do | row |
[ row [ :x ] . to_s ( :db ) , row [ :y ] . to_s ( :db ) ]
end
end
2015-01-14 11:00:51 -05:00
def get_header
2014-11-25 17:43:17 -05:00
2015-01-14 11:00:51 -05:00
case @entity
2015-01-14 05:47:22 -05:00
when 'user_list'
header_array = HEADER_ATTRS_FOR [ 'user_list' ] + HEADER_ATTRS_FOR [ 'user_stats' ]
2014-11-25 17:43:17 -05:00
if SiteSetting . enable_sso
2014-12-06 23:15:22 -05:00
header_array . concat ( HEADER_ATTRS_FOR [ 'user_sso' ] )
2014-11-25 17:43:17 -05:00
end
user_custom_fields = UserField . all
if user_custom_fields . present?
user_custom_fields . each do | custom_field |
header_array . push ( " #{ custom_field . name } (custom user field) " )
end
end
header_array . push ( " group_names " )
2014-12-06 23:15:22 -05:00
else
2015-01-14 11:00:51 -05:00
header_array = HEADER_ATTRS_FOR [ @entity ]
2014-12-06 23:15:22 -05:00
end
2014-11-25 17:43:17 -05:00
header_array
end
2014-08-09 06:28:57 -04:00
private
2014-09-06 11:41:05 -04:00
def get_group_names ( user )
2014-11-21 10:25:04 -05:00
group_names = [ ]
2014-10-23 15:06:45 -04:00
groups = user . groups
2014-09-06 11:41:05 -04:00
groups . each do | group |
group_names . push ( group . name )
end
return group_names
end
2014-12-22 11:17:04 -05:00
def get_user_archive_fields ( user_archive )
user_archive_array = [ ]
2014-12-29 06:58:33 -05:00
topic_data = user_archive . topic
user_archive = user_archive . as_json
2015-05-17 23:37:12 -04:00
topic_data = Topic . with_deleted . find_by ( id : user_archive [ 'topic_id' ] ) if topic_data . nil?
return user_archive_array if topic_data . nil?
category = topic_data . category
2014-12-29 06:58:33 -05:00
sub_category = " - "
if category
category_name = category . name
if ! category . parent_category_id . nil?
# sub category
category_name = Category . find_by ( id : category . parent_category_id ) . name
sub_category = category . name
end
else
# PM
category_name = " - "
end
is_pm = topic_data . archetype == " private_message " ? I18n . t ( " csv_export.boolean_yes " ) : I18n . t ( " csv_export.boolean_no " )
2015-07-06 18:19:31 -04:00
url = " #{ Discourse . base_uri } /t/ #{ topic_data . slug } / #{ topic_data . id } / #{ user_archive [ 'post_number' ] } "
2014-12-29 06:58:33 -05:00
topic_hash = { " post " = > user_archive [ 'raw' ] , " topic_title " = > topic_data . title , " category " = > category_name , " sub_category " = > sub_category , " is_pm " = > is_pm , " url " = > url }
user_archive . merge! ( topic_hash )
2014-12-22 11:17:04 -05:00
HEADER_ATTRS_FOR [ 'user_archive' ] . each do | attr |
2014-12-29 06:58:33 -05:00
user_archive_array . push ( user_archive [ attr ] )
2014-12-22 11:17:04 -05:00
end
user_archive_array
end
2015-01-02 01:59:05 -05:00
def get_user_list_fields ( user )
2014-11-21 10:25:04 -05:00
user_array = [ ]
2014-11-03 10:04:51 -05:00
2015-01-14 05:47:22 -05:00
HEADER_ATTRS_FOR [ 'user_list' ] . each do | attr |
2014-11-08 09:07:21 -05:00
user_array . push ( user . attributes [ attr ] )
2014-11-03 10:04:51 -05:00
end
2014-12-06 23:15:22 -05:00
HEADER_ATTRS_FOR [ 'user_stats' ] . each do | stat |
2014-11-08 09:07:21 -05:00
user_array . push ( user . user_stat . attributes [ stat ] )
2014-11-03 10:04:51 -05:00
end
2014-11-25 17:43:17 -05:00
if SiteSetting . enable_sso
sso = user . single_sign_on_record
2014-12-06 23:15:22 -05:00
HEADER_ATTRS_FOR [ 'user_sso' ] . each do | stat |
2014-11-25 17:43:17 -05:00
field = sso . attributes [ stat ] if sso
user_array . push ( field )
end
end
2014-11-12 03:42:50 -05:00
if user . user_fields . present?
user . user_fields . each do | custom_field |
user_array . push ( custom_field [ 1 ] )
end
end
2014-11-25 17:43:17 -05:00
user_array
2014-11-03 10:04:51 -05:00
end
2014-12-06 23:15:22 -05:00
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
2014-11-21 10:25:04 -05:00
def get_screened_ip_fields ( screened_ip )
screened_ip_array = [ ]
2014-11-12 03:42:50 -05:00
2014-12-06 23:15:22 -05:00
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 )
2014-11-21 10:25:04 -05:00
end
2014-11-25 17:43:17 -05:00
screened_ip_array
2014-12-06 23:15:22 -05:00
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
2014-11-21 10:25:04 -05:00
end
2014-11-12 03:42:50 -05:00
2014-08-09 06:28:57 -04:00
def set_file_path
2015-01-15 12:30:59 -05:00
if @entity == " user_archive "
file_name_prefix = " #{ @file_name . split ( '_' ) . join ( '-' ) } - #{ current_user . username } - #{ Time . now . strftime ( " %y%m%d-%H%M%S " ) } "
else
file_name_prefix = " #{ @file_name . split ( '_' ) . join ( '-' ) } - #{ Time . now . strftime ( " %y%m%d-%H%M%S " ) } "
end
@file = UserExport . create ( file_name : file_name_prefix , user_id : @current_user . id )
2015-01-02 01:59:05 -05:00
@file_name = " #{ file_name_prefix } - #{ @file . id } .csv "
2014-12-28 11:13:49 -05:00
2014-08-09 06:28:57 -04:00
# ensure directory exists
2014-12-28 11:13:49 -05:00
dir = File . dirname ( " #{ UserExport . base_directory } / #{ @file_name } " )
2014-08-09 06:28:57 -04:00
FileUtils . mkdir_p ( dir ) unless Dir . exists? ( dir )
end
2015-01-14 11:00:51 -05:00
def write_csv_file ( data )
2014-08-09 06:28:57 -04:00
# write to CSV file
2014-12-28 11:13:49 -05:00
CSV . open ( File . expand_path ( " #{ UserExport . base_directory } / #{ @file_name } " , __FILE__ ) , " w " ) do | csv |
2015-01-14 11:00:51 -05:00
csv << get_header
2014-08-09 06:28:57 -04:00
data . each do | value |
2014-08-15 13:53:17 -04:00
csv << value
2014-08-09 06:28:57 -04:00
end
end
2015-01-13 13:22:21 -05:00
# compress CSV file
2015-01-14 22:37:53 -05:00
` gzip -5 #{ File . expand_path ( " #{ UserExport . base_directory } / #{ @file_name } " , __FILE__ ) } `
2014-08-09 06:28:57 -04:00
end
def notify_user
if @current_user
2015-01-13 13:22:21 -05:00
if @file_name != " " && File . exists? ( " #{ UserExport . base_directory } / #{ @file_name } .gz " )
2015-07-06 18:19:31 -04:00
SystemMessage . create_from_system_user ( @current_user , :csv_export_succeeded , download_link : " #{ Discourse . base_uri } /export_csv/ #{ @file_name } .gz " , file_name : " #{ @file_name } .gz " , file_size : number_to_human_size ( File . size ( " #{ UserExport . base_directory } / #{ @file_name } .gz " ) ) )
2014-08-09 06:28:57 -04:00
else
SystemMessage . create_from_system_user ( @current_user , :csv_export_failed )
end
end
end
end
end