devise-two-factor icon indicating copy to clipboard operation
devise-two-factor copied to clipboard

update_with_otp

Open krtschmr opened this issue 6 years ago • 1 comments

checking an OTP to perform update method on the model

u = User.first
u.update_with_otp(secure_field: true, otp_attempt: 123456)
# => false
u.errors
# @details={:otp_attempt=>[{:error=>:invalid}]},
# @messages={:otp_attempt=>["is invalid"]}>

~~now the question is: does this OTP needs to be consumed?~~ i made it also consuming the OTP

pull request: https://github.com/tinfoil/devise-two-factor/pull/148

krtschmr avatar Jan 31 '19 03:01 krtschmr

User can only change password if he also can give an OTP

image

following testcase pass green


Class User
  def change_password(params)
    update_with_otp_and_password(params)
  end



  factory :user do
    email { "[email protected]" }
    password { "12345678" }
    otp_secret { "6fmq4ppm2eabwuphlrlskwae" }
  end



  describe "change password" do
    before do
      user.save
    end

    it "can change the password (without OTP)" do
      params = {current_password: "12345678", password: "aaaaaaaa", password_confirmation: "aaaaaaaa"}
      user.change_password(params)
      user.reload
      user.wont_be :valid_password?, "12345678"
      user.must_be :valid_password?, "aaaaaaaa"
    end

    it "can't change the password with wrong OTP" do
      user.update(otp_required_for_login: true)
      params = {current_password: "12345678", password: "aaaaaaaa", password_confirmation: "aaaaaaaa", otp_attempt: "faulty OTP"}
      user.change_password(params)
      user.errors[:otp_attempt].must_equal ["is invalid"]
    end

    it "can't change the password without OTP" do
      user.update(otp_required_for_login: true)
      params = {current_password: "12345678", password: "aaaaaaaa", password_confirmation: "aaaaaaaa"}
      user.change_password(params)
      user.errors[:otp_attempt].must_equal ["can't be blank"]
    end

    it "can change the password with correct OTP" do
      user.must_be :valid_password?, "12345678"
      user.update(otp_required_for_login: true)
      params = {current_password: "12345678", password: "aaaaaaaa", password_confirmation: "aaaaaaaa"}
      user.change_password( params.merge(otp_attempt: user.current_otp) )
      user.reload
      user.wont_be :valid_password?, "12345678"
      user.must_be :valid_password?, "aaaaaaaa"
    end
  end

krtschmr avatar Jan 31 '19 05:01 krtschmr