discourse/app/serializers/current_user_serializer.rb
Krzysztof Kotlarek e313190fdb
FEATURE: better UI to manage 2fa (#19338)
In this PR, we introduced an option, that when all authenticators are disabled, but backup codes still exists, user can authenticate with those backup codes. This was reverted as this is not expected behavior.

https://github.com/discourse/discourse/pull/18982

Instead, when the last authenticator is deleted, backup codes should be deleted as well. Because this disables 2fa, user is asked to confirm that action by typing text.

In addition, UI for 2fa preferences was refreshed.
2022-12-08 09:41:22 +11:00

312 lines
7.6 KiB
Ruby

# frozen_string_literal: true
class CurrentUserSerializer < BasicUserSerializer
include UserTagNotificationsMixin
include UserSidebarTagsMixin
attributes :name,
:unread_notifications,
:unread_private_messages,
:unread_high_priority_notifications,
:all_unread_notifications_count,
:read_first_notification?,
:admin?,
:notification_channel_position,
:moderator?,
:staff?,
:whisperer?,
:title,
:any_posts,
:trust_level,
:can_send_private_email_messages,
:can_send_private_messages,
:can_edit,
:can_invite_to_forum,
:no_password,
:can_delete_account,
:custom_fields,
:muted_category_ids,
:indirectly_muted_category_ids,
:regular_category_ids,
:tracked_category_ids,
:watched_first_post_category_ids,
:watched_category_ids,
:watched_tags,
:watching_first_post_tags,
:tracked_tags,
:muted_tags,
:regular_tags,
:dismissed_banner_key,
:is_anonymous,
:reviewable_count,
:unseen_reviewable_count,
:new_personal_messages_notifications_count,
:read_faq?,
:previous_visit_at,
:seen_notification_id,
:primary_group_id,
:flair_group_id,
:can_create_topic,
:can_create_group,
:link_posting_access,
:external_id,
:associated_account_ids,
:top_category_ids,
:groups,
:second_factor_enabled,
:ignored_users,
:featured_topic,
:do_not_disturb_until,
:has_topic_draft,
:can_review,
:draft_count,
:pending_posts_count,
:status,
:sidebar_category_ids,
:grouped_unread_notifications,
:redesigned_user_menu_enabled,
:redesigned_user_page_nav_enabled,
:sidebar_list_destination,
:redesigned_topic_timeline_enabled
delegate :user_stat, to: :object, private: true
delegate :any_posts, :draft_count, :pending_posts_count, :read_faq?, to: :user_stat
has_one :user_option, embed: :object, serializer: CurrentUserOptionSerializer
def groups
owned_group_ids = GroupUser.where(user_id: id, owner: true).pluck(:group_id).to_set
object.visible_groups.pluck(:id, :name, :has_messages).map do |id, name, has_messages|
group = { id: id, name: name, has_messages: has_messages }
group[:owner] = true if owned_group_ids.include?(id)
group
end
end
def link_posting_access
scope.link_posting_access
end
def can_create_topic
scope.can_create_topic?(nil)
end
def can_create_group
scope.can_create_group?
end
def include_can_create_group?
scope.can_create_group?
end
def sidebar_list_destination
object.user_option.sidebar_list_none_selected? ? SiteSetting.default_sidebar_list_destination : object.user_option.sidebar_list_destination
end
def can_send_private_email_messages
scope.can_send_private_messages_to_email?
end
def can_send_private_messages
scope.can_send_private_messages?
end
def can_edit
true
end
def can_invite_to_forum
scope.can_invite_to_forum?
end
def include_can_invite_to_forum?
scope.can_invite_to_forum?
end
def no_password
true
end
def include_no_password?
!object.has_password?
end
def include_can_delete_account?
scope.can_delete_user?(object)
end
def can_delete_account
true
end
def custom_fields
fields = nil
if SiteSetting.public_user_custom_fields.present?
fields = SiteSetting.public_user_custom_fields.split('|')
end
DiscoursePluginRegistry.serialized_current_user_fields.each do |f|
fields ||= []
fields << f
end
if fields.present?
User.custom_fields_for_ids([object.id], fields)[object.id] || {}
else
{}
end
end
def muted_category_ids
categories_with_notification_level(:muted)
end
def indirectly_muted_category_ids
CategoryUser.indirectly_muted_category_ids(object)
end
def regular_category_ids
categories_with_notification_level(:regular)
end
def tracked_category_ids
categories_with_notification_level(:tracking)
end
def watched_category_ids
categories_with_notification_level(:watching)
end
def watched_first_post_category_ids
categories_with_notification_level(:watching_first_post)
end
def ignored_users
IgnoredUser.where(user: object.id).joins(:ignored_user).pluck(:username)
end
def top_category_ids
omitted_notification_levels = [CategoryUser.notification_levels[:muted], CategoryUser.notification_levels[:regular]]
CategoryUser.where(user_id: object.id)
.where.not(notification_level: omitted_notification_levels)
.order("
CASE
WHEN notification_level = 3 THEN 1
WHEN notification_level = 2 THEN 2
WHEN notification_level = 4 THEN 3
END")
.pluck(:category_id)
.slice(0, SiteSetting.header_dropdown_category_count)
end
def dismissed_banner_key
object.user_profile.dismissed_banner_key
end
def is_anonymous
object.anonymous?
end
def can_review
scope.can_see_review_queue?
end
def include_primary_group_id?
object.primary_group_id.present?
end
def external_id
object&.single_sign_on_record&.external_id
end
def include_external_id?
SiteSetting.enable_discourse_connect
end
def associated_account_ids
values = {}
object.user_associated_accounts.map do |user_associated_account|
values[user_associated_account.provider_name] = user_associated_account.provider_uid
end
values
end
def include_associated_account_ids?
SiteSetting.include_associated_account_ids
end
def second_factor_enabled
object.totp_enabled? || object.security_keys_enabled?
end
def featured_topic
object.user_profile.featured_topic
end
def has_topic_draft
true
end
def include_has_topic_draft?
Draft.has_topic_draft(object)
end
def sidebar_category_ids
object.category_sidebar_section_links.pluck(:linkable_id) & scope.allowed_category_ids
end
def include_sidebar_category_ids?
SiteSetting.enable_experimental_sidebar_hamburger
end
def include_status?
SiteSetting.enable_user_status && object.has_status?
end
def status
UserStatusSerializer.new(object.user_status, root: false)
end
def unseen_reviewable_count
Reviewable.unseen_reviewable_count(object)
end
def redesigned_user_menu_enabled
object.redesigned_user_menu_enabled?
end
def include_all_unread_notifications_count?
redesigned_user_menu_enabled
end
def include_grouped_unread_notifications?
redesigned_user_menu_enabled
end
def include_unseen_reviewable_count?
redesigned_user_menu_enabled
end
def include_new_personal_messages_notifications_count?
redesigned_user_menu_enabled
end
def redesigned_user_page_nav_enabled
if SiteSetting.enable_new_user_profile_nav_groups.present?
object.in_any_groups?(SiteSetting.enable_new_user_profile_nav_groups_map)
else
false
end
end
def redesigned_topic_timeline_enabled
if SiteSetting.enable_experimental_topic_timeline_groups.present?
object.in_any_groups?(SiteSetting.enable_experimental_topic_timeline_groups.split("|").map(&:to_i))
else
false
end
end
end