diff options
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/admin/export_domain_blocks_controller_spec.rb | 34 | ||||
-rw-r--r-- | spec/controllers/admin/reports/actions_controller_spec.rb | 128 | ||||
-rw-r--r-- | spec/controllers/concerns/signature_verification_spec.rb | 107 | ||||
-rw-r--r-- | spec/fixtures/files/domain_blocks.csv | 6 | ||||
-rw-r--r-- | spec/fixtures/files/domain_blocks_list.txt | 3 | ||||
-rw-r--r-- | spec/services/update_status_service_spec.rb | 22 |
6 files changed, 266 insertions, 34 deletions
diff --git a/spec/controllers/admin/export_domain_blocks_controller_spec.rb b/spec/controllers/admin/export_domain_blocks_controller_spec.rb index 8697e0c21..2766102c8 100644 --- a/spec/controllers/admin/export_domain_blocks_controller_spec.rb +++ b/spec/controllers/admin/export_domain_blocks_controller_spec.rb @@ -9,9 +9,9 @@ RSpec.describe Admin::ExportDomainBlocksController, type: :controller do describe 'GET #export' do it 'renders instances' do - Fabricate(:domain_block, domain: 'bad.domain', severity: 'silence', public_comment: 'bad') - Fabricate(:domain_block, domain: 'worse.domain', severity: 'suspend', reject_media: true, reject_reports: true, public_comment: 'worse', obfuscate: true) - Fabricate(:domain_block, domain: 'reject.media', severity: 'noop', reject_media: true, public_comment: 'reject media') + Fabricate(:domain_block, domain: 'bad.domain', severity: 'silence', public_comment: 'bad server') + Fabricate(:domain_block, domain: 'worse.domain', severity: 'suspend', reject_media: true, reject_reports: true, public_comment: 'worse server', obfuscate: true) + Fabricate(:domain_block, domain: 'reject.media', severity: 'noop', reject_media: true, public_comment: 'reject media and test unicode characters ♥') Fabricate(:domain_block, domain: 'no.op', severity: 'noop', public_comment: 'noop') get :export, params: { format: :csv } @@ -21,10 +21,32 @@ RSpec.describe Admin::ExportDomainBlocksController, type: :controller do end describe 'POST #import' do - it 'blocks imported domains' do - post :import, params: { admin_import: { data: fixture_file_upload('domain_blocks.csv') } } + context 'with complete domain blocks CSV' do + before do + post :import, params: { admin_import: { data: fixture_file_upload('domain_blocks.csv') } } + end - expect(assigns(:domain_blocks).map(&:domain)).to match_array ['bad.domain', 'worse.domain', 'reject.media'] + it 'renders page with expected domain blocks' do + expect(assigns(:domain_blocks).map { |block| [block.domain, block.severity.to_sym] }).to match_array [['bad.domain', :silence], ['worse.domain', :suspend], ['reject.media', :noop]] + end + + it 'returns http success' do + expect(response).to have_http_status(200) + end + end + + context 'with a list of only domains' do + before do + post :import, params: { admin_import: { data: fixture_file_upload('domain_blocks_list.txt') } } + end + + it 'renders page with expected domain blocks' do + expect(assigns(:domain_blocks).map { |block| [block.domain, block.severity.to_sym] }).to match_array [['bad.domain', :suspend], ['worse.domain', :suspend], ['reject.media', :suspend]] + end + + it 'returns http success' do + expect(response).to have_http_status(200) + end end end diff --git a/spec/controllers/admin/reports/actions_controller_spec.rb b/spec/controllers/admin/reports/actions_controller_spec.rb index 6609798dc..9890ac9ce 100644 --- a/spec/controllers/admin/reports/actions_controller_spec.rb +++ b/spec/controllers/admin/reports/actions_controller_spec.rb @@ -4,39 +4,131 @@ describe Admin::Reports::ActionsController do render_views let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } - let(:account) { Fabricate(:account) } - let!(:status) { Fabricate(:status, account: account) } - let(:media_attached_status) { Fabricate(:status, account: account) } - let!(:media_attachment) { Fabricate(:media_attachment, account: account, status: media_attached_status) } - let(:media_attached_deleted_status) { Fabricate(:status, account: account, deleted_at: 1.day.ago) } - let!(:media_attachment2) { Fabricate(:media_attachment, account: account, status: media_attached_deleted_status) } - let(:last_media_attached_status) { Fabricate(:status, account: account) } - let!(:last_media_attachment) { Fabricate(:media_attachment, account: account, status: last_media_attached_status) } - let!(:last_status) { Fabricate(:status, account: account) } before do sign_in user, scope: :user end - describe 'POST #create' do - let(:report) { Fabricate(:report, status_ids: status_ids, account: user.account, target_account: account) } - let(:status_ids) { [media_attached_status.id, media_attached_deleted_status.id] } + describe 'POST #preview' do + let(:report) { Fabricate(:report) } before do - post :create, params: { report_id: report.id, action => '' } + post :preview, params: { report_id: report.id, action => '' } + end + + context 'when the action is "suspend"' do + let(:action) { 'suspend' } + + it 'returns http success' do + expect(response).to have_http_status(200) + end end - context 'when action is mark_as_sensitive' do + context 'when the action is "silence"' do + let(:action) { 'silence' } + it 'returns http success' do + expect(response).to have_http_status(200) + end + end + + context 'when the action is "delete"' do + let(:action) { 'delete' } + + it 'returns http success' do + expect(response).to have_http_status(200) + end + end + + context 'when the action is "mark_as_sensitive"' do let(:action) { 'mark_as_sensitive' } - it 'resolves the report' do - expect(report.reload.action_taken_at).to_not be_nil + it 'returns http success' do + expect(response).to have_http_status(200) + end + end + end + + describe 'POST #create' do + let(:target_account) { Fabricate(:account) } + let(:statuses) { [Fabricate(:status, account: target_account), Fabricate(:status, account: target_account)] } + let!(:media) { Fabricate(:media_attachment, account: target_account, status: statuses[0]) } + let(:report) { Fabricate(:report, target_account: target_account, status_ids: statuses.map(&:id)) } + let(:text) { 'hello' } + + shared_examples 'common behavior' do + it 'closes the report' do + expect { subject }.to change { report.reload.action_taken? }.from(false).to(true) end - it 'marks the non-deleted as sensitive' do - expect(media_attached_status.reload.sensitive).to eq true + it 'creates a strike with the expected text' do + expect { subject }.to change { report.target_account.strikes.count }.by(1) + expect(report.target_account.strikes.last.text).to eq text end + + it 'redirects' do + subject + expect(response).to redirect_to(admin_reports_path) + end + end + + shared_examples 'all action types' do + context 'when the action is "suspend"' do + let(:action) { 'suspend' } + + it_behaves_like 'common behavior' + + it 'suspends the target account' do + expect { subject }.to change { report.target_account.reload.suspended? }.from(false).to(true) + end + end + + context 'when the action is "silence"' do + let(:action) { 'silence' } + + it_behaves_like 'common behavior' + + it 'suspends the target account' do + expect { subject }.to change { report.target_account.reload.silenced? }.from(false).to(true) + end + end + + context 'when the action is "delete"' do + let(:action) { 'delete' } + + it_behaves_like 'common behavior' + end + + context 'when the action is "mark_as_sensitive"' do + let(:action) { 'mark_as_sensitive' } + let(:statuses) { [media_attached_status, media_attached_deleted_status] } + + let!(:status) { Fabricate(:status, account: target_account) } + let(:media_attached_status) { Fabricate(:status, account: target_account) } + let!(:media_attachment) { Fabricate(:media_attachment, account: target_account, status: media_attached_status) } + let(:media_attached_deleted_status) { Fabricate(:status, account: target_account, deleted_at: 1.day.ago) } + let!(:media_attachment2) { Fabricate(:media_attachment, account: target_account, status: media_attached_deleted_status) } + let(:last_media_attached_status) { Fabricate(:status, account: target_account) } + let!(:last_media_attachment) { Fabricate(:media_attachment, account: target_account, status: last_media_attached_status) } + let!(:last_status) { Fabricate(:status, account: target_account) } + + it_behaves_like 'common behavior' + + it 'marks the non-deleted as sensitive' do + subject + expect(media_attached_status.reload.sensitive).to eq true + end + end + end + + context 'action as submit button' do + subject { post :create, params: { report_id: report.id, text: text, action => '' } } + it_behaves_like 'all action types' + end + + context 'action as submit button' do + subject { post :create, params: { report_id: report.id, text: text, moderation_action: action } } + it_behaves_like 'all action types' end end end diff --git a/spec/controllers/concerns/signature_verification_spec.rb b/spec/controllers/concerns/signature_verification_spec.rb index 6e73643b4..13655f313 100644 --- a/spec/controllers/concerns/signature_verification_spec.rb +++ b/spec/controllers/concerns/signature_verification_spec.rb @@ -16,6 +16,8 @@ describe ApplicationController, type: :controller do controller do include SignatureVerification + before_action :require_actor_signature!, only: [:signature_required] + def success head 200 end @@ -23,10 +25,17 @@ describe ApplicationController, type: :controller do def alternative_success head 200 end + + def signature_required + head 200 + end end before do - routes.draw { match via: [:get, :post], 'success' => 'anonymous#success' } + routes.draw do + match via: [:get, :post], 'success' => 'anonymous#success' + match via: [:get, :post], 'signature_required' => 'anonymous#signature_required' + end end context 'without signature header' do @@ -118,6 +127,37 @@ describe ApplicationController, type: :controller do end end + context 'with request with unparseable Date header' do + before do + get :success + + fake_request = Request.new(:get, request.url) + fake_request.add_headers({ 'Date' => 'wrong date' }) + fake_request.on_behalf_of(author) + + request.headers.merge!(fake_request.headers) + end + + describe '#signed_request?' do + it 'returns true' do + expect(controller.signed_request?).to be true + end + end + + describe '#signed_request_account' do + it 'returns nil' do + expect(controller.signed_request_account).to be_nil + end + end + + describe '#signature_verification_failure_reason' do + it 'contains an error description' do + controller.signed_request_account + expect(controller.signature_verification_failure_reason[:error]).to eq 'Invalid Date header: not RFC 2616 compliant date: "wrong date"' + end + end + end + context 'with request older than a day' do before do get :success @@ -140,6 +180,13 @@ describe ApplicationController, type: :controller do expect(controller.signed_request_account).to be_nil end end + + describe '#signature_verification_failure_reason' do + it 'contains an error description' do + controller.signed_request_account + expect(controller.signature_verification_failure_reason[:error]).to eq 'Signed request date outside acceptable time window' + end + end end context 'with inaccessible key' do @@ -171,6 +218,7 @@ describe ApplicationController, type: :controller do context 'with body' do before do + allow(controller).to receive(:actor_refresh_key!).and_return(author) post :success, body: 'Hello world' fake_request = Request.new(:post, request.url, body: 'Hello world') @@ -189,21 +237,66 @@ describe ApplicationController, type: :controller do it 'returns an account' do expect(controller.signed_request_account).to eq author end + end - it 'returns nil when path does not match' do + context 'when path does not match' do + before do request.path = '/alternative-path' - expect(controller.signed_request_account).to be_nil end - it 'returns nil when method does not match' do + describe '#signed_request_account' do + it 'returns nil' do + expect(controller.signed_request_account).to be_nil + end + end + + describe '#signature_verification_failure_reason' do + it 'contains an error description' do + controller.signed_request_account + expect(controller.signature_verification_failure_reason[:error]).to include('using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)') + expect(controller.signature_verification_failure_reason[:signed_string]).to include("(request-target): post /alternative-path\n") + end + end + end + + context 'when method does not match' do + before do get :success - expect(controller.signed_request_account).to be_nil end - it 'returns nil when body has been tampered' do + describe '#signed_request_account' do + it 'returns nil' do + expect(controller.signed_request_account).to be_nil + end + end + end + + context 'when body has been tampered' do + before do post :success, body: 'doo doo doo' - expect(controller.signed_request_account).to be_nil end + + describe '#signed_request_account' do + it 'returns nil when body has been tampered' do + expect(controller.signed_request_account).to be_nil + end + end + end + end + end + + context 'when a signature is required' do + before do + get :signature_required + end + + context 'without signature header' do + it 'returns HTTP 401' do + expect(response).to have_http_status(401) + end + + it 'returns an error' do + expect(Oj.load(response.body)['error']).to eq 'Request not signed' end end end diff --git a/spec/fixtures/files/domain_blocks.csv b/spec/fixtures/files/domain_blocks.csv index 28ffb9175..9dbfb4eaf 100644 --- a/spec/fixtures/files/domain_blocks.csv +++ b/spec/fixtures/files/domain_blocks.csv @@ -1,4 +1,4 @@ #domain,#severity,#reject_media,#reject_reports,#public_comment,#obfuscate -bad.domain,silence,false,false,bad,false -worse.domain,suspend,true,true,worse,true -reject.media,noop,true,false,reject media,false +bad.domain,silence,false,false,bad server,false +worse.domain,suspend,true,true,worse server,true +reject.media,noop,true,false,reject media and test unicode characters ♥,false diff --git a/spec/fixtures/files/domain_blocks_list.txt b/spec/fixtures/files/domain_blocks_list.txt new file mode 100644 index 000000000..7b6b24253 --- /dev/null +++ b/spec/fixtures/files/domain_blocks_list.txt @@ -0,0 +1,3 @@ +bad.domain +worse.domain +reject.media diff --git a/spec/services/update_status_service_spec.rb b/spec/services/update_status_service_spec.rb index 71a73be5b..16e981d2b 100644 --- a/spec/services/update_status_service_spec.rb +++ b/spec/services/update_status_service_spec.rb @@ -87,6 +87,28 @@ RSpec.describe UpdateStatusService, type: :service do end end + context 'when already-attached media changes' do + let!(:status) { Fabricate(:status, text: 'Foo') } + let!(:media_attachment) { Fabricate(:media_attachment, account: status.account, description: 'Old description') } + + before do + status.media_attachments << media_attachment + subject.call(status, status.account_id, text: 'Foo', media_ids: [media_attachment.id], media_attributes: [{ id: media_attachment.id, description: 'New description' }]) + end + + it 'does not detach media attachment' do + expect(media_attachment.reload.status_id).to eq status.id + end + + it 'updates the media attachment description' do + expect(media_attachment.reload.description).to eq 'New description' + end + + it 'saves edit history' do + expect(status.edits.map { |edit| edit.ordered_media_attachments.map(&:description) }).to eq [['Old description'], ['New description']] + end + end + context 'when poll changes' do let(:account) { Fabricate(:account) } let!(:status) { Fabricate(:status, text: 'Foo', account: account, poll_attributes: {options: %w(Foo Bar), account: account, multiple: false, hide_totals: false, expires_at: 7.days.from_now }) } |