Class: UserSessionForm
- Inherits:
-
Object
show all
- Includes:
- ActiveModel::Validations, SentryLogging
- Defined in:
- app/models/user_session_form.rb
Constant Summary
collapse
- VALIDATIONS_FAILED_ERROR_CODE =
'004'
- SAML_REPLAY_VALID_SESSION_ERROR_CODE =
'002'
- ERRORS =
{ validations_failed: { code: VALIDATIONS_FAILED_ERROR_CODE,
tag: :validations_failed,
short_message: 'on User/Session Validation',
level: :error },
saml_replay_valid_session: { code: SAML_REPLAY_VALID_SESSION_ERROR_CODE,
tag: :saml_replay_valid_session,
short_message: 'SamlResponse is too late but user has current session',
level: :warn } }.freeze
Instance Attribute Summary collapse
Instance Method Summary
collapse
#log_exception_to_sentry, #log_message_to_sentry, #non_nil_hash?, #normalize_level, #rails_logger, #set_sentry_metadata
Constructor Details
Returns a new instance of UserSessionForm.
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
# File 'app/models/user_session_form.rb', line 21
def initialize(saml_response)
@saml_uuid = saml_response.in_response_to
saml_user = SAML::User.new(saml_response)
saml_attributes = normalize_saml(saml_user)
uuid = saml_attributes[:uuid]
existing_user = User.find(uuid)
@session = Session.new(uuid:, ssoe_transactionid: saml_user.user_attributes.try(:transactionid))
@user_identity = UserIdentity.new(saml_attributes)
@user = User.new(uuid:)
@user.session_handle = @session.token
@user.instance_variable_set(:@identity, @user_identity)
@user.invalidate_mpi_cache
if saml_user.changing_multifactor?
last_signed_in = existing_user&.last_signed_in || Time.current.utc
@user.mhv_last_signed_in = last_signed_in
@user.last_signed_in = last_signed_in
log_existing_user_warning(uuid, saml_attributes[:mhv_icn]) unless existing_user
else
@user.last_signed_in = Time.current.utc
end
end
|
Instance Attribute Details
#saml_uuid ⇒ Object
Returns the value of attribute saml_uuid.
19
20
21
|
# File 'app/models/user_session_form.rb', line 19
def saml_uuid
@saml_uuid
end
|
#session ⇒ Object
Returns the value of attribute session.
19
20
21
|
# File 'app/models/user_session_form.rb', line 19
def session
@session
end
|
#user ⇒ Object
Returns the value of attribute user.
19
20
21
|
# File 'app/models/user_session_form.rb', line 19
def user
@user
end
|
#user_identity ⇒ Object
Returns the value of attribute user_identity.
19
20
21
|
# File 'app/models/user_session_form.rb', line 19
def user_identity
@user_identity
end
|
Instance Method Details
#add_csp_id_to_mpi(saml_user_attributes, idme_uuid) ⇒ Object
61
62
63
64
65
66
67
68
69
70
71
|
# File 'app/models/user_session_form.rb', line 61
def add_csp_id_to_mpi(saml_user_attributes, idme_uuid)
return unless saml_user_attributes[:loa][:current] == LOA::THREE
Rails.logger.info("[UserSessionForm] Adding CSP ID to MPI, idme: #{idme_uuid}")
mpi_response = MPI::Service.new.add_person_implicit_search(first_name: saml_user_attributes[:first_name],
last_name: saml_user_attributes[:last_name],
ssn: saml_user_attributes[:ssn],
birth_date: saml_user_attributes[:birth_date],
idme_uuid:)
log_message_to_sentry("Failed Add CSP ID to MPI FAILED, idme: #{idme_uuid}", :warn) unless mpi_response.ok?
end
|
#error_code ⇒ Object
147
148
149
|
# File 'app/models/user_session_form.rb', line 147
def error_code
errors_hash[:code] if errors.any?
end
|
#error_instrumentation_code ⇒ Object
151
152
153
|
# File 'app/models/user_session_form.rb', line 151
def error_instrumentation_code
"error:#{errors_hash[:tag]}" if errors.any?
end
|
#errors_context ⇒ Object
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
# File 'app/models/user_session_form.rb', line 117
def errors_context
errors_hash.merge(
uuid: @user.uuid,
user: {
valid: @user&.valid?,
errors: @user&.errors&.full_messages
},
session: {
valid: @session.valid? && !@session.uuid.nil?,
errors: get_session_errors
},
identity: {
valid: @user_identity&.valid?,
errors: @user_identity&.errors&.full_messages,
authn_context: @user_identity&.authn_context,
loa: @user_identity&.loa
},
mvi: mvi_context
)
end
|
#errors_hash ⇒ Object
113
114
115
|
# File 'app/models/user_session_form.rb', line 113
def errors_hash
ERRORS[:validations_failed] if errors.any?
end
|
#errors_message ⇒ Object
109
110
111
|
# File 'app/models/user_session_form.rb', line 109
def errors_message
@errors_message ||= "Login Failed! #{errors_hash[:short_message]}" if errors.any?
end
|
#get_session_errors ⇒ Object
92
93
94
95
|
# File 'app/models/user_session_form.rb', line 92
def get_session_errors
@session.errors.add(:uuid, "can't be blank") if @session.uuid.nil?
@session.errors&.full_messages
end
|
#log_existing_user_warning(saml_uuid, saml_icn) ⇒ Object
157
158
159
160
|
# File 'app/models/user_session_form.rb', line 157
def log_existing_user_warning(saml_uuid, saml_icn)
message = "Couldn't locate exiting user after MFA establishment"
log_message_to_sentry(message, :warn, { saml_uuid:, saml_icn: })
end
|
#mvi_context ⇒ Object
138
139
140
141
142
143
144
145
|
# File 'app/models/user_session_form.rb', line 138
def mvi_context
latest_outage = MPI::Configuration.instance.breakers_service.latest_outage
if latest_outage && !latest_outage.ended?
'breakers is closed for MVI'
else
'breakers is open for MVI'
end
end
|
#normalize_saml(saml_user) ⇒ Object
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
# File 'app/models/user_session_form.rb', line 44
def normalize_saml(saml_user)
saml_user.validate!
saml_user_attributes = saml_user.to_hash
add_csp_id_to_mpi(saml_user_attributes, saml_user_attributes[:idme_uuid]) if saml_user.needs_csp_id_mpi_update?
saml_user_attributes
rescue SAML::UserAttributeError => e
raise unless e.code == SAML::UserAttributeError::UUID_MISSING_CODE
idme_uuid = uuid_from_account(e&.identifier)
raise if idme_uuid.blank?
Rails.logger.info('Account UUID injected into user SAML attributes')
saml_user_attributes = saml_user.to_hash
add_csp_id_to_mpi(saml_user_attributes, idme_uuid)
saml_user_attributes.merge({ uuid: idme_uuid, idme_uuid: })
end
|
#persist ⇒ Object
101
102
103
104
105
106
107
|
# File 'app/models/user_session_form.rb', line 101
def persist
if save
[user, session]
else
[nil, nil]
end
end
|
#save ⇒ Object
97
98
99
|
# File 'app/models/user_session_form.rb', line 97
def save
valid? && session.save && user.save && @user_identity.save
end
|
#uuid_from_account(identifier) ⇒ Object
73
74
75
76
77
78
79
80
81
82
83
|
# File 'app/models/user_session_form.rb', line 73
def uuid_from_account(identifier)
return if identifier.blank?
user_account = UserAccount.find_by(icn: identifier)
return unless user_account
idme_uuid_array = user_account.user_verifications.map(&:idme_uuid) +
user_account.user_verifications.map(&:backing_idme_uuid)
idme_uuid_array.compact.first
end
|
#valid? ⇒ Boolean
85
86
87
88
89
90
|
# File 'app/models/user_session_form.rb', line 85
def valid?
errors.add(:session, :invalid) unless session.valid?
errors.add(:user, :invalid) unless user.valid?
errors.add(:user_identity, :invalid) unless @user_identity.valid?
errors.empty?
end
|