Class: SignIn::AttributeValidator

Inherits:
Object
  • Object
show all
Defined in:
app/services/sign_in/attribute_validator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(user_attributes:) ⇒ AttributeValidator

Returns a new instance of AttributeValidator.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'app/services/sign_in/attribute_validator.rb', line 20

def initialize(user_attributes:)
  @idme_uuid = user_attributes[:idme_uuid]
  @logingov_uuid = user_attributes[:logingov_uuid]
  @auto_uplevel = user_attributes[:auto_uplevel]
  @current_ial = user_attributes[:current_ial]
  @service_name = user_attributes[:service_name]
  @first_name = user_attributes[:first_name]
  @last_name = user_attributes[:last_name]
  @birth_date = user_attributes[:birth_date]
  @credential_email = user_attributes[:csp_email]
  @address = user_attributes[:address]
  @ssn = user_attributes[:ssn]
  @mhv_icn = user_attributes[:mhv_icn]
  @edipi = user_attributes[:edipi]
  @mhv_correlation_id = user_attributes[:mhv_correlation_id]
end

Instance Attribute Details

#addressObject (readonly)

Returns the value of attribute address.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def address
  @address
end

#auto_uplevelObject (readonly)

Returns the value of attribute auto_uplevel.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def auto_uplevel
  @auto_uplevel
end

#birth_dateObject (readonly)

Returns the value of attribute birth_date.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def birth_date
  @birth_date
end

#credential_emailObject (readonly)

Returns the value of attribute credential_email.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def credential_email
  @credential_email
end

#current_ialObject (readonly)

Returns the value of attribute current_ial.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def current_ial
  @current_ial
end

#edipiObject (readonly)

Returns the value of attribute edipi.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def edipi
  @edipi
end

#first_nameObject (readonly)

Returns the value of attribute first_name.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def first_name
  @first_name
end

#idme_uuidObject (readonly)

Returns the value of attribute idme_uuid.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def idme_uuid
  @idme_uuid
end

#last_nameObject (readonly)

Returns the value of attribute last_name.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def last_name
  @last_name
end

#logingov_uuidObject (readonly)

Returns the value of attribute logingov_uuid.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def logingov_uuid
  @logingov_uuid
end

#mhv_correlation_idObject (readonly)

Returns the value of attribute mhv_correlation_id.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def mhv_correlation_id
  @mhv_correlation_id
end

#mhv_icnObject (readonly)

Returns the value of attribute mhv_icn.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def mhv_icn
  @mhv_icn
end

#service_nameObject (readonly)

Returns the value of attribute service_name.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def service_name
  @service_name
end

#ssnObject (readonly)

Returns the value of attribute ssn.



5
6
7
# File 'app/services/sign_in/attribute_validator.rb', line 5

def ssn
  @ssn
end

Instance Method Details

#add_mpi_userObject (private)



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'app/services/sign_in/attribute_validator.rb', line 66

def add_mpi_user
  add_person_response = mpi_service.add_person_implicit_search(first_name:,
                                                               last_name:,
                                                               ssn:,
                                                               birth_date:,
                                                               email: credential_email,
                                                               address:,
                                                               idme_uuid:,
                                                               logingov_uuid:)
  unless add_person_response.ok?
    handle_error('User MPI record cannot be created',
                 Constants::ErrorCode::GENERIC_EXTERNAL_ISSUE,
                 error: Errors::MPIUserCreationFailedError)
  end
end

#attribute_mismatch_check(type, credential_attribute, mpi_attribute, prevent_auth: false) ⇒ Object (private)



129
130
131
132
133
134
135
136
137
138
# File 'app/services/sign_in/attribute_validator.rb', line 129

def attribute_mismatch_check(type, credential_attribute, mpi_attribute, prevent_auth: false)
  return unless mpi_attribute

  if scrub_attribute(credential_attribute) != scrub_attribute(mpi_attribute)
    error = prevent_auth ? Errors::AttributeMismatchError : nil
    handle_error("Attribute mismatch, #{type} in credential does not match MPI attribute",
                 Constants::ErrorCode::GENERIC_EXTERNAL_ISSUE,
                 error:)
  end
end

#check_id_mismatch(id_array, id_description, code) ⇒ Object (private)



