tests for ip address role policy

This commit is contained in:
Dylan Knutson
2025-03-03 16:44:21 +00:00
parent 04661a8505
commit b080ac896f
12 changed files with 329 additions and 44 deletions

View File

@@ -150,6 +150,7 @@ end
group :production do
gem "sd_notify"
gem "cloudflare-rails"
end
gem "rack", "~> 2.2"

View File

@@ -123,6 +123,11 @@ GEM
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
cloudflare-rails (6.2.0)
actionpack (>= 7.1.0, < 8.1.0)
activesupport (>= 7.1.0, < 8.1.0)
railties (>= 7.1.0, < 8.1.0)
zeitwerk (>= 2.5.0)
coderay (1.1.3)
colorize (1.1.0)
concurrent-ruby (1.3.4)
@@ -557,6 +562,7 @@ DEPENDENCIES
attr_json
bootsnap
capybara
cloudflare-rails
colorize
concurrent-ruby-edge
concurrent-ruby-ext

View File

@@ -101,10 +101,8 @@ class Domain::Fa::Job::UserPageJob < Domain::Fa::Job::Base
end
if post_file && post_file.url_str.present? &&
(
post_file.state_pending? || post_file.log_entry.blank? ||
!post_file.state_terminal_error?
)
!post_file.state_terminal_error? &&
(post_file.state_pending? || post_file.log_entry.blank?)
logger.tagged(make_arg_tag(post_file)) do
logger.info(
"post is in recent gallery section, force enqueue ScanFileJob",

View File

@@ -10,7 +10,9 @@ class ApplicationPolicy
sig { returns(T.untyped) }
attr_reader :record
sig { params(user: T.nilable(User), record: T.untyped).void }
sig do
params(user: T.nilable(T.any(User, IpAddressRole)), record: T.untyped).void
end
def initialize(user, record)
@user = user
@record = record
@@ -48,6 +50,11 @@ class ApplicationPolicy
user&.user? || false
end
sig(:final) { returns(T::Boolean) }
def is_real_user?
user&.is_a?(User) || false
end
sig { returns(T::Boolean) }
def index?
false
@@ -91,7 +98,9 @@ class ApplicationPolicy
class Scope
extend T::Sig
sig { params(user: T.nilable(User), scope: T.untyped).void }
sig do
params(user: T.nilable(T.any(User, IpAddressRole)), scope: T.untyped).void
end
def initialize(user, scope)
@user = user
@scope = scope
@@ -104,7 +113,7 @@ class ApplicationPolicy
private
sig { returns(T.nilable(User)) }
sig { returns(T.nilable(T.any(User, IpAddressRole))) }
attr_reader :user
sig { returns(T.untyped) }

View File

@@ -14,22 +14,22 @@ class Domain::PostPolicy < ApplicationPolicy
sig { returns(T::Boolean) }
def view_file?
is_role_admin? || is_role_moderator?
is_role_admin? || is_role_moderator? || is_role_user?
end
sig { returns(T::Boolean) }
def view_scan_metadata?
is_role_admin? || is_role_moderator?
is_role_admin?
end
sig { returns(T::Boolean) }
def users_faving_post?
is_role_admin? || is_role_moderator?
is_role_admin? || is_role_moderator? || is_role_user?
end
sig { returns(T::Boolean) }
def view_faved_by?
is_role_admin? || is_role_moderator?
is_role_admin? || is_role_moderator? || is_role_user?
end
sig { returns(T::Boolean) }

View File

@@ -29,7 +29,7 @@ class Domain::UserPolicy < ApplicationPolicy
sig { returns(T::Boolean) }
def view_page_scanned_at_timestamps?
is_role_admin? || is_role_moderator?
is_role_admin?
end
sig { returns(T::Boolean) }
@@ -39,11 +39,11 @@ class Domain::UserPolicy < ApplicationPolicy
sig { returns(T::Boolean) }
def followed_by?
is_role_admin? || is_role_moderator?
is_role_admin? || is_role_moderator? || is_role_user?
end
sig { returns(T::Boolean) }
def following?
is_role_admin? || is_role_moderator?
is_role_admin? || is_role_moderator? || is_role_user?
end
end

View File

@@ -4,57 +4,57 @@ class GlobalStatePolicy < ApplicationPolicy
sig { returns(T::Boolean) }
def index?
is_role_admin?
is_real_user? && is_role_admin?
end
sig { returns(T::Boolean) }
def show?
is_role_admin?
is_real_user? && is_role_admin?
end
sig { returns(T::Boolean) }
def create?
is_role_admin?
is_real_user? && is_role_admin?
end
sig { returns(T::Boolean) }
def update?
is_role_admin?
is_real_user? && is_role_admin?
end
sig { returns(T::Boolean) }
def destroy?
is_role_admin?
is_real_user? && is_role_admin?
end
sig { returns(T::Boolean) }
def fa_cookies?
is_role_admin?
is_real_user? && is_role_admin?
end
sig { returns(T::Boolean) }
def edit_fa_cookies?
is_role_admin?
is_real_user? && is_role_admin?
end
sig { returns(T::Boolean) }
def update_fa_cookies?
is_role_admin?
is_real_user? && is_role_admin?
end
sig { returns(T::Boolean) }
def ib_cookies?
is_role_admin?
is_real_user? && is_role_admin?
end
sig { returns(T::Boolean) }
def edit_ib_cookies?
is_role_admin?
is_real_user? && is_role_admin?
end
sig { returns(T::Boolean) }
def update_ib_cookies?
is_role_admin?
is_real_user? && is_role_admin?
end
class Scope < ApplicationPolicy::Scope

View File

@@ -0,0 +1,7 @@
# typed: strict
class IpAddressRolePolicy < ApplicationPolicy
sig { returns(T::Boolean) }
def view_debug_info?
is_real_user? && is_role_admin?
end
end

View File

@@ -4,12 +4,12 @@ class State::IpAddressRolePolicy < ApplicationPolicy
sig { returns(T::Boolean) }
def index?
is_role_admin? || ip_is_admin?
is_role_admin?
end
sig { returns(T::Boolean) }
def create?
is_role_admin? || ip_is_admin?
is_role_admin?
end
sig { returns(T::Boolean) }
@@ -19,7 +19,7 @@ class State::IpAddressRolePolicy < ApplicationPolicy
sig { returns(T::Boolean) }
def update?
is_role_admin? || ip_is_admin?
is_role_admin?
end
sig { returns(T::Boolean) }
@@ -34,12 +34,6 @@ class State::IpAddressRolePolicy < ApplicationPolicy
private
sig { returns(T::Boolean) }
def ip_is_admin?
ip_role = @controller.current_ip_address_role
ip_role&.admin? || false
end
class Scope
extend T::Sig

View File

@@ -32,18 +32,31 @@
</span>
<% end %>
</h1>
<span class="font-mono text-slate-500">
<span>IP address</span>
<span class="font-mono text-slate-700">
<%= request.remote_ip %>
<% if policy(IpAddressRole).view_debug_info? %>
<span class="font-mono text-slate-500">
<span>IP address</span>
<span class="font-mono text-slate-700">
<%= request.remote_ip %>
</span>
</span>
</span>
<span class="font-mono text-slate-500">
<span>IP Address Role</span>
<span class="font-mono text-slate-700">
<%= current_ip_address_role ? current_ip_address_role.ip_address : "None" %>
<span class="font-mono text-slate-500">
<span>
<%= link_to "IP Address Role", state_ip_address_roles_path, class: "text-blue-500 hover:text-blue-700" %>
</span>
<span class="font-mono text-slate-700 relative group">
<% if role = current_ip_address_role %>
<%= role.ip_address %> / <%= role.role %>
<% if role.description.present? %>
<div class="absolute hidden group-hover:block bg-slate-800 text-white text-sm rounded px-2 py-1 top-full left-0 mt-1 whitespace-nowrap z-10">
<%= role.description %>
</div>
<% end %>
<% else %>
None
<% end %>
</span>
</span>
</span>
<% end %>
</span>
<div class="flex-grow"></div>
<nav class="flex items-center space-x-4">

View File

@@ -0,0 +1,248 @@
# typed: false
require "rails_helper"
RSpec.describe State::IpAddressRolesController, type: :controller do
let(:user) { create(:user, :admin) }
let(:ip_address_role) { create(:ip_address_role) }
before { sign_in user }
describe "GET #index" do
it "returns a success response" do
get :index
expect(response).to be_successful
end
it "orders ip address roles by created_at desc" do
older_role = create(:ip_address_role, created_at: 2.days.ago)
newer_role = create(:ip_address_role, created_at: 1.day.ago)
get :index
expect(assigns(:ip_address_roles)).to eq([newer_role, older_role])
end
end
describe "GET #new" do
it "returns a success response" do
get :new
expect(response).to be_successful
end
end
describe "GET #edit" do
it "returns a success response" do
get :edit, params: { id: ip_address_role.id }
expect(response).to be_successful
end
end
describe "POST #create" do
context "with valid params" do
let(:valid_attributes) do
{
ip_address: "192.168.1.0/24",
role: "admin",
description: "Test role",
active: true,
}
end
it "creates a new IpAddressRole" do
expect {
post :create, params: { ip_address_role: valid_attributes }
}.to change(IpAddressRole, :count).by(1)
end
it "redirects to the ip_address_roles list" do
post :create, params: { ip_address_role: valid_attributes }
expect(response).to redirect_to(state_ip_address_roles_path)
end
end
context "with invalid params" do
let(:invalid_attributes) { { ip_address: "", role: "admin" } }
it "returns a success response (i.e. to display the 'new' template)" do
post :create, params: { ip_address_role: invalid_attributes }
expect(response).to be_successful
end
end
end
describe "PUT #update" do
context "with valid params" do
let(:new_attributes) do
{ description: "Updated description", active: false }
end
it "updates the requested ip_address_role" do
put :update,
params: {
id: ip_address_role.id,
ip_address_role: new_attributes,
}
ip_address_role.reload
expect(ip_address_role.description).to eq("Updated description")
expect(ip_address_role.active).to eq(false)
end
it "redirects to the ip_address_roles list" do
put :update,
params: {
id: ip_address_role.id,
ip_address_role: new_attributes,
}
expect(response).to redirect_to(state_ip_address_roles_path)
end
end
context "with invalid params" do
let(:invalid_attributes) { { ip_address: "" } }
it "returns a success response (i.e. to display the 'edit' template)" do
put :update,
params: {
id: ip_address_role.id,
ip_address_role: invalid_attributes,
}
expect(response).to be_successful
end
end
end
describe "DELETE #destroy" do
it "destroys the requested ip_address_role" do
ip_address_role # Create the record
expect { delete :destroy, params: { id: ip_address_role.id } }.to change(
IpAddressRole,
:count,
).by(-1)
end
it "redirects to the ip_address_roles list" do
delete :destroy, params: { id: ip_address_role.id }
expect(response).to redirect_to(state_ip_address_roles_path)
end
end
describe "authorization" do
let(:regular_user) { create(:user, :user) }
context "with a regular user" do
before { sign_in regular_user }
it "denies access to index" do
get :index
expect(response).to redirect_to(root_path)
expect(flash[:alert]).to eq(
"You are not authorized to perform this action.",
)
end
it "denies access to new" do
get :new
expect(response).to redirect_to(root_path)
expect(flash[:alert]).to eq(
"You are not authorized to perform this action.",
)
end
it "denies access to create" do
post :create,
params: {
ip_address_role: {
ip_address: "192.168.1.0/24",
role: "user",
},
}
expect(response).to redirect_to(root_path)
expect(flash[:alert]).to eq(
"You are not authorized to perform this action.",
)
end
it "denies access to edit" do
get :edit, params: { id: ip_address_role.id }
expect(response).to redirect_to(root_path)
expect(flash[:alert]).to eq(
"You are not authorized to perform this action.",
)
end
it "denies access to update" do
put :update,
params: {
id: ip_address_role.id,
ip_address_role: {
description: "test",
},
}
expect(response).to redirect_to(root_path)
expect(flash[:alert]).to eq(
"You are not authorized to perform this action.",
)
end
it "denies access to destroy" do
delete :destroy, params: { id: ip_address_role.id }
expect(response).to redirect_to(root_path)
expect(flash[:alert]).to eq(
"You are not authorized to perform this action.",
)
end
end
context "with no user" do
before { sign_out :user }
it "redirects to login for index" do
get :index
expect(response).to redirect_to(new_user_session_path)
end
it "redirects to login for new" do
get :new
expect(response).to redirect_to(new_user_session_path)
end
it "redirects to login for create and does not create the role" do
expect {
post :create,
params: {
ip_address_role: {
ip_address: "192.168.1.0/24",
role: "user",
},
}
}.not_to change(IpAddressRole, :count)
expect(response).to redirect_to(new_user_session_path)
end
it "redirects to login for edit" do
get :edit, params: { id: ip_address_role.id }
expect(response).to redirect_to(new_user_session_path)
end
it "redirects to login for update and does not update the role" do
original_description = ip_address_role.description
put :update,
params: {
id: ip_address_role.id,
ip_address_role: {
description: "unauthorized update",
},
}
expect(response).to redirect_to(new_user_session_path)
expect(ip_address_role.reload.description).to eq(original_description)
end
it "redirects to login for destroy and does not delete the role" do
ip_address_role # Create the record
expect {
delete :destroy, params: { id: ip_address_role.id }
}.not_to change(IpAddressRole, :count)
expect(response).to redirect_to(new_user_session_path)
end
end
end
end

View File

@@ -0,0 +1,9 @@
# typed: false
FactoryBot.define do
factory :ip_address_role do
sequence(:ip_address) { |n| "192.168.#{n}.0/24" }
role { :user }
description { "Test IP address role" }
active { true }
end
end