Remove /ip_addresses page.

Remove the /ip_addresses page. This page allowed moderators to search
users by IP, and to see recent activity tied to an IP. However, it was
limited to IPs tied to uploads, comments, dmails, artist edits, note
edits, and wiki edits.

Remove this page because it was limited in scope and because there are
better ways of doing what it did. The /user_events page is better at
catching sockpuppets because it tracks IPs for every login, not just for
certain types of edits. And the /user_actions page is better at
monitoring user activity because it shows all activity associated with
an account, not just for certain types of edits.

Removing this allows us to drop IP addresses from all tables besides the
user_events table. This is good because these IPs are no longer necessary
for any purpose, and because storing them forever is a liability.
This commit is contained in:
evazion
2022-09-17 15:36:51 -05:00
parent 1ac56b72a7
commit 075199cd1e
18 changed files with 136 additions and 351 deletions

View File

@@ -3,21 +3,6 @@
class IpAddressesController < ApplicationController
respond_to :html, :xml, :json
def index
@ip_addresses = authorize IpAddress.visible(CurrentUser.user).paginated_search(params)
case search_params[:group_by]
when "ip_addr"
@ip_addresses = @ip_addresses.group_by_ip_addr(search_params[:ipv4_masklen], search_params[:ipv6_masklen])
when "user"
@ip_addresses = @ip_addresses.group_by_user.includes(:user)
else
@ip_addresses = @ip_addresses.includes(:user, :model)
end
respond_with(@ip_addresses)
end
def show
@ip_address = authorize IpAddress.new(ip_addr: params[:id])
@ip_info = @ip_address.ip_addr.ip_info

View File

@@ -195,7 +195,7 @@ module ApplicationHelper
def link_to_ip(ip, shorten: false, **options)
ip_addr = IPAddr.new(ip.to_s)
ip_addr.prefix = 64 if ip_addr.ipv6? && shorten
link_to ip_addr.to_s, ip_addresses_path(search: { ip_addr: ip, group_by: "user" }), **options
link_to ip_addr.to_s, user_events_path(search: { user_session: { ip_addr: ip }}), **options
end
def link_to_search(tag, **options)

View File

@@ -1,7 +1,7 @@
# frozen_string_literal: true
class IpAddressPolicy < ApplicationPolicy
def index?
def show?
user.is_moderator?
end

View File

@@ -1,9 +1,6 @@
<% content_for(:secondary_links) do %>
<%= quick_search_form_for(:user_name, bans_path, "users", autocomplete: "user") %>
<%= subnav_link_to "Listing", bans_path %>
<% if policy(IpAddress).index? %>
<%= subnav_link_to "IP Addresses", ip_addresses_path %>
<% end %>
<% if policy(IpBan).index? %>
<%= subnav_link_to "IP Bans", ip_bans_path %>
<% end %>

View File

@@ -1,24 +0,0 @@
<%= table_for @ip_addresses, class: "striped autofit" do |t| %>
<% t.column "IP Address" do |ip| %>
<%= 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" }) %>
<% end %>
<% t.column "Source" do |ip| %>
<%= link_to ip.model_type.underscore.humanize, ip_addresses_path(search: { model_type: ip.model_type }) %>
<% end %>
<% t.column "ID" do |ip| %>
<%= link_to "##{ip.model_id}", ip.model %>
<% end %>
<% t.column "User" do |ip| %>
<%= link_to_user ip.user %>
<%= link_to "»", ip_addresses_path(search: { user_id: ip.user_id, group_by: "ip_addr" }) %>
<% end %>
<% t.column "Date" do |ip| %>
<%= time_ago_in_words_tagged ip.created_at %>
<% end %>
<% t.column column: "ip-info" do |ip| %>
<%= link_to "Details", ip_address_path(ip.ip_addr.to_s) %>
| <%= link_to "Ban IP", new_ip_ban_path(ip_ban: { ip_addr: ip.ip_addr.to_s }) %>
| <%= link_to "Ban User", new_ban_path(ban: { user_name: ip.user.name, duration: 999999 }) %>
<% end %>
<% end %>

View File

@@ -1,16 +0,0 @@
<p>
<%= link_to "Find all users associated with the top 10 IP addresses", ip_addresses_path(search: { ip_addr: @ip_addresses.map(&:to_s).take(10).join(" "), group_by: "user" }) %>
</p>
<%= table_for @ip_addresses, class: "striped autofit" do |t| %>
<% t.column "IP Address" do |ip| %>
<%= link_to ip.to_s, ip_addresses_path(search: { ip_addr: ip.to_s }) %>
<%= link_to "»", ip_addresses_path(search: { ip_addr: ip.to_s, group_by: "user" }) %>
<% end %>
<% t.column "Uses" do |ip| %>
<%= link_to ip.count_all, ip_addresses_path(search: { ip_addr: ip.to_s }) %>
<% end %>
<% t.column column: "ip-info" do |ip| %>
<%= link_to "Details", ip_address_path(ip.ip_addr.to_s) %>
<% end %>
<% end %>