157
158
159
160
161
162
163
# File 'app/services/sign_in/attribute_validator.rb', line 157

def check_id_mismatch(id_array, id_description, code)
  if id_array && id_array.compact.uniq.size > 1
    handle_error("User attributes contain multiple distinct #{id_description} values",
                 code,
                 error: Errors::MPIMalformedAccountError)
  end
end

#check_lock_flag(attribute, attribute_description, code) ⇒ Object (private)



153
154
155
# File 'app/services/sign_in/attribute_validator.rb', line 153

def check_lock_flag(attribute, attribute_description, code)
  handle_error("#{attribute_description} Detected", code, error: Errors::MPILockedAccountError) if attribute
end

#credential_attribute_check(type, credential_attribute) ⇒ Object (private)



121
122
123
124
125
126
127
# File 'app/services/sign_in/attribute_validator.rb', line 121

def credential_attribute_check(type, credential_attribute)
  return if credential_attribute.present?

  handle_error("Missing attribute in credential: #{type}",
               Constants::ErrorCode::GENERIC_EXTERNAL_ISSUE,
               error: Errors::CredentialMissingAttributeError)
end

#credential_uuidObject (private)



193
194
195
# File 'app/services/sign_in/attribute_validator.rb', line 193

def credential_uuid
  @credential_uuid ||= idme_uuid || logingov_uuid
end

#dslogon_auth?Boolean (private)

Returns:

  • (Boolean)


213
214
215
# File 'app/services/sign_in/attribute_validator.rb', line 213

def dslogon_auth?
  service_name == Constants::Auth::DSLOGON
end

#handle_error(error_message, error_code, error: nil) ⇒ Object (private)



165
166
167
168
169
170
171
# File 'app/services/sign_in/attribute_validator.rb', line 165

def handle_error(error_message, error_code, error: nil)
  .info('attribute validator error', { errors: error_message,
                                                     credential_uuid:,
                                                     mhv_icn:,
                                                     type: service_name }.compact)
  raise error.new message: error_message, code: error_code if error
end

#loaObject (private)



205
206
207
# File 'app/services/sign_in/attribute_validator.rb', line 205

def loa
  @loa ||= { current: Constants::Auth::LOA_THREE, highest: Constants::Auth::LOA_THREE }
end

#mhv_auth?Boolean (private)

Returns:

  • (Boolean)


209
210
211
# File 'app/services/sign_in/attribute_validator.rb', line 209

def mhv_auth?
  service_name == Constants::Auth::MHV
end

#mpi_record_exists?Boolean (private)

Returns:

  • (Boolean)


197
198
199
# File 'app/services/sign_in/attribute_validator.rb', line 197

def mpi_record_exists?
  mpi_response_profile.present?
end

#mpi_response_profileObject (private)



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'app/services/sign_in/attribute_validator.rb', line 173

def mpi_response_profile
  @mpi_response_profile ||=
    if mhv_correlation_id
      mpi_service.find_profile_by_identifier(identifier: mhv_correlation_id,
                                             identifier_type: MPI::Constants::MHV_UUID)&.profile
    elsif idme_uuid
      mpi_service.find_profile_by_identifier(identifier: idme_uuid,
                                             identifier_type: MPI::Constants::IDME_UUID)&.profile
    elsif logingov_uuid
      mpi_service.find_profile_by_identifier(identifier: logingov_uuid,
                                             identifier_type: MPI::Constants::LOGINGOV_UUID)&.profile
    elsif mhv_icn
      mpi_service.find_profile_by_identifier(identifier: mhv_icn, identifier_type: MPI::Constants::ICN)&.profile
    end
end

#mpi_serviceObject (private)



201
202
203
# File 'app/services/sign_in/attribute_validator.rb', line 201

def mpi_service
  @mpi_service ||= MPI::Service.new
end

#performObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'app/services/sign_in/attribute_validator.rb', line 37

def perform
  return unless verified_credential?

  validate_credential_attributes

  if mhv_auth?
    validate_mhv_mpi_record
    validate_existing_mpi_attributes
  elsif mpi_record_exists?
    validate_existing_mpi_attributes
    update_mpi_correlation_record
  else
    add_mpi_user
    validate_existing_mpi_attributes
  end

  verified_icn
end

#scrub_attribute(attribute) ⇒ Object (private)



