diff --git a/db/schema.rb b/db/schema.rb index a297997d..86012613 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -280,7 +280,7 @@ ActiveRecord::Schema.define(version: 2020_11_01_155648) do t.boolean "export_processing", default: false, null: false t.datetime "export_created_at" t.string "otp_secret_key" - t.integer "otp_module" + t.integer "otp_module", default: 0, null: false t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true diff --git a/spec/controllers/user/sessions_controller_spec.rb b/spec/controllers/user/sessions_controller_spec.rb index ced9528c..3b3a61d2 100644 --- a/spec/controllers/user/sessions_controller_spec.rb +++ b/spec/controllers/user/sessions_controller_spec.rb @@ -21,5 +21,56 @@ describe User::SessionsController do expect(subject).to have_rendered('auth/two_factor_authentication') end + + context "2fa sign in attempt" do + subject do + post :create, + params: { user: { otp_attempt: code_input } }, + session: { user_sign_in_uid: user.id } + end + + before do + user.otp_module = :enabled + user.save + end + + context "incorrect code" do + let(:code_input) { 123456 } + + it "redirects to the sign in page" do + expect(subject).to redirect_to :new_user_session + end + end + + context "correct code" do + let(:code_input) { user.otp_code } + + it "redirects to the timeline" do + expect(subject).to redirect_to :root + end + end + + context "correct recovery code" do + let(:code_input) { 'raccoons' } + + before do + user.totp_recovery_codes << TotpRecoveryCode.create(code: 'raccoons') + end + + it "consumes the recovery code" do + expect { subject }.to change { user.totp_recovery_codes.count }.by(-1) + expect(response).to redirect_to :root + end + end + + context "incorrect recovery code" do + let(:code_input) { 'abcdefgh' } + + it "redirects to the sign in page" do + expect(subject).to redirect_to :new_user_session + expect(flash[:error]).to eq I18n.t('views.auth.2fa.errors.invalid_code') + end + end + end end end \ No newline at end of file