mirror of
https://github.com/discourse/discourse.git
synced 2026-08-06 05:42:36 +08:00
## Summary The public `GET /user_actions.json` endpoint accepted an unbounded client-supplied `limit` and forwarded it directly into the activity query, allowing an anonymous request to materialize and serialize an arbitrarily large number of actions. The controller now caps the effective limit at 100 while preserving the default of 30 and smaller caller-requested values, so oversized requests return a bounded page without excessive resource use. Public-action visibility and authorization filtering are unchanged. ## Source - Patch Triage: https://patch.discourse.org/patch-triage/1588
69 lines
2.1 KiB
Ruby
Vendored
69 lines
2.1 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
class UserActionsController < ApplicationController
|
|
def index
|
|
user_actions_params.require(:username)
|
|
|
|
user =
|
|
fetch_user_from_params(
|
|
include_inactive:
|
|
current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts),
|
|
)
|
|
offset = [0, user_actions_params[:offset].to_i].max
|
|
action_types = (user_actions_params[:filter] || "").split(",").map(&:to_i)
|
|
limit = [user_actions_params.fetch(:limit, 30).to_i, 100].min
|
|
|
|
ensure_user_actions_visible!(user, action_types)
|
|
|
|
if action_types.empty? && !guardian.can_see_user_actions?(user, UserAction.private_types)
|
|
action_types = UserAction.types.values - UserAction.private_types
|
|
end
|
|
|
|
opts = {
|
|
user_id: user.id,
|
|
user: user,
|
|
offset: offset,
|
|
limit: limit,
|
|
action_types: action_types,
|
|
guardian: guardian,
|
|
ignore_private_messages: params[:filter].blank?,
|
|
acting_username: params[:acting_username],
|
|
}
|
|
|
|
stream = UserAction.stream(opts).to_a
|
|
|
|
response = { user_actions: serialize_data(stream, UserActionSerializer) }
|
|
|
|
if guardian.can_lazy_load_categories?
|
|
category_ids = stream.map(&:category_id).compact.uniq
|
|
categories = Category.secured(guardian).with_parents(category_ids)
|
|
response[:categories] = serialize_data(categories, CategoryBadgeSerializer)
|
|
end
|
|
|
|
render json: response
|
|
end
|
|
|
|
def show
|
|
params.require(:id)
|
|
stream_item = UserAction.stream_item(params[:id], guardian)
|
|
raise Discourse::NotFound if stream_item.blank?
|
|
|
|
user = User.find_by(id: stream_item.target_user_id)
|
|
raise Discourse::NotFound if user.blank?
|
|
|
|
ensure_user_actions_visible!(user, [stream_item.action_type])
|
|
|
|
render_serialized(stream_item, UserActionSerializer)
|
|
end
|
|
|
|
private
|
|
|
|
def ensure_user_actions_visible!(user, action_types)
|
|
raise Discourse::NotFound unless guardian.can_see_profile?(user)
|
|
raise Discourse::NotFound unless guardian.can_see_user_actions?(user, action_types)
|
|
end
|
|
|
|
def user_actions_params
|
|
@user_actions_params ||= params.permit(:username, :filter, :offset, :acting_username, :limit)
|
|
end
|
|
end
|