Basic FASP support (#34031)
This commit is contained in:
parent
e5fd61a84e
commit
97b9994743
45 changed files with 1423 additions and 1 deletions
7
spec/fabricators/fasp/debug_callback_fabricator.rb
Normal file
7
spec/fabricators/fasp/debug_callback_fabricator.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Fabricator(:fasp_debug_callback, from: 'Fasp::DebugCallback') do
|
||||
fasp_provider
|
||||
ip '127.0.0.234'
|
||||
request_body 'MyText'
|
||||
end
|
31
spec/fabricators/fasp/provider_fabricator.rb
Normal file
31
spec/fabricators/fasp/provider_fabricator.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Fabricator(:fasp_provider, from: 'Fasp::Provider') do
|
||||
name { Faker::App.name }
|
||||
base_url { Faker::Internet.unique.url }
|
||||
sign_in_url { Faker::Internet.url }
|
||||
remote_identifier 'MyString'
|
||||
provider_public_key_pem "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAh2ldXsaej2MXj0DHdCx7XibSo66uKlrLfJ5J6hte1Gk=\n-----END PUBLIC KEY-----\n"
|
||||
server_private_key_pem "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEICDjlajhVb8XfzyTchQWKraMKwtQW+r4opoAg7V3kw1Q\n-----END PRIVATE KEY-----\n"
|
||||
capabilities []
|
||||
end
|
||||
|
||||
Fabricator(:confirmed_fasp, from: :fasp_provider) do
|
||||
confirmed true
|
||||
capabilities [
|
||||
{ id: 'callback', version: '0.1' },
|
||||
{ id: 'data_sharing', version: '0.1' },
|
||||
]
|
||||
end
|
||||
|
||||
Fabricator(:debug_fasp, from: :fasp_provider) do
|
||||
confirmed true
|
||||
capabilities [
|
||||
{ id: 'callback', version: '0.1', enabled: true },
|
||||
]
|
||||
|
||||
after_build do |fasp|
|
||||
# Prevent fabrication from attempting an HTTP call to the provider
|
||||
def fasp.update_remote_capabilities = true
|
||||
end
|
||||
end
|
57
spec/lib/fasp/request_spec.rb
Normal file
57
spec/lib/fasp/request_spec.rb
Normal file
|
@ -0,0 +1,57 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require 'securerandom'
|
||||
|
||||
RSpec.describe Fasp::Request do
|
||||
include ProviderRequestHelper
|
||||
|
||||
subject { described_class.new(provider) }
|
||||
|
||||
let(:provider) do
|
||||
Fabricate(:fasp_provider, base_url: 'https://reqprov.example.com/fasp')
|
||||
end
|
||||
|
||||
shared_examples 'a provider request' do |method|
|
||||
context 'when the response is signed by the provider' do
|
||||
before do
|
||||
stub_provider_request(provider, method:, path: '/test_path')
|
||||
end
|
||||
|
||||
it "performs a signed #{method.to_s.upcase} request relative to the base_path of the fasp" do
|
||||
subject.send(method, '/test_path')
|
||||
|
||||
expect(WebMock).to have_requested(method, 'https://reqprov.example.com/fasp/test_path')
|
||||
.with(headers: {
|
||||
'Signature' => /.+/,
|
||||
'Signature-Input' => /.+/,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the response is not signed' do
|
||||
before do
|
||||
stub_request(method, 'https://reqprov.example.com/fasp/test_path')
|
||||
.to_return(status: 200)
|
||||
end
|
||||
|
||||
it 'raises an error' do
|
||||
expect do
|
||||
subject.send(method, '/test_path')
|
||||
end.to raise_error(SignatureVerification::SignatureVerificationError)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get' do
|
||||
include_examples 'a provider request', :get
|
||||
end
|
||||
|
||||
describe '#post' do
|
||||
include_examples 'a provider request', :post
|
||||
end
|
||||
|
||||
describe '#delete' do
|
||||
include_examples 'a provider request', :delete
|
||||
end
|
||||
end
|
209
spec/models/fasp/provider_spec.rb
Normal file
209
spec/models/fasp/provider_spec.rb
Normal file
|
@ -0,0 +1,209 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Fasp::Provider do
|
||||
include ProviderRequestHelper
|
||||
|
||||
describe '#capabilities' do
|
||||
subject { described_class.new(confirmed: true, capabilities:) }
|
||||
|
||||
let(:capabilities) do
|
||||
[
|
||||
{ 'id' => 'one', 'enabled' => false },
|
||||
{ 'id' => 'two' },
|
||||
]
|
||||
end
|
||||
|
||||
it 'returns an array of `Fasp::Capability` objects' do
|
||||
expect(subject.capabilities).to all(be_a(Fasp::Capability))
|
||||
end
|
||||
end
|
||||
|
||||
describe '#capabilities_attributes=' do
|
||||
subject { described_class.new(confirmed: true) }
|
||||
|
||||
let(:capabilities_params) do
|
||||
{
|
||||
'0' => { 'id' => 'one', 'enabled' => '1' },
|
||||
'1' => { 'id' => 'two', 'enabled' => '0' },
|
||||
'2' => { 'id' => 'three' },
|
||||
}
|
||||
end
|
||||
|
||||
it 'sets capabilities from nested form style hash' do
|
||||
subject.capabilities_attributes = capabilities_params
|
||||
|
||||
expect(subject).to be_capability('one')
|
||||
expect(subject).to be_capability('two')
|
||||
expect(subject).to be_capability('three')
|
||||
expect(subject).to be_capability_enabled('one')
|
||||
expect(subject).to_not be_capability_enabled('two')
|
||||
expect(subject).to_not be_capability_enabled('three')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#capability?' do
|
||||
subject { described_class.new(confirmed:, capabilities:) }
|
||||
|
||||
let(:capabilities) do
|
||||
[
|
||||
{ 'id' => 'one', 'enabled' => false },
|
||||
{ 'id' => 'two', 'enabled' => true },
|
||||
]
|
||||
end
|
||||
|
||||
context 'when the provider is not confirmed' do
|
||||
let(:confirmed) { false }
|
||||
|
||||
it 'always returns false' do
|
||||
expect(subject.capability?('one')).to be false
|
||||
expect(subject.capability?('two')).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the provider is confirmed' do
|
||||
let(:confirmed) { true }
|
||||
|
||||
it 'returns true for available and false for missing capabilities' do
|
||||
expect(subject.capability?('one')).to be true
|
||||
expect(subject.capability?('two')).to be true
|
||||
expect(subject.capability?('three')).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#capability_enabled?' do
|
||||
subject { described_class.new(confirmed:, capabilities:) }
|
||||
|
||||
let(:capabilities) do
|
||||
[
|
||||
{ 'id' => 'one', 'enabled' => false },
|
||||
{ 'id' => 'two', 'enabled' => true },
|
||||
]
|
||||
end
|
||||
|
||||
context 'when the provider is not confirmed' do
|
||||
let(:confirmed) { false }
|
||||
|
||||
it 'always returns false' do
|
||||
expect(subject).to_not be_capability_enabled('one')
|
||||
expect(subject).to_not be_capability_enabled('two')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the provider is confirmed' do
|
||||
let(:confirmed) { true }
|
||||
|
||||
it 'returns true for enabled and false for disabled or missing capabilities' do
|
||||
expect(subject).to_not be_capability_enabled('one')
|
||||
expect(subject).to be_capability_enabled('two')
|
||||
expect(subject).to_not be_capability_enabled('three')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#server_private_key' do
|
||||
subject { Fabricate(:fasp_provider) }
|
||||
|
||||
it 'returns an OpenSSL::PKey::PKey' do
|
||||
expect(subject.server_private_key).to be_a OpenSSL::PKey::PKey
|
||||
end
|
||||
end
|
||||
|
||||
describe '#server_public_key_base64' do
|
||||
subject { Fabricate(:fasp_provider) }
|
||||
|
||||
it 'returns the server public key base64 encoded' do
|
||||
expect(subject.server_public_key_base64).to eq 'T2RHkakkqAOWEMRYv9OY7LGsuIcAdmBlxuXOKax6sjw='
|
||||
end
|
||||
end
|
||||
|
||||
describe '#provider_public_key_base64=' do
|
||||
subject { Fabricate(:fasp_provider) }
|
||||
|
||||
it 'allows setting the provider public key from a base64 encoded raw key' do
|
||||
subject.provider_public_key_base64 = '9qgjOfWRhozWc9dwx5JmbshizZ7TyPBhYk9+b5tE3e4='
|
||||
|
||||
expect(subject.provider_public_key_pem).to eq "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA9qgjOfWRhozWc9dwx5JmbshizZ7TyPBhYk9+b5tE3e4=\n-----END PUBLIC KEY-----\n"
|
||||
end
|
||||
end
|
||||
|
||||
describe '#provider_public_key' do
|
||||
subject { Fabricate(:fasp_provider) }
|
||||
|
||||
it 'returns an OpenSSL::PKey::PKey' do
|
||||
expect(subject.provider_public_key).to be_a OpenSSL::PKey::PKey
|
||||
end
|
||||
end
|
||||
|
||||
describe '#provider_public_key_raw' do
|
||||
subject { Fabricate(:fasp_provider) }
|
||||
|
||||
it 'returns a string comprised of raw bytes' do
|
||||
expect(subject.provider_public_key_raw).to be_a String
|
||||
expect(subject.provider_public_key_raw.encoding).to eq Encoding::BINARY
|
||||
end
|
||||
end
|
||||
|
||||
describe '#provider_public_key_fingerprint' do
|
||||
subject { Fabricate(:fasp_provider) }
|
||||
|
||||
it 'returns a base64 encoded sha256 hash of the public key' do
|
||||
expect(subject.provider_public_key_fingerprint).to eq '/AmW9EMlVq4o+Qcu9lNfTE8Ss/v9+evMPtyj2R437qE='
|
||||
end
|
||||
end
|
||||
|
||||
describe '#url' do
|
||||
subject { Fabricate(:fasp_provider, base_url: 'https://myprovider.example.com/fasp_base/') }
|
||||
|
||||
it 'returns a full URL for a given path' do
|
||||
url = subject.url('/test_path')
|
||||
expect(url).to eq 'https://myprovider.example.com/fasp_base/test_path'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#update_info!' do
|
||||
subject { Fabricate(:fasp_provider, base_url: 'https://myprov.example.com/fasp/') }
|
||||
|
||||
before do
|
||||
stub_provider_request(subject,
|
||||
path: '/provider_info',
|
||||
response_body: {
|
||||
capabilities: [
|
||||
{ id: 'debug', version: '0.1' },
|
||||
],
|
||||
contactEmail: 'newcontact@example.com',
|
||||
fediverseAccount: '@newfedi@social.example.com',
|
||||
privacyPolicy: 'https::///example.com/privacy',
|
||||
signInUrl: 'https://myprov.example.com/sign_in',
|
||||
})
|
||||
end
|
||||
|
||||
context 'when setting confirm to `true`' do
|
||||
it 'updates the provider and marks it as `confirmed`' do
|
||||
subject.update_info!(confirm: true)
|
||||
|
||||
expect(subject.contact_email).to eq 'newcontact@example.com'
|
||||
expect(subject.fediverse_account).to eq '@newfedi@social.example.com'
|
||||
expect(subject.privacy_policy).to eq 'https::///example.com/privacy'
|
||||
expect(subject.sign_in_url).to eq 'https://myprov.example.com/sign_in'
|
||||
expect(subject).to be_confirmed
|
||||
expect(subject).to be_persisted
|
||||
end
|
||||
end
|
||||
|
||||
context 'when setting confirm to `false`' do
|
||||
it 'updates the provider but does not mark it as `confirmed`' do
|
||||
subject.update_info!
|
||||
|
||||
expect(subject.contact_email).to eq 'newcontact@example.com'
|
||||
expect(subject.fediverse_account).to eq '@newfedi@social.example.com'
|
||||
expect(subject.privacy_policy).to eq 'https::///example.com/privacy'
|
||||
expect(subject.sign_in_url).to eq 'https://myprov.example.com/sign_in'
|
||||
expect(subject).to_not be_confirmed
|
||||
expect(subject).to be_persisted
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
34
spec/policies/admin/fasp/provider_policy_spec.rb
Normal file
34
spec/policies/admin/fasp/provider_policy_spec.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Admin::Fasp::ProviderPolicy, type: :policy do
|
||||
subject { described_class }
|
||||
|
||||
let(:admin) { Fabricate(:admin_user).account }
|
||||
let(:user) { Fabricate(:account) }
|
||||
|
||||
shared_examples 'admin only' do |target|
|
||||
let(:provider) { target.is_a?(Symbol) ? Fabricate(target) : target }
|
||||
|
||||
context 'with an admin' do
|
||||
it 'permits' do
|
||||
expect(subject).to permit(admin, provider)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a non-admin' do
|
||||
it 'denies' do
|
||||
expect(subject).to_not permit(user, provider)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
permissions :index?, :create? do
|
||||
include_examples 'admin only', Fasp::Provider
|
||||
end
|
||||
|
||||
permissions :show?, :create?, :update?, :destroy? do
|
||||
include_examples 'admin only', :fasp_provider
|
||||
end
|
||||
end
|
28
spec/requests/api/fasp/debug/v0/callback/responses_spec.rb
Normal file
28
spec/requests/api/fasp/debug/v0/callback/responses_spec.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Api::Fasp::Debug::V0::Callback::Responses', feature: :fasp do
|
||||
include ProviderRequestHelper
|
||||
|
||||
describe 'POST /api/fasp/debug/v0/callback/responses' do
|
||||
let(:provider) { Fabricate(:debug_fasp) }
|
||||
|
||||
it 'create a record of the callback' do
|
||||
payload = { test: 'call' }
|
||||
headers = request_authentication_headers(provider,
|
||||
url: api_fasp_debug_v0_callback_responses_url,
|
||||
method: :post,
|
||||
body: payload)
|
||||
|
||||
expect do
|
||||
post api_fasp_debug_v0_callback_responses_path, headers:, params: payload, as: :json
|
||||
end.to change(Fasp::DebugCallback, :count).by(1)
|
||||
expect(response).to have_http_status(201)
|
||||
|
||||
debug_callback = Fasp::DebugCallback.last
|
||||
expect(debug_callback.fasp_provider).to eq provider
|
||||
expect(debug_callback.request_body).to eq '{"test":"call"}'
|
||||
end
|
||||
end
|
||||
end
|
42
spec/requests/api/fasp/registrations_spec.rb
Normal file
42
spec/requests/api/fasp/registrations_spec.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Api::Fasp::Registrations', feature: :fasp do
|
||||
describe 'POST /api/fasp/registration' do
|
||||
subject do
|
||||
post api_fasp_registration_path, params:
|
||||
end
|
||||
|
||||
context 'when given valid data' do
|
||||
let(:params) do
|
||||
{
|
||||
name: 'Test Provider',
|
||||
baseUrl: 'https://newprovider.example.com/fasp',
|
||||
serverId: '123',
|
||||
publicKey: '9qgjOfWRhozWc9dwx5JmbshizZ7TyPBhYk9+b5tE3e4=',
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates a new provider' do
|
||||
expect { subject }.to change(Fasp::Provider, :count).by(1)
|
||||
|
||||
expect(response).to have_http_status 200
|
||||
end
|
||||
end
|
||||
|
||||
context 'when given invalid data' do
|
||||
let(:params) do
|
||||
{
|
||||
name: 'incomplete',
|
||||
}
|
||||
end
|
||||
|
||||
it 'does not create a provider and returns an error code' do
|
||||
expect { subject }.to_not change(Fasp::Provider, :count)
|
||||
|
||||
expect(response).to have_http_status 422
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
72
spec/support/fasp/provider_request_helper.rb
Normal file
72
spec/support/fasp/provider_request_helper.rb
Normal file
|
@ -0,0 +1,72 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module ProviderRequestHelper
|
||||
private
|
||||
|
||||
def stub_provider_request(provider, path: '/', method: :get, response_status: 200, response_body: '')
|
||||
response_body = encode_body(response_body)
|
||||
response_headers = {
|
||||
'content-type' => 'application/json',
|
||||
}.merge(response_authentication_headers(provider, response_status, response_body))
|
||||
|
||||
stub_request(method, provider.url(path))
|
||||
.to_return do |_request|
|
||||
{
|
||||
status: response_status,
|
||||
body: response_body,
|
||||
headers: response_headers,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def request_authentication_headers(provider, url: root_url, method: :get, body: '')
|
||||
body = encode_body(body)
|
||||
headers = {}
|
||||
headers['content-digest'] = content_digest(body)
|
||||
request = Linzer.new_request(method, url, {}, headers)
|
||||
key = private_key_for(provider)
|
||||
signature = sign(request, key, %w(@method @target-uri content-digest))
|
||||
headers.merge(signature.to_h)
|
||||
end
|
||||
|
||||
def response_authentication_headers(provider, status, body)
|
||||
headers = {}
|
||||
headers['content-digest'] = content_digest(body)
|
||||
response = Linzer.new_response(body, status, headers)
|
||||
key = private_key_for(provider)
|
||||
signature = sign(response, key, %w(@status content-digest))
|
||||
headers.merge(signature.to_h)
|
||||
end
|
||||
|
||||
def private_key_for(provider)
|
||||
@cached_provider_keys ||= {}
|
||||
@cached_provider_keys[provider] ||=
|
||||
begin
|
||||
key = OpenSSL::PKey.generate_key('ed25519')
|
||||
provider.update!(provider_public_key_pem: key.public_to_pem)
|
||||
key
|
||||
end
|
||||
|
||||
{
|
||||
id: provider.id.to_s,
|
||||
private_key: @cached_provider_keys[provider].private_to_pem,
|
||||
}
|
||||
end
|
||||
|
||||
def sign(request_or_response, key, components)
|
||||
message = Linzer::Message.new(request_or_response)
|
||||
linzer_key = Linzer.new_ed25519_key(key[:private_key], key[:id])
|
||||
Linzer.sign(linzer_key, message, components)
|
||||
end
|
||||
|
||||
def encode_body(body)
|
||||
return body if body.nil? || body.is_a?(String)
|
||||
|
||||
encoder = ActionDispatch::RequestEncoder.encoder(:json)
|
||||
encoder.encode_params(body)
|
||||
end
|
||||
|
||||
def content_digest(content)
|
||||
"sha-256=:#{OpenSSL::Digest.base64digest('sha256', content)}:"
|
||||
end
|
||||
end
|
29
spec/system/admin/fasp/debug/callbacks_spec.rb
Normal file
29
spec/system/admin/fasp/debug/callbacks_spec.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Debug FASP Callback Management', feature: :fasp do
|
||||
before { sign_in Fabricate(:admin_user) }
|
||||
|
||||
describe 'Viewing and deleting callbacks' do
|
||||
let(:provider) { Fabricate(:fasp_provider, name: 'debug prov') }
|
||||
|
||||
before do
|
||||
Fabricate(:fasp_debug_callback, fasp_provider: provider, request_body: 'called back')
|
||||
end
|
||||
|
||||
it 'displays callbacks and allows to delete them' do
|
||||
visit admin_fasp_debug_callbacks_path
|
||||
|
||||
expect(page).to have_css('h2', text: I18n.t('admin.fasp.debug.callbacks.title'))
|
||||
expect(page).to have_css('td', text: 'debug prov')
|
||||
expect(page).to have_css('code', text: 'called back')
|
||||
|
||||
expect do
|
||||
click_on I18n.t('admin.fasp.debug.callbacks.delete')
|
||||
|
||||
expect(page).to have_css('h2', text: I18n.t('admin.fasp.debug.callbacks.title'))
|
||||
end.to change(Fasp::DebugCallback, :count).by(-1)
|
||||
end
|
||||
end
|
||||
end
|
33
spec/system/admin/fasp/debug_calls_spec.rb
Normal file
33
spec/system/admin/fasp/debug_calls_spec.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'FASP Debug Calls', feature: :fasp do
|
||||
include ProviderRequestHelper
|
||||
|
||||
before { sign_in Fabricate(:admin_user) }
|
||||
|
||||
describe 'Triggering a FASP debug call' do
|
||||
let!(:provider) { Fabricate(:debug_fasp) }
|
||||
let!(:debug_call) do
|
||||
stub_provider_request(provider,
|
||||
method: :post,
|
||||
path: '/debug/v0/callback/logs',
|
||||
response_status: 201)
|
||||
end
|
||||
|
||||
it 'makes a debug call to the provider' do
|
||||
visit admin_fasp_providers_path
|
||||
|
||||
expect(page).to have_css('h2', text: I18n.t('admin.fasp.providers.title'))
|
||||
expect(page).to have_css('td', text: provider.name)
|
||||
|
||||
within 'table#providers' do
|
||||
click_on I18n.t('admin.fasp.providers.callback')
|
||||
end
|
||||
|
||||
expect(page).to have_css('h2', text: I18n.t('admin.fasp.providers.title'))
|
||||
expect(debug_call).to have_been_requested
|
||||
end
|
||||
end
|
||||
end
|
81
spec/system/admin/fasp/providers_spec.rb
Normal file
81
spec/system/admin/fasp/providers_spec.rb
Normal file
|
@ -0,0 +1,81 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'FASP Management', feature: :fasp do
|
||||
include ProviderRequestHelper
|
||||
|
||||
before { sign_in Fabricate(:admin_user) }
|
||||
|
||||
describe 'Managing capabilities' do
|
||||
let!(:provider) { Fabricate(:confirmed_fasp) }
|
||||
let!(:enable_call) do
|
||||
stub_provider_request(provider,
|
||||
method: :post,
|
||||
path: '/capabilities/callback/0/activation')
|
||||
end
|
||||
let!(:disable_call) do
|
||||
stub_provider_request(provider,
|
||||
method: :delete,
|
||||
path: '/capabilities/callback/0/activation')
|
||||
end
|
||||
|
||||
before do
|
||||
# We currently err on the side of caution and prefer to send
|
||||
# a "disable capability" call too often over risking to miss
|
||||
# one. So the following call _can_ happen here, and if it does
|
||||
# that is fine, but it has no bearing on the behavior that is
|
||||
# being tested.
|
||||
stub_provider_request(provider,
|
||||
method: :delete,
|
||||
path: '/capabilities/data_sharing/0/activation')
|
||||
end
|
||||
|
||||
it 'allows enabling and disabling of capabilities' do
|
||||
visit admin_fasp_providers_path
|
||||
|
||||
expect(page).to have_css('h2', text: I18n.t('admin.fasp.providers.title'))
|
||||
expect(page).to have_css('td', text: provider.name)
|
||||
|
||||
click_on I18n.t('admin.fasp.providers.edit')
|
||||
|
||||
expect(page).to have_css('h2', text: I18n.t('admin.fasp.providers.edit'))
|
||||
|
||||
check 'callback'
|
||||
|
||||
click_on I18n.t('admin.fasp.providers.save')
|
||||
|
||||
expect(page).to have_css('h2', text: I18n.t('admin.fasp.providers.title'))
|
||||
expect(provider.reload).to be_capability_enabled('callback')
|
||||
expect(enable_call).to have_been_requested
|
||||
|
||||
click_on I18n.t('admin.fasp.providers.edit')
|
||||
|
||||
expect(page).to have_css('h2', text: I18n.t('admin.fasp.providers.edit'))
|
||||
|
||||
uncheck 'callback'
|
||||
|
||||
click_on I18n.t('admin.fasp.providers.save')
|
||||
|
||||
expect(page).to have_css('h2', text: I18n.t('admin.fasp.providers.title'))
|
||||
expect(provider.reload).to_not be_capability_enabled('callback')
|
||||
expect(disable_call).to have_been_requested
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Removing a provider' do
|
||||
let!(:provider) { Fabricate(:fasp_provider) }
|
||||
|
||||
it 'allows to completely remove a provider' do
|
||||
visit admin_fasp_providers_path
|
||||
|
||||
expect(page).to have_css('h2', text: I18n.t('admin.fasp.providers.title'))
|
||||
expect(page).to have_css('td', text: provider.name)
|
||||
|
||||
click_on I18n.t('admin.fasp.providers.delete')
|
||||
|
||||
expect(page).to have_css('h2', text: I18n.t('admin.fasp.providers.title'))
|
||||
expect(page).to have_no_css('td', text: provider.name)
|
||||
end
|
||||
end
|
||||
end
|
39
spec/system/admin/fasp/registrations_spec.rb
Normal file
39
spec/system/admin/fasp/registrations_spec.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'FASP registration', feature: :fasp do
|
||||
include ProviderRequestHelper
|
||||
|
||||
before { sign_in Fabricate(:admin_user) }
|
||||
|
||||
describe 'Confirming an unconfirmed FASP' do
|
||||
let(:provider) { Fabricate(:fasp_provider, confirmed: false) }
|
||||
|
||||
before do
|
||||
stub_provider_request(provider,
|
||||
path: '/provider_info',
|
||||
response_body: {
|
||||
capabilities: [
|
||||
{ id: 'debug', version: '0.1' },
|
||||
],
|
||||
contactEmail: 'newcontact@example.com',
|
||||
fediverseAccount: '@newfedi@social.example.com',
|
||||
privacyPolicy: 'https::///example.com/privacy',
|
||||
signInUrl: 'https://myprov.example.com/sign_in',
|
||||
})
|
||||
end
|
||||
|
||||
it 'displays key fingerprint and updates the provider on confirmation' do
|
||||
visit new_admin_fasp_provider_registration_path(provider)
|
||||
|
||||
expect(page).to have_css('code', text: provider.provider_public_key_fingerprint)
|
||||
|
||||
click_on I18n.t('admin.fasp.providers.registrations.confirm')
|
||||
|
||||
expect(page).to have_css('h2', text: I18n.t('admin.fasp.providers.edit'))
|
||||
|
||||
expect(provider.reload).to be_confirmed
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue