statuses_controller_spec.rb 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. describe StatusesController do
  4. render_views
  5. describe 'GET #show' do
  6. let(:account) { Fabricate(:account) }
  7. let(:status) { Fabricate(:status, account: account) }
  8. context 'when account is permanently suspended' do
  9. before do
  10. account.suspend!
  11. account.deletion_request.destroy
  12. get :show, params: { account_username: account.username, id: status.id }
  13. end
  14. it 'returns http gone' do
  15. expect(response).to have_http_status(410)
  16. end
  17. end
  18. context 'when account is temporarily suspended' do
  19. before do
  20. account.suspend!
  21. get :show, params: { account_username: account.username, id: status.id }
  22. end
  23. it 'returns http forbidden' do
  24. expect(response).to have_http_status(403)
  25. end
  26. end
  27. context 'when status is a reblog' do
  28. let(:original_account) { Fabricate(:account, domain: 'example.com') }
  29. let(:original_status) { Fabricate(:status, account: original_account, url: 'https://example.com/123') }
  30. let(:status) { Fabricate(:status, account: account, reblog: original_status) }
  31. before do
  32. get :show, params: { account_username: status.account.username, id: status.id }
  33. end
  34. it 'redirects to the original status' do
  35. expect(response).to redirect_to(original_status.url)
  36. end
  37. end
  38. context 'when status is public' do
  39. before do
  40. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  41. end
  42. context 'with HTML' do
  43. let(:format) { 'html' }
  44. it 'renders status successfully', :aggregate_failures do
  45. expect(response)
  46. .to have_http_status(200)
  47. .and render_template(:show)
  48. expect(response.headers).to include(
  49. 'Vary' => 'Accept, Accept-Language, Cookie',
  50. 'Cache-Control' => include('public'),
  51. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  52. )
  53. expect(response.body).to include status.text
  54. end
  55. end
  56. context 'with JSON' do
  57. let(:format) { 'json' }
  58. it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
  59. it 'renders ActivityPub Note object successfully', :aggregate_failures do
  60. expect(response)
  61. .to have_http_status(200)
  62. expect(response.headers).to include(
  63. 'Vary' => 'Accept, Accept-Language, Cookie',
  64. 'Content-Type' => include('application/activity+json'),
  65. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  66. )
  67. expect(body_as_json)
  68. .to include(content: include(status.text))
  69. end
  70. end
  71. end
  72. context 'when status is private' do
  73. let(:status) { Fabricate(:status, account: account, visibility: :private) }
  74. before do
  75. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  76. end
  77. context 'with JSON' do
  78. let(:format) { 'json' }
  79. it 'returns http not found' do
  80. expect(response).to have_http_status(404)
  81. end
  82. end
  83. context 'with HTML' do
  84. let(:format) { 'html' }
  85. it 'returns http not found' do
  86. expect(response).to have_http_status(404)
  87. end
  88. end
  89. end
  90. context 'when status is direct' do
  91. let(:status) { Fabricate(:status, account: account, visibility: :direct) }
  92. before do
  93. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  94. end
  95. context 'with JSON' do
  96. let(:format) { 'json' }
  97. it 'returns http not found' do
  98. expect(response).to have_http_status(404)
  99. end
  100. end
  101. context 'with HTML' do
  102. let(:format) { 'html' }
  103. it 'returns http not found' do
  104. expect(response).to have_http_status(404)
  105. end
  106. end
  107. end
  108. context 'when signed-in' do
  109. let(:user) { Fabricate(:user) }
  110. before do
  111. sign_in(user)
  112. end
  113. context 'when account blocks user' do
  114. before do
  115. account.block!(user.account)
  116. get :show, params: { account_username: status.account.username, id: status.id }
  117. end
  118. it 'returns http not found' do
  119. expect(response).to have_http_status(404)
  120. end
  121. end
  122. context 'when status is public' do
  123. before do
  124. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  125. end
  126. context 'with HTML' do
  127. let(:format) { 'html' }
  128. it 'renders status successfully', :aggregate_failures do
  129. expect(response)
  130. .to have_http_status(200)
  131. .and render_template(:show)
  132. expect(response.headers).to include(
  133. 'Vary' => 'Accept, Accept-Language, Cookie',
  134. 'Cache-Control' => include('private'),
  135. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  136. )
  137. expect(response.body).to include status.text
  138. end
  139. end
  140. context 'with JSON' do
  141. let(:format) { 'json' }
  142. it 'renders ActivityPub Note object successfully', :aggregate_failures do
  143. expect(response)
  144. .to have_http_status(200)
  145. expect(response.headers).to include(
  146. 'Vary' => 'Accept, Accept-Language, Cookie',
  147. 'Cache-Control' => include('private'),
  148. 'Content-Type' => include('application/activity+json'),
  149. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  150. )
  151. expect(body_as_json)
  152. .to include(content: include(status.text))
  153. end
  154. end
  155. end
  156. context 'when status is private' do
  157. let(:status) { Fabricate(:status, account: account, visibility: :private) }
  158. context 'when user is authorized to see it' do
  159. before do
  160. user.account.follow!(account)
  161. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  162. end
  163. context 'with HTML' do
  164. let(:format) { 'html' }
  165. it 'renders status successfully', :aggregate_failures do
  166. expect(response)
  167. .to have_http_status(200)
  168. .and render_template(:show)
  169. expect(response.headers).to include(
  170. 'Vary' => 'Accept, Accept-Language, Cookie',
  171. 'Cache-Control' => include('private'),
  172. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  173. )
  174. expect(response.body).to include status.text
  175. end
  176. end
  177. context 'with JSON' do
  178. let(:format) { 'json' }
  179. it 'renders ActivityPub Note object successfully', :aggregate_failures do
  180. expect(response)
  181. .to have_http_status(200)
  182. expect(response.headers).to include(
  183. 'Vary' => 'Accept, Accept-Language, Cookie',
  184. 'Cache-Control' => include('private'),
  185. 'Content-Type' => include('application/activity+json'),
  186. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  187. )
  188. expect(body_as_json)
  189. .to include(content: include(status.text))
  190. end
  191. end
  192. end
  193. context 'when user is not authorized to see it' do
  194. before do
  195. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  196. end
  197. context 'with JSON' do
  198. let(:format) { 'json' }
  199. it 'returns http not found' do
  200. expect(response).to have_http_status(404)
  201. end
  202. end
  203. context 'with HTML' do
  204. let(:format) { 'html' }
  205. it 'returns http not found' do
  206. expect(response).to have_http_status(404)
  207. end
  208. end
  209. end
  210. end
  211. context 'when status is direct' do
  212. let(:status) { Fabricate(:status, account: account, visibility: :direct) }
  213. context 'when user is authorized to see it' do
  214. before do
  215. Fabricate(:mention, account: user.account, status: status)
  216. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  217. end
  218. context 'with HTML' do
  219. let(:format) { 'html' }
  220. it 'renders status successfully', :aggregate_failures do
  221. expect(response)
  222. .to have_http_status(200)
  223. .and render_template(:show)
  224. expect(response.headers).to include(
  225. 'Vary' => 'Accept, Accept-Language, Cookie',
  226. 'Cache-Control' => include('private'),
  227. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  228. )
  229. expect(response.body).to include status.text
  230. end
  231. end
  232. context 'with JSON' do
  233. let(:format) { 'json' }
  234. it 'renders ActivityPub Note object successfully' do
  235. expect(response)
  236. .to have_http_status(200)
  237. expect(response.headers).to include(
  238. 'Vary' => 'Accept, Accept-Language, Cookie',
  239. 'Cache-Control' => include('private'),
  240. 'Content-Type' => include('application/activity+json'),
  241. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  242. )
  243. expect(body_as_json)
  244. .to include(content: include(status.text))
  245. end
  246. end
  247. end
  248. context 'when user is not authorized to see it' do
  249. before do
  250. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  251. end
  252. context 'with JSON' do
  253. let(:format) { 'json' }
  254. it 'returns http not found' do
  255. expect(response).to have_http_status(404)
  256. end
  257. end
  258. context 'with HTML' do
  259. let(:format) { 'html' }
  260. it 'returns http not found' do
  261. expect(response).to have_http_status(404)
  262. end
  263. end
  264. end
  265. end
  266. end
  267. context 'with signature' do
  268. let(:remote_account) { Fabricate(:account, domain: 'example.com') }
  269. before do
  270. allow(controller).to receive(:signed_request_actor).and_return(remote_account)
  271. end
  272. context 'when account blocks account' do
  273. before do
  274. account.block!(remote_account)
  275. get :show, params: { account_username: status.account.username, id: status.id }
  276. end
  277. it 'returns http not found' do
  278. expect(response).to have_http_status(404)
  279. end
  280. end
  281. context 'when account domain blocks account' do
  282. before do
  283. account.block_domain!(remote_account.domain)
  284. get :show, params: { account_username: status.account.username, id: status.id }
  285. end
  286. it 'returns http not found' do
  287. expect(response).to have_http_status(404)
  288. end
  289. end
  290. context 'when status is public' do
  291. before do
  292. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  293. end
  294. context 'with HTML' do
  295. let(:format) { 'html' }
  296. it 'renders status successfully', :aggregate_failures do
  297. expect(response)
  298. .to have_http_status(200)
  299. .and render_template(:show)
  300. expect(response.headers).to include(
  301. 'Vary' => 'Accept, Accept-Language, Cookie',
  302. 'Cache-Control' => include('private'),
  303. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  304. )
  305. expect(response.body).to include status.text
  306. end
  307. end
  308. context 'with JSON' do
  309. let(:format) { 'json' }
  310. it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie'
  311. it 'renders ActivityPub Note object successfully', :aggregate_failures do
  312. expect(response)
  313. .to have_http_status(200)
  314. expect(response.headers).to include(
  315. 'Vary' => 'Accept, Accept-Language, Cookie',
  316. 'Content-Type' => include('application/activity+json'),
  317. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  318. )
  319. expect(body_as_json)
  320. .to include(content: include(status.text))
  321. end
  322. end
  323. end
  324. context 'when status is private' do
  325. let(:status) { Fabricate(:status, account: account, visibility: :private) }
  326. context 'when user is authorized to see it' do
  327. before do
  328. remote_account.follow!(account)
  329. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  330. end
  331. context 'with HTML' do
  332. let(:format) { 'html' }
  333. it 'renders status successfully', :aggregate_failures do
  334. expect(response)
  335. .to have_http_status(200)
  336. .and render_template(:show)
  337. expect(response.headers).to include(
  338. 'Vary' => 'Accept, Accept-Language, Cookie',
  339. 'Cache-Control' => include('private'),
  340. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  341. )
  342. expect(response.body).to include status.text
  343. end
  344. end
  345. context 'with JSON' do
  346. let(:format) { 'json' }
  347. it 'renders ActivityPub Note object successfully' do
  348. expect(response)
  349. .to have_http_status(200)
  350. expect(response.headers).to include(
  351. 'Vary' => 'Accept, Accept-Language, Cookie',
  352. 'Cache-Control' => include('private'),
  353. 'Content-Type' => include('application/activity+json'),
  354. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  355. )
  356. expect(body_as_json)
  357. .to include(content: include(status.text))
  358. end
  359. end
  360. end
  361. context 'when user is not authorized to see it' do
  362. before do
  363. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  364. end
  365. context 'with JSON' do
  366. let(:format) { 'json' }
  367. it 'returns http not found' do
  368. expect(response).to have_http_status(404)
  369. end
  370. end
  371. context 'with HTML' do
  372. let(:format) { 'html' }
  373. it 'returns http not found' do
  374. expect(response).to have_http_status(404)
  375. end
  376. end
  377. end
  378. end
  379. context 'when status is direct' do
  380. let(:status) { Fabricate(:status, account: account, visibility: :direct) }
  381. context 'when user is authorized to see it' do
  382. before do
  383. Fabricate(:mention, account: remote_account, status: status)
  384. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  385. end
  386. context 'with HTML' do
  387. let(:format) { 'html' }
  388. it 'renders status successfully', :aggregate_failures do
  389. expect(response)
  390. .to have_http_status(200)
  391. .and render_template(:show)
  392. expect(response.headers).to include(
  393. 'Vary' => 'Accept, Accept-Language, Cookie',
  394. 'Cache-Control' => include('private'),
  395. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  396. )
  397. expect(response.body).to include status.text
  398. end
  399. end
  400. context 'with JSON' do
  401. let(:format) { 'json' }
  402. it 'renders ActivityPub Note object', :aggregate_failures do
  403. expect(response)
  404. .to have_http_status(200)
  405. expect(response.headers).to include(
  406. 'Vary' => 'Accept, Accept-Language, Cookie',
  407. 'Cache-Control' => include('private'),
  408. 'Content-Type' => include('application/activity+json'),
  409. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  410. )
  411. expect(body_as_json)
  412. .to include(content: include(status.text))
  413. end
  414. end
  415. end
  416. context 'when user is not authorized to see it' do
  417. before do
  418. get :show, params: { account_username: status.account.username, id: status.id, format: format }
  419. end
  420. context 'with JSON' do
  421. let(:format) { 'json' }
  422. it 'returns http not found' do
  423. expect(response).to have_http_status(404)
  424. end
  425. end
  426. context 'with HTML' do
  427. let(:format) { 'html' }
  428. it 'returns http not found' do
  429. expect(response).to have_http_status(404)
  430. end
  431. end
  432. end
  433. end
  434. end
  435. end
  436. describe 'GET #activity' do
  437. let(:account) { Fabricate(:account) }
  438. let(:status) { Fabricate(:status, account: account) }
  439. context 'when account is permanently suspended' do
  440. before do
  441. account.suspend!
  442. account.deletion_request.destroy
  443. get :activity, params: { account_username: account.username, id: status.id }
  444. end
  445. it 'returns http gone' do
  446. expect(response).to have_http_status(410)
  447. end
  448. end
  449. context 'when account is temporarily suspended' do
  450. before do
  451. account.suspend!
  452. get :activity, params: { account_username: account.username, id: status.id }
  453. end
  454. it 'returns http forbidden' do
  455. expect(response).to have_http_status(403)
  456. end
  457. end
  458. context 'when status is public' do
  459. before do
  460. status.update(visibility: :public)
  461. get :activity, params: { account_username: account.username, id: status.id }
  462. end
  463. it 'returns http success' do
  464. expect(response).to have_http_status(:success)
  465. end
  466. end
  467. context 'when status is private' do
  468. before do
  469. status.update(visibility: :private)
  470. get :activity, params: { account_username: account.username, id: status.id }
  471. end
  472. it 'returns http not_found' do
  473. expect(response).to have_http_status(404)
  474. end
  475. end
  476. context 'when status is direct' do
  477. before do
  478. status.update(visibility: :direct)
  479. get :activity, params: { account_username: account.username, id: status.id }
  480. end
  481. it 'returns http not_found' do
  482. expect(response).to have_http_status(404)
  483. end
  484. end
  485. context 'when signed-in' do
  486. let(:user) { Fabricate(:user) }
  487. before do
  488. sign_in(user)
  489. end
  490. context 'when status is public' do
  491. before do
  492. status.update(visibility: :public)
  493. get :activity, params: { account_username: account.username, id: status.id }
  494. end
  495. it 'returns http success' do
  496. expect(response).to have_http_status(:success)
  497. end
  498. end
  499. context 'when status is private' do
  500. before do
  501. status.update(visibility: :private)
  502. end
  503. context 'when user is authorized to see it' do
  504. before do
  505. user.account.follow!(account)
  506. get :activity, params: { account_username: account.username, id: status.id }
  507. end
  508. it 'returns http success' do
  509. expect(response).to have_http_status(200)
  510. end
  511. end
  512. context 'when user is not authorized to see it' do
  513. before do
  514. get :activity, params: { account_username: account.username, id: status.id }
  515. end
  516. it 'returns http not_found' do
  517. expect(response).to have_http_status(404)
  518. end
  519. end
  520. end
  521. context 'when status is direct' do
  522. before do
  523. status.update(visibility: :direct)
  524. end
  525. context 'when user is authorized to see it' do
  526. before do
  527. Fabricate(:mention, account: user.account, status: status)
  528. get :activity, params: { account_username: account.username, id: status.id }
  529. end
  530. it 'returns http success' do
  531. expect(response).to have_http_status(200)
  532. end
  533. end
  534. context 'when user is not authorized to see it' do
  535. before do
  536. get :activity, params: { account_username: account.username, id: status.id }
  537. end
  538. it 'returns http not_found' do
  539. expect(response).to have_http_status(404)
  540. end
  541. end
  542. end
  543. end
  544. context 'with signature' do
  545. let(:remote_account) { Fabricate(:account, domain: 'example.com') }
  546. before do
  547. allow(controller).to receive(:signed_request_actor).and_return(remote_account)
  548. end
  549. context 'when status is public' do
  550. before do
  551. status.update(visibility: :public)
  552. get :activity, params: { account_username: account.username, id: status.id }
  553. end
  554. it 'returns http success' do
  555. expect(response).to have_http_status(:success)
  556. end
  557. end
  558. context 'when status is private' do
  559. before do
  560. status.update(visibility: :private)
  561. end
  562. context 'when user is authorized to see it' do
  563. before do
  564. remote_account.follow!(account)
  565. get :activity, params: { account_username: account.username, id: status.id }
  566. end
  567. it 'returns http success' do
  568. expect(response).to have_http_status(200)
  569. end
  570. end
  571. context 'when user is not authorized to see it' do
  572. before do
  573. get :activity, params: { account_username: account.username, id: status.id }
  574. end
  575. it 'returns http not_found' do
  576. expect(response).to have_http_status(404)
  577. end
  578. end
  579. end
  580. context 'when status is direct' do
  581. before do
  582. status.update(visibility: :direct)
  583. end
  584. context 'when user is authorized to see it' do
  585. before do
  586. Fabricate(:mention, account: remote_account, status: status)
  587. get :activity, params: { account_username: account.username, id: status.id }
  588. end
  589. it 'returns http success' do
  590. expect(response).to have_http_status(200)
  591. end
  592. end
  593. context 'when user is not authorized to see it' do
  594. before do
  595. get :activity, params: { account_username: account.username, id: status.id }
  596. end
  597. it 'returns http not_found' do
  598. expect(response).to have_http_status(404)
  599. end
  600. end
  601. end
  602. end
  603. end
  604. describe 'GET #embed' do
  605. let(:account) { Fabricate(:account) }
  606. let(:status) { Fabricate(:status, account: account) }
  607. context 'when account is suspended' do
  608. let(:account) { Fabricate(:account, suspended: true) }
  609. before do
  610. get :embed, params: { account_username: account.username, id: status.id }
  611. end
  612. it 'returns http gone' do
  613. expect(response).to have_http_status(410)
  614. end
  615. end
  616. context 'when status is a reblog' do
  617. let(:original_account) { Fabricate(:account, domain: 'example.com') }
  618. let(:original_status) { Fabricate(:status, account: original_account, url: 'https://example.com/123') }
  619. let(:status) { Fabricate(:status, account: account, reblog: original_status) }
  620. before do
  621. get :embed, params: { account_username: status.account.username, id: status.id }
  622. end
  623. it 'returns http not found' do
  624. expect(response).to have_http_status(404)
  625. end
  626. end
  627. context 'when status is public' do
  628. before do
  629. get :embed, params: { account_username: status.account.username, id: status.id }
  630. end
  631. it 'renders status successfully', :aggregate_failures do
  632. expect(response)
  633. .to have_http_status(200)
  634. .and render_template(:embed)
  635. expect(response.headers).to include(
  636. 'Vary' => 'Accept, Accept-Language, Cookie',
  637. 'Cache-Control' => include('public'),
  638. 'Link' => satisfy { |header| header.to_s.include?('activity+json') }
  639. )
  640. expect(response.body).to include status.text
  641. end
  642. end
  643. context 'when status is private' do
  644. let(:status) { Fabricate(:status, account: account, visibility: :private) }
  645. before do
  646. get :embed, params: { account_username: status.account.username, id: status.id }
  647. end
  648. it 'returns http not found' do
  649. expect(response).to have_http_status(404)
  650. end
  651. end
  652. context 'when status is direct' do
  653. let(:status) { Fabricate(:status, account: account, visibility: :direct) }
  654. before do
  655. get :embed, params: { account_username: status.account.username, id: status.id }
  656. end
  657. it 'returns http not found' do
  658. expect(response).to have_http_status(404)
  659. end
  660. end
  661. end
  662. end