2022-11-30 10:06:33 +01:00
|
|
|
describe APIToken, type: :model do
|
|
|
|
let(:administrateur) { create(:administrateur) }
|
|
|
|
|
|
|
|
describe '#generate' do
|
2023-08-03 10:23:05 +02:00
|
|
|
let(:api_token_and_packed_token) { APIToken.generate(administrateur) }
|
|
|
|
let(:api_token) { api_token_and_packed_token.first }
|
|
|
|
let(:packed_token) { api_token_and_packed_token.second }
|
|
|
|
|
2023-08-03 17:53:34 +02:00
|
|
|
before { api_token_and_packed_token }
|
|
|
|
|
|
|
|
it 'with a full access token' do
|
2022-11-30 10:06:33 +01:00
|
|
|
expect(api_token.administrateur).to eq(administrateur)
|
|
|
|
expect(api_token.prefix).to eq(packed_token.slice(0, 5))
|
|
|
|
expect(api_token.version).to eq(3)
|
2023-02-13 14:57:51 +01:00
|
|
|
expect(api_token.write_access?).to eq(true)
|
|
|
|
expect(api_token.procedure_ids).to eq([])
|
2023-11-08 11:21:45 +01:00
|
|
|
expect(api_token.context).to eq(administrateur_id: administrateur.id, procedure_ids: [], write_access: true, api_token_id: api_token.id)
|
2023-02-13 14:57:51 +01:00
|
|
|
expect(api_token.full_access?).to be_truthy
|
|
|
|
end
|
|
|
|
|
2023-08-03 17:53:34 +02:00
|
|
|
context 'updated read_only' do
|
2023-02-13 14:57:51 +01:00
|
|
|
before { api_token.update(write_access: false) }
|
2023-08-03 17:53:34 +02:00
|
|
|
|
2023-02-13 14:57:51 +01:00
|
|
|
it do
|
2023-11-08 11:21:45 +01:00
|
|
|
expect(api_token.context).to eq(administrateur_id: administrateur.id, procedure_ids: [], write_access: false, api_token_id: api_token.id)
|
2023-02-13 14:57:51 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-08-03 17:53:34 +02:00
|
|
|
context 'with a new added procedure' do
|
2023-02-13 14:57:51 +01:00
|
|
|
let(:procedure) { create(:procedure, administrateurs: [administrateur]) }
|
2023-08-03 17:53:34 +02:00
|
|
|
|
|
|
|
before do
|
|
|
|
procedure
|
|
|
|
api_token.reload
|
|
|
|
end
|
2023-02-13 14:57:51 +01:00
|
|
|
|
|
|
|
it do
|
2023-08-03 17:53:34 +02:00
|
|
|
expect(api_token.full_access?).to be_truthy
|
2023-02-13 14:57:51 +01:00
|
|
|
expect(api_token.procedure_ids).to eq([procedure.id])
|
2023-08-03 17:53:34 +02:00
|
|
|
expect(api_token.procedures).to eq([procedure])
|
2023-11-08 11:21:45 +01:00
|
|
|
expect(api_token.context).to eq(administrateur_id: administrateur.id, procedure_ids: [procedure.id], write_access: true, api_token_id: api_token.id)
|
2023-02-13 14:57:51 +01:00
|
|
|
end
|
|
|
|
|
2023-08-03 17:53:34 +02:00
|
|
|
context 'and another procedure, but access only to the first one' do
|
2023-02-13 14:57:51 +01:00
|
|
|
let(:other_procedure) { create(:procedure, administrateurs: [administrateur]) }
|
2023-08-03 17:53:34 +02:00
|
|
|
|
|
|
|
before do
|
|
|
|
other_procedure
|
|
|
|
api_token.update(allowed_procedure_ids: [procedure.id])
|
|
|
|
api_token.reload
|
|
|
|
end
|
2023-02-13 14:57:51 +01:00
|
|
|
|
|
|
|
it do
|
2023-08-03 17:53:34 +02:00
|
|
|
expect(api_token.full_access?).to be_falsey
|
|
|
|
expect(api_token.procedure_ids).to match_array([procedure.id])
|
|
|
|
expect(api_token.targetable_procedures).to eq([other_procedure])
|
2023-11-08 11:21:45 +01:00
|
|
|
expect(api_token.context).to eq(administrateur_id: administrateur.id, procedure_ids: [procedure.id], write_access: true, api_token_id: api_token.id)
|
2023-02-13 14:57:51 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-08-03 17:53:34 +02:00
|
|
|
context 'but acces to a wrong procedure_id' do
|
|
|
|
let(:forbidden_procedure) { create(:procedure) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
api_token.update(allowed_procedure_ids: [forbidden_procedure.id])
|
|
|
|
api_token.reload
|
|
|
|
end
|
2023-02-13 14:57:51 +01:00
|
|
|
|
|
|
|
it do
|
|
|
|
expect(api_token.full_access?).to be_falsey
|
|
|
|
expect(api_token.procedure_ids).to eq([])
|
2023-08-03 17:53:34 +02:00
|
|
|
expect(api_token.targetable_procedures).to eq([procedure])
|
2023-11-08 11:21:45 +01:00
|
|
|
expect(api_token.context).to eq(administrateur_id: administrateur.id, procedure_ids: [], write_access: true, api_token_id: api_token.id)
|
2023-02-13 14:57:51 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'update with destroyed procedure_id' do
|
|
|
|
let(:procedure) { create(:procedure, administrateurs: [administrateur]) }
|
2023-08-03 17:53:34 +02:00
|
|
|
|
|
|
|
before do
|
|
|
|
api_token.update(allowed_procedure_ids: [procedure.id])
|
|
|
|
procedure.destroy
|
|
|
|
api_token.reload
|
|
|
|
end
|
2023-02-13 14:57:51 +01:00
|
|
|
|
|
|
|
it do
|
|
|
|
expect(api_token.full_access?).to be_falsey
|
|
|
|
expect(api_token.procedure_ids).to eq([])
|
2023-08-03 17:53:34 +02:00
|
|
|
expect(api_token.targetable_procedures).to eq([])
|
2023-11-08 11:21:45 +01:00
|
|
|
expect(api_token.context).to eq(administrateur_id: administrateur.id, procedure_ids: [], write_access: true, api_token_id: api_token.id)
|
2023-02-13 14:57:51 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'update with detached procedure_id' do
|
|
|
|
let(:procedure) { create(:procedure, administrateurs: [administrateur]) }
|
2023-08-03 17:53:34 +02:00
|
|
|
let(:other_procedure) { create(:procedure, administrateurs: [administrateur]) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
api_token.update(allowed_procedure_ids: [procedure.id])
|
|
|
|
other_procedure
|
|
|
|
administrateur.procedures.delete(procedure)
|
|
|
|
api_token.reload
|
|
|
|
end
|
2023-02-13 14:57:51 +01:00
|
|
|
|
|
|
|
it do
|
|
|
|
expect(api_token.full_access?).to be_falsey
|
2023-08-03 17:53:34 +02:00
|
|
|
expect(api_token.procedure_ids).to eq([])
|
|
|
|
expect(api_token.targetable_procedures).to eq([other_procedure])
|
2023-11-08 11:21:45 +01:00
|
|
|
expect(api_token.context).to eq(administrateur_id: administrateur.id, procedure_ids: [], write_access: true, api_token_id: api_token.id)
|
2023-02-13 14:57:51 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2022-11-30 10:06:33 +01:00
|
|
|
end
|
|
|
|
|
2023-08-03 15:27:33 +02:00
|
|
|
describe '#authenticate' do
|
2023-08-03 10:23:05 +02:00
|
|
|
let(:api_token_and_packed_token) { APIToken.generate(administrateur) }
|
|
|
|
let(:api_token) { api_token_and_packed_token.first }
|
|
|
|
let(:packed_token) { api_token_and_packed_token.second }
|
|
|
|
let(:bearer_token) { packed_token }
|
2022-11-30 10:06:33 +01:00
|
|
|
|
2023-08-03 15:27:33 +02:00
|
|
|
subject { APIToken.authenticate(bearer_token) }
|
2022-11-30 10:06:33 +01:00
|
|
|
|
2023-08-03 10:23:05 +02:00
|
|
|
context 'with the legit packed token' do
|
|
|
|
it { is_expected.to eq(api_token) }
|
2022-11-30 10:06:33 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'with destroyed token' do
|
|
|
|
before { api_token.destroy }
|
|
|
|
|
2023-08-03 10:23:05 +02:00
|
|
|
it { is_expected.to be_nil }
|
2022-11-30 10:06:33 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'with destroyed administrateur' do
|
|
|
|
before { api_token.administrateur.destroy }
|
|
|
|
|
2023-08-03 10:23:05 +02:00
|
|
|
it { is_expected.to be_nil }
|
2022-11-30 10:06:33 +01:00
|
|
|
end
|
|
|
|
|
2023-08-03 10:23:05 +02:00
|
|
|
context "with a bearer token with the wrong plain_token" do
|
|
|
|
let(:bearer_token) do
|
2023-08-03 17:53:34 +02:00
|
|
|
APIToken::BearerToken.new(api_token.id, 'wrong').to_string
|
2022-11-30 10:06:33 +01:00
|
|
|
end
|
|
|
|
|
2023-08-03 10:23:05 +02:00
|
|
|
it { is_expected.to be_nil }
|
2022-11-30 10:06:33 +01:00
|
|
|
end
|
|
|
|
end
|
2023-12-21 15:58:03 +01:00
|
|
|
|
|
|
|
describe '#store_new_ip' do
|
|
|
|
let(:api_token) { APIToken.generate(administrateur).first }
|
|
|
|
let(:ip) { '192.168.0.1' }
|
|
|
|
|
|
|
|
subject do
|
|
|
|
api_token.store_new_ip(ip)
|
|
|
|
api_token.stored_ips
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when none ip is stored' do
|
|
|
|
it { is_expected.to eq([IPAddr.new(ip)]) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the ip is already stored' do
|
|
|
|
before { api_token.update!(stored_ips: [ip]) }
|
|
|
|
|
|
|
|
it { is_expected.to eq([IPAddr.new(ip)]) }
|
|
|
|
end
|
|
|
|
end
|
2023-12-21 13:59:21 +01:00
|
|
|
|
|
|
|
describe '#forbidden_network?' do
|
|
|
|
let(:api_token_and_packed_token) { APIToken.generate(administrateur) }
|
|
|
|
let(:api_token) { api_token_and_packed_token.first }
|
|
|
|
let(:authorized_networks) { [] }
|
|
|
|
|
|
|
|
before { api_token.update!(authorized_networks: authorized_networks) }
|
|
|
|
|
|
|
|
subject { api_token.forbidden_network?(ip) }
|
|
|
|
|
|
|
|
context 'when no authorized networks are defined' do
|
|
|
|
let(:ip) { '192.168.1.1' }
|
|
|
|
|
|
|
|
it { is_expected.to be_falsey }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when a single authorized network is defined' do
|
|
|
|
let(:authorized_networks) { [IPAddr.new('192.168.1.0/24')] }
|
|
|
|
|
|
|
|
context 'and the request comes from it' do
|
|
|
|
let(:ip) { '192.168.1.1' }
|
|
|
|
|
|
|
|
it { is_expected.to be_falsey }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'and the request does not come from it' do
|
|
|
|
let(:ip) { '192.168.2.1' }
|
|
|
|
|
|
|
|
it { is_expected.to be_truthy }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2024-01-23 17:20:53 +01:00
|
|
|
|
|
|
|
describe '#expiring_within' do
|
|
|
|
let(:api_token) { APIToken.generate(administrateur).first }
|
|
|
|
|
|
|
|
subject { APIToken.expiring_within(7.days) }
|
|
|
|
|
|
|
|
context 'when the token is not expiring' do
|
|
|
|
it { is_expected.to be_empty }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the token is expiring in the range' do
|
|
|
|
before { api_token.update!(expires_at: 1.day.from_now) }
|
|
|
|
|
|
|
|
it { is_expected.to eq([api_token]) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the token is not expiring in the range' do
|
|
|
|
before { api_token.update!(expires_at: 8.days.from_now) }
|
|
|
|
|
|
|
|
it { is_expected.to be_empty }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the token is expired' do
|
|
|
|
before { api_token.update!(expires_at: 1.day.ago) }
|
|
|
|
|
|
|
|
it { is_expected.to be_empty }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#without_any_expiration_notice_sent_within' do
|
|
|
|
let(:api_token) { APIToken.generate(administrateur).first }
|
|
|
|
let(:today) { Date.new(2018, 01, 01) }
|
|
|
|
let(:expires_at) { Date.new(2018, 06, 01) }
|
|
|
|
|
|
|
|
subject { APIToken.without_any_expiration_notice_sent_within(7.days) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
travel_to(today)
|
|
|
|
api_token.update!(created_at: today, expires_at:)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the token has not been notified' do
|
|
|
|
it { is_expected.to eq([api_token]) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the token has been notified' do
|
|
|
|
before do
|
|
|
|
api_token.expiration_notices_sent_at << expires_at - 7.days
|
|
|
|
api_token.save!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to be_empty }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the token has been notified outside the window' do
|
|
|
|
before do
|
|
|
|
api_token.expiration_notices_sent_at << expires_at - 8.days
|
|
|
|
api_token.save!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to eq([api_token]) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#with_expiration_notice_to_send_for' do
|
|
|
|
let(:api_token) { APIToken.generate(administrateur).first }
|
|
|
|
let(:duration) { 7.days }
|
|
|
|
|
|
|
|
subject do
|
|
|
|
APIToken.with_expiration_notice_to_send_for(duration)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the token is expiring in the range' do
|
|
|
|
before { api_token.update!(expires_at: 1.day.from_now, created_at:) }
|
|
|
|
|
|
|
|
let(:created_at) { 1.year.ago }
|
|
|
|
|
|
|
|
it do
|
|
|
|
is_expected.to eq([api_token])
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the token has been created within the time frame' do
|
|
|
|
let(:created_at) { 2.days.ago }
|
|
|
|
|
|
|
|
it { is_expected.to be_empty }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the token has already been notified' do
|
|
|
|
before do
|
|
|
|
api_token.expiration_notices_sent_at << 1.day.ago
|
|
|
|
api_token.save!
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to be_empty }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the token has already been notified for another window' do
|
|
|
|
before do
|
|
|
|
api_token.expiration_notices_sent_at << 1.month.ago
|
|
|
|
api_token.save!
|
|
|
|
end
|
|
|
|
|
|
|
|
it do
|
|
|
|
is_expected.to eq([api_token])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2022-11-30 10:06:33 +01:00
|
|
|
end
|