You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

247 lines
7.9 KiB

  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. RSpec.describe ActivityPub::RepliesController, type: :controller do
  4. let(:status) { Fabricate(:status, visibility: parent_visibility) }
  5. let(:remote_reply_id) { nil }
  6. let(:remote_account) { nil }
  7. shared_examples 'cachable response' do
  8. it 'does not set cookies' do
  9. expect(response.cookies).to be_empty
  10. expect(response.headers['Set-Cookies']).to be nil
  11. end
  12. it 'does not set sessions' do
  13. response
  14. expect(session).to be_empty
  15. end
  16. it 'returns public Cache-Control header' do
  17. expect(response.headers['Cache-Control']).to include 'public'
  18. end
  19. end
  20. before do
  21. allow(controller).to receive(:signed_request_account).and_return(remote_account)
  22. Fabricate(:status, thread: status, visibility: :public)
  23. Fabricate(:status, thread: status, visibility: :public)
  24. Fabricate(:status, thread: status, visibility: :private)
  25. Fabricate(:status, account: status.account, thread: status, visibility: :public)
  26. Fabricate(:status, account: status.account, thread: status, visibility: :private)
  27. Fabricate(:status, account: remote_account, thread: status, visibility: :public, uri: remote_reply_id) if remote_reply_id
  28. end
  29. describe 'GET #index' do
  30. context 'with no signature' do
  31. subject(:response) { get :index, params: { account_username: status.account.username, status_id: status.id } }
  32. subject(:body) { body_as_json }
  33. context 'when account is permanently suspended' do
  34. let(:parent_visibility) { :public }
  35. before do
  36. status.account.suspend!
  37. status.account.deletion_request.destroy
  38. end
  39. it 'returns http gone' do
  40. expect(response).to have_http_status(410)
  41. end
  42. end
  43. context 'when account is temporarily suspended' do
  44. let(:parent_visibility) { :public }
  45. before do
  46. status.account.suspend!
  47. end
  48. it 'returns http forbidden' do
  49. expect(response).to have_http_status(403)
  50. end
  51. end
  52. context 'when status is public' do
  53. let(:parent_visibility) { :public }
  54. it 'returns http success' do
  55. expect(response).to have_http_status(200)
  56. end
  57. it 'returns application/activity+json' do
  58. expect(response.media_type).to eq 'application/activity+json'
  59. end
  60. it_behaves_like 'cachable response'
  61. it 'returns items with account\'s own replies' do
  62. expect(body[:first]).to be_a Hash
  63. expect(body[:first][:items]).to be_an Array
  64. expect(body[:first][:items].size).to eq 1
  65. expect(body[:first][:items].all? { |item| item[:to].include?(ActivityPub::TagManager::COLLECTIONS[:public]) || item[:cc].include?(ActivityPub::TagManager::COLLECTIONS[:public]) }).to be true
  66. end
  67. end
  68. context 'when status is private' do
  69. let(:parent_visibility) { :private }
  70. it 'returns http not found' do
  71. expect(response).to have_http_status(404)
  72. end
  73. end
  74. context 'when status is direct' do
  75. let(:parent_visibility) { :direct }
  76. it 'returns http not found' do
  77. expect(response).to have_http_status(404)
  78. end
  79. end
  80. end
  81. context 'with signature' do
  82. let(:remote_account) { Fabricate(:account, domain: 'example.com') }
  83. let(:only_other_accounts) { nil }
  84. context do
  85. before do
  86. get :index, params: { account_username: status.account.username, status_id: status.id, only_other_accounts: only_other_accounts }
  87. end
  88. context 'when status is public' do
  89. let(:parent_visibility) { :public }
  90. it 'returns http success' do
  91. expect(response).to have_http_status(200)
  92. end
  93. it 'returns application/activity+json' do
  94. expect(response.media_type).to eq 'application/activity+json'
  95. end
  96. it_behaves_like 'cachable response'
  97. context 'without only_other_accounts' do
  98. it 'returns items with account\'s own replies' do
  99. json = body_as_json
  100. expect(json[:first]).to be_a Hash
  101. expect(json[:first][:items]).to be_an Array
  102. expect(json[:first][:items].size).to eq 1
  103. expect(json[:first][:items].all? { |item| item[:to].include?(ActivityPub::TagManager::COLLECTIONS[:public]) || item[:cc].include?(ActivityPub::TagManager::COLLECTIONS[:public]) }).to be true
  104. end
  105. end
  106. context 'with only_other_accounts' do
  107. let(:only_other_accounts) { 'true' }
  108. it 'returns items with other public or unlisted replies' do
  109. json = body_as_json
  110. expect(json[:first]).to be_a Hash
  111. expect(json[:first][:items]).to be_an Array
  112. expect(json[:first][:items].size).to eq 2
  113. expect(json[:first][:items].all? { |item| item[:to].include?(ActivityPub::TagManager::COLLECTIONS[:public]) || item[:cc].include?(ActivityPub::TagManager::COLLECTIONS[:public]) }).to be true
  114. end
  115. context 'with remote responses' do
  116. let(:remote_reply_id) { 'foo' }
  117. it 'returned items are all inlined local toots or are ids' do
  118. json = body_as_json
  119. expect(json[:first]).to be_a Hash
  120. expect(json[:first][:items]).to be_an Array
  121. expect(json[:first][:items].size).to eq 3
  122. expect(json[:first][:items].all? { |item| item.is_a?(Hash) ? ActivityPub::TagManager.instance.local_uri?(item[:id]) : item.is_a?(String) }).to be true
  123. expect(json[:first][:items]).to include remote_reply_id
  124. end
  125. end
  126. end
  127. end
  128. context 'when status is private' do
  129. let(:parent_visibility) { :private }
  130. it 'returns http not found' do
  131. expect(response).to have_http_status(404)
  132. end
  133. end
  134. context 'when status is direct' do
  135. let(:parent_visibility) { :direct }
  136. it 'returns http not found' do
  137. expect(response).to have_http_status(404)
  138. end
  139. end
  140. end
  141. context 'when signed request account is blocked' do
  142. before do
  143. status.account.block!(remote_account)
  144. get :index, params: { account_username: status.account.username, status_id: status.id }
  145. end
  146. context 'when status is public' do
  147. let(:parent_visibility) { :public }
  148. it 'returns http not found' do
  149. expect(response).to have_http_status(404)
  150. end
  151. end
  152. context 'when status is private' do
  153. let(:parent_visibility) { :private }
  154. it 'returns http not found' do
  155. expect(response).to have_http_status(404)
  156. end
  157. end
  158. context 'when status is direct' do
  159. let(:parent_visibility) { :direct }
  160. it 'returns http not found' do
  161. expect(response).to have_http_status(404)
  162. end
  163. end
  164. end
  165. context 'when signed request account is domain blocked' do
  166. before do
  167. status.account.block_domain!(remote_account.domain)
  168. get :index, params: { account_username: status.account.username, status_id: status.id }
  169. end
  170. context 'when status is public' do
  171. let(:parent_visibility) { :public }
  172. it 'returns http not found' do
  173. expect(response).to have_http_status(404)
  174. end
  175. end
  176. context 'when status is private' do
  177. let(:parent_visibility) { :private }
  178. it 'returns http not found' do
  179. expect(response).to have_http_status(404)
  180. end
  181. end
  182. context 'when status is direct' do
  183. let(:parent_visibility) { :direct }
  184. it 'returns http not found' do
  185. expect(response).to have_http_status(404)
  186. end
  187. end
  188. end
  189. end
  190. end
  191. end