mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-11 11:25:16 +08:00
When a site is created, any staff users created in that period should not see a blue dot for the upcoming change link in the admin sidebar, we don't need to notify them of "new" upcoming changes when they have only just joined. Additionally, any new admins or moderators created later on should also not immediately see a blue dot in the upcoming change sidebar, though these changes are "new" to them, they could potentially be quite old upcoming changes.
551 lines
16 KiB
Ruby
551 lines
16 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe CurrentUserSerializer do
|
|
fab!(:user)
|
|
subject(:serializer) { described_class.new(user, scope: guardian, root: false) }
|
|
|
|
let(:guardian) { user.guardian }
|
|
|
|
context "when SSO is not enabled" do
|
|
it "should not include the external_id field" do
|
|
payload = serializer.as_json
|
|
expect(payload).not_to have_key(:external_id)
|
|
end
|
|
end
|
|
|
|
context "when SSO is enabled" do
|
|
let :user do
|
|
user = Fabricate(:user)
|
|
SingleSignOnRecord.create!(user_id: user.id, external_id: "12345", last_payload: "")
|
|
user
|
|
end
|
|
|
|
it "should include the external_id" do
|
|
SiteSetting.discourse_connect_url = "http://example.com/discourse_sso"
|
|
SiteSetting.discourse_connect_secret = "12345678910"
|
|
SiteSetting.enable_discourse_connect = true
|
|
payload = serializer.as_json
|
|
expect(payload[:external_id]).to eq("12345")
|
|
end
|
|
end
|
|
|
|
describe "#top_category_ids" do
|
|
fab!(:category1, :category)
|
|
fab!(:category2, :category)
|
|
fab!(:category3, :category)
|
|
|
|
it "should include empty top_category_ids array" do
|
|
payload = serializer.as_json
|
|
expect(payload[:top_category_ids]).to eq([])
|
|
end
|
|
|
|
it "should include correct id in top_category_ids array" do
|
|
_category = Category.first
|
|
CategoryUser.create!(
|
|
user_id: user.id,
|
|
category_id: category1.id,
|
|
notification_level: CategoryUser.notification_levels[:tracking],
|
|
)
|
|
|
|
CategoryUser.create!(
|
|
user_id: user.id,
|
|
category_id: category2.id,
|
|
notification_level: CategoryUser.notification_levels[:watching],
|
|
)
|
|
|
|
CategoryUser.create!(
|
|
user_id: user.id,
|
|
category_id: category3.id,
|
|
notification_level: CategoryUser.notification_levels[:regular],
|
|
)
|
|
|
|
payload = serializer.as_json
|
|
expect(payload[:top_category_ids]).to eq([category2.id, category1.id])
|
|
end
|
|
end
|
|
|
|
describe "#muted_tag" do
|
|
fab!(:tag)
|
|
|
|
let!(:tag_user) do
|
|
TagUser.create!(
|
|
user_id: user.id,
|
|
notification_level: TagUser.notification_levels[:muted],
|
|
tag_id: tag.id,
|
|
)
|
|
end
|
|
|
|
it "includes muted tags" do
|
|
payload = serializer.as_json
|
|
expect(payload[:muted_tags]).to eq([{ id: tag.id, name: tag.name, slug: tag.slug }])
|
|
end
|
|
end
|
|
|
|
describe "#second_factor_enabled" do
|
|
let(:guardian) { user.guardian }
|
|
let(:json) { serializer.as_json }
|
|
|
|
it "is false by default" do
|
|
expect(json[:second_factor_enabled]).to eq(false)
|
|
end
|
|
|
|
context "when totp enabled" do
|
|
before { User.any_instance.stubs(:totp_enabled?).returns(true) }
|
|
|
|
it "is true" do
|
|
expect(json[:second_factor_enabled]).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when security_keys enabled" do
|
|
before { User.any_instance.stubs(:security_keys_enabled?).returns(true) }
|
|
|
|
it "is true" do
|
|
expect(json[:second_factor_enabled]).to eq(true)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#groups" do
|
|
it "should only show visible groups" do
|
|
Fabricate(:group, visibility_level: Group.visibility_levels[:public])
|
|
hidden_group = Fabricate(:group, visibility_level: Group.visibility_levels[:owners])
|
|
public_group =
|
|
Fabricate(
|
|
:group,
|
|
visibility_level: Group.visibility_levels[:public],
|
|
name: "UppercaseGroupName",
|
|
)
|
|
hidden_group.add(user)
|
|
public_group.add(user)
|
|
payload = serializer.as_json
|
|
|
|
expect(payload[:groups]).to contain_exactly(
|
|
{ id: public_group.id, name: public_group.name, has_messages: false },
|
|
)
|
|
end
|
|
end
|
|
|
|
describe "#can_ignore_users" do
|
|
let(:guardian) { user.guardian }
|
|
let(:payload) { serializer.as_json }
|
|
|
|
context "when user is a regular one" do
|
|
let(:user) { Fabricate(:user) }
|
|
|
|
it "return false for regular users" do
|
|
expect(payload[:can_ignore_users]).to eq(false)
|
|
end
|
|
end
|
|
|
|
context "when user is a staff member" do
|
|
let(:user) { Fabricate(:moderator) }
|
|
|
|
it "returns true" do
|
|
expect(payload[:can_ignore_users]).to eq(true)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#can_review" do
|
|
let(:guardian) { user.guardian }
|
|
let(:payload) { serializer.as_json }
|
|
|
|
context "when user is a regular one" do
|
|
let(:user) { Fabricate(:user) }
|
|
|
|
it "return false for regular users" do
|
|
expect(payload[:can_review]).to eq(false)
|
|
end
|
|
end
|
|
|
|
context "when user is a staff member" do
|
|
let(:user) { Fabricate(:admin) }
|
|
|
|
it "returns true" do
|
|
expect(payload[:can_review]).to eq(true)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#pending_posts_count" do
|
|
subject(:pending_posts_count) { serializer.pending_posts_count }
|
|
|
|
let(:user) { Fabricate(:user) }
|
|
|
|
before { user.user_stat.pending_posts_count = 3 }
|
|
|
|
it "serializes 'pending_posts_count'" do
|
|
expect(pending_posts_count).to eq 3
|
|
end
|
|
end
|
|
|
|
describe "#status" do
|
|
fab!(:user_status)
|
|
fab!(:user) { Fabricate(:user, user_status: user_status) }
|
|
let(:serializer) { described_class.new(user, scope: user.guardian, root: false) }
|
|
|
|
it "adds user status when enabled" do
|
|
SiteSetting.enable_user_status = true
|
|
|
|
json = serializer.as_json
|
|
|
|
expect(json[:status]).to_not be_nil do |status|
|
|
expect(status.description).to eq(user_status.description)
|
|
expect(status.emoji).to eq(user_status.emoji)
|
|
end
|
|
end
|
|
|
|
it "doesn't add user status when disabled" do
|
|
SiteSetting.enable_user_status = false
|
|
json = serializer.as_json
|
|
expect(json.keys).not_to include :status
|
|
end
|
|
|
|
it "doesn't add expired user status" do
|
|
SiteSetting.enable_user_status = true
|
|
|
|
user.user_status.ends_at = 1.minute.ago
|
|
serializer = described_class.new(user, scope: user.guardian, root: false)
|
|
json = serializer.as_json
|
|
|
|
expect(json.keys).not_to include :status
|
|
end
|
|
|
|
it "doesn't return status if user doesn't have it set" do
|
|
SiteSetting.enable_user_status = true
|
|
|
|
user.clear_status!
|
|
user.reload
|
|
json = serializer.as_json
|
|
|
|
expect(json.keys).not_to include :status
|
|
end
|
|
end
|
|
|
|
describe "#likes_notifications_disabled" do
|
|
it "is true if the user disables likes notifications" do
|
|
user.user_option.update!(
|
|
like_notification_frequency: UserOption.like_notification_frequency_type[:never],
|
|
)
|
|
expect(serializer.as_json[:user_option][:likes_notifications_disabled]).to eq(true)
|
|
end
|
|
|
|
it "is false if the user doesn't disable likes notifications" do
|
|
user.user_option.update!(
|
|
like_notification_frequency: UserOption.like_notification_frequency_type[:always],
|
|
)
|
|
expect(serializer.as_json[:user_option][:likes_notifications_disabled]).to eq(false)
|
|
user.user_option.update!(
|
|
like_notification_frequency:
|
|
UserOption.like_notification_frequency_type[:first_time_and_daily],
|
|
)
|
|
expect(serializer.as_json[:user_option][:likes_notifications_disabled]).to eq(false)
|
|
user.user_option.update!(
|
|
like_notification_frequency: UserOption.like_notification_frequency_type[:first_time],
|
|
)
|
|
expect(serializer.as_json[:user_option][:likes_notifications_disabled]).to eq(false)
|
|
end
|
|
end
|
|
|
|
describe "#associated_account_ids" do
|
|
before do
|
|
UserAssociatedAccount.create(
|
|
user_id: user.id,
|
|
provider_name: "twitter",
|
|
provider_uid: "1",
|
|
info: {
|
|
nickname: "sam",
|
|
},
|
|
)
|
|
end
|
|
|
|
it "should not include associated account ids by default" do
|
|
expect(serializer.as_json[:associated_account_ids]).to be_nil
|
|
end
|
|
|
|
it "should include associated account ids when site setting enabled" do
|
|
SiteSetting.include_associated_account_ids = true
|
|
expect(serializer.as_json[:associated_account_ids]).to eq({ "twitter" => "1" })
|
|
end
|
|
end
|
|
|
|
describe "#new_personal_messages_notifications_count" do
|
|
fab!(:notification) do
|
|
Fabricate(
|
|
:notification,
|
|
user: user,
|
|
read: false,
|
|
notification_type: Notification.types[:private_message],
|
|
)
|
|
end
|
|
|
|
it "is included when sidebar is enabled" do
|
|
SiteSetting.navigation_menu = "sidebar"
|
|
|
|
expect(serializer.as_json[:new_personal_messages_notifications_count]).to eq(1)
|
|
end
|
|
end
|
|
|
|
include_examples "User Sidebar Serializer Attributes", described_class
|
|
|
|
describe "#sidebar_sections" do
|
|
fab!(:group)
|
|
fab!(:sidebar_section) { Fabricate(:sidebar_section, user: user) }
|
|
|
|
it "eager loads sidebar_urls" do
|
|
custom_sidebar_section_link_1 =
|
|
Fabricate(:custom_sidebar_section_link, user: user, sidebar_section: sidebar_section)
|
|
|
|
# warmup
|
|
described_class.new(user, scope: user.guardian, root: false).as_json
|
|
|
|
initial_count =
|
|
track_sql_queries do
|
|
serialized = described_class.new(user, scope: user.guardian, root: false).as_json
|
|
|
|
expect(serialized[:sidebar_sections].count).to eq(2)
|
|
|
|
expect(serialized[:sidebar_sections].last[:links].map { |link| link.id }).to eq(
|
|
[custom_sidebar_section_link_1.linkable.id],
|
|
)
|
|
end.count
|
|
|
|
custom_sidebar_section_link_2 =
|
|
Fabricate(:custom_sidebar_section_link, user: user, sidebar_section: sidebar_section)
|
|
|
|
final_count =
|
|
track_sql_queries do
|
|
serialized = described_class.new(user, scope: user.guardian, root: false).as_json
|
|
|
|
expect(serialized[:sidebar_sections].count).to eq(2)
|
|
|
|
expect(serialized[:sidebar_sections].last[:links].map { |link| link.id }).to eq(
|
|
[custom_sidebar_section_link_1.linkable.id, custom_sidebar_section_link_2.linkable.id],
|
|
)
|
|
end.count
|
|
|
|
expect(initial_count).to eq(final_count)
|
|
end
|
|
end
|
|
|
|
describe "#can_create_category" do
|
|
let(:payload) { serializer.as_json }
|
|
|
|
context "when user is an admin" do
|
|
let(:user) { Fabricate(:admin) }
|
|
|
|
it "returns true" do
|
|
expect(payload[:can_create_category]).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when user is a moderator and moderators_manage_categories is enabled" do
|
|
let(:user) { Fabricate(:moderator) }
|
|
|
|
before { SiteSetting.moderators_manage_categories = true }
|
|
|
|
it "returns true" do
|
|
expect(payload[:can_create_category]).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when user is a moderator and moderators_manage_categories is disabled" do
|
|
let(:user) { Fabricate(:moderator) }
|
|
|
|
before { SiteSetting.moderators_manage_categories = false }
|
|
|
|
it "is not included" do
|
|
expect(payload).not_to have_key(:can_create_category)
|
|
end
|
|
end
|
|
|
|
context "when user is a regular user" do
|
|
it "is not included" do
|
|
expect(payload).not_to have_key(:can_create_category)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#can_see_ip" do
|
|
let(:payload) { serializer.as_json }
|
|
|
|
context "when user is an admin" do
|
|
let(:user) { Fabricate(:admin) }
|
|
|
|
it "includes can_see_ip as true" do
|
|
expect(payload[:can_see_ip]).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when user is a moderator and moderators_view_ips is enabled" do
|
|
let(:user) { Fabricate(:moderator) }
|
|
|
|
before { SiteSetting.moderators_view_ips = true }
|
|
|
|
it "includes can_see_ip as true" do
|
|
expect(payload[:can_see_ip]).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when user is a moderator and moderators_view_ips is disabled" do
|
|
let(:user) { Fabricate(:moderator) }
|
|
|
|
before { SiteSetting.moderators_view_ips = false }
|
|
|
|
it "does not include can_see_ip" do
|
|
expect(payload).not_to have_key(:can_see_ip)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#featured_topic" do
|
|
fab!(:featured_topic, :topic)
|
|
|
|
before { user.user_profile.update!(featured_topic_id: featured_topic.id) }
|
|
|
|
it "includes the featured topic" do
|
|
payload = serializer.as_json
|
|
|
|
expect(payload[:featured_topic]).to_not be_nil
|
|
expect(payload[:featured_topic][:id]).to eq(featured_topic.id)
|
|
expect(payload[:featured_topic][:title]).to eq(featured_topic.title)
|
|
expect(payload[:featured_topic].keys).to contain_exactly(
|
|
:id,
|
|
:title,
|
|
:fancy_title,
|
|
:slug,
|
|
:posts_count,
|
|
)
|
|
end
|
|
end
|
|
|
|
describe "#show_site_owner_onboarding" do
|
|
fab!(:admin)
|
|
fab!(:topic)
|
|
fab!(:another_admin, :admin)
|
|
|
|
let(:admin_serializer) { described_class.new(admin, scope: Guardian.new(admin), root: false) }
|
|
|
|
before { SiteSetting.enable_site_owner_onboarding = true }
|
|
|
|
it "is not included for non-admin users" do
|
|
payload = serializer.as_json
|
|
expect(payload).not_to have_key(:show_site_owner_onboarding)
|
|
end
|
|
|
|
it "is not included when setting is disabled" do
|
|
SiteSetting.enable_site_owner_onboarding = false
|
|
payload = admin_serializer.as_json
|
|
expect(payload).not_to have_key(:show_site_owner_onboarding)
|
|
end
|
|
|
|
it "is true for the first admin on a new site" do
|
|
payload = admin_serializer.as_json
|
|
expect(payload[:show_site_owner_onboarding]).to eq(true)
|
|
end
|
|
|
|
it "is not included for a second admin" do
|
|
serializer2 =
|
|
described_class.new(another_admin, scope: Guardian.new(another_admin), root: false)
|
|
payload = serializer2.as_json
|
|
expect(payload).not_to have_key(:show_site_owner_onboarding)
|
|
end
|
|
|
|
it "is not included when the site is older than the max days setting" do
|
|
SiteSetting.site_owner_onboarding_max_days = 5
|
|
Topic.update_all(created_at: 6.days.ago)
|
|
payload = admin_serializer.as_json
|
|
expect(payload).not_to have_key(:show_site_owner_onboarding)
|
|
end
|
|
end
|
|
|
|
describe "#can_toggle_nested_mode" do
|
|
it "is not included when nested replies is disabled" do
|
|
SiteSetting.nested_replies_enabled = false
|
|
expect(serializer.as_json).not_to have_key(:can_toggle_nested_mode)
|
|
end
|
|
|
|
context "when nested replies is enabled" do
|
|
before { SiteSetting.nested_replies_enabled = true }
|
|
|
|
it "is true when user is in an allowed group" do
|
|
SiteSetting.nested_replies_toggle_mode_groups = Group::AUTO_GROUPS[:staff].to_s
|
|
user.update!(admin: true)
|
|
Group.refresh_automatic_groups!
|
|
user.reload
|
|
expect(serializer.as_json[:can_toggle_nested_mode]).to eq(true)
|
|
end
|
|
|
|
it "is false when user is not in an allowed group" do
|
|
SiteSetting.nested_replies_toggle_mode_groups = Group::AUTO_GROUPS[:staff].to_s
|
|
expect(serializer.as_json[:can_toggle_nested_mode]).to eq(false)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#has_new_upcoming_changes" do
|
|
def serialize_for(user)
|
|
described_class.new(user, scope: user.guardian, root: false).as_json
|
|
end
|
|
|
|
it "is false for an admin created during the new-site window, regardless of `added` events" do
|
|
Discourse.stubs(:site_creation_date).returns(10.minutes.ago)
|
|
admin = Fabricate(:admin)
|
|
UpcomingChangeEvent.create!(
|
|
event_type: :added,
|
|
upcoming_change_name: "some_setting",
|
|
created_at: 5.minutes.ago,
|
|
)
|
|
UpcomingChangeEvent.create!(
|
|
event_type: :added,
|
|
upcoming_change_name: "future_setting",
|
|
created_at: 1.minute.from_now,
|
|
)
|
|
expect(serialize_for(admin)[:has_new_upcoming_changes]).to eq(false)
|
|
end
|
|
|
|
it "ignores `added` events that predate the user when no last_visited is set" do
|
|
Discourse.stubs(:site_creation_date).returns(2.years.ago)
|
|
UpcomingChangeEvent.create!(
|
|
event_type: :added,
|
|
upcoming_change_name: "old_setting",
|
|
created_at: 1.year.ago,
|
|
)
|
|
admin = Fabricate(:admin)
|
|
expect(serialize_for(admin)[:has_new_upcoming_changes]).to eq(false)
|
|
end
|
|
|
|
it "shows `added` events created after the user when no last_visited is set" do
|
|
Discourse.stubs(:site_creation_date).returns(2.years.ago)
|
|
admin = Fabricate(:admin)
|
|
UpcomingChangeEvent.create!(
|
|
event_type: :added,
|
|
upcoming_change_name: "fresh_setting",
|
|
created_at: 1.minute.from_now,
|
|
)
|
|
expect(serialize_for(admin)[:has_new_upcoming_changes]).to eq(true)
|
|
end
|
|
|
|
it "honors last_visited_upcoming_changes_at when set" do
|
|
Discourse.stubs(:site_creation_date).returns(2.years.ago)
|
|
admin = Fabricate(:admin)
|
|
admin.custom_fields["last_visited_upcoming_changes_at"] = 1.hour.ago.iso8601
|
|
admin.save_custom_fields
|
|
|
|
UpcomingChangeEvent.create!(
|
|
event_type: :added,
|
|
upcoming_change_name: "before_visit",
|
|
created_at: 2.hours.ago,
|
|
)
|
|
expect(serialize_for(admin)[:has_new_upcoming_changes]).to eq(false)
|
|
|
|
UpcomingChangeEvent.create!(
|
|
event_type: :added,
|
|
upcoming_change_name: "after_visit",
|
|
created_at: 1.minute.ago,
|
|
)
|
|
expect(serialize_for(admin)[:has_new_upcoming_changes]).to eq(true)
|
|
end
|
|
end
|
|
end
|