From d3d517108d73a92d808f6107d4f2ab936931fedc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Mon, 24 Nov 2014 19:34:04 +0100 Subject: [PATCH] FIX: display total number of other accounts with the same IP address in the IP lookup dialog --- .../admin/components/ip-lookup.js.es6 | 25 ++- .../templates/components/ip-lookup.hbs | 4 +- app/controllers/admin/users_controller.rb | 12 +- config/locales/client.en.yml | 2 +- config/routes.rb | 1 + lib/admin_user_index_query.rb | 151 +++++++++--------- 6 files changed, 112 insertions(+), 83 deletions(-) diff --git a/app/assets/javascripts/admin/components/ip-lookup.js.es6 b/app/assets/javascripts/admin/components/ip-lookup.js.es6 index ee6cc037385..bf46c9a2da4 100644 --- a/app/assets/javascripts/admin/components/ip-lookup.js.es6 +++ b/app/assets/javascripts/admin/components/ip-lookup.js.es6 @@ -9,6 +9,13 @@ export default Ember.Component.extend({ ].filter(Boolean).join(", "); }.property("location.{city,region,country}"), + otherAccountsToDelete: function() { + // can only delete up to 50 accounts at a time + var total = Math.min(50, this.get("totalOthersWithSameIP") || 0); + var visible = Math.min(50, this.get("other_accounts.length") || 0); + return Math.max(visible, total); + }.property("other_accounts", "totalOthersWithSameIP"), + actions: { lookup: function () { var self = this; @@ -24,11 +31,18 @@ export default Ember.Component.extend({ if (!this.get("other_accounts")) { this.set("otherAccountsLoading", true); - Discourse.AdminUser.findAll("active", { + + var data = { "ip": this.get("ip"), "exclude": this.get("userId"), "order": "trust_level DESC" - }).then(function (users) { + }; + + Discourse.ajax("/admin/users/total-others-with-same-ip.json", { data: data }).then(function (result) { + self.set("totalOthersWithSameIP", result.total); + }); + + Discourse.AdminUser.findAll("active", data).then(function (users) { self.setProperties({ other_accounts: users, otherAccountsLoading: false, @@ -45,7 +59,12 @@ export default Ember.Component.extend({ var self = this; bootbox.confirm(I18n.t("ip_lookup.confirm_delete_other_accounts"), I18n.t("no_value"), I18n.t("yes_value"), function (confirmed) { if (confirmed) { - self.setProperties({ other_accounts: null, otherAccountsLoading: true }); + self.setProperties({ + other_accounts: null, + otherAccountsLoading: true, + totalOthersWithSameIP: null + }); + Discourse.ajax("/admin/users/delete-others-with-same-ip.json", { type: "DELETE", data: { diff --git a/app/assets/javascripts/discourse/templates/components/ip-lookup.hbs b/app/assets/javascripts/discourse/templates/components/ip-lookup.hbs index f7c7851bfea..396235b569d 100644 --- a/app/assets/javascripts/discourse/templates/components/ip-lookup.hbs +++ b/app/assets/javascripts/discourse/templates/components/ip-lookup.hbs @@ -39,10 +39,10 @@
{{i18n ip_lookup.other_accounts}} - {{other_accounts.length}} + {{totalOthersWithSameIP}} {{#if other_accounts.length}} {{/if}}
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 9158fa52de3..6649d2223cf 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -278,18 +278,24 @@ class Admin::UsersController < Admin::AdminController params.require(:exclude) params.require(:order) - params[:limit] = 50 - user_destroyer = UserDestroyer.new(current_user) options = { delete_posts: true, block_email: true, block_urls: true, block_ip: true, delete_as_spammer: true } - AdminUserIndexQuery.new(params).find_users.each do |user| + AdminUserIndexQuery.new(params).find_users(50).each do |user| user_destroyer.destroy(user, options) rescue nil end render json: success_json end + def total_other_accounts_with_same_ip + params.require(:ip) + params.require(:exclude) + params.require(:order) + + render json: { total: AdminUserIndexQuery.new(params).count_users } + end + def invite_admin email = params[:email] diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 0d189d93861..4e4ef72b085 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -279,7 +279,7 @@ en: organisation: Organization phone: Phone other_accounts: "Other accounts with this IP address:" - delete_other_accounts: "Delete up to 50" + delete_other_accounts: "Delete %{count}" username: "username" trust_level: "TL" read_time: "read time" diff --git a/config/routes.rb b/config/routes.rb index 78f923d67b4..d56d603376a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -53,6 +53,7 @@ Discourse::Application.routes.draw do get "list/:query" => "users#index" get "ip-info" => "users#ip_info" delete "delete-others-with-same-ip" => "users#delete_other_accounts_with_same_ip" + get "total-others-with-same-ip" => "users#total_other_accounts_with_same_ip" put "approve-bulk" => "users#approve_bulk" delete "reject-bulk" => "users#reject_bulk" end diff --git a/lib/admin_user_index_query.rb b/lib/admin_user_index_query.rb index a5d3d66ff70..f01094704f2 100644 --- a/lib/admin_user_index_query.rb +++ b/lib/admin_user_index_query.rb @@ -1,6 +1,7 @@ require_dependency 'trust_level' class AdminUserIndexQuery + def initialize(params = {}, klass = User, trust_levels = TrustLevel.levels) @params = params @query = initialize_query_with_order(klass) @@ -9,80 +10,7 @@ class AdminUserIndexQuery attr_reader :params, :trust_levels - def initialize_query_with_order(klass) - order = [params[:order]] - - if params[:query] == "active" - order << "COALESCE(last_seen_at, to_date('1970-01-01', 'YYYY-MM-DD')) DESC" - else - order << "created_at DESC" - end - - order << "username" - - klass.order(order.reject(&:blank?).join(",")) - end - - def filter_by_trust - levels = trust_levels.map { |key, _| key.to_s } - if levels.include?(params[:query]) - @query.where('trust_level = ?', trust_levels[params[:query].to_sym]) - end - end - - def filter_by_query_classification - case params[:query] - when 'admins' then @query.where(admin: true) - when 'moderators' then @query.where(moderator: true) - when 'blocked' then @query.blocked - when 'suspended' then @query.suspended - when 'pending' then @query.not_suspended.where(approved: false) - end - end - - def filter_by_search - if params[:filter].present? - if ip = IPAddr.new(params[:filter]) rescue nil - @query.where('ip_address <<= :ip OR registration_ip_address <<= :ip', ip: ip.to_cidr_s) - else - @query.where('username_lower ILIKE :filter OR email ILIKE :filter', filter: "%#{params[:filter]}%") - end - end - end - - def filter_by_ip - if params[:ip].present? - @query.where('ip_address = :ip OR registration_ip_address = :ip', ip: params[:ip]) - end - end - - def filter_exclude - if params[:exclude].present? - @query.where('id != ?', params[:exclude]) - end - end - - def limit - limit = params[:limit].to_i - @query.limit(limit > 0 ? limit : 100) - end - - # this might not be needed in rails 4 ? - def append(active_relation) - @query = active_relation if active_relation - end - - def find_users_query - append filter_by_trust - append filter_by_query_classification - append filter_by_ip - append filter_exclude - append filter_by_search - append limit - @query - end - - def find_users + def find_users(limit=100) find_users_query.includes(:user_stat) .includes(:single_sign_on_record) .includes(:facebook_user_info) @@ -91,5 +19,80 @@ class AdminUserIndexQuery .includes(:google_user_info) .includes(:oauth2_user_info) .includes(:user_open_ids) + .limit(limit) end + + def count_users + find_users_query.count + end + + private + + def initialize_query_with_order(klass) + order = [params[:order]] + + if params[:query] == "active" + order << "COALESCE(last_seen_at, to_date('1970-01-01', 'YYYY-MM-DD')) DESC" + else + order << "created_at DESC" + end + + order << "username" + + klass.order(order.reject(&:blank?).join(",")) + end + + def filter_by_trust + levels = trust_levels.map { |key, _| key.to_s } + if levels.include?(params[:query]) + @query.where('trust_level = ?', trust_levels[params[:query].to_sym]) + end + end + + def filter_by_query_classification + case params[:query] + when 'admins' then @query.where(admin: true) + when 'moderators' then @query.where(moderator: true) + when 'blocked' then @query.blocked + when 'suspended' then @query.suspended + when 'pending' then @query.not_suspended.where(approved: false) + end + end + + def filter_by_search + if params[:filter].present? + if ip = IPAddr.new(params[:filter]) rescue nil + @query.where('ip_address <<= :ip OR registration_ip_address <<= :ip', ip: ip.to_cidr_s) + else + @query.where('username_lower ILIKE :filter OR email ILIKE :filter', filter: "%#{params[:filter]}%") + end + end + end + + def filter_by_ip + if params[:ip].present? + @query.where('ip_address = :ip OR registration_ip_address = :ip', ip: params[:ip]) + end + end + + def filter_exclude + if params[:exclude].present? + @query.where('id != ?', params[:exclude]) + end + end + + # this might not be needed in rails 4 ? + def append(active_relation) + @query = active_relation if active_relation + end + + def find_users_query + append filter_by_trust + append filter_by_query_classification + append filter_by_ip + append filter_exclude + append filter_by_search + @query + end + end