mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-27 18:59:19 +08:00
Policy reminder jobs could create `topic_reminder` notifications for users who were in the policy group but could not see the policy post. That allowed restricted policy topics to be referenced by reminder notifications even though the topic itself remained private. This commit fixes `Jobs::DiscoursePolicy::CheckPolicy` to check post visibility for each missing policy user before replacing the reminder notification. Users who cannot see the post are skipped, while visible policy users continue to receive the reminder.
361 lines
8.6 KiB
Ruby
Vendored
361 lines
8.6 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
describe Jobs::DiscoursePolicy::CheckPolicy do
|
|
subject(:job) { described_class.new }
|
|
|
|
fab!(:user1, :user)
|
|
fab!(:user2, :user)
|
|
|
|
fab!(:group) do
|
|
group = Fabricate(:group)
|
|
group.add(user1)
|
|
group.add(user2)
|
|
group
|
|
end
|
|
|
|
before do
|
|
enable_current_plugin
|
|
Jobs.run_immediately!
|
|
end
|
|
|
|
def accept_policy(post)
|
|
[user1, user2].each { |u| PolicyUser.add!(u, post.post_policy) }
|
|
end
|
|
|
|
it "correctly renews policies with no renew-start" do
|
|
freeze_time Time.utc(2019)
|
|
|
|
raw = <<~MD
|
|
[policy group=#{group.name} renew=400]
|
|
I always open **doors**!
|
|
[/policy]
|
|
MD
|
|
|
|
post = create_post(raw: raw, user: Fabricate(:admin))
|
|
|
|
freeze_time Time.utc(2021)
|
|
accept_policy(post)
|
|
|
|
freeze_time Time.utc(2022)
|
|
job.execute
|
|
|
|
post.reload
|
|
expect(post.post_policy.accepted_by).to contain_exactly(user1, user2)
|
|
|
|
freeze_time Time.utc(2023)
|
|
job.execute
|
|
|
|
post.reload
|
|
expect(post.post_policy.accepted_by).to be_empty
|
|
end
|
|
|
|
it "expires only for user with expired policy" do
|
|
freeze_time Time.utc(2019)
|
|
|
|
raw = <<~MD
|
|
[policy group=#{group.name} renew=364]
|
|
I always open **doors**!
|
|
[/policy]
|
|
MD
|
|
|
|
post = create_post(raw: raw, user: Fabricate(:admin))
|
|
|
|
freeze_time Time.utc(2021)
|
|
accept_policy(post)
|
|
|
|
freeze_time Time.utc(2022)
|
|
PolicyUser.where(user_id: user2.id).update(accepted_at: Time.now)
|
|
job.execute
|
|
|
|
post.reload
|
|
expect(post.post_policy.accepted_by).to contain_exactly(user2)
|
|
end
|
|
|
|
it "expires just for expired policy" do
|
|
freeze_time Time.utc(2019)
|
|
|
|
raw = <<~MD
|
|
[policy group=#{group.name} renew=364]
|
|
I always open **doors**!
|
|
[/policy]
|
|
MD
|
|
|
|
raw2 = <<~MD
|
|
[policy group=#{group.name} renew=1000]
|
|
I always open **doors**!
|
|
[/policy]
|
|
MD
|
|
|
|
post = create_post(raw: raw, user: Fabricate(:admin))
|
|
post2 = create_post(raw: raw2, user: Fabricate(:admin))
|
|
|
|
freeze_time Time.utc(2021)
|
|
accept_policy(post)
|
|
accept_policy(post2)
|
|
|
|
freeze_time Time.utc(2022)
|
|
job.execute
|
|
|
|
post.reload
|
|
expect(post.post_policy.accepted_by).to be_empty
|
|
expect(post2.post_policy.accepted_by).to contain_exactly(user1, user2)
|
|
end
|
|
|
|
it "correctly renews policies" do
|
|
freeze_time Time.utc(2019)
|
|
|
|
raw = <<~MD
|
|
[policy group=#{group.name} renew=100 renew-start="2020-10-17"]
|
|
I always open **doors**!
|
|
[/policy]
|
|
MD
|
|
|
|
post = create_post(raw: raw, user: Fabricate(:admin))
|
|
|
|
accept_policy(post)
|
|
|
|
freeze_time Time.utc(2020)
|
|
job.execute
|
|
|
|
post.reload
|
|
# did not hit renew start
|
|
expect(post.post_policy.accepted_by).to contain_exactly(user1, user2)
|
|
|
|
freeze_time Time.utc(2020, 10, 18)
|
|
|
|
job.execute
|
|
|
|
post.reload
|
|
expect(post.post_policy.accepted_by).to be_empty
|
|
|
|
accept_policy(post)
|
|
|
|
freeze_time(Time.utc(2020, 10, 17) + 101.days)
|
|
|
|
PolicyUser.add!(user2, post.post_policy)
|
|
|
|
job.execute
|
|
|
|
post.reload
|
|
expect(post.post_policy.accepted_by).to contain_exactly(user2)
|
|
end
|
|
|
|
%w[monthly quarterly yearly].each do |how_often|
|
|
it "sets correctly next_renew_at for #{how_often} when renew-start is set" do
|
|
period =
|
|
case how_often
|
|
when "monthly"
|
|
1.month
|
|
when "quarterly"
|
|
3.months
|
|
when "yearly"
|
|
12.months
|
|
end
|
|
freeze_time Time.utc(2020, 10, 16)
|
|
|
|
raw = <<~MD
|
|
[policy group=#{group.name} renew=#{how_often} renew-start="2020-10-17"]
|
|
I always open **doors**!
|
|
[/policy]
|
|
MD
|
|
|
|
post = create_post(raw: raw, user: Fabricate(:admin))
|
|
|
|
accept_policy(post)
|
|
|
|
freeze_time Time.utc(2020, 10, 17)
|
|
|
|
job.execute
|
|
|
|
post.reload
|
|
expect(post.post_policy.accepted_by).to contain_exactly(user1, user2)
|
|
|
|
freeze_time Time.utc(2020, 10, 18)
|
|
|
|
job.execute
|
|
|
|
post.reload
|
|
expect(post.post_policy.accepted_by).to be_empty
|
|
expect(post.post_policy.next_renew_at.to_s).to eq((Time.utc(2020, 10, 17) + period).to_s)
|
|
end
|
|
end
|
|
|
|
%w[monthly quarterly yearly].each do |how_often|
|
|
it "expires policies when #{how_often}" do
|
|
period =
|
|
case how_often
|
|
when "monthly"
|
|
1.month
|
|
when "quarterly"
|
|
3.months
|
|
when "yearly"
|
|
12.months
|
|
end
|
|
freeze_time Time.utc(2020, 10, 16)
|
|
|
|
raw = <<~MD
|
|
[policy group=#{group.name} renew=#{how_often}]
|
|
I always open **doors**!
|
|
[/policy]
|
|
MD
|
|
|
|
post = create_post(raw: raw, user: Fabricate(:admin))
|
|
|
|
accept_policy(post)
|
|
|
|
freeze_time Time.utc(2020, 10, 30)
|
|
|
|
job.execute
|
|
|
|
post.reload
|
|
expect(post.post_policy.accepted_by).to contain_exactly(user1, user2)
|
|
|
|
freeze_time Time.utc(2020, 10, 16) + period + 1.day
|
|
|
|
job.execute
|
|
|
|
post.reload
|
|
expect(post.post_policy.accepted_by).to be_empty
|
|
expect(post.post_policy.renew_start).to eq(nil)
|
|
end
|
|
end
|
|
|
|
it "will correctly notify users with high priority notifications" do
|
|
Jobs.run_immediately!
|
|
freeze_time
|
|
|
|
raw = <<~MD
|
|
[policy group=#{group.name} reminder=weekly]
|
|
I always open **doors**!
|
|
[/policy]
|
|
MD
|
|
|
|
post = create_post(raw: raw, user: Fabricate(:admin))
|
|
|
|
job.execute
|
|
|
|
expect(
|
|
user1.notifications.where(notification_type: Notification.types[:topic_reminder]).count,
|
|
).to eq(0)
|
|
expect(
|
|
user2.notifications.where(notification_type: Notification.types[:topic_reminder]).count,
|
|
).to eq(0)
|
|
|
|
freeze_time 2.weeks.from_now
|
|
|
|
job.execute
|
|
job.execute
|
|
|
|
user1_notifications =
|
|
user1.notifications.where(
|
|
notification_type: Notification.types[:topic_reminder],
|
|
topic_id: post.topic_id,
|
|
post_number: 1,
|
|
)
|
|
expect(user1_notifications.count).to eq(1)
|
|
expect(user1_notifications.first.high_priority).to eq(true)
|
|
user2_notifications =
|
|
user2.notifications.where(
|
|
notification_type: Notification.types[:topic_reminder],
|
|
topic_id: post.topic_id,
|
|
post_number: 1,
|
|
)
|
|
expect(user2_notifications.count).to eq(1)
|
|
expect(user2_notifications.first.high_priority).to eq(true)
|
|
end
|
|
|
|
context "when the policy topic is restricted" do
|
|
it "creates reminders only for users who can see it" do
|
|
freeze_time
|
|
|
|
policy_user_with_topic_access = Fabricate(:user)
|
|
policy_user_without_topic_access = Fabricate(:user)
|
|
|
|
policy_target_group = Fabricate(:group)
|
|
policy_target_group.add(policy_user_with_topic_access)
|
|
policy_target_group.add(policy_user_without_topic_access)
|
|
|
|
private_category_access_group = Fabricate(:group)
|
|
private_category_access_group.add(policy_user_with_topic_access)
|
|
private_category = Fabricate(:private_category, group: private_category_access_group)
|
|
|
|
raw = <<~MD
|
|
[policy group=#{policy_target_group.name} reminder=weekly]
|
|
I always open **doors**!
|
|
[/policy]
|
|
MD
|
|
|
|
post = create_post(raw: raw, user: Fabricate(:admin), category: private_category)
|
|
|
|
freeze_time 2.weeks.from_now
|
|
|
|
job.execute
|
|
|
|
expect(
|
|
Notification.where(
|
|
notification_type: Notification.types[:topic_reminder],
|
|
topic_id: post.topic_id,
|
|
post_number: 1,
|
|
).pluck(:user_id),
|
|
).to contain_exactly(policy_user_with_topic_access.id)
|
|
end
|
|
end
|
|
|
|
it "will delete the existing policy reminder notification before creating a new one" do
|
|
Jobs.run_immediately!
|
|
freeze_time
|
|
|
|
raw = <<~MD
|
|
[policy group=#{group.name} reminder=weekly]
|
|
I always open **doors**!
|
|
[/policy]
|
|
MD
|
|
|
|
post = create_post(raw: raw, user: Fabricate(:admin))
|
|
|
|
job.execute
|
|
|
|
expect(
|
|
user1.notifications.where(notification_type: Notification.types[:topic_reminder]).count,
|
|
).to eq(0)
|
|
|
|
freeze_time 2.weeks.from_now
|
|
|
|
job.execute
|
|
|
|
user1_notification =
|
|
user1
|
|
.notifications
|
|
.where(
|
|
notification_type: Notification.types[:topic_reminder],
|
|
topic_id: post.topic_id,
|
|
post_number: 1,
|
|
)
|
|
.last
|
|
expect(user1_notification).not_to eq(nil)
|
|
|
|
freeze_time 2.weeks.from_now
|
|
|
|
job.execute
|
|
|
|
expect(
|
|
user1
|
|
.notifications
|
|
.where(
|
|
notification_type: Notification.types[:topic_reminder],
|
|
topic_id: post.topic_id,
|
|
post_number: 1,
|
|
)
|
|
.count,
|
|
).to eq(1)
|
|
expect(Notification.find_by(id: user1_notification.id)).to eq(nil)
|
|
end
|
|
|
|
it "clears the next_renew_at when renew_start is nil" do
|
|
policy = Fabricate(:post_policy, next_renew_at: 3.hours.ago, renew_start: nil, renew_days: 10)
|
|
|
|
job.execute
|
|
|
|
expect(policy.reload.next_renew_at).to be_nil
|
|
end
|
|
end
|