diff --git a/app/controllers/better_together/notifications_controller.rb b/app/controllers/better_together/notifications_controller.rb index cf7bf7e45..85ac0ea2b 100644 --- a/app/controllers/better_together/notifications_controller.rb +++ b/app/controllers/better_together/notifications_controller.rb @@ -6,15 +6,21 @@ class NotificationsController < ApplicationController include BetterTogether::NotificationReadable before_action :authenticate_user! + after_action :verify_authorized + + rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized before_action :disallow_robots def index + authorize :notifications, :index? @notifications = helpers.current_person.notifications.includes(:event).order(created_at: :desc) @unread_count = helpers.current_person.notifications.unread.size end # TODO: Make a Stimulus controller to dispatch this action async when messages are viewed def mark_as_read # rubocop:todo Metrics/AbcSize, Metrics/MethodLength + authorize :notifications, :mark_as_read? + if params[:id] mark_notification_as_read(params[:id]) elsif params[:record_id] @@ -40,11 +46,13 @@ def mark_as_read # rubocop:todo Metrics/AbcSize, Metrics/MethodLength end def mark_notification_as_read(id) + authorize :notifications, :mark_notification_as_read? @notification = helpers.current_person.notifications.find(id) @notification.update(read_at: Time.current) end def mark_record_notification_as_read(id) + authorize :notifications, :mark_record_notification_as_read? mark_notifications_read_for_record_id(id) end end diff --git a/app/policies/better_together/notifications_policy.rb b/app/policies/better_together/notifications_policy.rb new file mode 100644 index 000000000..aa0795306 --- /dev/null +++ b/app/policies/better_together/notifications_policy.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module BetterTogether + # Authorization rules for notifications actions + class NotificationsPolicy < ApplicationPolicy + def index? + user.present? + end + + def mark_as_read? + user.present? + end + + def mark_notification_as_read? + mark_as_read? + end + + def mark_record_notification_as_read? + mark_as_read? + end + + class Scope < ApplicationPolicy::Scope + end + end +end diff --git a/spec/policies/better_together/notifications_policy_spec.rb b/spec/policies/better_together/notifications_policy_spec.rb new file mode 100644 index 000000000..2d36b541d --- /dev/null +++ b/spec/policies/better_together/notifications_policy_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'rails_helper' + +module BetterTogether + # rubocop:disable Metrics/BlockLength + RSpec.describe NotificationsPolicy do + subject(:policy) { described_class.new(user, :notifications) } + + context 'when user is logged in' do + let(:user) { build(:user) } + + it 'permits index' do + expect(policy.index?).to be true + end + + it 'permits mark_as_read' do + expect(policy.mark_as_read?).to be true + end + + it 'permits mark_notification_as_read' do + expect(policy.mark_notification_as_read?).to be true + end + + it 'permits mark_record_notification_as_read' do + expect(policy.mark_record_notification_as_read?).to be true + end + end + + context 'when user is nil' do + let(:user) { nil } + + it 'denies index' do + expect(policy.index?).to be false + end + + it 'denies mark_as_read' do + expect(policy.mark_as_read?).to be false + end + + it 'denies mark_notification_as_read' do + expect(policy.mark_notification_as_read?).to be false + end + + it 'denies mark_record_notification_as_read' do + expect(policy.mark_record_notification_as_read?).to be false + end + end + end + # rubocop:enable Metrics/BlockLength +end diff --git a/spec/requests/better_together/notifications_spec.rb b/spec/requests/better_together/notifications_spec.rb new file mode 100644 index 000000000..766929e27 --- /dev/null +++ b/spec/requests/better_together/notifications_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Notifications', type: :request do + let(:user) { create(:user, :confirmed) } + + describe 'GET /notifications' do + it 'redirects unauthorized users' do + login(user) + allow_any_instance_of(BetterTogether::NotificationsPolicy).to receive(:index?).and_return(false) + + get better_together.notifications_path + + expect(response).to redirect_to(better_together.home_page_path) + end + end + + describe 'POST /notifications/mark_all_as_read' do + it 'redirects unauthorized users' do + login(user) + allow_any_instance_of(BetterTogether::NotificationsPolicy).to receive(:mark_as_read?).and_return(false) + + post better_together.mark_all_as_read_notifications_path + + expect(response).to redirect_to(better_together.home_page_path) + end + end +end