fix(reminders): align visible scope with instance-level authorization check (#22615)

The class-level visible scope now verifies the user retains access to
the associated remindable, consistent with the existing instance method.
Updated specs to reflect the corrected authorization behavior.
This commit is contained in:
Kabiru Mwenja
2026-03-31 16:43:55 +03:00
committed by GitHub
parent 93b3c9ca68
commit eaee546c81
3 changed files with 49 additions and 13 deletions
+3 -1
View File
@@ -36,9 +36,11 @@ class Reminder < ApplicationRecord
has_many :notifications, through: :reminder_notifications
# Currently, reminders are personal, meaning
# they are only visible to the user who created them.
# they are only visible to the user who created them
# and who still has access to the remindable.
def self.visible(user)
where(creator: user)
.where(remindable_type: WorkPackage.name, remindable_id: WorkPackage.visible(user).select(:id))
end
def self.upcoming_and_visible_to(user)
+44 -10
View File
@@ -41,31 +41,65 @@ RSpec.describe Reminder do
describe "Scopes" do
describe ".visible" do
it "returns reminders where the creator is the given user" do
user = create(:user)
other_user = create(:user)
reminder = create(:reminder, creator: user)
_other_reminder = create(:reminder, creator: other_user)
role = create(:project_role, permissions: %i[view_work_packages])
project = create(:project)
user = create(:user, member_with_roles: { project => role })
other_user = create(:user, member_with_roles: { project => role })
work_package = create(:work_package, project:)
reminder = create(:reminder, creator: user, remindable: work_package)
_other_reminder = create(:reminder, creator: other_user, remindable: work_package)
expect(described_class.visible(user)).to contain_exactly(reminder)
end
it "excludes reminders whose remindable is no longer visible to the user" do
role = create(:project_role, permissions: %i[view_work_packages])
project = create(:project)
user = create(:user, member_with_roles: { project => role })
work_package = create(:work_package, project:)
reminder = create(:reminder, creator: user, remindable: work_package)
expect(described_class.visible(user)).to contain_exactly(reminder)
Member.where(principal: user, project:).destroy_all
expect(described_class.visible(user)).to be_empty
end
end
describe ".upcoming_and_visible_to" do
it "returns reminders where the creator is the given user" \
"and there are no reminder_notifications for it yet" do
user = create(:user)
other_user = create(:user)
reminder = create(:reminder, creator: user)
_another_reminder_with_notification = create(:reminder, creator: user) do |r|
role = create(:project_role, permissions: %i[view_work_packages])
project = create(:project)
user = create(:user, member_with_roles: { project => role })
other_user = create(:user, member_with_roles: { project => role })
work_package = create(:work_package, project:)
reminder = create(:reminder, creator: user, remindable: work_package)
_another_reminder_with_notification = create(:reminder, creator: user, remindable: work_package) do |r|
create(:reminder_notification, reminder: r)
end
_other_users_reminder_with_notification = create(:reminder, creator: other_user) do |r|
_other_users_reminder_with_notification = create(:reminder, creator: other_user, remindable: work_package) do |r|
create(:reminder_notification, reminder: r)
end
_other_users_reminder = create(:reminder, creator: other_user)
_other_users_reminder = create(:reminder, creator: other_user, remindable: work_package)
expect(described_class.upcoming_and_visible_to(user)).to contain_exactly(reminder)
end
it "excludes reminders whose remindable is no longer visible to the user" do
role = create(:project_role, permissions: %i[view_work_packages])
project = create(:project)
user = create(:user, member_with_roles: { project => role })
work_package = create(:work_package, project:)
reminder = create(:reminder, creator: user, remindable: work_package)
expect(described_class.upcoming_and_visible_to(user)).to contain_exactly(reminder)
Member.where(principal: user, project:).destroy_all
expect(described_class.upcoming_and_visible_to(user)).to be_empty
end
end
end
@@ -130,7 +130,7 @@ RSpec.describe API::V3::Reminders::RemindersAPI do
it_behaves_like "error response",
404, "NotFound",
"The requested resource could not be found."
"The reminder you are looking for cannot be found or has been deleted."
end
end
@@ -191,7 +191,7 @@ RSpec.describe API::V3::Reminders::RemindersAPI do
it_behaves_like "error response",
404, "NotFound",
"The requested resource could not be found."
"The reminder you are looking for cannot be found or has been deleted."
end
end
end