@ -7,468 +7,319 @@ RSpec.describe AccountsController do
let ( :account ) { Fabricate ( :account ) }
shared_examples 'cacheable response' do
it 'does not set cookies' do
expect ( response . cookies ) . to be_empty
expect ( response . headers [ 'Set-Cookies' ] ) . to be_nil
end
it 'does not set sessions' do
expect ( session ) . to be_empty
end
shared_examples 'unapproved account check' do
before { account . user . update ( approved : false ) }
it 'returns Vary header' do
expect ( response . headers [ 'Vary' ] ) . to include 'Accept'
end
it 'returns http not found' do
get :show , params : { username : account . username , format : format }
it 'returns public Cache-Control header' do
expect ( response . headers [ 'Cache-Control' ] ) . to include 'public'
expect ( response ) . to have_http_status ( 404 )
end
end
describe 'GET #show' do
let ( :format ) { 'html' }
let! ( :status ) { Fabricate ( :status , account : account ) }
let! ( :status_reply ) { Fabricate ( :status , account : account , thread : Fabricate ( :status ) ) }
let! ( :status_self_reply ) { Fabricate ( :status , account : account , thread : status ) }
let! ( :status_media ) { Fabricate ( :status , account : account ) }
let! ( :status_pinned ) { Fabricate ( :status , account : account ) }
let! ( :status_private ) { Fabricate ( :status , account : account , visibility : :private ) }
let! ( :status_direct ) { Fabricate ( :status , account : account , visibility : :direct ) }
let! ( :status_reblog ) { Fabricate ( :status , account : account , reblog : Fabricate ( :status ) ) }
shared_examples 'permanently suspended account check' do
before do
status_media . media_attachments << Fabricate ( :media_attachment , account : account , type : :image )
account . pinned_statuses << status_pinned
account . pinned_statuses << status_private
account . suspend!
account . deletion_request . destroy
end
shared_examples 'preliminary checks' do
context 'when account is not approved' do
before do
account . user . update ( approved : false )
end
it 'returns http gone' do
get :show , params : { username : account . username , format : format }
it 'returns http not found' do
get :show , params : { username : account . username , format : format }
expect ( response ) . to have_http_status ( 404 )
end
end
expect ( response ) . to have_http_status ( 410 )
end
end
context 'with HTML' do
let ( :format ) { 'html' }
it_behaves_like 'preliminary checks'
context 'when account is permanently suspended' do
before do
account . suspend!
account . deletion_request . destroy
end
it 'returns http gone' do
get :show , params : { username : account . username , format : format }
expect ( response ) . to have_http_status ( 410 )
end
end
context 'when account is temporarily suspended' do
before do
account . suspend!
end
it 'returns http forbidden' do
get :show , params : { username : account . username , format : format }
expect ( response ) . to have_http_status ( 403 )
end
end
shared_examples 'temporarily suspended account check' do | code : 403 |
before { account . suspend! }
shared_examples 'common response characteristics' do
it 'returns http success' do
expect ( response ) . to have_http_status ( 200 )
end
it 'returns appropriate http response code' do
get :show , params : { username : account . username , format : format }
it 'returns Link header' do
expect ( response . headers [ 'Link' ] . to_s ) . to include ActivityPub :: TagManager . instance . uri_for ( account )
end
it 'renders show template' do
expect ( response ) . to render_template ( :show )
end
end
expect ( response ) . to have_http_status ( code )
end
end
context 'with a normal account in an HTML request ' do
before do
get :show , params : { username : account . username , format : format }
end
describe 'GET #show' do
context 'with basic account status checks' do
context 'with HTML' do
let ( :format ) { 'html' }
it_behaves_like 'common response characteristics'
it_behaves_like 'unapproved account check'
it_behaves_like 'permanently suspended account check'
it_behaves_like 'temporarily suspended account check'
end
context 'with replies' do
before do
allow ( controller ) . to receive ( :replies_requested? ) . and_return ( true )
get :show , params : { username : account . username , format : format }
end
context 'with JSON' do
let ( :format ) { 'json' }
it_behaves_like 'common response characteristics'
it_behaves_like 'unapproved account check'
it_behaves_like 'permanently suspended account check'
it_behaves_like 'temporarily suspended account check' , code : 200
end
context 'with media' do
before do
allow ( controller ) . to receive ( :media_requested? ) . and_return ( true )
get :show , params : { username : account . username , format : format }
end
context 'with RSS' do
let ( :format ) { 'rss' }
it_behaves_like 'common response characteristics'
end
context 'with tag' do
let ( :tag ) { Fabricate ( :tag ) }
let! ( :status_tag ) { Fabricate ( :status , account : account ) }
before do
allow ( controller ) . to receive ( :tag_requested? ) . and_return ( true )
status_tag . tags << tag
get :show , params : { username : account . username , format : format , tag : tag . to_param }
end
it_behaves_like 'common response characteristics'
it_behaves_like 'unapproved account check'
it_behaves_like 'permanently suspended account check'
it_behaves_like 'temporarily suspended account check'
end
end
context 'with JSON' do
let ( :authorized_fetch_mode ) { false }
let ( :format ) { 'json' }
context 'with existing statuses' do
let! ( :status ) { Fabricate ( :status , account : account ) }
let! ( :status_reply ) { Fabricate ( :status , account : account , thread : Fabricate ( :status ) ) }
let! ( :status_self_reply ) { Fabricate ( :status , account : account , thread : status ) }
let! ( :status_media ) { Fabricate ( :status , account : account ) }
let! ( :status_pinned ) { Fabricate ( :status , account : account ) }
let! ( :status_private ) { Fabricate ( :status , account : account , visibility : :private ) }
let! ( :status_direct ) { Fabricate ( :status , account : account , visibility : :direct ) }
let! ( :status_reblog ) { Fabricate ( :status , account : account , reblog : Fabricate ( :status ) ) }
before do
allow ( controller ) . to receive ( :authorized_fetch_mode? ) . and_return ( authorized_fetch_mode )
status_media . media_attachments << Fabricate ( :media_attachment , account : account , type : :image )
account . pinned_statuses << status_pinned
account . pinned_statuses << status_private
end
it_behaves_like 'preliminary checks'
context 'with HTML' do
let ( :format ) { 'html' }
context 'when account is suspended permanently' do
before do
account . suspend!
account . deletion_request . destroy
end
it 'returns http gone' do
get :show , params : { username : account . username , format : format }
expect ( response ) . to have_http_status ( 410 )
end
end
context 'when account is suspended temporarily' do
before do
account . suspend!
end
shared_examples 'common HTML response' do
it 'returns a standard HTML response' , :aggregate_failures do
expect ( response ) . to have_http_status ( 200 )
it 'returns http success' do
get :show , params : { username : account . username , format : format }
expect ( response ) . to have_http_status ( 200 )
end
end
expect ( response . headers [ 'Link' ] . to_s ) . to include ActivityPub :: TagManager . instance . uri_for ( account )
context 'with a normal account in a JSON request' do
before do
get :show , params : { username : account . username , format : format }
expect ( response ) . to render_template ( :show )
end
end
it 'returns http success' do
expect ( response ) . to have_http_status ( 200 )
end
context 'with a normal account in an HTML request' do
before do
get :show , params : { username : account . username , format : format }
end
it 'returns application/activity+json' do
expect ( response . media_type ) . to eq 'application/activity+json'
it_behaves_like 'common HTML response'
end
it_behaves_like 'cacheable response'
context 'with replies' do
before do
allow ( controller ) . to receive ( :replies_requested? ) . and_return ( true )
get :show , params : { username : account . username , format : format }
end
it 'renders account' do
json = body_as_json
expect ( json ) . to include ( :id , :type , :preferredUsername , :inbox , :publicKey , :name , :summary )
it_behaves_like 'common HTML response'
end
context 'with authorized fetch mode' do
let ( :authorized_fetch_mode ) { true }
it 'returns http unauthorized' do
expect ( response ) . to have_http_status ( 401 )
context 'with media' do
before do
allow ( controller ) . to receive ( :media_requested? ) . and_return ( true )
get :show , params : { username : account . username , format : format }
end
end
end
context 'when signed in' do
let ( :user ) { Fabricate ( :user ) }
before do
sign_in ( user )
get :show , params : { username : account . username , format : format }
it_behaves_like 'common HTML response'
end
it 'returns http success' do
expect ( response ) . to have_http_status ( 200 )
end
context 'with tag' do
let ( :tag ) { Fabricate ( :tag ) }
it 'returns application/activity+json' do
expect ( response . media_type ) . to eq 'application/activity+json'
end
let! ( :status_tag ) { Fabricate ( :status , account : account ) }
it 'returns private Cache-Control header' do
expect ( response . headers [ 'Cache-Control' ] ) . to include 'private'
end
before do
allow ( controller ) . to receive ( :tag_requested? ) . and_return ( true )
status_tag . tags << tag
get :show , params : { username : account . username , format : format , tag : tag . to_param }
end
it 'renders account' do
json = body_as_json
expect ( json ) . to include ( :id , :type , :preferredUsername , :inbox , :publicKey , :name , :summary )
it_behaves_like 'common HTML response'
end
end
context 'with signature' do
let ( :remote_account ) { Fabricate ( :account , domain : 'example.com' ) }
context 'with JSON' do
let ( :authorized_fetch_mode ) { false }
let ( :format ) { 'json' }
before do
allow ( controller ) . to receive ( :signed_request_actor ) . and_return ( remote_account )
get :show , params : { username : account . username , format : format }
end
it 'returns http success' do
expect ( response ) . to have_http_status ( 200 )
allow ( controller ) . to receive ( :authorized_fetch_mode? ) . and_return ( authorized_fetch_mode )
end
it 'returns application/activity+json' do
expect ( response . media_type ) . to eq 'application/activity+json'
end
it_behaves_like 'cacheable response'
it 'renders account' do
json = body_as_json
expect ( json ) . to include ( :id , :type , :preferredUsername , :inbox , :publicKey , :name , :summary )
end
context 'with authorized fetch mode' do
let ( :authorized_fetch_mode ) { true }
context 'with a normal account in a JSON request' do
before do
get :show , params : { username : account . username , format : format }
end
it 'returns http success' do
it 'returns a JSON version of the account' , :aggregate_failures do
expect ( response ) . to have_http_status ( 200 )
end
it 'returns application/activity+json' do
expect ( response . media_type ) . to eq 'application/activity+json'
end
it 'returns private Cache-Control header' do
expect ( response . headers [ 'Cache-Control' ] ) . to include 'private'
expect ( body_as_json ) . to include ( :id , :type , :preferredUsername , :inbox , :publicKey , :name , :summary )
end
it 'returns Vary header with Signature' do
expect ( response . headers [ 'Vary' ] ) . to include 'Signature'
end
it 'renders account' do
json = body_as_json
expect ( json ) . to include ( :id , :type , :preferredUsername , :inbox , :publicKey , :name , :summary )
end
end
end
end
it_behaves_like 'cacheable response' , expects_vary : 'Accept, Accept-Language, Cookie'
context 'with RSS ' do
let ( :format ) { 'rss' }
context 'with authorized fetch mode' do
let ( :authorized_fetch_mode ) { true }
it_behaves_like 'preliminary checks'
context 'when account is permanently suspended' do
before do
account . suspend!
account . deletion_request . destroy
end
it 'returns http gone' do
get :show , params : { username : account . username , format : format }
expect ( response ) . to have_http_status ( 410 )
end
end
context 'when account is temporarily suspended' do
before do
account . suspend!
end
it 'returns http forbidden' do
get :show , params : { username : account . username , format : format }
expect ( response ) . to have_http_status ( 403 )
end
end
shared_examples 'common response characteristics' do
it 'returns http success' do
expect ( response ) . to have_http_status ( 200 )
it 'returns http unauthorized' do
expect ( response ) . to have_http_status ( 401 )
end
end
end
it_behaves_like 'cacheable response'
end
context 'when signed in' do
let ( :user ) { Fabricate ( :user ) }
context 'with a normal account in an RSS request' do
before do
get :show , params : { username : account . username , format : format }
end
it_behaves_like 'common response characteristics'
before do
sign_in ( user )
get :show , params : { username : account . username , format : format }
end
it 'renders public status' do
expect ( response . body ) . to include ( ActivityPub :: TagManager . instance . url_for ( status ) )
end
it 'returns a private JSON version of the account' , :aggregate_failures do
expect ( response ) . to have_http_status ( 200 )
it 'renders self-reply' do
expect ( response . body ) . to include ( ActivityPub :: TagManager . instance . url_for ( status_self_reply ) )
end
expect ( response . media_type ) . to eq 'application/activity+json'
it 'renders status with media' do
expect ( response . body ) . to include ( ActivityPub :: TagManager . instance . url_for ( status_media ) )
end
expect ( response . headers [ 'Cache-Control' ] ) . to include 'private'
it 'does not render reblog' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_reblog . reblog ) )
expect ( body_as_json ) . to include ( :id , :type , :preferredUsername , :inbox , :publicKey , :name , :summary )
end
end
it 'does not render private status' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_private ) )
end
context 'with signature' do
let ( :remote_account ) { Fabricate ( :account , domain : 'example.com' ) }
it 'does not render direct status' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_direct ) )
end
before do
allow ( controller ) . to receive ( :signed_request_actor ) . and_return ( remote_account )
get :show , params : { username : account . username , format : format }
end
it 'does not render reply to someone else' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_reply ) )
end
end
it 'returns a JSON version of the account' , :aggregate_failures do
expect ( response ) . to have_http_status ( 200 )
context 'with replies' do
before do
allow ( controller ) . to receive ( :replies_requested? ) . and_return ( true )
get :show , params : { username : account . username , format : format }
end
expect ( response . media_type ) . to eq 'application/activity+json'
it_behaves_like 'common response characteristics'
expect ( body_as_json ) . to include ( :id , :type , :preferredUsername , :inbox , :publicKey , :name , :summary )
end
it 'renders public status' do
expect ( response . body ) . to include ( ActivityPub :: TagManager . instance . url_for ( status ) )
end
it_behaves_like 'cacheable response' , expects_vary : 'Accept, Accept-Language, Cookie'
it 'renders self-reply' do
expect ( response . body ) . to include ( ActivityPub :: TagManager . instance . url_for ( status_self_reply ) )
end
context 'with authorized fetch mode' do
let ( :authorized_fetch_mode ) { true }
it 'renders status with media' do
expect ( response . body ) . to include ( ActivityPub :: TagManager . instance . url_for ( status_media ) )
end
it 'returns a private signature JSON version of the account' , :aggregate_failures do
expect ( response ) . to have_http_status ( 200 )
it 'does not render reblog' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_reblog . reblog ) )
end
expect ( response . media_type ) . to eq 'application/activity+json'
it 'does not render private status' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_private ) )
end
expect ( response . headers [ 'Cache-Control' ] ) . to include 'private'
it 'does not render direct status' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_direct ) )
end
expect ( response . headers [ 'Vary' ] ) . to include 'Signature'
it 'renders reply to someone else' do
expect ( response . body ) . to include ( ActivityPub :: TagManager . instance . url_for ( status_reply ) )
expect ( body_as_json ) . to include ( :id , :type , :preferredUsername , :inbox , :publicKey , :name , :summary )
end
end
end
end
context 'with media' do
before do
allow ( controller ) . to receive ( :media_requested? ) . and_return ( true )
get :show , params : { username : account . username , format : format }
end
it_behaves_like 'common response characteristics'
context 'with RSS' do
let ( :format ) { 'rss' }
it 'does not render public status' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status ) )
end
it 'does not render self-reply' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_self_reply ) )
end
shared_examples 'common RSS response' do
it 'returns http success' do
expect ( response ) . to have_http_status ( 200 )
end
it 'renders status with media' do
expect ( response . body ) . to include ( ActivityPub :: TagManager . instance . url_for ( status_media ) )
it_behaves_like 'cacheable response' , expects_vary : 'Accept, Accept-Language, Cookie'
end
it 'does not render reblog' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_reblog . reblog ) )
end
context 'with a normal account in an RSS request' do
before do
get :show , params : { username : account . username , format : format }
end
it 'does not render private status' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_private ) )
end
it_behaves_like 'common RSS response'
it 'does not render direct status' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_direct ) )
end
it 'does not render reply to someone else' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_reply ) )
it 'responds with correct statuses' , :aggregate_failures do
expect ( response . body ) . to include_status_tag ( status_media )
expect ( response . body ) . to include_status_tag ( status_self_reply )
expect ( response . body ) . to include_status_tag ( status )
expect ( response . body ) . to_not include_status_tag ( status_direct )
expect ( response . body ) . to_not include_status_tag ( status_private )
expect ( response . body ) . to_not include_status_tag ( status_reblog . reblog )
expect ( response . body ) . to_not include_status_tag ( status_reply )
end
end
end
context 'with tag' do
let ( :tag ) { Fabricate ( :tag ) }
let! ( :status_tag ) { Fabricate ( :status , account : account ) }
before do
allow ( controller ) . to receive ( :tag_requested? ) . and_return ( true )
status_tag . tags << tag
get :show , params : { username : account . username , format : format , tag : tag . to_param }
end
context 'with replies' do
before do
allow ( controller ) . to receive ( :replies_requested? ) . and_return ( true )
get :show , params : { username : account . username , format : format }
end
it_behaves_like 'common response characteristics '
it_behaves_like 'common RSS response'
it 'does not render public status' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status ) )
it 'responds with correct statuses with replies' , :aggregate_failures do
expect ( response . body ) . to include_status_tag ( status_media )
expect ( response . body ) . to include_status_tag ( status_reply )
expect ( response . body ) . to include_status_tag ( status_self_reply )
expect ( response . body ) . to include_status_tag ( status )
expect ( response . body ) . to_not include_status_tag ( status_direct )
expect ( response . body ) . to_not include_status_tag ( status_private )
expect ( response . body ) . to_not include_status_tag ( status_reblog . reblog )
end
end
it 'does not render self-reply' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_self_reply ) )
end
context 'with media' do
before do
allow ( controller ) . to receive ( :media_requested? ) . and_return ( true )
get :show , params : { username : account . username , format : format }
end
it 'does not render status with media' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_media ) )
end
it_behaves_like 'common RSS response'
it 'does not render reblog' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_reblog . reblog ) )
it 'responds with correct statuses with media' , :aggregate_failures do
expect ( response . body ) . to include_status_tag ( status_media )
expect ( response . body ) . to_not include_status_tag ( status_direct )
expect ( response . body ) . to_not include_status_tag ( status_private )
expect ( response . body ) . to_not include_status_tag ( status_reblog . reblog )
expect ( response . body ) . to_not include_status_tag ( status_reply )
expect ( response . body ) . to_not include_status_tag ( status_self_reply )
expect ( response . body ) . to_not include_status_tag ( status )
end
end
it 'does not render private status' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_private ) )
end
context 'with tag' do
let ( :tag ) { Fabricate ( :tag ) }
it 'does not render direct status' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_direct ) )
end
let! ( :status_tag ) { Fabricate ( :status , account : account ) }
it 'does not render reply to someone else' do
expect ( response . body ) . to_not include ( ActivityPub :: TagManager . instance . url_for ( status_reply ) )
end
before do
allow ( controller ) . to receive ( :tag_requested? ) . and_return ( true )
status_tag . tags << tag
get :show , params : { username : account . username , format : format , tag : tag . to_param }
end
it 'renders status with tag' do
expect ( response . body ) . to include ( ActivityPub :: TagManager . instance . url_for ( status_tag ) )
it_behaves_like 'common RSS response'
it 'responds with correct statuses with a tag' , :aggregate_failures do
expect ( response . body ) . to include_status_tag ( status_tag )
expect ( response . body ) . to_not include_status_tag ( status_direct )
expect ( response . body ) . to_not include_status_tag ( status_media )
expect ( response . body ) . to_not include_status_tag ( status_private )
expect ( response . body ) . to_not include_status_tag ( status_reblog . reblog )
expect ( response . body ) . to_not include_status_tag ( status_reply )
expect ( response . body ) . to_not include_status_tag ( status_self_reply )
expect ( response . body ) . to_not include_status_tag ( status )
end
end
end
end
end
def include_status_tag ( status )
include ActivityPub :: TagManager . instance . url_for ( status )
end
end