Skip to content

Commit

Permalink
arf-80297 load ogc_number and poa_codes into the RepresentatveUserLoader
Browse files Browse the repository at this point in the history
  • Loading branch information
gabezurita committed Apr 25, 2024
1 parent 4f082e5 commit 9eb26e1
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

class CreateAccreditedRepresentativePortalVerifiedRepresentatives < ActiveRecord::Migration[7.1]
def change
create_table :accredited_representative_portal_verified_representatives do |t|
t.string :ogc_registration_number, null: false
t.string :first_name
t.string :last_name
t.string :middle_initial
t.string :email, null: false

t.timestamps

t.index 'ogc_registration_number', unique: true, name: 'index_verified_representatives_on_ogc_number'
t.index 'email', unique: true, name: 'index_verified_representatives_on_email'
end
end
end
12 changes: 11 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class RepresentativeUser < Common::RedisStore
attribute :last_signed_in
attribute :loa
attribute :logingov_uuid
attribute :ogc_number
attribute :ogc_registration_number
attribute :poa_codes
attribute :sign_in
attribute :uuid
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module AccreditedRepresentativePortal
# Represents a verified representative within the Accredited Representative Portal.
# This class is responsible for managing the data associated with individuals who have
# been verified as representatives by the ARF Team. The model includes validations to ensure the presence and
# uniqueness of identifiers such as the OGC registration number and email.
#
# Currently, this model is populated manually by engineers as users are accepted into the pilot program.
# There is potential for a UI to be developed in the future that would facilitate administrative tasks
# related to managing verified representatives.
#
# A more automated process may be possible once OGC and MPI data facilitate such a process.
#
# == Associations
# This model may eventually be associated with AccreditedIndividuals to pull POA codes,
# if they exist, based on the OGC registration number. It currently does so via a helper method.
class VerifiedRepresentative < ApplicationRecord
validates :ogc_registration_number, presence: true, uniqueness: { case_sensitive: false }
validates :first_name, presence: true
validates :last_name, presence: true
validates :email, presence: true, uniqueness: true, format: { with: URI::MailTo::EMAIL_REGEXP }

# NOTE: given there will be RepresentativeUsers who are not VerifiedRepresentatives,
# it's okay for this to return nil
def poa_codes
AccreditedIndividual.find_by(registration_number: ogc_registration_number)&.poa_codes
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class RepresentativeNotFoundError < StandardError; end
def initialize(access_token:, request_ip:)
@access_token = access_token
@request_ip = request_ip
@verified_representative = VerifiedRepresentative.find_by(email: session&.credential_email)
end

def perform
Expand Down Expand Up @@ -56,16 +57,16 @@ def user_verification
@user_verification ||= session.user_verification
end

def get_poa_codes
rep = Veteran::Service::Representative.find_by(representative_id: ogc_number)
# TODO-ARF 80297: Determine how to get ogc_number into RepresentativeUserLoader
# raise RepresentativeNotFoundError unless rep

rep&.poa_codes
# NOTE: given there will be RepresentativeUsers who are not VerifiedRepresentatives,
# it's okay for this to return nil
def get_ogc_registration_number
@verified_representative&.ogc_registration_number
end

def ogc_number
# TODO-ARF 80297: Determine how to get ogc_number into RepresentativeUserLoader
# NOTE: given there will be RepresentativeUsers who are not VerifiedRepresentatives,
# it's okay for this to return nil
def get_poa_codes
@verified_representative&.poa_codes
end