140
141
142
# File 'app/services/sign_in/attribute_validator.rb', line 140

def scrub_attribute(attribute)
  attribute.tr('-', '').downcase
end

#sign_in_loggerObject (private)



221
222
223
# File 'app/services/sign_in/attribute_validator.rb', line 221

def 
  @sign_in_logger = Logger.new(prefix: self.class)
end

#update_mpi_correlation_recordObject (private)



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'app/services/sign_in/attribute_validator.rb', line 82

def update_mpi_correlation_record
  return if auto_uplevel

  user_attribute_mismatch_checks
  update_profile_response = mpi_service.update_profile(last_name:,
                                                       ssn:,
                                                       birth_date:,
                                                       icn: verified_icn,
                                                       email: credential_email,
                                                       address:,
                                                       idme_uuid:,
                                                       logingov_uuid:,
                                                       edipi:,
                                                       first_name:)
  unless update_profile_response&.ok?
    handle_error('User MPI record cannot be updated', Constants::ErrorCode::GENERIC_EXTERNAL_ISSUE)
  end
end

#user_attribute_mismatch_checksObject (private)



101
102
103
104
105
106
# File 'app/services/sign_in/attribute_validator.rb', line 101

def user_attribute_mismatch_checks
  attribute_mismatch_check(:first_name, first_name, mpi_response_profile.given_names.first)
  attribute_mismatch_check(:last_name, last_name, mpi_response_profile.family_name)
  attribute_mismatch_check(:birth_date, birth_date, mpi_response_profile.birth_date)
  attribute_mismatch_check(:ssn, ssn, mpi_response_profile.ssn, prevent_auth: true)
end

#validate_credential_attributesObject (private)



108
109
110
111
112
113
114
115
116
117
118
119
# File 'app/services/sign_in/attribute_validator.rb', line 108

def validate_credential_attributes
  if mhv_auth?
    credential_attribute_check(:icn, mhv_icn)
    credential_attribute_check(:mhv_uuid, mhv_correlation_id)
  else
    credential_attribute_check(:dslogon_uuid, edipi) if dslogon_auth?
    credential_attribute_check(:last_name, last_name) unless auto_uplevel
    credential_attribute_check(:birth_date, birth_date) unless auto_uplevel
  end
  credential_attribute_check(:uuid, logingov_uuid || idme_uuid)
  credential_attribute_check(:email, credential_email)
end

#validate_existing_mpi_attributesObject (private)



58
59
60
61
62
63
64
# File 'app/services/sign_in/attribute_validator.rb', line 58

def validate_existing_mpi_attributes
  check_lock_flag(mpi_response_profile.id_theft_flag, 'Theft Flag', Constants::ErrorCode::MPI_LOCKED_ACCOUNT)
  check_lock_flag(mpi_response_profile.deceased_date, 'Death Flag', Constants::ErrorCode::MPI_LOCKED_ACCOUNT)
  check_id_mismatch(mpi_response_profile.edipis, 'EDIPI', Constants::ErrorCode::MULTIPLE_EDIPI)
  check_id_mismatch(mpi_response_profile.mhv_iens, 'MHV_ID', Constants::ErrorCode::MULTIPLE_MHV_IEN)
  check_id_mismatch(mpi_response_profile.participant_ids, 'CORP_ID', Constants::ErrorCode::MULTIPLE_CORP_ID)
end

#validate_mhv_mpi_recordObject (private)



144
145
146
147
148
149
150
151
# File 'app/services/sign_in/attribute_validator.rb', line 144

def validate_mhv_mpi_record
  unless mpi_response_profile
    handle_error('No MPI Record for MHV Account',
                 Constants::ErrorCode::GENERIC_EXTERNAL_ISSUE,
                 error: Errors::MHVMissingMPIRecordError)
  end
  attribute_mismatch_check(:icn, mhv_icn, verified_icn)
end

#verified_credential?Boolean (private)

Returns:

  • (Boolean)


217
218
219
# File 'app/services/sign_in/attribute_validator.rb', line 217

def verified_credential?
  current_ial == Constants::Auth::IAL_TWO
end

#verified_icnObject (private)



189
190
191
# File 'app/services/sign_in/attribute_validator.rb', line 189

def verified_icn
  @verified_icn ||= mpi_response_profile.icn
end