mirror of
https://github.com/mastodon/mastodon.git
synced 2024-12-22 19:56:04 +01:00
Change lists to be able to include accounts with pending follow requests (#19727)
This commit is contained in:
parent
598e63dad2
commit
6693a4fe7c
8 changed files with 127 additions and 19 deletions
|
@ -272,6 +272,7 @@ module AccountInteractions
|
|||
|
||||
def lists_for_local_distribution
|
||||
lists.joins(account: :user)
|
||||
.where.not(list_accounts: { follow_id: nil })
|
||||
.where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago)
|
||||
end
|
||||
|
||||
|
|
|
@ -32,7 +32,8 @@ class FollowRequest < ApplicationRecord
|
|||
validates :languages, language: true
|
||||
|
||||
def authorize!
|
||||
account.follow!(target_account, reblogs: show_reblogs, notify: notify, languages: languages, uri: uri, bypass_limit: true)
|
||||
follow = account.follow!(target_account, reblogs: show_reblogs, notify: notify, languages: languages, uri: uri, bypass_limit: true)
|
||||
ListAccount.where(follow_request: self).update_all(follow_request_id: nil, follow_id: follow.id) # rubocop:disable Rails/SkipsModelValidations
|
||||
MergeWorker.perform_async(target_account.id, account.id) if account.local?
|
||||
destroy!
|
||||
end
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
# list_id :bigint(8) not null
|
||||
# account_id :bigint(8) not null
|
||||
# follow_id :bigint(8)
|
||||
# follow_request_id :bigint(8)
|
||||
#
|
||||
|
||||
class ListAccount < ApplicationRecord
|
||||
belongs_to :list
|
||||
belongs_to :account
|
||||
belongs_to :follow, optional: true
|
||||
belongs_to :follow_request, optional: true
|
||||
|
||||
validates :account_id, uniqueness: { scope: :list_id }
|
||||
|
||||
|
@ -22,6 +24,10 @@ class ListAccount < ApplicationRecord
|
|||
private
|
||||
|
||||
def set_follow
|
||||
self.follow = Follow.find_by!(account_id: list.account_id, target_account_id: account.id) unless list.account_id == account.id
|
||||
return if list.account_id == account.id
|
||||
|
||||
self.follow = Follow.find_by!(account_id: list.account_id, target_account_id: account.id)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
self.follow_request = FollowRequest.find_by!(account_id: list.account_id, target_account_id: account.id)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddFollowRequestIdToListAccounts < ActiveRecord::Migration[6.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def change
|
||||
safety_assured { add_reference :list_accounts, :follow_request, foreign_key: { on_delete: :cascade }, index: false }
|
||||
add_index :list_accounts, :follow_request_id, algorithm: :concurrently, where: 'follow_request_id IS NOT NULL'
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2023_03_30_140036) do
|
||||
ActiveRecord::Schema.define(version: 2023_03_30_155710) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -554,8 +554,10 @@ ActiveRecord::Schema.define(version: 2023_03_30_140036) do
|
|||
t.bigint "list_id", null: false
|
||||
t.bigint "account_id", null: false
|
||||
t.bigint "follow_id"
|
||||
t.bigint "follow_request_id"
|
||||
t.index ["account_id", "list_id"], name: "index_list_accounts_on_account_id_and_list_id", unique: true
|
||||
t.index ["follow_id"], name: "index_list_accounts_on_follow_id", where: "(follow_id IS NOT NULL)"
|
||||
t.index ["follow_request_id"], name: "index_list_accounts_on_follow_request_id", where: "(follow_request_id IS NOT NULL)"
|
||||
t.index ["list_id", "account_id"], name: "index_list_accounts_on_list_id_and_account_id"
|
||||
end
|
||||
|
||||
|
@ -1198,6 +1200,7 @@ ActiveRecord::Schema.define(version: 2023_03_30_140036) do
|
|||
add_foreign_key "imports", "accounts", name: "fk_6db1b6e408", on_delete: :cascade
|
||||
add_foreign_key "invites", "users", on_delete: :cascade
|
||||
add_foreign_key "list_accounts", "accounts", on_delete: :cascade
|
||||
add_foreign_key "list_accounts", "follow_requests", on_delete: :cascade
|
||||
add_foreign_key "list_accounts", "follows", on_delete: :cascade
|
||||
add_foreign_key "list_accounts", "lists", on_delete: :cascade
|
||||
add_foreign_key "lists", "accounts", on_delete: :cascade
|
||||
|
|
|
@ -29,6 +29,7 @@ describe Api::V1::Lists::AccountsController do
|
|||
let(:scopes) { 'write:lists' }
|
||||
let(:bob) { Fabricate(:account, username: 'bob') }
|
||||
|
||||
context 'when the added account is followed' do
|
||||
before do
|
||||
user.account.follow!(bob)
|
||||
post :create, params: { list_id: list.id, account_ids: [bob.id] }
|
||||
|
@ -43,6 +44,36 @@ describe Api::V1::Lists::AccountsController do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when the added account has been sent a follow request' do
|
||||
before do
|
||||
user.account.follow_requests.create!(target_account: bob)
|
||||
post :create, params: { list_id: list.id, account_ids: [bob.id] }
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
|
||||
it 'adds account to the list' do
|
||||
expect(list.accounts.include?(bob)).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the added account is not followed' do
|
||||
before do
|
||||
post :create, params: { list_id: list.id, account_ids: [bob.id] }
|
||||
end
|
||||
|
||||
it 'returns http not found' do
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
|
||||
it 'does not add the account to the list' do
|
||||
expect(list.accounts.include?(bob)).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
let(:scopes) { 'write:lists' }
|
||||
|
||||
|
|
|
@ -683,4 +683,28 @@ describe AccountInteractions do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#lists_for_local_distribution' do
|
||||
let!(:inactive_follower_user) { Fabricate(:user, current_sign_in_at: 5.years.ago) }
|
||||
let!(:follower_user) { Fabricate(:user, current_sign_in_at: Time.now.utc) }
|
||||
let!(:follow_request_user) { Fabricate(:user, current_sign_in_at: Time.now.utc) }
|
||||
|
||||
let!(:inactive_follower_list) { Fabricate(:list, account: inactive_follower_user.account) }
|
||||
let!(:follower_list) { Fabricate(:list, account: follower_user.account) }
|
||||
let!(:follow_request_list) { Fabricate(:list, account: follow_request_user.account) }
|
||||
|
||||
before do
|
||||
inactive_follower_user.account.follow!(account)
|
||||
follower_user.account.follow!(account)
|
||||
follow_request_user.account.follow_requests.create!(target_account: account)
|
||||
|
||||
inactive_follower_list.accounts << account
|
||||
follower_list.accounts << account
|
||||
follow_request_list.accounts << account
|
||||
end
|
||||
|
||||
it 'includes only the list from the active follower' do
|
||||
expect(account.lists_for_local_distribution.to_a).to eq [follower_list]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,12 +4,26 @@ require 'rails_helper'
|
|||
|
||||
RSpec.describe FollowRequest, type: :model do
|
||||
describe '#authorize!' do
|
||||
let(:follow_request) { Fabricate(:follow_request, account: account, target_account: target_account) }
|
||||
let!(:follow_request) { Fabricate(:follow_request, account: account, target_account: target_account) }
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:target_account) { Fabricate(:account) }
|
||||
|
||||
context 'when the to-be-followed person has been added to a list' do
|
||||
let!(:list) { Fabricate(:list, account: account) }
|
||||
|
||||
before do
|
||||
list.accounts << target_account
|
||||
end
|
||||
|
||||
it 'updates the ListAccount' do
|
||||
expect { follow_request.authorize! }.to change { [list.list_accounts.first.follow_request_id, list.list_accounts.first.follow_id] }.from([follow_request.id, nil]).to([nil, anything])
|
||||
end
|
||||
end
|
||||
|
||||
it 'calls Account#follow!, MergeWorker.perform_async, and #destroy!' do
|
||||
expect(account).to receive(:follow!).with(target_account, reblogs: true, notify: false, uri: follow_request.uri, languages: nil, bypass_limit: true)
|
||||
expect(account).to receive(:follow!).with(target_account, reblogs: true, notify: false, uri: follow_request.uri, languages: nil, bypass_limit: true) do
|
||||
account.active_relationships.create!(target_account: target_account)
|
||||
end
|
||||
expect(MergeWorker).to receive(:perform_async).with(target_account.id, account.id)
|
||||
expect(follow_request).to receive(:destroy!)
|
||||
follow_request.authorize!
|
||||
|
@ -29,4 +43,22 @@ RSpec.describe FollowRequest, type: :model do
|
|||
expect(follow_request.account.muting_reblogs?(target)).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#reject!' do
|
||||
let!(:follow_request) { Fabricate(:follow_request, account: account, target_account: target_account) }
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:target_account) { Fabricate(:account) }
|
||||
|
||||
context 'when the to-be-followed person has been added to a list' do
|
||||
let!(:list) { Fabricate(:list, account: account) }
|
||||
|
||||
before do
|
||||
list.accounts << target_account
|
||||
end
|
||||
|
||||
it 'deletes the ListAccount record' do
|
||||
expect { follow_request.reject! }.to change { list.accounts.count }.from(1).to(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue