0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-05 22:42:07 +08:00
discourse/app/serializers/admin_detailed_user_serializer.rb
Juan David Martínez Cubillos 54ed0fa270
DEV: External IDs, and hidden groups to admins only. Allow moderators to see SSO when the moderators_view_sso_details site setting is enabled (#41496)
#### Description

Moderators could access admin-only SSO, external identity and hidden
groups data via GET /admin/users/:id.json — the single_sign_on_record
field, external_ids field and hidden groups were serialized
unconditionally for all staff members instead of being restricted to
admins. This PR restricts External IDs, and hidden group to admins only
but allows moderators to see SSO information when the
`moderators_view_sso_details` SiteSetting is enabled

Context: `t/180409`
2026-08-03 11:25:34 -05:00

208 lines
4.7 KiB
Ruby
Vendored

# frozen_string_literal: true
class AdminDetailedUserSerializer < AdminUserSerializer
attributes :moderator,
:can_grant_admin,
:can_revoke_admin,
:can_grant_moderation,
:can_revoke_moderation,
:can_impersonate,
:like_count,
:like_given_count,
:post_count,
:topic_count,
:post_edits_count,
:flags_given_count,
:flags_received_count,
:private_topics_count,
:can_delete_all_posts,
:can_be_deleted,
:can_be_anonymized,
:can_be_merged,
:full_suspend_reason,
:suspended_till,
:full_silence_reason,
:silence_reason,
:penalty_counts,
:next_penalty,
:primary_group_id,
:badge_count,
:warnings_received_count,
:user_fields,
:bounce_score,
:reset_bounce_score_after,
:can_view_action_logs,
:second_factor_enabled,
:can_disable_second_factor,
:can_delete_sso_record,
:api_key_count,
:external_ids,
:similar_users_count,
:latest_export,
:upcoming_changes_stats
has_one :approved_by, serializer: BasicUserSerializer, embed: :objects
has_one :suspended_by, serializer: BasicUserSerializer, embed: :objects
has_one :silenced_by, serializer: BasicUserSerializer, embed: :objects
has_one :tl3_requirements, serializer: TrustLevel3RequirementsSerializer, embed: :objects
has_many :groups, embed: :object, serializer: BasicGroupSerializer
def include_name?
scope.user.admin?
end
def second_factor_enabled
object.totp_enabled? || object.security_keys_enabled?
end
def can_disable_second_factor
scope.is_admin? && (object&.id != scope.user.id)
end
def can_revoke_admin
scope.can_revoke_admin?(object)
end
def can_grant_admin
scope.can_grant_admin?(object)
end
def can_revoke_moderation
scope.can_revoke_moderation?(object)
end
def can_grant_moderation
scope.can_grant_moderation?(object)
end
def can_delete_all_posts
scope.can_delete_all_posts?(object)
end
def can_be_deleted
scope.can_delete_user?(object)
end
def can_be_anonymized
scope.can_anonymize_user?(object)
end
def can_be_merged
scope.can_merge_user?(object)
end
def topic_count
object.topics.count
end
def include_api_key?
scope.is_admin? && api_key.present?
end
def suspended_by
object.suspend_record.try(:acting_user)
end
def silence_reason
object.silence_reason
end
def penalty_counts
TrustLevel3Requirements.new(object).penalty_counts
end
def next_penalty
step_number = penalty_counts.total
steps = SiteSetting.penalty_step_hours.split("|")
step_number = [step_number, steps.length].min
penalty_hours = steps[step_number]
Integer(penalty_hours, 10).hours.from_now
rescue StandardError
nil
end
def silenced_by
object.silenced_record.try(:acting_user)
end
def include_tl3_requirements?
object.has_trust_level?(TrustLevel[2])
end
def include_user_fields?
object.user_fields.present?
end
def bounce_score
object.user_stat.bounce_score
end
def reset_bounce_score_after
object.user_stat.reset_bounce_score_after
end
def can_view_action_logs
scope.can_view_action_logs?(object)
end
def post_count
object.posts.count
end
def api_key_count
object.api_keys.active.count
end
def include_external_ids?
scope.is_admin?
end
def external_ids
external_ids = {}
object.user_associated_accounts.map do |user_associated_account|
external_ids[user_associated_account.provider_name] = user_associated_account.provider_uid
end
external_ids
end
def similar_users_count
@options[:similar_users_count]
end
def include_similar_users_count?
@options[:similar_users_count].present?
end
def can_delete_sso_record
scope.can_delete_sso_record?(object)
end
def latest_export
export =
UserExport
.where(user_id: object&.id)
.where("created_at > ?", UserExport::DESTROY_CREATED_BEFORE.ago)
.order(created_at: :desc)
.first
UserExportSerializer.new(export, scope:).as_json if export
end
def include_latest_export?
scope.can_export_entity?("user_archive", object.id)
end
def upcoming_changes_stats
object.upcoming_change_stats(scope)
end
def include_upcoming_changes_stats?
scope.is_staff?
end
def groups
object.groups.visible_groups(scope.user)
end
end