discourse/app/controllers/admin/screened_ip_addresses_controller.rb
benj 72e4e53fda
FEATURE: add option to hide IP addresses from moderators (#33682)
# Hide IP Addresses from Moderators When `moderators_view_ips` is
Disabled

## Summary 
Feature Request Link -
https://meta.discourse.org/t/option-to-hide-ip-addresses-from-moderators/207715/51
This PR implements a feature to **hide IP addresses from moderators**
when the `moderators_view_ips` site setting is disabled. Previously,
moderators could view IPs in multiple locations across the admin UI.
This update ensures that IP addresses are visible to moderators when the
setting allows it.

## Changes Implemented  

### Backend Updates
- **Added `moderators_view_ips` site setting** in `site_settings.yml`
- **Updated `CurrentUserSerializer`** to include `can_see_ip` field
based on the user’s role and site setting.
- **Modified `AdminUserSerializer`** to restrict IP address visibility.
- **Updated `UsersController`** to prevent IP addresses from being
included in API responses.
- **Restricted IPs in `ScreenedIpAddressesController`** by throwing
`Discourse::InvalidAccess` if the user lacks permission.

### Frontend Updates
- **Hid "Screened IPs" tab** in `/admin/logs` when `moderators_view_ips`
is disabled.
- **Blocked direct access to `/admin/logs/screened_ip_addresses`** for
unauthorized users.
- **Updated `user-index.hbs` and `logs.hbs`** to conditionally hide IP
fields.

### UI Screenshots

New option for Admins in the Admin Security settings dashboard:
![Screenshot 2025-02-21 at 5 32
00 PM](https://github.com/user-attachments/assets/5b315434-7724-4cb9-a3dc-d88750df00a6)


Moderator's view before:
![Screenshot 2025-02-21 at 5 25
41 PM](https://github.com/user-attachments/assets/0fb269e2-db40-488b-b11d-8bdfbe2a5245)
Moderator's view after:
![Screenshot 2025-02-21 at 5 26
59 PM](https://github.com/user-attachments/assets/efb848b0-1d7f-4ec9-8238-d8ee4eddbbe1)

Moderator's view before:
![Screenshot 2025-02-21 at 5 23
52 PM](https://github.com/user-attachments/assets/226e6d63-df3e-45d0-833f-de52593a086e)
Moderator's view after:
![Screenshot 2025-02-21 at 5 23
15 PM](https://github.com/user-attachments/assets/af313af2-2329-46d1-827d-290243c320e5)

---------

Co-authored-by: Bennett Dungan <bennettdungan@gmail.com>
2025-08-05 10:09:02 -05:00

65 lines
1.8 KiB
Ruby

# frozen_string_literal: true
class Admin::ScreenedIpAddressesController < Admin::StaffController
before_action :can_see_ip
before_action :fetch_screened_ip_address, only: %i[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 allowed_params
params.require(:ip_address)
params.permit(:ip_address, :action_name)
end
def fetch_screened_ip_address
@screened_ip_address = ScreenedIpAddress.find(params[:id])
end
end