Destroy `NotificationRequest`s that are dismissed (#31008)
This commit is contained in:
		
							parent
							
								
									c929b4cace
								
							
						
					
					
						commit
						35a437a03f
					
				| 
						 | 
					@ -28,14 +28,14 @@ class Api::V1::Notifications::RequestsController < Api::BaseController
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def dismiss
 | 
					  def dismiss
 | 
				
			||||||
    @request.update!(dismissed: true)
 | 
					    @request.destroy!
 | 
				
			||||||
    render_empty
 | 
					    render_empty
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def load_requests
 | 
					  def load_requests
 | 
				
			||||||
    requests = NotificationRequest.where(account: current_account).where(dismissed: truthy_param?(:dismissed) || false).includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id(
 | 
					    requests = NotificationRequest.where(account: current_account).includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id(
 | 
				
			||||||
      limit_param(DEFAULT_ACCOUNTS_LIMIT),
 | 
					      limit_param(DEFAULT_ACCOUNTS_LIMIT),
 | 
				
			||||||
      params_slice(:max_id, :since_id, :min_id)
 | 
					      params_slice(:max_id, :since_id, :min_id)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
| 
						 | 
					@ -68,8 +68,4 @@ class Api::V1::Notifications::RequestsController < Api::BaseController
 | 
				
			||||||
  def pagination_since_id
 | 
					  def pagination_since_id
 | 
				
			||||||
    @requests.first.id
 | 
					    @requests.first.id
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					 | 
				
			||||||
  def pagination_params(core_params)
 | 
					 | 
				
			||||||
    params.slice(:dismissed).permit(:dismissed).merge(core_params)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,6 @@ class NotificationPolicy < ApplicationRecord
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def pending_notification_requests
 | 
					  def pending_notification_requests
 | 
				
			||||||
    @pending_notification_requests ||= notification_requests.where(dismissed: false).limit(MAX_MEANINGFUL_COUNT).pick(Arel.sql('count(*), coalesce(sum(notifications_count), 0)::bigint'))
 | 
					    @pending_notification_requests ||= notification_requests.limit(MAX_MEANINGFUL_COUNT).pick(Arel.sql('count(*), coalesce(sum(notifications_count), 0)::bigint'))
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,12 +9,13 @@
 | 
				
			||||||
#  from_account_id     :bigint(8)        not null
 | 
					#  from_account_id     :bigint(8)        not null
 | 
				
			||||||
#  last_status_id      :bigint(8)
 | 
					#  last_status_id      :bigint(8)
 | 
				
			||||||
#  notifications_count :bigint(8)        default(0), not null
 | 
					#  notifications_count :bigint(8)        default(0), not null
 | 
				
			||||||
#  dismissed           :boolean          default(FALSE), not null
 | 
					 | 
				
			||||||
#  created_at          :datetime         not null
 | 
					#  created_at          :datetime         not null
 | 
				
			||||||
#  updated_at          :datetime         not null
 | 
					#  updated_at          :datetime         not null
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NotificationRequest < ApplicationRecord
 | 
					class NotificationRequest < ApplicationRecord
 | 
				
			||||||
 | 
					  self.ignored_columns += %w(dismissed)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  include Paginable
 | 
					  include Paginable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  MAX_MEANINGFUL_COUNT = 100
 | 
					  MAX_MEANINGFUL_COUNT = 100
 | 
				
			||||||
| 
						 | 
					@ -34,8 +35,6 @@ class NotificationRequest < ApplicationRecord
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def reconsider_existence!
 | 
					  def reconsider_existence!
 | 
				
			||||||
    return if dismissed?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    prepare_notifications_count
 | 
					    prepare_notifications_count
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if notifications_count.positive?
 | 
					    if notifications_count.positive?
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RemoveDismissedFromNotificationRequests < ActiveRecord::Migration[7.1]
 | 
				
			||||||
 | 
					  def up
 | 
				
			||||||
 | 
					    safety_assured do
 | 
				
			||||||
 | 
					      execute 'DELETE FROM notification_requests WHERE dismissed'
 | 
				
			||||||
 | 
					      remove_column :notification_requests, :dismissed
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def down
 | 
				
			||||||
 | 
					    add_column :notification_requests, :dismissed, :boolean, default: false, null: false
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# It's strongly recommended that you check this file into your version control system.
 | 
					# It's strongly recommended that you check this file into your version control system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ActiveRecord::Schema[7.1].define(version: 2024_06_07_094856) do
 | 
					ActiveRecord::Schema[7.1].define(version: 2024_07_12_064044) do
 | 
				
			||||||
  # These are extensions that must be enabled in order to support this database
 | 
					  # These are extensions that must be enabled in order to support this database
 | 
				
			||||||
  enable_extension "plpgsql"
 | 
					  enable_extension "plpgsql"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -706,11 +706,9 @@ ActiveRecord::Schema[7.1].define(version: 2024_06_07_094856) do
 | 
				
			||||||
    t.bigint "from_account_id", null: false
 | 
					    t.bigint "from_account_id", null: false
 | 
				
			||||||
    t.bigint "last_status_id"
 | 
					    t.bigint "last_status_id"
 | 
				
			||||||
    t.bigint "notifications_count", default: 0, null: false
 | 
					    t.bigint "notifications_count", default: 0, null: false
 | 
				
			||||||
    t.boolean "dismissed", default: false, null: false
 | 
					 | 
				
			||||||
    t.datetime "created_at", null: false
 | 
					    t.datetime "created_at", null: false
 | 
				
			||||||
    t.datetime "updated_at", null: false
 | 
					    t.datetime "updated_at", null: false
 | 
				
			||||||
    t.index ["account_id", "from_account_id"], name: "index_notification_requests_on_account_id_and_from_account_id", unique: true
 | 
					    t.index ["account_id", "from_account_id"], name: "index_notification_requests_on_account_id_and_from_account_id", unique: true
 | 
				
			||||||
    t.index ["account_id", "id"], name: "index_notification_requests_on_account_id_and_id", order: { id: :desc }, where: "(dismissed = false)"
 | 
					 | 
				
			||||||
    t.index ["from_account_id"], name: "index_notification_requests_on_from_account_id"
 | 
					    t.index ["from_account_id"], name: "index_notification_requests_on_from_account_id"
 | 
				
			||||||
    t.index ["last_status_id"], name: "index_notification_requests_on_last_status_id"
 | 
					    t.index ["last_status_id"], name: "index_notification_requests_on_last_status_id"
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,5 +4,4 @@ Fabricator(:notification_request) do
 | 
				
			||||||
  account
 | 
					  account
 | 
				
			||||||
  from_account { Fabricate.build(:account) }
 | 
					  from_account { Fabricate.build(:account) }
 | 
				
			||||||
  last_status { Fabricate.build(:status) }
 | 
					  last_status { Fabricate.build(:status) }
 | 
				
			||||||
  dismissed false
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,9 +4,7 @@ require 'rails_helper'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RSpec.describe NotificationRequest do
 | 
					RSpec.describe NotificationRequest do
 | 
				
			||||||
  describe '#reconsider_existence!' do
 | 
					  describe '#reconsider_existence!' do
 | 
				
			||||||
    subject { Fabricate(:notification_request, dismissed: dismissed) }
 | 
					    subject { Fabricate(:notification_request) }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    let(:dismissed) { false }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    context 'when there are remaining notifications' do
 | 
					    context 'when there are remaining notifications' do
 | 
				
			||||||
      before do
 | 
					      before do
 | 
				
			||||||
| 
						 | 
					@ -28,14 +26,6 @@ RSpec.describe NotificationRequest do
 | 
				
			||||||
        subject.reconsider_existence!
 | 
					        subject.reconsider_existence!
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      context 'when dismissed' do
 | 
					 | 
				
			||||||
        let(:dismissed) { true }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        it 'leaves request intact' do
 | 
					 | 
				
			||||||
          expect(subject.destroyed?).to be false
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      it 'removes the request' do
 | 
					      it 'removes the request' do
 | 
				
			||||||
        expect(subject.destroyed?).to be true
 | 
					        expect(subject.destroyed?).to be true
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,6 @@ RSpec.describe 'Requests' do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    before do
 | 
					    before do
 | 
				
			||||||
      Fabricate(:notification_request, account: user.account)
 | 
					      Fabricate(:notification_request, account: user.account)
 | 
				
			||||||
      Fabricate(:notification_request, account: user.account, dismissed: true)
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it_behaves_like 'forbidden for wrong scope', 'write write:notifications'
 | 
					    it_behaves_like 'forbidden for wrong scope', 'write write:notifications'
 | 
				
			||||||
| 
						 | 
					@ -29,16 +28,6 @@ RSpec.describe 'Requests' do
 | 
				
			||||||
        expect(response).to have_http_status(200)
 | 
					        expect(response).to have_http_status(200)
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					 | 
				
			||||||
    context 'with dismissed' do
 | 
					 | 
				
			||||||
      let(:params) { { dismissed: '1' } }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      it 'returns http success', :aggregate_failures do
 | 
					 | 
				
			||||||
        subject
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        expect(response).to have_http_status(200)
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe 'POST /api/v1/notifications/requests/:id/accept' do
 | 
					  describe 'POST /api/v1/notifications/requests/:id/accept' do
 | 
				
			||||||
| 
						 | 
					@ -78,15 +67,14 @@ RSpec.describe 'Requests' do
 | 
				
			||||||
      post "/api/v1/notifications/requests/#{notification_request.id}/dismiss", headers: headers
 | 
					      post "/api/v1/notifications/requests/#{notification_request.id}/dismiss", headers: headers
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let(:notification_request) { Fabricate(:notification_request, account: user.account) }
 | 
					    let!(:notification_request) { Fabricate(:notification_request, account: user.account) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it_behaves_like 'forbidden for wrong scope', 'read read:notifications'
 | 
					    it_behaves_like 'forbidden for wrong scope', 'read read:notifications'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it 'returns http success and dismisses the notification request', :aggregate_failures do
 | 
					    it 'returns http success and destroys the notification request', :aggregate_failures do
 | 
				
			||||||
      subject
 | 
					      expect { subject }.to change(NotificationRequest, :count).by(-1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      expect(response).to have_http_status(200)
 | 
					      expect(response).to have_http_status(200)
 | 
				
			||||||
      expect(notification_request.reload.dismissed?).to be true
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    context 'when notification request belongs to someone else' do
 | 
					    context 'when notification request belongs to someone else' do
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,6 +129,39 @@ RSpec.describe NotifyService do
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  context 'with filtered notifications' do
 | 
				
			||||||
 | 
					    let(:unknown)  { Fabricate(:account, username: 'unknown') }
 | 
				
			||||||
 | 
					    let(:status)   { Fabricate(:status, account: unknown) }
 | 
				
			||||||
 | 
					    let(:activity) { Fabricate(:mention, account: recipient, status: status) }
 | 
				
			||||||
 | 
					    let(:type)     { :mention }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    before do
 | 
				
			||||||
 | 
					      Fabricate(:notification_policy, account: recipient, filter_not_following: true)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'creates a filtered notification' do
 | 
				
			||||||
 | 
					      expect { subject }.to change(Notification, :count)
 | 
				
			||||||
 | 
					      expect(Notification.last).to be_filtered
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    context 'when no notification request exists' do
 | 
				
			||||||
 | 
					      it 'creates a notification request' do
 | 
				
			||||||
 | 
					        expect { subject }.to change(NotificationRequest, :count)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    context 'when a notification request exists' do
 | 
				
			||||||
 | 
					      let!(:notification_request) do
 | 
				
			||||||
 | 
					        Fabricate(:notification_request, account: recipient, from_account: unknown, last_status: Fabricate(:status, account: unknown))
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it 'updates the existing notification request' do
 | 
				
			||||||
 | 
					        expect { subject }.to_not change(NotificationRequest, :count)
 | 
				
			||||||
 | 
					        expect(notification_request.reload.last_status).to eq status
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe NotifyService::DismissCondition do
 | 
					  describe NotifyService::DismissCondition do
 | 
				
			||||||
    subject { described_class.new(notification) }
 | 
					    subject { described_class.new(notification) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue