Merge branch 'master' into glitch-soc/merge-upstream
Conflicts: - `app/controllers/activitypub/collections_controller.rb`: Conflict due to glitch-soc having to take care of local-only pinned toots in that controller. Took upstream's changes and restored the local-only special handling. - `app/controllers/auth/sessions_controller.rb`: Minor conflicts due to the theming system, applied upstream changes, adapted the following two files for glitch-soc's theming system: - `app/controllers/concerns/sign_in_token_authentication_concern.rb` - `app/controllers/concerns/two_factor_authentication_concern.rb` - `app/services/backup_service.rb`: Minor conflict due to glitch-soc having to handle local-only toots specially. Applied upstream changes and restored the local-only special handling. - `app/views/admin/custom_emojis/index.html.haml`: Minor conflict due to the theming system. - `package.json`: Upstream dependency updated, too close to a glitch-soc-only dependency in the file. - `yarn.lock`: Upstream dependency updated, too close to a glitch-soc-only dependency in the file.
This commit is contained in:
@@ -4,6 +4,7 @@ require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::RepliesController, type: :controller do
|
||||
let(:status) { Fabricate(:status, visibility: parent_visibility) }
|
||||
let(:remote_reply_id) { nil }
|
||||
let(:remote_account) { nil }
|
||||
|
||||
before do
|
||||
@@ -14,6 +15,8 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do
|
||||
Fabricate(:status, thread: status, visibility: :private)
|
||||
Fabricate(:status, account: status.account, thread: status, visibility: :public)
|
||||
Fabricate(:status, account: status.account, thread: status, visibility: :private)
|
||||
|
||||
Fabricate(:status, account: remote_account, thread: status, visibility: :public, uri: remote_reply_id) if remote_reply_id
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
@@ -110,6 +113,20 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do
|
||||
expect(json[:first][:items].size).to eq 2
|
||||
expect(json[:first][:items].all? { |item| item[:to].include?(ActivityPub::TagManager::COLLECTIONS[:public]) || item[:cc].include?(ActivityPub::TagManager::COLLECTIONS[:public]) }).to be true
|
||||
end
|
||||
|
||||
context 'with remote responses' do
|
||||
let(:remote_reply_id) { 'foo' }
|
||||
|
||||
it 'returned items are all inlined local toots or are ids' do
|
||||
json = body_as_json
|
||||
|
||||
expect(json[:first]).to be_a Hash
|
||||
expect(json[:first][:items]).to be_an Array
|
||||
expect(json[:first][:items].size).to eq 3
|
||||
expect(json[:first][:items].all? { |item| item.is_a?(Hash) ? ActivityPub::TagManager.instance.local_uri?(item[:id]) : item.is_a?(String) }).to be true
|
||||
expect(json[:first][:items]).to include remote_reply_id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -215,7 +215,7 @@ RSpec.describe Auth::SessionsController, type: :controller do
|
||||
|
||||
context 'using a valid OTP' do
|
||||
before do
|
||||
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { otp_user_id: user.id }
|
||||
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id }
|
||||
end
|
||||
|
||||
it 'redirects to home' do
|
||||
@@ -230,7 +230,7 @@ RSpec.describe Auth::SessionsController, type: :controller do
|
||||
context 'when the server has an decryption error' do
|
||||
before do
|
||||
allow_any_instance_of(User).to receive(:validate_and_consume_otp!).and_raise(OpenSSL::Cipher::CipherError)
|
||||
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { otp_user_id: user.id }
|
||||
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id }
|
||||
end
|
||||
|
||||
it 'shows a login error' do
|
||||
@@ -244,7 +244,7 @@ RSpec.describe Auth::SessionsController, type: :controller do
|
||||
|
||||
context 'using a valid recovery code' do
|
||||
before do
|
||||
post :create, params: { user: { otp_attempt: recovery_codes.first } }, session: { otp_user_id: user.id }
|
||||
post :create, params: { user: { otp_attempt: recovery_codes.first } }, session: { attempt_user_id: user.id }
|
||||
end
|
||||
|
||||
it 'redirects to home' do
|
||||
@@ -258,7 +258,7 @@ RSpec.describe Auth::SessionsController, type: :controller do
|
||||
|
||||
context 'using an invalid OTP' do
|
||||
before do
|
||||
post :create, params: { user: { otp_attempt: 'wrongotp' } }, session: { otp_user_id: user.id }
|
||||
post :create, params: { user: { otp_attempt: 'wrongotp' } }, session: { attempt_user_id: user.id }
|
||||
end
|
||||
|
||||
it 'shows a login error' do
|
||||
@@ -270,5 +270,63 @@ RSpec.describe Auth::SessionsController, type: :controller do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when 2FA is disabled and IP is unfamiliar' do
|
||||
let!(:user) { Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', current_sign_in_at: 3.weeks.ago, current_sign_in_ip: '0.0.0.0') }
|
||||
|
||||
before do
|
||||
request.remote_ip = '10.10.10.10'
|
||||
request.user_agent = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0'
|
||||
|
||||
allow(UserMailer).to receive(:sign_in_token).and_return(double('email', deliver_later!: nil))
|
||||
end
|
||||
|
||||
context 'using email and password' do
|
||||
before do
|
||||
post :create, params: { user: { email: user.email, password: user.password } }
|
||||
end
|
||||
|
||||
it 'renders sign in token authentication page' do
|
||||
expect(controller).to render_template("sign_in_token")
|
||||
end
|
||||
|
||||
it 'generates sign in token' do
|
||||
expect(user.reload.sign_in_token).to_not be_nil
|
||||
end
|
||||
|
||||
it 'sends sign in token e-mail' do
|
||||
expect(UserMailer).to have_received(:sign_in_token)
|
||||
end
|
||||
end
|
||||
|
||||
context 'using a valid sign in token' do
|
||||
before do
|
||||
user.generate_sign_in_token && user.save
|
||||
post :create, params: { user: { sign_in_token_attempt: user.sign_in_token } }, session: { attempt_user_id: user.id }
|
||||
end
|
||||
|
||||
it 'redirects to home' do
|
||||
expect(response).to redirect_to(root_path)
|
||||
end
|
||||
|
||||
it 'logs the user in' do
|
||||
expect(controller.current_user).to eq user
|
||||
end
|
||||
end
|
||||
|
||||
context 'using an invalid sign in token' do
|
||||
before do
|
||||
post :create, params: { user: { sign_in_token_attempt: 'wrongotp' } }, session: { attempt_user_id: user.id }
|
||||
end
|
||||
|
||||
it 'shows a login error' do
|
||||
expect(flash[:alert]).to match I18n.t('users.invalid_sign_in_token')
|
||||
end
|
||||
|
||||
it "doesn't log the user in" do
|
||||
expect(controller.current_user).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
8
spec/fabricators/device_fabricator.rb
Normal file
8
spec/fabricators/device_fabricator.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
Fabricator(:device) do
|
||||
access_token
|
||||
account
|
||||
device_id { Faker::Number.number(digits: 5) }
|
||||
name { Faker::App.name }
|
||||
fingerprint_key { Base64.strict_encode64(Ed25519::SigningKey.generate.verify_key.to_bytes) }
|
||||
identity_key { Base64.strict_encode64(Ed25519::SigningKey.generate.verify_key.to_bytes) }
|
||||
end
|
||||
8
spec/fabricators/encrypted_message_fabricator.rb
Normal file
8
spec/fabricators/encrypted_message_fabricator.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
Fabricator(:encrypted_message) do
|
||||
device
|
||||
from_account
|
||||
from_device_id { Faker::Number.number(digits: 5) }
|
||||
type 0
|
||||
body ""
|
||||
message_franking ""
|
||||
end
|
||||
11
spec/fabricators/one_time_key_fabricator.rb
Normal file
11
spec/fabricators/one_time_key_fabricator.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
Fabricator(:one_time_key) do
|
||||
device
|
||||
key_id { Faker::Alphanumeric.alphanumeric(number: 10) }
|
||||
key { Base64.strict_encode64(Ed25519::SigningKey.generate.verify_key.to_bytes) }
|
||||
|
||||
signature do |attrs|
|
||||
signing_key = Ed25519::SigningKey.generate
|
||||
attrs[:device].update(fingerprint_key: Base64.strict_encode64(signing_key.verify_key.to_bytes))
|
||||
Base64.strict_encode64(signing_key.sign(attrs[:key]))
|
||||
end
|
||||
end
|
||||
3
spec/fabricators/system_key_fabricator.rb
Normal file
3
spec/fabricators/system_key_fabricator.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
Fabricator(:system_key) do
|
||||
|
||||
end
|
||||
@@ -579,6 +579,62 @@ RSpec.describe ActivityPub::Activity::Create do
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an encrypted message' do
|
||||
let(:recipient) { Fabricate(:account) }
|
||||
let(:target_device) { Fabricate(:device, account: recipient) }
|
||||
|
||||
subject { described_class.new(json, sender, delivery: true, delivered_to_account_id: recipient.id) }
|
||||
|
||||
let(:object_json) do
|
||||
{
|
||||
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
|
||||
type: 'EncryptedMessage',
|
||||
attributedTo: {
|
||||
type: 'Device',
|
||||
deviceId: '1234',
|
||||
},
|
||||
to: {
|
||||
type: 'Device',
|
||||
deviceId: target_device.device_id,
|
||||
},
|
||||
messageType: 1,
|
||||
cipherText: 'Foo',
|
||||
messageFranking: 'Baz678',
|
||||
digest: {
|
||||
digestAlgorithm: 'Bar456',
|
||||
digestValue: 'Foo123',
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
subject.perform
|
||||
end
|
||||
|
||||
it 'creates an encrypted message' do
|
||||
encrypted_message = target_device.encrypted_messages.reload.first
|
||||
|
||||
expect(encrypted_message).to_not be_nil
|
||||
expect(encrypted_message.from_device_id).to eq '1234'
|
||||
expect(encrypted_message.from_account).to eq sender
|
||||
expect(encrypted_message.type).to eq 1
|
||||
expect(encrypted_message.body).to eq 'Foo'
|
||||
expect(encrypted_message.digest).to eq 'Foo123'
|
||||
end
|
||||
|
||||
it 'creates a message franking' do
|
||||
encrypted_message = target_device.encrypted_messages.reload.first
|
||||
message_franking = encrypted_message.message_franking
|
||||
|
||||
crypt = ActiveSupport::MessageEncryptor.new(SystemKey.current_key, serializer: Oj)
|
||||
json = crypt.decrypt_and_verify(message_franking)
|
||||
|
||||
expect(json['source_account_id']).to eq sender.id
|
||||
expect(json['target_account_id']).to eq recipient.id
|
||||
expect(json['original_franking']).to eq 'Baz678'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when sender is followed by local users' do
|
||||
subject { described_class.new(json, sender, delivery: true) }
|
||||
|
||||
|
||||
@@ -59,4 +59,9 @@ class UserMailerPreview < ActionMailer::Preview
|
||||
def warning
|
||||
UserMailer.warning(User.first, AccountWarning.new(text: '', action: :silence), [Status.first.id])
|
||||
end
|
||||
|
||||
# Preview this email at http://localhost:3000/rails/mailers/user_mailer/sign_in_token
|
||||
def sign_in_token
|
||||
UserMailer.sign_in_token(User.first.tap { |user| user.generate_sign_in_token }, '127.0.0.1', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0', Time.now.utc)
|
||||
end
|
||||
end
|
||||
|
||||
5
spec/models/device_spec.rb
Normal file
5
spec/models/device_spec.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Device, type: :model do
|
||||
|
||||
end
|
||||
5
spec/models/encrypted_message_spec.rb
Normal file
5
spec/models/encrypted_message_spec.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe EncryptedMessage, type: :model do
|
||||
|
||||
end
|
||||
5
spec/models/one_time_key_spec.rb
Normal file
5
spec/models/one_time_key_spec.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe OneTimeKey, type: :model do
|
||||
|
||||
end
|
||||
5
spec/models/system_key_spec.rb
Normal file
5
spec/models/system_key_spec.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe SystemKey, type: :model do
|
||||
|
||||
end
|
||||
23
spec/services/clear_domain_media_service_spec.rb
Normal file
23
spec/services/clear_domain_media_service_spec.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ClearDomainMediaService, type: :service do
|
||||
let!(:bad_account) { Fabricate(:account, username: 'badguy666', domain: 'evil.org') }
|
||||
let!(:bad_status1) { Fabricate(:status, account: bad_account, text: 'You suck') }
|
||||
let!(:bad_status2) { Fabricate(:status, account: bad_account, text: 'Hahaha') }
|
||||
let!(:bad_attachment) { Fabricate(:media_attachment, account: bad_account, status: bad_status2, file: attachment_fixture('attachment.jpg')) }
|
||||
|
||||
subject { ClearDomainMediaService.new }
|
||||
|
||||
describe 'for a silence with reject media' do
|
||||
before do
|
||||
subject.call(DomainBlock.create!(domain: 'evil.org', severity: :silence, reject_media: true))
|
||||
end
|
||||
|
||||
it 'leaves the domains status and attachements, but clears media' do
|
||||
expect { bad_status1.reload }.not_to raise_error
|
||||
expect { bad_status2.reload }.not_to raise_error
|
||||
expect { bad_attachment.reload }.not_to raise_error
|
||||
expect(bad_attachment.file.exists?).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -8,7 +8,7 @@ describe DomainBlockWorker do
|
||||
describe 'perform' do
|
||||
let(:domain_block) { Fabricate(:domain_block) }
|
||||
|
||||
it 'returns true for non-existent domain block' do
|
||||
it 'calls domain block service for relevant domain block' do
|
||||
service = double(call: nil)
|
||||
allow(BlockDomainService).to receive(:new).and_return(service)
|
||||
result = subject.perform(domain_block.id)
|
||||
@@ -17,7 +17,7 @@ describe DomainBlockWorker do
|
||||
expect(service).to have_received(:call).with(domain_block, false)
|
||||
end
|
||||
|
||||
it 'calls domain block service for relevant domain block' do
|
||||
it 'returns true for non-existent domain block' do
|
||||
result = subject.perform('aaa')
|
||||
|
||||
expect(result).to eq(true)
|
||||
|
||||
26
spec/workers/domain_clear_media_worker_spec.rb
Normal file
26
spec/workers/domain_clear_media_worker_spec.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe DomainClearMediaWorker do
|
||||
subject { described_class.new }
|
||||
|
||||
describe 'perform' do
|
||||
let(:domain_block) { Fabricate(:domain_block, severity: :silence, reject_media: true) }
|
||||
|
||||
it 'calls domain clear media service for relevant domain block' do
|
||||
service = double(call: nil)
|
||||
allow(ClearDomainMediaService).to receive(:new).and_return(service)
|
||||
result = subject.perform(domain_block.id)
|
||||
|
||||
expect(result).to be_nil
|
||||
expect(service).to have_received(:call).with(domain_block)
|
||||
end
|
||||
|
||||
it 'returns true for non-existent domain block' do
|
||||
result = subject.perform('aaa')
|
||||
|
||||
expect(result).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user