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:
evazion
2019-11-10 23:24:28 -06:00
parent 2aac42b112
commit bf6bb94702
17 changed files with 311 additions and 2 deletions

View File

@@ -0,0 +1,30 @@
<table class="striped autofit">
<thead>
<tr>
<th>Source</th>
<th>ID</th>
<th>IP Address</th>
<th>User</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<% @ip_addresses.each do |ip| %>
<tr>
<td><%= link_to ip.model_type.underscore.humanize, ip_addresses_path(search: { model_type: ip.model_type }) %></td>
<td><%= link_to "##{ip.model_id}", ip.model %></td>
<td>
<%= link_to ip.ip_addr, ip_addresses_path(search: { ip_addr: ip.ip_addr }) %>
<%= link_to "»", ip_addresses_path(search: { ip_addr: ip.ip_addr, group_by: "user" }) %>
</td>
<td>
<%= link_to_user ip.user %>
<%= link_to "»", ip_addresses_path(search: { user_id: ip.user_id, group_by: "ip_addr" }) %>
</td>
<td><%= time_ago_in_words_tagged ip.created_at %></td>
</tr>
<% end %>
</tbody>
</table>
<%= numbered_paginator(@ip_addresses) %>

View File

@@ -0,0 +1,19 @@
<table class="striped autofit">
<thead>
<tr>
<th>IP Address</th>
<th>Uses</th>
</tr>
</thead>
<tbody>
<% @ip_addresses.each do |ip| %>
<tr>
<td>
<%= link_to ip.ip_addr, ip_addresses_path(search: { ip_addr: ip.ip_addr }) %>
<%= link_to "»", ip_addresses_path(search: { ip_addr: ip.ip_addr, group_by: "user" }) %>
</td>
<td><%= link_to ip.count_all, ip_addresses_path(search: { ip_addr: ip.ip_addr }) %></td>
</tr>
<% end %>
</tbody>
</table>

View File

@@ -0,0 +1,19 @@
<table class="striped autofit">
<thead>
<tr>
<th>User</th>
<th>Uses</th>
</tr>
</thead>
<tbody>
<% @ip_addresses.each do |ip| %>
<tr>
<td>
<%= link_to_user ip.user %>
<%= link_to "»", ip_addresses_path(search: { user_id: ip.user_id, group_by: "ip_addr" }) %>
</td>
<td><%= link_to ip.count_all, ip_addresses_path(search: { user_id: ip.user_id, ip_addr: params[:search][:ip_addr] }) %></td>
</tr>
<% end %>
</tbody>
</table>

View File

@@ -0,0 +1,21 @@
<div id="c-ip-addresses">
<div id="a-index">
<%= search_form_for(ip_addresses_path) do |f| %>
<%= f.input :user_id, label: "User ID", input_html: { value: params[:search][:user_id] }, hint: "Separate with spaces" %>
<%= f.input :user_name, label: "User Name", input_html: { "data-autocomplete": "user", value: params[:search][:user_name] }, hint: "Use * for wildcard" %>
<%= f.input :ip_addr, label: "IP Address", input_html: { value: params[:search][:ip_addr] } %>
<%= f.input :created_at, label: "Date", input_html: { value: params[:search][:created_at] } %>
<%= f.input :model_type, label: "Source", collection: IpAddress.model_types, include_blank: true, selected: params[:search][:model_type] %>
<%= f.input :group_by, label: "Group By", collection: [["User", "user"], ["IP Address", "ip_addr"]], include_blank: true, selected: params[:search][:group_by] %>
<%= f.submit "Search" %>
<% end %>
<% if params[:search][:group_by] == "user" %>
<%= render "index_by_user" %>
<% elsif params[:search][:group_by] == "ip_addr" %>
<%= render "index_by_ip_addr" %>
<% elsif @ip_addresses.present? %>
<%= render "index" %>
<% end %>
</div>
</div>

View File

@@ -10,6 +10,16 @@
<th>Join Date</th>
<td><%= presenter.join_date %></td>
</tr>
<% if CurrentUser.is_moderator? %>
<tr>
<th>Last IP</th>
<td>
<%= link_to user.last_ip_addr, ip_addresses_path(search: { ip_addr: user.last_ip_addr }) %>
(<%= link_to "users", ip_addresses_path(search: { ip_addr: user.last_ip_addr, group_by: "user" }) %>,
<%= link_to "IPs", ip_addresses_path(search: { user_id: user.id, group_by: "ip_addr" }) %>)
</td>
</tr>
<% end %>
<tr>
<th>Inviter</th>