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.

661 lines
22 KiB

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