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.

612 lines
21 KiB

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