From 78537aad39d68cb846a2dee1375579f5a1147db8 Mon Sep 17 00:00:00 2001 From: Arpit Jalan Date: Tue, 30 Dec 2014 18:07:05 +0530 Subject: [PATCH] FIX: rate limit user posts export --- .../javascripts/discourse/controllers/user.js.es6 | 3 +-- .../javascripts/discourse/models/export_csv.js | 8 +++++++- app/controllers/export_csv_controller.rb | 4 +--- config/locales/client.en.yml | 1 + lib/guardian.rb | 6 ++++-- spec/controllers/export_csv_controller_spec.rb | 14 ++++++++++++++ 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/discourse/controllers/user.js.es6 b/app/assets/javascripts/discourse/controllers/user.js.es6 index bf2b7d21b..247ebfffd 100644 --- a/app/assets/javascripts/discourse/controllers/user.js.es6 +++ b/app/assets/javascripts/discourse/controllers/user.js.es6 @@ -1,6 +1,5 @@ import ObjectController from 'discourse/controllers/object'; import CanCheckEmails from 'discourse/mixins/can-check-emails'; -import { outputExportResult } from 'discourse/lib/export-result'; export default ObjectController.extend(CanCheckEmails, { indexStream: false, @@ -55,7 +54,7 @@ export default ObjectController.extend(CanCheckEmails, { }, exportUserArchive: function() { - Discourse.ExportCsv.exportUserArchive().then(outputExportResult); + Discourse.ExportCsv.exportUserArchive(); } } }); diff --git a/app/assets/javascripts/discourse/models/export_csv.js b/app/assets/javascripts/discourse/models/export_csv.js index a2f559968..be678c392 100644 --- a/app/assets/javascripts/discourse/models/export_csv.js +++ b/app/assets/javascripts/discourse/models/export_csv.js @@ -15,7 +15,13 @@ Discourse.ExportCsv.reopenClass({ @method export_user_archive **/ exportUserArchive: function() { - return Discourse.ajax("/export_csv/export_entity.json", {data: {entity_type: 'user', entity: 'user_archive'}}); + return Discourse.ajax("/export_csv/export_entity.json", { + data: {entity_type: 'user', entity: 'user_archive'} + }).then(function() { + bootbox.alert(I18n.t("admin.export_csv.success")); + }).catch(function() { + bootbox.alert(I18n.t("admin.export_csv.rate_limit_error")); + }); }, /** diff --git a/app/controllers/export_csv_controller.rb b/app/controllers/export_csv_controller.rb index 0db074d1f..c28ffe864 100644 --- a/app/controllers/export_csv_controller.rb +++ b/app/controllers/export_csv_controller.rb @@ -5,9 +5,7 @@ class ExportCsvController < ApplicationController def export_entity params.require(:entity) params.require(:entity_type) - if params[:entity_type] == "admin" - guardian.ensure_can_export_admin_entity!(current_user) - end + guardian.ensure_can_export_entity!(params[:entity_type]) Jobs.enqueue(:export_csv_file, entity: params[:entity], user_id: current_user.id) render json: success_json diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 294010a1c..801fc0b37 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1697,6 +1697,7 @@ en: export_csv: success: "Export initiated, you will be notified via private message when the process is complete." failed: "Export failed. Please check the logs." + rate_limit_error: "Posts can be downloaded once per day, please try again tomorrow." button_text: "Export" button_title: user: "Export full user list in CSV format." diff --git a/lib/guardian.rb b/lib/guardian.rb index 97643ff3a..f2e452335 100644 --- a/lib/guardian.rb +++ b/lib/guardian.rb @@ -249,8 +249,10 @@ class Guardian @can_see_emails end - def can_export_admin_entity?(user) - user.staff? + def can_export_entity?(entity_type) + return true if is_staff? + return false if entity_type == "admin" + UserExport.where(user_id: @user.id, created_at: (Time.zone.now.beginning_of_day..Time.zone.now.end_of_day)).count == 0 end private diff --git a/spec/controllers/export_csv_controller_spec.rb b/spec/controllers/export_csv_controller_spec.rb index 12b70046e..cb40652ee 100644 --- a/spec/controllers/export_csv_controller_spec.rb +++ b/spec/controllers/export_csv_controller_spec.rb @@ -14,6 +14,13 @@ describe ExportCsvController do response.should be_success end + it "should not enqueue export job if rate limit is reached" do + Jobs::ExportCsvFile.any_instance.expects(:execute).never + UserExport.create(export_type: "user", user_id: @user.id) + xhr :post, :export_entity, entity: "user_archive", entity_type: "user" + response.should_not be_success + end + it "returns 404 when normal user tries to export admin entity" do xhr :post, :export_entity, entity: "staff_action", entity_type: "admin" response.should_not be_success @@ -55,6 +62,13 @@ describe ExportCsvController do xhr :post, :export_entity, entity: "staff_action", entity_type: "admin" response.should be_success end + + it "should not rate limit export for staff" do + Jobs.expects(:enqueue).with(:export_csv_file, has_entries(entity: "staff_action", user_id: @admin.id)) + UserExport.create(export_type: "admin", user_id: @admin.id) + xhr :post, :export_entity, entity: "staff_action", entity_type: "admin" + response.should be_success + end end describe ".download" do