discourse/app/controllers/admin/screened_ip_addresses_controller.rb
Isaac Janzen 1444702c84
DEV: Require admin for allow_admin screened IP mutations (#38545)
## Summary
- Moderators with IP visibility could create, update, and delete
`allow_admin` screened IP records, bypassing admin-only IP allowlist
controls
- Adds `before_action` guard restricting `allow_admin` mutations to
admins
- Moderators retain full access to `block` and `do_nothing` records
2026-03-12 10:43:19 -07:00

80 lines
2.3 KiB
Ruby
Vendored

# frozen_string_literal: true
class Admin::ScreenedIpAddressesController < Admin::StaffController
before_action :can_see_ip
before_action :fetch_screened_ip_address, only: %i[update destroy]
before_action :ensure_admin_for_allow_admin, only: %i[create update destroy]
def index
filter = params[:filter]
filter = IPAddr.handle_wildcards(filter)
screened_ip_addresses = ScreenedIpAddress
screened_ip_addresses =
screened_ip_addresses.where(
"cidr :filter >>= ip_address OR ip_address >>= cidr :filter",
filter: filter,
) if filter.present?
screened_ip_addresses = screened_ip_addresses.limit(200).order("match_count desc")
begin
screened_ip_addresses = screened_ip_addresses.to_a
rescue ActiveRecord::StatementInvalid
# postgresql throws a PG::InvalidTextRepresentation exception when filter isn't a valid cidr expression
screened_ip_addresses = []
end
render_serialized(screened_ip_addresses, ScreenedIpAddressSerializer)
end
def create
screened_ip_address = ScreenedIpAddress.new(allowed_params)
if screened_ip_address.save
render_serialized(screened_ip_address, ScreenedIpAddressSerializer)
else
render_json_error(screened_ip_address)
end
end
def update
if @screened_ip_address.update(allowed_params)
render_serialized(@screened_ip_address, ScreenedIpAddressSerializer)
else
render_json_error(@screened_ip_address)
end
end
def destroy
@screened_ip_address.destroy
render json: success_json
end
private
def can_see_ip
raise Discourse::InvalidAccess.new if !guardian.can_see_ip?
end
def ensure_admin_for_allow_admin
return if current_user.admin?
if params[:action_name].to_s == "allow_admin" ||
@screened_ip_address&.action_type == ScreenedIpAddress.actions[:allow_admin]
raise Discourse::InvalidAccess
end
end
def allowed_params
params.require(:ip_address)
permitted = params.permit(:ip_address, :action_name)
if permitted[:action_name].present? &&
!ScreenedIpAddress.actions.has_key?(permitted[:action_name].to_sym)
raise Discourse::InvalidParameters.new(:action_name)
end
permitted
end
def fetch_screened_ip_address
@screened_ip_address = ScreenedIpAddress.find(params[:id])
end
end