View File

@@ -1,14 +0,0 @@
<p>
<%= link_to "Find all IP addresses associated with these users", ip_addresses_path(search: { user_id: @ip_addresses.map(&:user_id).join(" "), group_by: "ip_addr" }) %>
</p>
<%= table_for @ip_addresses, class: "striped autofit" do |t| %>
<% t.column "User" do |ip| %>
<%= link_to_user ip.user %>
<%= link_to "»", ip_addresses_path(search: { user_id: ip.user_id, group_by: "ip_addr" }) %>
<% end %>
<% t.column "Uses" do |ip| %>
<%= link_to ip.count_all, ip_addresses_path(search: { user_id: ip.user_id, ip_addr: params[:search][:ip_addr] }) %>
<% end %>
<% end %>

View File

@@ -20,7 +20,7 @@
<tr>
<th>Network</th>
<td>
<%= link_to ip_info[:network], ip_addresses_path(search: { ip_addr: ip_info[:network] }) %>
<%= link_to ip_info[:network], user_events_path(search: { user_session: { ip_addr: ip_info[:network] }}) %>
(<%= link_to "info", "https://ipinfo.io/AS#{ip_info[:asn]}/#{ip_info[:network]}" %>)
</td>
</tr>

View File

@@ -1,6 +1,4 @@
<% content_for(:secondary_links) do %>
<%= quick_search_form_for(:ip_addr, ip_addresses_path, "ip addresses") %>
<%= subnav_link_to "Listing", ip_addresses_path %>
<%= subnav_link_to "IP Bans", ip_bans_path %>
<%= subnav_link_to "Bans", bans_path %>
<%= subnav_link_to "Feedbacks", user_feedbacks_path %>

View File

@@ -1,35 +0,0 @@
<%= render "secondary_links" %>
<div id="c-ip-addresses">
<div id="a-index">
<% if @ip_address %>
<h1>IP Address: <%= @ip_address.ip_addr %></h1>
<% else %>
<h1>IP Addresses</h1>
<% end %>
<%= 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] } %>
<%= f.input :ip_addr, label: "IP Address", input_html: { value: params[:search][:ip_addr] }, hint: '<a href="https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation">CIDR notation</a> supported.'.html_safe %>
<%= 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] %>
<% if params[:search][:group_by] == "ip_addr" %>
<%= f.input :ipv4_masklen, label: "IPv4 Subnet", collection: [["/32", 32], ["/24", 24], ["/16", 16], ["/8", 8]], include_blank: false, selected: params[:search][:ipv4_masklen], hint: "Lower to group together IPs with the same prefix." %>
<%= f.input :ipv6_masklen, label: "IPv6 Subnet", collection: [["/128", 128], ["/80", 80], ["/64", 64], ["/48", 48]], include_blank: false, selected: params[:search][:ipv6_masklen] %>
<% end %>
<%= 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 %>
<%= numbered_paginator(@ip_addresses) %>
</div>
</div>

View File

@@ -1,9 +1,6 @@
<% content_for(:secondary_links) do %>
<%= quick_search_form_for(:ip_addr, ip_bans_path, "ip addresses") %>
<%= subnav_link_to "Listing", ip_bans_path %>
<% if policy(IpAddress).index? %>
<%= subnav_link_to "IP Addresses", ip_addresses_path %>
<% end %>
<%= subnav_link_to "Bans", bans_path %>
<%= subnav_link_to "Feedbacks", user_feedbacks_path %>
<% if policy(IpBan).create? %>

View File

@@ -184,10 +184,6 @@
<li><%= link_to("Moderation Reports", moderation_reports_path) %></li>
<% end %>
<% if policy(IpAddress).index? %>
<li><%= link_to("IP Addresses", ip_addresses_path) %></li>
<% end %>
<% if policy(NewsUpdate).index? %>
<li><%= link_to("News Updates", news_updates_path) %></li>
<% end %>

View File

