# frozen_string_literal: true require "rails_helper" describe User::SessionsController do before do # Required for devise to register routes @request.env["devise.mapping"] = Devise.mappings[:user] end describe "#create" do let(:user) { FactoryBot.create(:user, password: "/bin/animals64") } subject { post :create, params: { user: { login: user.email, password: user.password } } } it "logs in users without 2FA enabled without any further input" do expect(subject).to redirect_to :root end it "prompts users with 2FA enabled to enter a code" do user.otp_module = :enabled user.save 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("errors.invalid_otp") end end end context "permanently banned user sign in attempt" do before do user.ban(nil, "Do not feed the animals") end it "redirects to the sign in page" do expect(subject).to redirect_to :new_user_session expect(flash[:notice]).to eq "#{I18n.t('user.sessions.create.banned', name: user.screen_name)}\n#{I18n.t('user.sessions.create.reason', reason: 'Do not feed the animals')}" end end context "temporarily banned user sign in attempt" do let(:expiry) { DateTime.now.utc + 3.hours } before do user.ban(expiry, "Do not feed the animals") end it "redirects to the sign in page" do expect(subject).to redirect_to :new_user_session expect(flash[:notice]).to eq I18n.t("user.sessions.create.banned", name: user.screen_name) + "\n#{I18n.t('user.sessions.create.reason', reason: 'Do not feed the animals')}" \ "\n#{I18n.t('user.sessions.create.until', time: expiry)}" end end end end