discourse/app/serializers/current_user_serializer.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

320 lines
7.8 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
2013-02-06 03:16:51 +08:00
class CurrentUserSerializer < BasicUserSerializer
include UserTagNotificationsMixin
include UserSidebarMixin
include UserStatusMixin
2013-02-06 03:16:51 +08:00
2013-02-26 00:42:20 +08:00
attributes :name,
:unread_notifications,
:unread_high_priority_notifications,
:all_unread_notifications_count,
:read_first_notification?,
2013-02-26 00:42:20 +08:00
:admin?,
:notification_channel_position,
:moderator?,
:staff?,
:whisperer?,
:title,
:any_posts,
:trust_level,
:can_send_private_email_messages,
:can_send_private_messages,
:can_upload_avatar,
:can_edit,
:can_invite_to_forum,
:no_password,
:can_delete_account,
:can_post_anonymously,
:can_ignore_users,
:can_delete_all_posts_and_topics,
:can_summarize,
:custom_fields,
2014-06-19 02:04:10 +08:00
: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,
2020-12-18 23:03:51 +08:00
:do_not_disturb_until,
:has_topic_draft,
:can_review,
:draft_count,
:pending_posts_count,
:grouped_unread_notifications,
:display_sidebar_tags,
:sidebar_tags,
:sidebar_category_ids,
:sidebar_sections,
:new_new_view_enabled?,
:use_experimental_topic_bulk_actions?,
:use_experimental_topic_bulk_actions?,
DEV: Convert header to glimmer (#25214) Here is a breakdown of the changes that will be implemented in this PR. # Widgets -> Glimmer Obviously, the intention of the todo here is to convert the header from widgets to glimmer. This PR splits the respective widgets as so: ### widgets/site-header.js ```mermaid height=200 flowchart TB A[widgets/site-header.js] A-->B[components/glimmer-site-header.gjs] ``` ### widgets/header.js and children ```mermaid height=200 flowchart TB A[widgets/header.js] A-->B[components/glimmer-header.gjs] B-->C[glimmer-header/contents.gjs] C-->D[./auth-buttons.gjs] C-->E[./icons.gjs] C-->F[./user-menu-wrapper.gjs] C-->G[./hamburger-dropdown-wrapper.gjs] C-->H[./user-menu-wrapper.gjs] C-->I[./sidebar-toggle.gjs] C-->J[./topic/info.gjs] ``` There are additional components rendered within the `glimmer-header/*` components, but I will leave those out for now. From this view you can see that we split apart the logic of `widgets/header.js` into 10+ components. Breaking apart these mega files has many benefits (readability, etc). # Services I have introduced a [header](https://github.com/discourse/discourse/blob/cdb42caa04ebcd1cf395dbe0cea96a13ce007099/app/assets/javascripts/discourse/app/services/header.js) service. This simplifies how we pass around data in the header, as well as fixes a bug we have with "swiping" menu panels. # Modifiers Added a [close-on-click-outside](https://github.com/discourse/discourse/blob/cdb42caa04ebcd1cf395dbe0cea96a13ce007099/app/assets/javascripts/discourse/app/modifiers/close-on-click-outside.js) modifier that is built upon the [close-on-click-outside modifier](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/float-kit/addon/modifiers/close-on-click-outside.js) that @jjaffeux built for float-kit. I think we could replace float-kit's implementation with mine and have it in a centralized location as they are extremely similar. # Tests Rewrote the existing header tests ([1](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/tests/integration/components/widgets/header-test.js), [2](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/tests/integration/components/site-header-test.js)) as system tests. # Other - Converted `widgets/user-status-bubble.js` to a gjs component - Converted `widgets/sidebar-toggle.js` to a gjs component - Converted `topicFeaturedLinkNode()` to a gjs component - Deprecated the [docking mixin](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/mixins/docking.js)
2024-02-24 02:08:15 +08:00
:use_admin_sidebar,
:glimmer_header_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 initialize(object, options = {})
super
options[:include_status] = true
end
def sidebar_sections
SidebarSection
.public_sections
.or(SidebarSection.where(user_id: object.id))
.includes(:sidebar_urls)
.order("(section_type IS NOT NULL) DESC, (public IS TRUE) DESC")
.map { |section| SidebarSectionSerializer.new(section, root: false) }
end
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
2013-02-06 03:16:51 +08:00
def can_create_group
scope.can_create_group?
end
def include_can_create_group?
scope.can_create_group?
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 use_admin_sidebar
object.admin? && object.in_any_groups?(SiteSetting.admin_sidebar_enabled_groups_map)
end
def include_user_admin_sidebar?
object.admin?
end
def can_post_anonymously
SiteSetting.allow_anonymous_posting &&
(is_anonymous || object.in_any_groups?(SiteSetting.anonymous_posting_allowed_groups_map))
end
def can_ignore_users
!is_anonymous && object.in_any_groups?(SiteSetting.ignore_allowed_groups_map)
end
def can_delete_all_posts_and_topics
object.in_any_groups?(SiteSetting.delete_all_posts_and_topics_allowed_groups_map)
end
def can_summarize
object.in_any_groups?(SiteSetting.custom_summarization_allowed_groups_map)
end
def can_upload_avatar
!is_anonymous && object.in_any_groups?(SiteSetting.uploaded_avatars_allowed_groups_map)
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?
2014-02-14 04:51:19 +08:00
scope.can_delete_user?(object)
end
def can_delete_account
2014-02-14 04:51:19 +08:00
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
2014-06-19 02:04:10 +08:00
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?
FEATURE: Rename 'Discourse SSO' to DiscourseConnect (#11978) The 'Discourse SSO' protocol is being rebranded to DiscourseConnect. This should help to reduce confusion when 'SSO' is used in the generic sense. This commit aims to: - Rename `sso_` site settings. DiscourseConnect specific ones are prefixed `discourse_connect_`. Generic settings are prefixed `auth_` - Add (server-side-only) backwards compatibility for the old setting names, with deprecation notices - Copy `site_settings` database records to the new names - Rename relevant translation keys - Update relevant translations This commit does **not** aim to: - Rename any Ruby classes or methods. This might be done in a future commit - Change any URLs. This would break existing integrations - Make any changes to the protocol. This would break existing integrations - Change any functionality. Further normalization across DiscourseConnect and other auth methods will be done separately The risks are: - There is no backwards compatibility for site settings on the client-side. Accessing auth-related site settings in Javascript is fairly rare, and an error on the client side would not be security-critical. - If a plugin is monkey-patching parts of the auth process, changes to locale keys could cause broken error messages. This should also be unlikely. The old site setting names remain functional, so security-related overrides will remain working. A follow-up commit will be made with a post-deploy migration to delete the old `site_settings` rows.
2021-02-08 18:04:33 +08:00
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 unseen_reviewable_count
Reviewable.unseen_reviewable_count(object)
end
def use_experimental_topic_bulk_actions?
scope.user.in_any_groups?(SiteSetting.experimental_topic_bulk_actions_enabled_groups_map)
end
2013-02-06 03:16:51 +08:00
end