def current_user
Expand All @@ -81,7 +82,7 @@ def current_user
user.authn_context = authn_context
user.loa = loa
user.logingov_uuid = user_verification.logingov_uuid
user.ogc_number = ogc_number # TODO-ARF 80297: Determine how to get ogc_number into RepresentativeUserLoader
user.ogc_registration_number = get_ogc_registration_number
user.poa_codes = get_poa_codes
user.idme_uuid = user_verification.idme_uuid
user.last_signed_in = session.created_at
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
last_signed_in { Time.zone.now }
authn_context { LOA::IDME_LOA3_VETS }
loa { { current: LOA::THREE, highest: LOA::THREE } }
ogc_number { '123456789' }
poa_codes { %w[1234 5678] }
sign_in {
{ service_name: SignIn::Constants::Auth::IDME, client_id: SecureRandom.uuid,
auth_broker: SignIn::Constants::Auth::BROKER_CODE }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

FactoryBot.define do
factory :verified_representative, class: 'AccreditedRepresentativePortal::VerifiedRepresentative' do
ogc_registration_number { Faker::Number.unique.number(digits: 6).to_s }
first_name { Faker::Name.first_name }
last_name { Faker::Name.last_name }
middle_initial { Faker::Name.middle_name }
email { Faker::Internet.unique.email }
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe AccreditedRepresentativePortal::VerifiedRepresentative, type: :model do
describe 'validations' do
subject { build(:verified_representative) }

it { is_expected.to validate_presence_of(:ogc_registration_number) }
it { is_expected.to validate_uniqueness_of(:ogc_registration_number).case_insensitive }
it { is_expected.to validate_presence_of(:first_name) }
it { is_expected.to validate_presence_of(:last_name) }
it { is_expected.to validate_presence_of(:email) }
it { is_expected.to validate_uniqueness_of(:email) }

it do
expect(subject).to allow_value('[email protected]').for(:email)
expect(subject).not_to allow_value('invalid_email').for(:email)
end
end

describe '#poa_codes' do
let(:ogc_registration_number) { '12345' }

context 'when an AccreditedIndividual with a matching registration number exists' do
let!(:accredited_individual) do
create(:accredited_individual, :with_organizations, registration_number: ogc_registration_number)
end
let(:verified_representative) do
create(:verified_representative, ogc_registration_number:)
end

it 'returns the correct POA codes' do
expect(verified_representative.poa_codes).to be_present
expect(verified_representative.poa_codes).to match_array(accredited_individual.poa_codes)
end
end

context 'when no AccreditedIndividual with a matching registration number exists' do
let(:verified_representative) do
create(:verified_representative, ogc_registration_number:)
end

it 'returns nil' do
expect(verified_representative.poa_codes).to be_nil
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
let(:reloaded_user) { representative_user_loader.perform }

let(:access_token) { create(:access_token, user_uuid: user.uuid, session_handle:) }
let(:ogc_number) { '123456' } # TODO-ARF 80297: Determine how to get ogc_number into RepresentativeUserLoader
let(:poa_codes) { %w[A1 B2 C3] }
let!(:user) do
create(:representative_user, uuid: user_uuid, icn: user_icn, loa: user_loa)
end
Expand All @@ -22,14 +20,6 @@
let(:session) { create(:oauth_session, user_account:, user_verification:) }
let(:session_handle) { session.handle }
let(:request_ip) { '123.456.78.90' }
let!(:representative) do
FactoryBot.create(:representative, first_name: 'Bob', last_name: 'Smith', representative_id: ogc_number,
poa_codes:)
end

before do
allow_any_instance_of(described_class).to receive(:ogc_number).and_return(ogc_number)
end

shared_examples 'reloaded user' do
context 'and associated session cannot be found' do
Expand Down Expand Up @@ -71,14 +61,56 @@
expect(reloaded_user.icn).to eq(user_icn)
expect(reloaded_user.idme_uuid).to eq(idme_uuid)
expect(reloaded_user.logingov_uuid).to eq(nil)
expect(reloaded_user.ogc_number).to eq(ogc_number)
expect(reloaded_user.poa_codes).to eq(poa_codes)
expect(reloaded_user.fingerprint).to eq(request_ip)
expect(reloaded_user.last_signed_in).to eq(session.created_at)
expect(reloaded_user.authn_context).to eq(authn_context)
expect(reloaded_user.loa).to eq(user_loa)
expect(reloaded_user.sign_in).to eq(sign_in)
end

context 'verified_representatives' do
let!(:ogc_registration_number) { '12300' }
let!(:verified_representative) do
create(:verified_representative, email: session.credential_email,
ogc_registration_number:)
end
let!(:accredited_individual) do
create(:accredited_individual, :with_organizations, registration_number: ogc_registration_number)
end

describe '#ogc_registration_number' do
context 'when a matching verified_representative is found' do
it 'returns the OGC registration number' do
expect(reloaded_user.ogc_registration_number).to eq(verified_representative.ogc_registration_number)
end
end

context 'when a verified_representative record does not exist for the user' do
let(:verified_representative) { nil }

it 'returns nil' do
expect(reloaded_user.ogc_registration_number).to be_nil
end
end
end

describe '#poa_codes' do
context 'when reloading a user' do
it 'sets the poa_codes based on the ogc_registration_number on the accredited_individual' do
expect(reloaded_user.poa_codes).to be_present
expect(reloaded_user.poa_codes).to match_array(accredited_individual.poa_codes)
end
end

context 'when a verified_representative record does not exist for the user' do
let(:verified_representative) { nil }

it 'returns nil' do
expect(reloaded_user.poa_codes).to be_nil
end
end
end
end
end
end

Expand All @@ -99,31 +131,5 @@

it_behaves_like 'reloaded user'
end

describe '#get_poa_codes' do
before do
user.destroy
end

context 'when reloading a user' do
it 'sets the poa_codes based on the ogc_number' do
expect(reloaded_user.poa_codes).to match_array(poa_codes)
end
end

# context 'when no representative is found for the ogc_number' do
# let(:non_existent_ogc_number) { 'non-existent-number' }

# before do
# allow_any_instance_of(described_class).to receive(:ogc_number).and_return(non_existent_ogc_number)
# end

# it 'raises a RepresentativeNotFoundError' do
# expect do
# reloaded_user
# end.to raise_error(described_class::RepresentativeNotFoundError)
# end
# end
end
end
end

0 comments on commit 9eb26e1

Please sign in to comment.