@@ -1,9 +1,6 @@
<% content_for(:secondary_links) do %>
<%= quick_search_form_for(:user_name, user_feedbacks_path, "users", autocomplete: "user") %>
<%= subnav_link_to "Listing", user_feedbacks_path %>
<% if policy(IpAddress).index? %>
<%= subnav_link_to "IP Addresses", ip_addresses_path %>
<% end %>
<% if policy(IpBan).index? %>
<%= subnav_link_to "IP Bans", ip_bans_path %>
<% end %>

View File

@@ -23,13 +23,9 @@
<th>Last IP</th>
<td>
<% if user.last_ip_addr.present? %>
<%= link_to user.last_ip_addr, ip_addresses_path(search: { ip_addr: user.last_ip_addr }) %>
(<%= link_to "info", ip_address_path(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" }) %>)
<%= link_to user.last_ip_addr, ip_address_path(user.last_ip_addr) %>
<% else %>
<em>unknown</em>
(<%= link_to "IPs", ip_addresses_path(search: { user_id: user.id, group_by: "ip_addr" }) %>)
<% end %>
</td>
</tr>
@@ -39,8 +35,12 @@
<tr>
<th>User Events</th>
<td>
<% if user.last_ip_addr.present? %>
<%= link_to "By Name", user_events_path(search: { user_name: user.name }) %>,
<%= link_to "By IP", user_events_path(search: { user_session: { ip_addr: user.last_ip_addr }}) %>
<% else %>
<%= link_to "By Name", user_events_path(search: { user_name: user.name }) %>
<% end %>
<td>
</tr>
<% end %>

View File

@@ -34,11 +34,6 @@ Rails.application.routes.draw do
end
end
end
resources :ip_addrs, :only => [:index, :search] do
collection do
get :search
end
end
end
namespace :explore do
resources :posts, :only => [] do
@@ -143,7 +138,7 @@ Rails.application.routes.draw do
end
resources :forum_topic_visits, only: [:index]
resources :ip_bans, only: [:index, :new, :create, :update]
resources :ip_addresses, only: [:show, :index], id: /.+?(?=\.json|\.xml|\.html)|.+/
resources :ip_addresses, only: [:show], id: /.+?(?=\.json|\.xml|\.html)|.+/
resources :ip_geolocations, only: [:index]
resource :iqdb_queries, :only => [:show, :create] do
collection do

View File

@@ -0,0 +1,5 @@
class DropIpAddressesView < ActiveRecord::Migration[7.0]
def change
drop_view :ip_addresses, revert_to_version: 1
end
end

View File

@@ -837,187 +837,6 @@ CREATE TABLE public.good_jobs (
);
--
-- Name: note_versions; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.note_versions (
id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
x integer NOT NULL,
y integer NOT NULL,
width integer NOT NULL,
height integer NOT NULL,
body text NOT NULL,
updater_ip_addr inet NOT NULL,
is_active boolean DEFAULT true NOT NULL,
note_id integer NOT NULL,
post_id integer NOT NULL,
updater_id integer NOT NULL,
version integer DEFAULT 0 NOT NULL
);
--
-- Name: posts; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.posts (
id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
uploader_id integer NOT NULL,
score integer DEFAULT 0 NOT NULL,
source character varying DEFAULT ''::character varying NOT NULL,
md5 character varying NOT NULL,
last_comment_bumped_at timestamp without time zone,
rating character(1) DEFAULT 'q'::bpchar NOT NULL,
image_width integer NOT NULL,
image_height integer NOT NULL,
uploader_ip_addr inet NOT NULL,
tag_string text DEFAULT ''::text NOT NULL,
fav_count integer DEFAULT 0 NOT NULL,
file_ext character varying NOT NULL,
last_noted_at timestamp without time zone,
parent_id integer,
has_children boolean DEFAULT false NOT NULL,
approver_id integer,
tag_count_general integer DEFAULT 0 NOT NULL,
tag_count_artist integer DEFAULT 0 NOT NULL,
tag_count_character integer DEFAULT 0 NOT NULL,
tag_count_copyright integer DEFAULT 0 NOT NULL,
file_size integer NOT NULL,
up_score integer DEFAULT 0 NOT NULL,
down_score integer DEFAULT 0 NOT NULL,
is_pending boolean DEFAULT false NOT NULL,
is_flagged boolean DEFAULT false NOT NULL,
is_deleted boolean DEFAULT false NOT NULL,
tag_count integer DEFAULT 0 NOT NULL,
updated_at timestamp without time zone NOT NULL,
is_banned boolean DEFAULT false NOT NULL,
pixiv_id integer,
last_commented_at timestamp without time zone,
has_active_children boolean DEFAULT false,
bit_flags bigint DEFAULT 0 NOT NULL,
tag_count_meta integer DEFAULT 0 NOT NULL
);
--
-- Name: users; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.users (
id integer NOT NULL,
name character varying NOT NULL,
level integer NOT NULL,
inviter_id integer,
created_at timestamp without time zone NOT NULL,
last_logged_in_at timestamp without time zone,
last_forum_read_at timestamp without time zone,
comment_threshold integer NOT NULL,
updated_at timestamp without time zone,
default_image_size character varying NOT NULL,
favorite_tags text,
blacklisted_tags text,
time_zone character varying NOT NULL,
post_update_count integer NOT NULL,
note_update_count integer NOT NULL,
favorite_count integer NOT NULL,
post_upload_count integer NOT NULL,
bcrypt_password_hash text NOT NULL,
per_page integer NOT NULL,
custom_style text,
bit_prefs bigint NOT NULL,
last_ip_addr inet,
unread_dmail_count integer NOT NULL,
theme integer NOT NULL,
upload_points integer NOT NULL
);
--
-- Name: wiki_page_versions; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.wiki_page_versions (
id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
title character varying NOT NULL,
body text NOT NULL,
updater_id integer NOT NULL,
updater_ip_addr inet NOT NULL,
wiki_page_id integer NOT NULL,
is_locked boolean NOT NULL,
other_names text[] DEFAULT '{}'::text[] NOT NULL,
is_deleted boolean DEFAULT false NOT NULL
);
--
-- Name: ip_addresses; Type: VIEW; Schema: public; Owner: -
--
CREATE VIEW public.ip_addresses AS
SELECT 'ArtistVersion'::text AS model_type,
artist_versions.id AS model_id,
artist_versions.updater_id AS user_id,
artist_versions.updater_ip_addr AS ip_addr,
artist_versions.created_at
FROM public.artist_versions
UNION ALL
SELECT 'ArtistCommentaryVersion'::text AS model_type,
artist_commentary_versions.id AS model_id,
artist_commentary_versions.updater_id AS user_id,
artist_commentary_versions.updater_ip_addr AS ip_addr,
artist_commentary_versions.created_at
FROM public.artist_commentary_versions
UNION ALL
SELECT 'Comment'::text AS model_type,
comments.id AS model_id,
comments.creator_id AS user_id,
comments.creator_ip_addr AS ip_addr,
comments.created_at
FROM public.comments
UNION ALL
SELECT 'Dmail'::text AS model_type,
dmails.id AS model_id,
dmails.from_id AS user_id,
dmails.creator_ip_addr AS ip_addr,
dmails.created_at
FROM public.dmails
UNION ALL
SELECT 'NoteVersion'::text AS model_type,
note_versions.id AS model_id,
note_versions.updater_id AS user_id,
note_versions.updater_ip_addr AS ip_addr,
note_versions.created_at
FROM public.note_versions
UNION ALL
SELECT 'Post'::text AS model_type,
posts.id AS model_id,
posts.uploader_id AS user_id,
posts.uploader_ip_addr AS ip_addr,
posts.created_at
FROM public.posts
UNION ALL
SELECT 'User'::text AS model_type,
users.id AS model_id,
users.id AS user_id,
users.last_ip_addr AS ip_addr,
users.created_at
FROM public.users
WHERE (users.last_ip_addr IS NOT NULL)
UNION ALL
SELECT 'WikiPageVersion'::text AS model_type,
wiki_page_versions.id AS model_id,
wiki_page_versions.updater_id AS user_id,
wiki_page_versions.updater_ip_addr AS ip_addr,
wiki_page_versions.created_at
FROM public.wiki_page_versions;
--
-- Name: ip_bans; Type: TABLE; Schema: public; Owner: -
--
@@ -1273,6 +1092,28 @@ CREATE SEQUENCE public.news_updates_id_seq
ALTER SEQUENCE public.news_updates_id_seq OWNED BY public.news_updates.id;
--
-- Name: note_versions; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.note_versions (
id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
x integer NOT NULL,
y integer NOT NULL,
width integer NOT NULL,
height integer NOT NULL,
body text NOT NULL,
updater_ip_addr inet NOT NULL,
is_active boolean DEFAULT true NOT NULL,
note_id integer NOT NULL,
post_id integer NOT NULL,
updater_id integer NOT NULL,
version integer DEFAULT 0 NOT NULL
);
--
-- Name: note_versions_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
@@ -1708,6 +1549,50 @@ CREATE SEQUENCE public.post_votes_id_seq
ALTER SEQUENCE public.post_votes_id_seq OWNED BY public.post_votes.id;
--
-- Name: posts; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.posts (
id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
uploader_id integer NOT NULL,
score integer DEFAULT 0 NOT NULL,
source character varying DEFAULT ''::character varying NOT NULL,
md5 character varying NOT NULL,
last_comment_bumped_at timestamp without time zone,
rating character(1) DEFAULT 'q'::bpchar NOT NULL,
image_width integer NOT NULL,
image_height integer NOT NULL,
uploader_ip_addr inet NOT NULL,
tag_string text DEFAULT ''::text NOT NULL,
fav_count integer DEFAULT 0 NOT NULL,
file_ext character varying NOT NULL,
last_noted_at timestamp without time zone,
parent_id integer,
has_children boolean DEFAULT false NOT NULL,
approver_id integer,
tag_count_general integer DEFAULT 0 NOT NULL,
tag_count_artist integer DEFAULT 0 NOT NULL,
tag_count_character integer DEFAULT 0 NOT NULL,
tag_count_copyright integer DEFAULT 0 NOT NULL,
file_size integer NOT NULL,
up_score integer DEFAULT 0 NOT NULL,
down_score integer DEFAULT 0 NOT NULL,
is_pending boolean DEFAULT false NOT NULL,
is_flagged boolean DEFAULT false NOT NULL,
is_deleted boolean DEFAULT false NOT NULL,
tag_count integer DEFAULT 0 NOT NULL,
updated_at timestamp without time zone NOT NULL,
is_banned boolean DEFAULT false NOT NULL,
pixiv_id integer,
last_commented_at timestamp without time zone,
has_active_children boolean DEFAULT false,
bit_flags bigint DEFAULT 0 NOT NULL,
tag_count_meta integer DEFAULT 0 NOT NULL
);
--
-- Name: posts_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
@@ -2127,6 +2012,58 @@ CREATE TABLE public.user_upgrades (
);
--
-- Name: users; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.users (
id integer NOT NULL,
name character varying NOT NULL,
level integer NOT NULL,
inviter_id integer,
created_at timestamp without time zone NOT NULL,
last_logged_in_at timestamp without time zone,
last_forum_read_at timestamp without time zone,
comment_threshold integer NOT NULL,
updated_at timestamp without time zone,
default_image_size character varying NOT NULL,
favorite_tags text,
blacklisted_tags text,
time_zone character varying NOT NULL,
post_update_count integer NOT NULL,
note_update_count integer NOT NULL,
favorite_count integer NOT NULL,
post_upload_count integer NOT NULL,
bcrypt_password_hash text NOT NULL,
per_page integer NOT NULL,
custom_style text,
bit_prefs bigint NOT NULL,
last_ip_addr inet,
unread_dmail_count integer NOT NULL,
theme integer NOT NULL,
upload_points integer NOT NULL
);
--
-- Name: wiki_page_versions; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.wiki_page_versions (
id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
title character varying NOT NULL,
body text NOT NULL,
updater_id integer NOT NULL,
updater_ip_addr inet NOT NULL,
wiki_page_id integer NOT NULL,
is_locked boolean NOT NULL,
other_names text[] DEFAULT '{}'::text[] NOT NULL,
is_deleted boolean DEFAULT false NOT NULL
);
--
-- Name: user_actions; Type: VIEW; Schema: public; Owner: -
--
@@ -6755,6 +6692,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20220909205433'),
('20220909211649'),
('20220913191300'),
('20220913191309');
('20220913191309'),
('20220917204044');

View File

@@ -5,40 +5,6 @@ class IpAddressesControllerTest < ActionDispatch::IntegrationTest
setup do
@mod = create(:mod_user, last_ip_addr: "1.2.3.4")
@user = create(:user, last_ip_addr: "5.6.7.8")
CurrentUser.scoped(@user, "5.6.7.9") do
@note = create(:note)
@artist = create(:artist)
end
end
context "index action" do
should "list all IP addresses" do
get_auth ip_addresses_path, @mod
assert_response :success
end
should "allow searching by subnet" do
get_auth ip_addresses_path(search: { ip_addr: "5.0.0.0/8" }), @mod, as: :json
assert_response :success
assert(response.parsed_body.present?)
end
should "allow grouping by user" do
get_auth ip_addresses_path(search: { ip_addr: @user.last_ip_addr, group_by: "user" }), @mod
assert_response :success
end
should "allow grouping by IP" do
get_auth ip_addresses_path(search: { user_id: @user.id, group_by: "ip_addr" }), @mod
assert_response :success
end
should "not allow non-moderators to view IP addresses" do
get_auth ip_addresses_path, @user
assert_response 403
end
end
context "show action" do