diff --git a/app/controllers/concerns/two_factor_authenticatable.rb b/app/controllers/concerns/two_factor_authenticatable.rb index 6478ebfa0ce..422346d5af2 100644 --- a/app/controllers/concerns/two_factor_authenticatable.rb +++ b/app/controllers/concerns/two_factor_authenticatable.rb @@ -121,6 +121,7 @@ def update_invalid_user def handle_valid_otp_for_confirmation_context assign_phone + MarkUserAsMfaEnabled.new(current_user).call end def handle_valid_otp_for_authentication_context diff --git a/app/forms/totp_setup_form.rb b/app/forms/totp_setup_form.rb index f895be2385f..99c3a9a64cb 100644 --- a/app/forms/totp_setup_form.rb +++ b/app/forms/totp_setup_form.rb @@ -26,6 +26,7 @@ def valid_totp_code? def process_valid_submission user.save! Event.create(user_id: user.id, event_type: :authenticator_enabled) + MarkUserAsMfaEnabled.new(user).call end def extra_analytics_attributes diff --git a/app/forms/user_piv_cac_setup_form.rb b/app/forms/user_piv_cac_setup_form.rb index 52e98dd8d3c..1c9de178bc5 100644 --- a/app/forms/user_piv_cac_setup_form.rb +++ b/app/forms/user_piv_cac_setup_form.rb @@ -19,6 +19,7 @@ def process_valid_submission user.x509_dn_uuid = x509_dn_uuid user.save! Event.create(user_id: user.id, event_type: :piv_cac_enabled) + MarkUserAsMfaEnabled.new(user).call true rescue PG::UniqueViolation self.error_type = 'piv_cac.already_associated' diff --git a/app/forms/webauthn_setup_form.rb b/app/forms/webauthn_setup_form.rb index 776e2498a04..f5988c2570a 100644 --- a/app/forms/webauthn_setup_form.rb +++ b/app/forms/webauthn_setup_form.rb @@ -25,6 +25,7 @@ def submit(protocol, params) if success create_webauthn_configuration create_user_event + MarkUserAsMfaEnabled.new(user).call end FormResponse.new(success: success, errors: errors.messages, extra: extra_analytics_attributes) diff --git a/app/services/mark_user_as_mfa_enabled.rb b/app/services/mark_user_as_mfa_enabled.rb new file mode 100644 index 00000000000..8730e24f384 --- /dev/null +++ b/app/services/mark_user_as_mfa_enabled.rb @@ -0,0 +1,15 @@ +class MarkUserAsMfaEnabled + def initialize(user) + @user = user + end + + def call + return if user.mfa_enabled? + + UpdateUser.new(user: user, attributes: { mfa_enabled: true }).call + end + + private + + attr_reader :user +end diff --git a/db/migrate/20181121044822_add_mfa_enabled_to_users.rb b/db/migrate/20181121044822_add_mfa_enabled_to_users.rb new file mode 100644 index 00000000000..f0f4fc1f7f9 --- /dev/null +++ b/db/migrate/20181121044822_add_mfa_enabled_to_users.rb @@ -0,0 +1,10 @@ +class AddMfaEnabledToUsers < ActiveRecord::Migration[5.1] + def up + add_column :users, :mfa_enabled, :boolean + change_column_default :users, :mfa_enabled, false + end + + def down + remove_column :users, :mfa_enabled + end +end diff --git a/db/migrate/20181121051244_add_mfa_enabled_index_to_users.rb b/db/migrate/20181121051244_add_mfa_enabled_index_to_users.rb new file mode 100644 index 00000000000..916620915bf --- /dev/null +++ b/db/migrate/20181121051244_add_mfa_enabled_index_to_users.rb @@ -0,0 +1,7 @@ +class AddMfaEnabledIndexToUsers < ActiveRecord::Migration[5.1] + disable_ddl_transaction! + + def change + add_index :users, :mfa_enabled, algorithm: :concurrently + end +end diff --git a/db/schema.rb b/db/schema.rb index cb124630707..198ad2c18e6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20181029203754) do +ActiveRecord::Schema.define(version: 20181121051244) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -250,9 +250,11 @@ t.string "encrypted_password_digest", default: "" t.string "encrypted_recovery_code_digest", default: "" t.datetime "remember_device_revoked_at" + t.boolean "mfa_enabled", default: false t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["email_fingerprint"], name: "index_users_on_email_fingerprint", unique: true t.index ["encrypted_otp_secret_key"], name: "index_users_on_encrypted_otp_secret_key", unique: true + t.index ["mfa_enabled"], name: "index_users_on_mfa_enabled" t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true t.index ["unconfirmed_email"], name: "index_users_on_unconfirmed_email" t.index ["unlock_token"], name: "index_users_on_unlock_token"