accounts_controller_spec.rb 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. require 'rails_helper'
  2. RSpec.describe AccountsController, type: :controller do
  3. render_views
  4. let(:account) { Fabricate(:account) }
  5. shared_examples 'cacheable response' do
  6. it 'does not set cookies' do
  7. expect(response.cookies).to be_empty
  8. expect(response.headers['Set-Cookies']).to be nil
  9. end
  10. it 'does not set sessions' do
  11. expect(session).to be_empty
  12. end
  13. it 'returns public Cache-Control header' do
  14. expect(response.headers['Cache-Control']).to include 'public'
  15. end
  16. end
  17. describe 'GET #show' do
  18. let(:format) { 'html' }
  19. let!(:status) { Fabricate(:status, account: account) }
  20. let!(:status_reply) { Fabricate(:status, account: account, thread: Fabricate(:status)) }
  21. let!(:status_self_reply) { Fabricate(:status, account: account, thread: status) }
  22. let!(:status_media) { Fabricate(:status, account: account) }
  23. let!(:status_pinned) { Fabricate(:status, account: account) }
  24. let!(:status_private) { Fabricate(:status, account: account, visibility: :private) }
  25. let!(:status_direct) { Fabricate(:status, account: account, visibility: :direct) }
  26. let!(:status_reblog) { Fabricate(:status, account: account, reblog: Fabricate(:status)) }
  27. before do
  28. status_media.media_attachments << Fabricate(:media_attachment, account: account, type: :image)
  29. account.pinned_statuses << status_pinned
  30. account.pinned_statuses << status_private
  31. end
  32. shared_examples 'preliminary checks' do
  33. context 'when account is not approved' do
  34. before do
  35. account.user.update(approved: false)
  36. end
  37. it 'returns http not found' do
  38. get :show, params: { username: account.username, format: format }
  39. expect(response).to have_http_status(404)
  40. end
  41. end
  42. end
  43. context 'as HTML' do
  44. let(:format) { 'html' }
  45. it_behaves_like 'preliminary checks'
  46. context 'when account is permanently suspended' do
  47. before do
  48. account.suspend!
  49. account.deletion_request.destroy
  50. end
  51. it 'returns http gone' do
  52. get :show, params: { username: account.username, format: format }
  53. expect(response).to have_http_status(410)
  54. end
  55. end
  56. context 'when account is temporarily suspended' do
  57. before do
  58. account.suspend!
  59. end
  60. it 'returns http forbidden' do
  61. get :show, params: { username: account.username, format: format }
  62. expect(response).to have_http_status(403)
  63. end
  64. end
  65. shared_examples 'common response characteristics' do
  66. it 'returns http success' do
  67. expect(response).to have_http_status(200)
  68. end
  69. it 'returns Link header' do
  70. expect(response.headers['Link'].to_s).to include ActivityPub::TagManager.instance.uri_for(account)
  71. end
  72. it 'renders show template' do
  73. expect(response).to render_template(:show)
  74. end
  75. end
  76. context do
  77. before do
  78. get :show, params: { username: account.username, format: format }
  79. end
  80. it_behaves_like 'common response characteristics'
  81. it 'renders public status' do
  82. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status))
  83. end
  84. it 'renders self-reply' do
  85. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_self_reply))
  86. end
  87. it 'renders status with media' do
  88. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_media))
  89. end
  90. it 'renders reblog' do
  91. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
  92. end
  93. it 'renders pinned status' do
  94. expect(response.body).to include(I18n.t('stream_entries.pinned'))
  95. end
  96. it 'does not render private status' do
  97. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
  98. end
  99. it 'does not render direct status' do
  100. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
  101. end
  102. it 'does not render reply to someone else' do
  103. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reply))
  104. end
  105. end
  106. context 'when signed-in' do
  107. let(:user) { Fabricate(:user) }
  108. before do
  109. sign_in(user)
  110. end
  111. context 'when user follows account' do
  112. before do
  113. user.account.follow!(account)
  114. get :show, params: { username: account.username, format: format }
  115. end
  116. it 'does not render private status' do
  117. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
  118. end
  119. end
  120. context 'when user is blocked' do
  121. before do
  122. account.block!(user.account)
  123. get :show, params: { username: account.username, format: format }
  124. end
  125. it 'renders unavailable message' do
  126. expect(response.body).to include(I18n.t('accounts.unavailable'))
  127. end
  128. it 'does not render public status' do
  129. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status))
  130. end
  131. it 'does not render self-reply' do
  132. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_self_reply))
  133. end
  134. it 'does not render status with media' do
  135. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_media))
  136. end
  137. it 'does not render reblog' do
  138. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
  139. end
  140. it 'does not render pinned status' do
  141. expect(response.body).to_not include(I18n.t('stream_entries.pinned'))
  142. end
  143. it 'does not render private status' do
  144. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
  145. end
  146. it 'does not render direct status' do
  147. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
  148. end
  149. it 'does not render reply to someone else' do
  150. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reply))
  151. end
  152. end
  153. end
  154. context 'with replies' do
  155. before do
  156. allow(controller).to receive(:replies_requested?).and_return(true)
  157. get :show, params: { username: account.username, format: format }
  158. end
  159. it_behaves_like 'common response characteristics'
  160. it 'renders public status' do
  161. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status))
  162. end
  163. it 'renders self-reply' do
  164. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_self_reply))
  165. end
  166. it 'renders status with media' do
  167. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_media))
  168. end
  169. it 'renders reblog' do
  170. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
  171. end
  172. it 'does not render pinned status' do
  173. expect(response.body).to_not include(I18n.t('stream_entries.pinned'))
  174. end
  175. it 'does not render private status' do
  176. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
  177. end
  178. it 'does not render direct status' do
  179. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
  180. end
  181. it 'renders reply to someone else' do
  182. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_reply))
  183. end
  184. end
  185. context 'with media' do
  186. before do
  187. allow(controller).to receive(:media_requested?).and_return(true)
  188. get :show, params: { username: account.username, format: format }
  189. end
  190. it_behaves_like 'common response characteristics'
  191. it 'does not render public status' do
  192. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status))
  193. end
  194. it 'does not render self-reply' do
  195. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_self_reply))
  196. end
  197. it 'renders status with media' do
  198. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_media))
  199. end
  200. it 'does not render reblog' do
  201. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
  202. end
  203. it 'does not render pinned status' do
  204. expect(response.body).to_not include(I18n.t('stream_entries.pinned'))
  205. end
  206. it 'does not render private status' do
  207. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
  208. end
  209. it 'does not render direct status' do
  210. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
  211. end
  212. it 'does not render reply to someone else' do
  213. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reply))
  214. end
  215. end
  216. context 'with tag' do
  217. let(:tag) { Fabricate(:tag) }
  218. let!(:status_tag) { Fabricate(:status, account: account) }
  219. before do
  220. allow(controller).to receive(:tag_requested?).and_return(true)
  221. status_tag.tags << tag
  222. get :show, params: { username: account.username, format: format, tag: tag.to_param }
  223. end
  224. it_behaves_like 'common response characteristics'
  225. it 'does not render public status' do
  226. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status))
  227. end
  228. it 'does not render self-reply' do
  229. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_self_reply))
  230. end
  231. it 'does not render status with media' do
  232. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_media))
  233. end
  234. it 'does not render reblog' do
  235. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
  236. end
  237. it 'does not render pinned status' do
  238. expect(response.body).to_not include(I18n.t('stream_entries.pinned'))
  239. end
  240. it 'does not render private status' do
  241. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
  242. end
  243. it 'does not render direct status' do
  244. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
  245. end
  246. it 'does not render reply to someone else' do
  247. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reply))
  248. end
  249. it 'renders status with tag' do
  250. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_tag))
  251. end
  252. end
  253. end
  254. context 'as JSON' do
  255. let(:authorized_fetch_mode) { false }
  256. let(:format) { 'json' }
  257. before do
  258. allow(controller).to receive(:authorized_fetch_mode?).and_return(authorized_fetch_mode)
  259. end
  260. it_behaves_like 'preliminary checks'
  261. context 'when account is suspended permanently' do
  262. before do
  263. account.suspend!
  264. account.deletion_request.destroy
  265. end
  266. it 'returns http gone' do
  267. get :show, params: { username: account.username, format: format }
  268. expect(response).to have_http_status(410)
  269. end
  270. end
  271. context 'when account is suspended temporarily' do
  272. before do
  273. account.suspend!
  274. end
  275. it 'returns http success' do
  276. get :show, params: { username: account.username, format: format }
  277. expect(response).to have_http_status(200)
  278. end
  279. end
  280. context do
  281. before do
  282. get :show, params: { username: account.username, format: format }
  283. end
  284. it 'returns http success' do
  285. expect(response).to have_http_status(200)
  286. end
  287. it 'returns application/activity+json' do
  288. expect(response.media_type).to eq 'application/activity+json'
  289. end
  290. it_behaves_like 'cacheable response'
  291. it 'renders account' do
  292. json = body_as_json
  293. expect(json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
  294. end
  295. context 'in authorized fetch mode' do
  296. let(:authorized_fetch_mode) { true }
  297. it 'returns http unauthorized' do
  298. expect(response).to have_http_status(401)
  299. end
  300. end
  301. end
  302. context 'when signed in' do
  303. let(:user) { Fabricate(:user) }
  304. before do
  305. sign_in(user)
  306. get :show, params: { username: account.username, format: format }
  307. end
  308. it 'returns http success' do
  309. expect(response).to have_http_status(200)
  310. end
  311. it 'returns application/activity+json' do
  312. expect(response.media_type).to eq 'application/activity+json'
  313. end
  314. it 'returns public Cache-Control header' do
  315. expect(response.headers['Cache-Control']).to include 'public'
  316. end
  317. it 'renders account' do
  318. json = body_as_json
  319. expect(json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
  320. end
  321. end
  322. context 'with signature' do
  323. let(:remote_account) { Fabricate(:account, domain: 'example.com') }
  324. before do
  325. allow(controller).to receive(:signed_request_account).and_return(remote_account)
  326. get :show, params: { username: account.username, format: format }
  327. end
  328. it 'returns http success' do
  329. expect(response).to have_http_status(200)
  330. end
  331. it 'returns application/activity+json' do
  332. expect(response.media_type).to eq 'application/activity+json'
  333. end
  334. it_behaves_like 'cacheable response'
  335. it 'renders account' do
  336. json = body_as_json
  337. expect(json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
  338. end
  339. context 'in authorized fetch mode' do
  340. let(:authorized_fetch_mode) { true }
  341. it 'returns http success' do
  342. expect(response).to have_http_status(200)
  343. end
  344. it 'returns application/activity+json' do
  345. expect(response.media_type).to eq 'application/activity+json'
  346. end
  347. it 'returns private Cache-Control header' do
  348. expect(response.headers['Cache-Control']).to include 'private'
  349. end
  350. it 'returns Vary header with Signature' do
  351. expect(response.headers['Vary']).to include 'Signature'
  352. end
  353. it 'renders account' do
  354. json = body_as_json
  355. expect(json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary)
  356. end
  357. end
  358. end
  359. end
  360. context 'as RSS' do
  361. let(:format) { 'rss' }
  362. it_behaves_like 'preliminary checks'
  363. context 'when account is permanently suspended' do
  364. before do
  365. account.suspend!
  366. account.deletion_request.destroy
  367. end
  368. it 'returns http gone' do
  369. get :show, params: { username: account.username, format: format }
  370. expect(response).to have_http_status(410)
  371. end
  372. end
  373. context 'when account is temporarily suspended' do
  374. before do
  375. account.suspend!
  376. end
  377. it 'returns http forbidden' do
  378. get :show, params: { username: account.username, format: format }
  379. expect(response).to have_http_status(403)
  380. end
  381. end
  382. shared_examples 'common response characteristics' do
  383. it 'returns http success' do
  384. expect(response).to have_http_status(200)
  385. end
  386. it_behaves_like 'cacheable response'
  387. end
  388. context do
  389. before do
  390. get :show, params: { username: account.username, format: format }
  391. end
  392. it_behaves_like 'common response characteristics'
  393. it 'renders public status' do
  394. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status))
  395. end
  396. it 'renders self-reply' do
  397. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_self_reply))
  398. end
  399. it 'renders status with media' do
  400. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_media))
  401. end
  402. it 'does not render reblog' do
  403. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
  404. end
  405. it 'does not render private status' do
  406. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
  407. end
  408. it 'does not render direct status' do
  409. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
  410. end
  411. it 'does not render reply to someone else' do
  412. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reply))
  413. end
  414. end
  415. context 'with replies' do
  416. before do
  417. allow(controller).to receive(:replies_requested?).and_return(true)
  418. get :show, params: { username: account.username, format: format }
  419. end
  420. it_behaves_like 'common response characteristics'
  421. it 'renders public status' do
  422. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status))
  423. end
  424. it 'renders self-reply' do
  425. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_self_reply))
  426. end
  427. it 'renders status with media' do
  428. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_media))
  429. end
  430. it 'does not render reblog' do
  431. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
  432. end
  433. it 'does not render private status' do
  434. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
  435. end
  436. it 'does not render direct status' do
  437. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
  438. end
  439. it 'renders reply to someone else' do
  440. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_reply))
  441. end
  442. end
  443. context 'with media' do
  444. before do
  445. allow(controller).to receive(:media_requested?).and_return(true)
  446. get :show, params: { username: account.username, format: format }
  447. end
  448. it_behaves_like 'common response characteristics'
  449. it 'does not render public status' do
  450. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status))
  451. end
  452. it 'does not render self-reply' do
  453. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_self_reply))
  454. end
  455. it 'renders status with media' do
  456. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_media))
  457. end
  458. it 'does not render reblog' do
  459. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
  460. end
  461. it 'does not render private status' do
  462. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
  463. end
  464. it 'does not render direct status' do
  465. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
  466. end
  467. it 'does not render reply to someone else' do
  468. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reply))
  469. end
  470. end
  471. context 'with tag' do
  472. let(:tag) { Fabricate(:tag) }
  473. let!(:status_tag) { Fabricate(:status, account: account) }
  474. before do
  475. allow(controller).to receive(:tag_requested?).and_return(true)
  476. status_tag.tags << tag
  477. get :show, params: { username: account.username, format: format, tag: tag.to_param }
  478. end
  479. it_behaves_like 'common response characteristics'
  480. it 'does not render public status' do
  481. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status))
  482. end
  483. it 'does not render self-reply' do
  484. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_self_reply))
  485. end
  486. it 'does not render status with media' do
  487. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_media))
  488. end
  489. it 'does not render reblog' do
  490. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reblog.reblog))
  491. end
  492. it 'does not render private status' do
  493. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_private))
  494. end
  495. it 'does not render direct status' do
  496. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_direct))
  497. end
  498. it 'does not render reply to someone else' do
  499. expect(response.body).to_not include(ActivityPub::TagManager.instance.url_for(status_reply))
  500. end
  501. it 'renders status with tag' do
  502. expect(response.body).to include(ActivityPub::TagManager.instance.url_for(status_tag))
  503. end
  504. end
  505. end
  506. end
  507. end