generated from DFE-Digital/govuk-rails-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add token generation service for parity check (#1810)
* Add ECF models for ApiToken generation Bring across the models from ECF that we need to be able to generate API tokens for ECF in NPQ registration. I haven't improved the test coverage here, just a quick lift and shift from ECF. * Add token generation service for ECF/NPQ As part of the parity check we will need to generate API tokens for lead providers in ECF and NPQ reg on the fly to be able to make requests to the API as these providers. Add service to generate tokens for each lead provider.
- Loading branch information
1 parent
17d82f8
commit f2ded5f
Showing
14 changed files
with
193 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# frozen_string_literal: true | ||
|
||
require "abstract_interface" | ||
|
||
module Migration::Ecf | ||
class APIToken < BaseRecord | ||
has_paper_trail ignore: %i[updated_at last_used_at] | ||
# This is meant to be an abstract class | ||
# Since it is a base class for a STI, we can't actually make it abstract (not backed by a table) | ||
include AbstractInterface | ||
implement_instance_method :owner | ||
|
||
def self.create_with_random_token!(**options) | ||
unhashed_token, hashed_token = Devise.token_generator.generate(APIToken, :hashed_token) | ||
create!(hashed_token:, **options) | ||
unhashed_token | ||
end | ||
|
||
def self.find_by_unhashed_token(unhashed_token) | ||
hashed_token = Devise.token_generator.digest(APIToken, :hashed_token, unhashed_token) | ||
find_by(hashed_token:) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# frozen_string_literal: true | ||
|
||
module Migration::Ecf | ||
class LeadProviderAPIToken < APIToken | ||
belongs_to :lead_provider, optional: true | ||
belongs_to :cpd_lead_provider, optional: true | ||
|
||
def owner | ||
cpd_lead_provider | ||
end | ||
|
||
def owner_description | ||
"CPD lead provider: #{cpd_lead_provider.name}" | ||
end | ||
|
||
def readonly? | ||
false | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
module Migration::ParityCheck | ||
class TokenProvider | ||
class UnsupportedEnvironmentError < RuntimeError; end | ||
|
||
def generate! | ||
raise UnsupportedEnvironmentError, "The parity check functionality is disabled for this environment" unless enabled? | ||
|
||
LeadProvider.all.each_with_object({}) do |lead_provider, hash| | ||
hash[lead_provider.ecf_id] = { | ||
ecf: generate_ecf_token!(lead_provider), | ||
npq: generate_npq_token!(lead_provider), | ||
} | ||
end | ||
end | ||
|
||
private | ||
|
||
def generate_ecf_token!(lead_provider) | ||
cpd_lead_provider = Migration::Ecf::NpqLeadProvider.find(lead_provider.ecf_id).cpd_lead_provider | ||
Migration::Ecf::LeadProviderAPIToken.create_with_random_token!(cpd_lead_provider:) | ||
end | ||
|
||
def generate_npq_token!(lead_provider) | ||
APIToken.create_with_random_token!(lead_provider:) | ||
end | ||
|
||
def enabled? | ||
Rails.application.config.npq_separation[:parity_check][:enabled] | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,5 +12,8 @@ | |
api_enabled: true, | ||
migration_enabled: true, | ||
ecf_api_disabled: true, | ||
parity_check: { | ||
enabled: true, | ||
}, | ||
} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,5 +9,8 @@ | |
api_enabled: true, | ||
migration_enabled: false, | ||
ecf_api_disabled: false, | ||
parity_check: { | ||
enabled: false, | ||
}, | ||
} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,5 +10,8 @@ | |
api_enabled: false, | ||
migration_enabled: false, | ||
ecf_api_disabled: false, | ||
parity_check: { | ||
enabled: false, | ||
}, | ||
} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,5 +10,8 @@ | |
api_enabled: true, | ||
migration_enabled: false, | ||
ecf_api_disabled: true, | ||
parity_check: { | ||
enabled: false, | ||
}, | ||
} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,5 +10,8 @@ | |
api_enabled: true, | ||
migration_enabled: false, | ||
ecf_api_disabled: false, | ||
parity_check: { | ||
enabled: false, | ||
}, | ||
} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# frozen_string_literal: true | ||
|
||
module AbstractInterface | ||
extend ActiveSupport::Concern | ||
|
||
included do | ||
extend AbstractInterfaceClassMethods | ||
end | ||
|
||
module AbstractInterfaceClassMethods | ||
def implement_class_method(*methods) | ||
methods.each do |key| | ||
define_singleton_method(key) { raise NotImplementedError, "Class method #{key} must be implemented" } unless self.class.respond_to?(key) | ||
end | ||
end | ||
|
||
def implement_instance_method(*methods) | ||
methods.each do |key| | ||
define_method(key) { raise NotImplementedError, "Instance method #{key} must be implemented" } unless respond_to?(key) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
require "rails_helper" | ||
|
||
RSpec.describe Migration::Ecf::LeadProviderAPIToken, type: :model do | ||
it { expect(described_class.new).not_to be_readonly } | ||
|
||
it "generates a hashed token that can be used" do | ||
unhashed_token = described_class.create_with_random_token!(lead_provider: create(:lead_provider)) | ||
|
||
expect( | ||
described_class.find_by_unhashed_token(unhashed_token), | ||
).to eql(described_class.order(:created_at).last) | ||
end | ||
end |
58 changes: 58 additions & 0 deletions
58
spec/services/migration/parity_check/token_provider_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
require "rails_helper" | ||
|
||
RSpec.describe Migration::ParityCheck::TokenProvider do | ||
let(:instance) { described_class.new } | ||
|
||
before do | ||
LeadProvider.all.find_each do |lead_provider| | ||
create(:ecf_migration_npq_lead_provider, id: lead_provider.ecf_id) | ||
end | ||
end | ||
|
||
describe "#generate!" do | ||
subject(:tokens_by_lead_provider) { instance.generate! } | ||
|
||
it { is_expected.to be_present } | ||
it { expect(tokens_by_lead_provider.keys).to match_array(LeadProvider.pluck(:ecf_id)) } | ||
|
||
it "generates valid ECF tokens" do | ||
tokens_by_lead_provider.each do |ecf_id, tokens| | ||
cpd_lead_provider = Migration::Ecf::NpqLeadProvider.find(ecf_id).cpd_lead_provider | ||
|
||
expect(Migration::Ecf::LeadProviderAPIToken.find_by_unhashed_token(tokens[:ecf]).cpd_lead_provider).to eq(cpd_lead_provider) | ||
end | ||
end | ||
|
||
it "generates valid NPQ tokens" do | ||
tokens_by_lead_provider.each do |ecf_id, tokens| | ||
lead_provider = LeadProvider.find_by(ecf_id:) | ||
|
||
expect(APIToken.find_by_unhashed_token(tokens[:npq]).lead_provider).to eq(lead_provider) | ||
end | ||
end | ||
|
||
context "when not running in the test environment" do | ||
before { allow(Rails).to receive(:env) { "migration".inquiry } } | ||
|
||
it "generates valid ECF tokens" do | ||
tokens_by_lead_provider.each do |ecf_id, tokens| | ||
cpd_lead_provider = Migration::Ecf::NpqLeadProvider.find(ecf_id).cpd_lead_provider | ||
|
||
expect(Migration::Ecf::LeadProviderAPIToken.find_by_unhashed_token(tokens[:ecf]).cpd_lead_provider).to eq(cpd_lead_provider) | ||
end | ||
end | ||
end | ||
|
||
context "when the parity check is disabled" do | ||
before do | ||
allow(Rails.application.config).to receive(:npq_separation).and_return({ | ||
parity_check: { | ||
enabled: false, | ||
}, | ||
}) | ||
end | ||
|
||
it { expect { tokens_by_lead_provider }.to raise_error(described_class::UnsupportedEnvironmentError, "The parity check functionality is disabled for this environment") } | ||
end | ||
end | ||
end |