Add new IP address search page.
Add a new IP address search page at /ip_addresses. Replaces the old search page at /moderator/ip_addrs. On user profile pages, show the user's last known IP to mods. Also add search links for finding other IPs or accounts associated with the user. IP address search uses a big UNION ALL statement to merge IP addresses across various tables into a single view. This makes searching easier, but is known to timeout in certain cases. Fixes #4207 (the new IP search page supports searching by subnet).
This commit is contained in:
@@ -50,6 +50,11 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
where.not("#{qualified_column_for(attr)} ~ ?", "(?e)" + value)
|
||||
end
|
||||
|
||||
def where_inet_matches(attr, value)
|
||||
ip = IPAddress.parse(value)
|
||||
where("#{qualified_column_for(attr)} <<= ?", ip.to_string)
|
||||
end
|
||||
|
||||
def where_array_includes_any(attr, values)
|
||||
where("#{qualified_column_for(attr)} && ARRAY[?]", values)
|
||||
end
|
||||
@@ -79,6 +84,14 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def search_inet_attribute(attr, params)
|
||||
if params[attr].present?
|
||||
where_inet_matches(attr, params[attr])
|
||||
else
|
||||
all
|
||||
end
|
||||
end
|
||||
|
||||
# range: "5", ">5", "<5", ">=5", "<=5", "5..10", "5,6,7"
|
||||
def numeric_attribute_matches(attribute, range)
|
||||
return all unless range.present?
|
||||
@@ -130,6 +143,8 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
search_boolean_attribute(name, params)
|
||||
when :integer, :datetime
|
||||
numeric_attribute_matches(name, params[name])
|
||||
when :inet
|
||||
search_inet_attribute(name, params)
|
||||
else
|
||||
raise NotImplementedError, "unhandled attribute type"
|
||||
end
|
||||
|
||||
28
app/models/ip_address.rb
Normal file
28
app/models/ip_address.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
class IpAddress < ApplicationRecord
|
||||
belongs_to :model, polymorphic: true
|
||||
belongs_to :user
|
||||
attribute :ip_addr, IpAddressType.new
|
||||
|
||||
def self.model_types
|
||||
%w[Post User Comment Dmail ArtistVersion ArtistCommentaryVersion NoteVersion WikiPageVersion]
|
||||
end
|
||||
|
||||
def self.search(params)
|
||||
q = super
|
||||
q = q.where.not(model_type: "Dmail") unless CurrentUser.is_admin?
|
||||
q = q.search_attributes(params, :user, :model_type, :model_id, :ip_addr)
|
||||
q.order(created_at: :desc)
|
||||
end
|
||||
|
||||
def self.group_by_ip_addr
|
||||
group(:ip_addr).select("ip_addr, COUNT(*) AS count_all").reorder("count_all DESC, ip_addr")
|
||||
end
|
||||
|
||||
def self.group_by_user
|
||||
group(:user_id).select("user_id, COUNT(*) AS count_all").reorder("count_all DESC, user_id")
|
||||
end
|
||||
|
||||
def readonly?
|
||||
true
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user