two_factor_authentication 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +41 -2
- data/app/controllers/devise/two_factor_authentication_controller.rb +1 -1
- data/config/locales/ru.yml +1 -0
- data/lib/generators/active_record/two_factor_authentication_generator.rb +1 -1
- data/lib/two_factor_authentication.rb +5 -0
- data/lib/two_factor_authentication/controllers/helpers.rb +3 -3
- data/lib/two_factor_authentication/hooks/two_factor_authenticatable.rb +1 -1
- data/lib/two_factor_authentication/models/two_factor_authenticatable.rb +4 -4
- data/lib/two_factor_authentication/version.rb +1 -1
- data/spec/controllers/two_factor_auth_spec.rb +3 -5
- data/spec/features/two_factor_authenticatable_spec.rb +5 -3
- data/spec/lib/two_factor_authentication/models/two_factor_authenticatable_spec.rb +12 -8
- data/spec/rails_app/app/views/home/dashboard.html.erb +4 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/support/features_spec_helper.rb +1 -1
- data/two_factor_authentication.gemspec +2 -2
- metadata +9 -62
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: fb84a503671c99963674feb9a48b9e0b4078c457
         | 
| 4 | 
            +
              data.tar.gz: e1004e05b1adfb4fc9dbae58638f3091a29cd4c9
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 7f790fd330b74c0bed8199477a23dce4d52d5035c86495a62d2d5e5b0bc77f5d97c4cea8b6b9aee5a6b3b306d9d45664fb95b5a0c3ca89838b3a832302de1590
         | 
| 7 | 
            +
              data.tar.gz: 48d79bca0d7eb2f51ed606d4c34aea8b7f7d01cf0c2e59e763a0fd6eaad167dbc53c4c7db495bc0931fa6b061c4a095a6d521b868334eeaf77267538861b3cf6
         | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -38,11 +38,12 @@ Add the following line to your model to fully enable two-factor auth: | |
| 38 38 |  | 
| 39 39 | 
             
                has_one_time_password
         | 
| 40 40 |  | 
| 41 | 
            -
            Set config values if desired for maximum second factor attempts count  | 
| 41 | 
            +
            Set config values, if desired, for maximum second factor attempts count, allowed time drift, and OTP length.
         | 
| 42 42 |  | 
| 43 43 | 
             
            ```ruby
         | 
| 44 44 | 
             
            config.max_login_attempts = 3
         | 
| 45 45 | 
             
            config.allowed_otp_drift_seconds = 30
         | 
| 46 | 
            +
            config.otp_length = 6
         | 
| 46 47 | 
             
            ```
         | 
| 47 48 |  | 
| 48 49 | 
             
            Override the method to send one-time passwords in your model, this is automatically called when a user logs in:
         | 
| @@ -66,11 +67,12 @@ Add the following line to your model to fully enable two-factor auth: | |
| 66 67 |  | 
| 67 68 | 
             
                has_one_time_password
         | 
| 68 69 |  | 
| 69 | 
            -
            Set config values if desired for maximum second factor attempts count  | 
| 70 | 
            +
            Set config values, if desired, for maximum second factor attempts count, allowed time drift, and OTP length.
         | 
| 70 71 |  | 
| 71 72 | 
             
            ```ruby
         | 
| 72 73 | 
             
            config.max_login_attempts = 3
         | 
| 73 74 | 
             
            config.allowed_otp_drift_seconds = 30
         | 
| 75 | 
            +
            config.otp_length = 6
         | 
| 74 76 | 
             
            ```
         | 
| 75 77 |  | 
| 76 78 | 
             
            Override the method to send one-time passwords in your model, this is automatically called when a user logs in:
         | 
| @@ -81,6 +83,7 @@ def send_two_factor_authentication_code | |
| 81 83 | 
             
            end
         | 
| 82 84 | 
             
            ```
         | 
| 83 85 |  | 
| 86 | 
            +
             | 
| 84 87 | 
             
            ### Customisation and Usage
         | 
| 85 88 |  | 
| 86 89 | 
             
            By default second factor authentication enabled for each user, you can change it with this method in your User model:
         | 
| @@ -99,6 +102,42 @@ This gem is compatible with Google Authenticator (https://support.google.com/acc | |
| 99 102 |  | 
| 100 103 | 
             
            This provisioning uri can then be turned in to a QR code if desired so that users may add the app to Google Authenticator easily.  Once this is done they may retrieve a one-time password directly from the Google Authenticator app as well as through whatever method you define in `send_two_factor_authentication_code`
         | 
| 101 104 |  | 
| 105 | 
            +
            #### Overriding the view
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            The default view that shows the form can be overridden by first adding a folder named: "two_factor_authentication" inside "app/views/devise", in here you want to create a "show.html.erb" view.
         | 
| 108 | 
            +
             | 
| 109 | 
            +
            The full path should be "app/views/devise/two_factor_authentication/show.html.erb"
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            ```html
         | 
| 112 | 
            +
            <h2>Hi, you received a code by email, please enter it below, thanks!</h2>
         | 
| 113 | 
            +
             | 
| 114 | 
            +
            <%= form_tag([resource_name, :two_factor_authentication], :method => :put) do %>
         | 
| 115 | 
            +
              <%= text_field_tag :code %>
         | 
| 116 | 
            +
              <%= submit_tag "Log in!" %>
         | 
| 117 | 
            +
            <% end %>
         | 
| 118 | 
            +
             | 
| 119 | 
            +
            <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            ```
         | 
| 122 | 
            +
             | 
| 123 | 
            +
            #### Updating existing users with OTP secret key
         | 
| 124 | 
            +
             | 
| 125 | 
            +
            If you have existing users that needs to be provided with a OTP secret key, so they can take benefit of the two factor authentication, create a rake. It could look like this one below:
         | 
| 126 | 
            +
             | 
| 127 | 
            +
            ```ruby
         | 
| 128 | 
            +
            desc "rake task to update users with otp secret key"
         | 
| 129 | 
            +
            task :update_users_with_otp_secret_key  => :environment do
         | 
| 130 | 
            +
            	users = User.all
         | 
| 131 | 
            +
             | 
| 132 | 
            +
            	users.each do |user|
         | 
| 133 | 
            +
            		key = ROTP::Base32.random_base32
         | 
| 134 | 
            +
            		user.update_attributes(:otp_secret_key => key)
         | 
| 135 | 
            +
            		user.save
         | 
| 136 | 
            +
            		puts "Rake[:update_users_with_otp_secret_key] => User '#{user.email}' OTP secret key set to '#{key}'"
         | 
| 137 | 
            +
            	end
         | 
| 138 | 
            +
            end
         | 
| 139 | 
            +
            ```
         | 
| 140 | 
            +
             | 
| 102 141 | 
             
            ### Example
         | 
| 103 142 |  | 
| 104 143 | 
             
            [TwoFactorAuthenticationExample](https://github.com/Houdini/TwoFactorAuthenticationExample)
         | 
| @@ -9,7 +9,7 @@ class Devise::TwoFactorAuthenticationController < DeviseController | |
| 9 9 | 
             
                render :show and return if params[:code].nil?
         | 
| 10 10 |  | 
| 11 11 | 
             
                if resource.authenticate_otp(params[:code])
         | 
| 12 | 
            -
                  warden.session(resource_name)[ | 
| 12 | 
            +
                  warden.session(resource_name)[TwoFactorAuthentication::NEED_AUTHENTICATION] = false
         | 
| 13 13 | 
             
                  sign_in resource_name, resource, :bypass => true
         | 
| 14 14 | 
             
                  set_flash_message :notice, :success
         | 
| 15 15 | 
             
                  redirect_to stored_location_for(resource_name) || :root
         | 
    
        data/config/locales/ru.yml
    CHANGED
    
    | @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            ru:
         | 
| 2 2 | 
             
              devise:
         | 
| 3 3 | 
             
                two_factor_authentication:
         | 
| 4 | 
            +
                  success: "Двухфакторная авторизация успешно пройдена."
         | 
| 4 5 | 
             
                  attempt_failed: "Неверный код."
         | 
| 5 6 | 
             
                  max_login_attempts_reached: "Доступ заблокирован. Превышено число попыток авторизации"
         | 
| 6 7 | 
             
                  contact_administrator: "Пожалуйста, свяжитесь с системным администратором."
         | 
| @@ -6,7 +6,7 @@ module ActiveRecord | |
| 6 6 | 
             
                  source_root File.expand_path("../templates", __FILE__)
         | 
| 7 7 |  | 
| 8 8 | 
             
                  def copy_two_factor_authentication_migration
         | 
| 9 | 
            -
                    migration_template "migration.rb", "db/migrate/two_factor_authentication_add_to_#{table_name}"
         | 
| 9 | 
            +
                    migration_template "migration.rb", "db/migrate/two_factor_authentication_add_to_#{table_name}.rb"
         | 
| 10 10 | 
             
                  end
         | 
| 11 11 |  | 
| 12 12 | 
             
                end
         | 
| @@ -13,9 +13,14 @@ module Devise | |
| 13 13 |  | 
| 14 14 | 
             
              mattr_accessor :allowed_otp_drift_seconds
         | 
| 15 15 | 
             
              @@allowed_otp_drift_seconds = 30
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              mattr_accessor :otp_length
         | 
| 18 | 
            +
              @@otp_length = 6
         | 
| 16 19 | 
             
            end
         | 
| 17 20 |  | 
| 18 21 | 
             
            module TwoFactorAuthentication
         | 
| 22 | 
            +
              NEED_AUTHENTICATION = 'need_two_factor_authentication'
         | 
| 23 | 
            +
             | 
| 19 24 | 
             
              autoload :Schema, 'two_factor_authentication/schema'
         | 
| 20 25 | 
             
              module Controllers
         | 
| 21 26 | 
             
                autoload :Helpers, 'two_factor_authentication/controllers/helpers'
         | 
| @@ -12,7 +12,7 @@ module TwoFactorAuthentication | |
| 12 12 | 
             
                  def handle_two_factor_authentication
         | 
| 13 13 | 
             
                    unless devise_controller?
         | 
| 14 14 | 
             
                      Devise.mappings.keys.flatten.any? do |scope|
         | 
| 15 | 
            -
                        if signed_in?(scope) and warden.session(scope)[ | 
| 15 | 
            +
                        if signed_in?(scope) and warden.session(scope)[TwoFactorAuthentication::NEED_AUTHENTICATION]
         | 
| 16 16 | 
             
                          handle_failed_second_factor(scope)
         | 
| 17 17 | 
             
                        end
         | 
| 18 18 | 
             
                      end
         | 
| @@ -21,7 +21,7 @@ module TwoFactorAuthentication | |
| 21 21 |  | 
| 22 22 | 
             
                  def handle_failed_second_factor(scope)
         | 
| 23 23 | 
             
                    if request.format.present? and request.format.html?
         | 
| 24 | 
            -
                      session["#{scope}_return_to"] = request.path if request.get?
         | 
| 24 | 
            +
                      session["#{scope}_return_to"] = "#{request.path}?#{request.query_string}" if request.get?
         | 
| 25 25 | 
             
                      redirect_to two_factor_authentication_path_for(scope)
         | 
| 26 26 | 
             
                    else
         | 
| 27 27 | 
             
                      render nothing: true, status: :unauthorized
         | 
| @@ -42,7 +42,7 @@ module Devise | |
| 42 42 | 
             
              module Controllers
         | 
| 43 43 | 
             
                module Helpers
         | 
| 44 44 | 
             
                  def is_fully_authenticated?
         | 
| 45 | 
            -
                    !session["warden.user.user.session"].try(:[],  | 
| 45 | 
            +
                    !session["warden.user.user.session"].try(:[], TwoFactorAuthentication::NEED_AUTHENTICATION)
         | 
| 46 46 | 
             
                  end
         | 
| 47 47 | 
             
                end
         | 
| 48 48 | 
             
              end
         | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            Warden::Manager.after_authentication do |user, auth, options|
         | 
| 2 2 | 
             
              if user.respond_to?(:need_two_factor_authentication?)
         | 
| 3 | 
            -
                if auth.session(options[:scope])[ | 
| 3 | 
            +
                if auth.session(options[:scope])[TwoFactorAuthentication::NEED_AUTHENTICATION] = user.need_two_factor_authentication?(auth.request)
         | 
| 4 4 | 
             
                  user.send_two_factor_authentication_code
         | 
| 5 5 | 
             
                end
         | 
| 6 6 | 
             
              end
         | 
| @@ -20,19 +20,19 @@ module Devise | |
| 20 20 | 
             
                        end
         | 
| 21 21 | 
             
                      end
         | 
| 22 22 | 
             
                    end
         | 
| 23 | 
            -
                    ::Devise::Models.config(self, :max_login_attempts, :allowed_otp_drift_seconds)
         | 
| 23 | 
            +
                    ::Devise::Models.config(self, :max_login_attempts, :allowed_otp_drift_seconds, :otp_length)
         | 
| 24 24 | 
             
                  end
         | 
| 25 25 |  | 
| 26 26 | 
             
                  module InstanceMethodsOnActivation
         | 
| 27 27 | 
             
                    def authenticate_otp(code, options = {})
         | 
| 28 | 
            -
                      totp = ROTP::TOTP.new(self.otp_column)
         | 
| 28 | 
            +
                      totp = ROTP::TOTP.new(self.otp_column, { digits: options[:otp_length] || self.class.otp_length })
         | 
| 29 29 | 
             
                      drift = options[:drift] || self.class.allowed_otp_drift_seconds
         | 
| 30 30 |  | 
| 31 31 | 
             
                      totp.verify_with_drift(code, drift)
         | 
| 32 32 | 
             
                    end
         | 
| 33 33 |  | 
| 34 | 
            -
                    def otp_code(time = Time.now)
         | 
| 35 | 
            -
                      ROTP::TOTP.new(self.otp_column).at(time, true)
         | 
| 34 | 
            +
                    def otp_code(time = Time.now, options = {})
         | 
| 35 | 
            +
                      ROTP::TOTP.new(self.otp_column, { digits: options[:otp_length] || self.class.otp_length }).at(time, true)
         | 
| 36 36 | 
             
                    end
         | 
| 37 37 |  | 
| 38 38 | 
             
                    def provisioning_uri(account = nil, options = {})
         | 
| @@ -2,7 +2,7 @@ require 'spec_helper' | |
| 2 2 |  | 
| 3 3 | 
             
            include Warden::Test::Helpers
         | 
| 4 4 |  | 
| 5 | 
            -
            describe HomeController do
         | 
| 5 | 
            +
            describe HomeController, :type => :controller do
         | 
| 6 6 | 
             
              context "passed only 1st factor auth" do
         | 
| 7 7 | 
             
                let(:user) { create_user }
         | 
| 8 8 |  | 
| @@ -11,10 +11,8 @@ describe HomeController do | |
| 11 11 | 
             
                    login_as user, scope: :user
         | 
| 12 12 | 
             
                    visit user_two_factor_authentication_path
         | 
| 13 13 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
                    controller.is_fully_authenticated?.should be_true
         | 
| 14 | 
            +
                    expect(controller.is_fully_authenticated?).to be_truthy
         | 
| 16 15 | 
             
                  end
         | 
| 17 16 | 
             
                end
         | 
| 18 | 
            -
             | 
| 19 17 | 
             
              end
         | 
| 20 | 
            -
            end
         | 
| 18 | 
            +
            end
         | 
| @@ -11,14 +11,14 @@ feature "User of two factor authentication" do | |
| 11 11 | 
             
              end
         | 
| 12 12 |  | 
| 13 13 | 
             
              scenario "sends two factor authentication code after sign in" do
         | 
| 14 | 
            -
                SMSProvider.messages. | 
| 14 | 
            +
                expect(SMSProvider.messages).to be_empty
         | 
| 15 15 |  | 
| 16 16 | 
             
                visit new_user_session_path
         | 
| 17 17 | 
             
                complete_sign_in_form_for(user)
         | 
| 18 18 |  | 
| 19 19 | 
             
                expect(page).to have_content "Enter your personal code"
         | 
| 20 20 |  | 
| 21 | 
            -
                SMSProvider.messages.size. | 
| 21 | 
            +
                expect(SMSProvider.messages.size).to eq(1)
         | 
| 22 22 | 
             
                message = SMSProvider.last_message
         | 
| 23 23 | 
             
                expect(message.to).to eq(user.phone_number)
         | 
| 24 24 | 
             
                expect(message.body).to eq(user.otp_code)
         | 
| @@ -45,7 +45,7 @@ feature "User of two factor authentication" do | |
| 45 45 | 
             
                end
         | 
| 46 46 |  | 
| 47 47 | 
             
                scenario "is redirected to TFA when path requires authentication" do
         | 
| 48 | 
            -
                  visit dashboard_path
         | 
| 48 | 
            +
                  visit dashboard_path + "?A=param%20a&B=param%20b"
         | 
| 49 49 |  | 
| 50 50 | 
             
                  expect(page).to_not have_content("Your Personal Dashboard")
         | 
| 51 51 |  | 
| @@ -54,6 +54,8 @@ feature "User of two factor authentication" do | |
| 54 54 |  | 
| 55 55 | 
             
                  expect(page).to have_content("Your Personal Dashboard")
         | 
| 56 56 | 
             
                  expect(page).to have_content("You are signed in as Marissa")
         | 
| 57 | 
            +
                  expect(page).to have_content("Param A is param a")
         | 
| 58 | 
            +
                  expect(page).to have_content("Param B is param b")
         | 
| 57 59 | 
             
                end
         | 
| 58 60 |  | 
| 59 61 | 
             
                scenario "is locked out after max failed attempts" do
         | 
| @@ -21,11 +21,15 @@ describe Devise::Models::TwoFactorAuthenticatable, '#otp_code' do | |
| 21 21 | 
             
                  subject
         | 
| 22 22 | 
             
                end
         | 
| 23 23 |  | 
| 24 | 
            +
                it "should be configured length" do
         | 
| 25 | 
            +
                  expect(subject.length).to eq(Devise.otp_length)
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 24 28 | 
             
                context "with a known time" do
         | 
| 25 29 | 
             
                  let(:time) { 1392852756 }
         | 
| 26 30 |  | 
| 27 31 | 
             
                  it "should return a known result" do
         | 
| 28 | 
            -
                    expect(subject).to eq( | 
| 32 | 
            +
                    expect(subject).to eq("0000000524562202".split(//).last(Devise.otp_length).join)
         | 
| 29 33 | 
             
                  end
         | 
| 30 34 | 
             
                end
         | 
| 31 35 |  | 
| @@ -33,7 +37,7 @@ describe Devise::Models::TwoFactorAuthenticatable, '#otp_code' do | |
| 33 37 | 
             
                  let(:time) { 1393065856 }
         | 
| 34 38 |  | 
| 35 39 | 
             
                  it "should return a known result padded with zeroes" do
         | 
| 36 | 
            -
                    expect(subject).to eq( | 
| 40 | 
            +
                    expect(subject).to eq("0000001608007672".split(//).last(Devise.otp_length).join)
         | 
| 37 41 | 
             
                  end
         | 
| 38 42 | 
             
                end
         | 
| 39 43 | 
             
              end
         | 
| @@ -146,19 +150,19 @@ describe Devise::Models::TwoFactorAuthenticatable, '#max_login_attempts' do | |
| 146 150 |  | 
| 147 151 | 
             
              it "returns false as boolean" do
         | 
| 148 152 | 
             
                instance.second_factor_attempts_count = nil
         | 
| 149 | 
            -
                expect(instance.max_login_attempts?).to  | 
| 153 | 
            +
                expect(instance.max_login_attempts?).to be_falsey
         | 
| 150 154 | 
             
                instance.second_factor_attempts_count = 0
         | 
| 151 | 
            -
                expect(instance.max_login_attempts?).to  | 
| 155 | 
            +
                expect(instance.max_login_attempts?).to be_falsey
         | 
| 152 156 | 
             
                instance.second_factor_attempts_count = 1
         | 
| 153 | 
            -
                expect(instance.max_login_attempts?).to  | 
| 157 | 
            +
                expect(instance.max_login_attempts?).to be_falsey
         | 
| 154 158 | 
             
                instance.second_factor_attempts_count = 2
         | 
| 155 | 
            -
                expect(instance.max_login_attempts?).to  | 
| 159 | 
            +
                expect(instance.max_login_attempts?).to be_falsey
         | 
| 156 160 | 
             
              end
         | 
| 157 161 |  | 
| 158 162 | 
             
              it "returns true as boolean after too many attempts" do
         | 
| 159 163 | 
             
                instance.second_factor_attempts_count = 3
         | 
| 160 | 
            -
                expect(instance.max_login_attempts?).to  | 
| 164 | 
            +
                expect(instance.max_login_attempts?).to be_truthy
         | 
| 161 165 | 
             
                instance.second_factor_attempts_count = 4
         | 
| 162 | 
            -
                expect(instance.max_login_attempts?).to  | 
| 166 | 
            +
                expect(instance.max_login_attempts?).to be_truthy
         | 
| 163 167 | 
             
              end
         | 
| 164 168 | 
             
            end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    | @@ -5,12 +5,13 @@ require 'rspec/rails' | |
| 5 5 |  | 
| 6 6 | 
             
            # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
         | 
| 7 7 | 
             
            RSpec.configure do |config|
         | 
| 8 | 
            -
              config.treat_symbols_as_metadata_keys_with_true_values = true
         | 
| 9 8 | 
             
              config.run_all_when_everything_filtered = true
         | 
| 10 9 | 
             
              config.filter_run :focus
         | 
| 11 10 |  | 
| 12 11 | 
             
              config.use_transactional_examples = true
         | 
| 13 12 |  | 
| 13 | 
            +
              config.include Capybara::DSL
         | 
| 14 | 
            +
             | 
| 14 15 | 
             
              # Run specs in random order to surface order dependencies. If you find an
         | 
| 15 16 | 
             
              # order dependency and want to debug it, you can fix the order by providing
         | 
| 16 17 | 
             
              # the seed, which is printed after each run.
         | 
| @@ -31,7 +31,7 @@ Gem::Specification.new do |s| | |
| 31 31 |  | 
| 32 32 | 
             
              s.add_development_dependency 'bundler'
         | 
| 33 33 | 
             
              s.add_development_dependency 'rake'
         | 
| 34 | 
            -
              s.add_development_dependency 'rspec-rails'
         | 
| 35 | 
            -
              s.add_development_dependency 'capybara'
         | 
| 34 | 
            +
              s.add_development_dependency 'rspec-rails', '>= 3.0.1'
         | 
| 35 | 
            +
              s.add_development_dependency 'capybara', '2.4.1'
         | 
| 36 36 | 
             
              s.add_development_dependency 'pry'
         | 
| 37 37 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: two_factor_authentication
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.1. | 
| 4 | 
            +
              version: 1.1.3
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Dmitrii Golub
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2014- | 
| 11 | 
            +
            date: 2014-12-14 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rails
         | 
| @@ -100,28 +100,28 @@ dependencies: | |
| 100 100 | 
             
                requirements:
         | 
| 101 101 | 
             
                - - '>='
         | 
| 102 102 | 
             
                  - !ruby/object:Gem::Version
         | 
| 103 | 
            -
                    version:  | 
| 103 | 
            +
                    version: 3.0.1
         | 
| 104 104 | 
             
              type: :development
         | 
| 105 105 | 
             
              prerelease: false
         | 
| 106 106 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 107 107 | 
             
                requirements:
         | 
| 108 108 | 
             
                - - '>='
         | 
| 109 109 | 
             
                  - !ruby/object:Gem::Version
         | 
| 110 | 
            -
                    version:  | 
| 110 | 
            +
                    version: 3.0.1
         | 
| 111 111 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 112 112 | 
             
              name: capybara
         | 
| 113 113 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 114 114 | 
             
                requirements:
         | 
| 115 | 
            -
                - - ' | 
| 115 | 
            +
                - - '='
         | 
| 116 116 | 
             
                  - !ruby/object:Gem::Version
         | 
| 117 | 
            -
                    version:  | 
| 117 | 
            +
                    version: 2.4.1
         | 
| 118 118 | 
             
              type: :development
         | 
| 119 119 | 
             
              prerelease: false
         | 
| 120 120 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 121 121 | 
             
                requirements:
         | 
| 122 | 
            -
                - - ' | 
| 122 | 
            +
                - - '='
         | 
| 123 123 | 
             
                  - !ruby/object:Gem::Version
         | 
| 124 | 
            -
                    version:  | 
| 124 | 
            +
                    version: 2.4.1
         | 
| 125 125 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 126 126 | 
             
              name: pry
         | 
| 127 127 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -248,58 +248,5 @@ rubygems_version: 2.2.2 | |
| 248 248 | 
             
            signing_key: 
         | 
| 249 249 | 
             
            specification_version: 4
         | 
| 250 250 | 
             
            summary: Two factor authentication plugin for devise
         | 
| 251 | 
            -
            test_files:
         | 
| 252 | 
            -
            - spec/controllers/two_factor_auth_spec.rb
         | 
| 253 | 
            -
            - spec/features/two_factor_authenticatable_spec.rb
         | 
| 254 | 
            -
            - spec/lib/two_factor_authentication/models/two_factor_authenticatable_spec.rb
         | 
| 255 | 
            -
            - spec/rails_app/.gitignore
         | 
| 256 | 
            -
            - spec/rails_app/README.md
         | 
| 257 | 
            -
            - spec/rails_app/Rakefile
         | 
| 258 | 
            -
            - spec/rails_app/app/assets/javascripts/application.js
         | 
| 259 | 
            -
            - spec/rails_app/app/assets/stylesheets/application.css
         | 
| 260 | 
            -
            - spec/rails_app/app/controllers/application_controller.rb
         | 
| 261 | 
            -
            - spec/rails_app/app/controllers/home_controller.rb
         | 
| 262 | 
            -
            - spec/rails_app/app/helpers/application_helper.rb
         | 
| 263 | 
            -
            - spec/rails_app/app/mailers/.gitkeep
         | 
| 264 | 
            -
            - spec/rails_app/app/models/.gitkeep
         | 
| 265 | 
            -
            - spec/rails_app/app/models/guest_user.rb
         | 
| 266 | 
            -
            - spec/rails_app/app/models/user.rb
         | 
| 267 | 
            -
            - spec/rails_app/app/views/home/dashboard.html.erb
         | 
| 268 | 
            -
            - spec/rails_app/app/views/home/index.html.erb
         | 
| 269 | 
            -
            - spec/rails_app/app/views/layouts/application.html.erb
         | 
| 270 | 
            -
            - spec/rails_app/config.ru
         | 
| 271 | 
            -
            - spec/rails_app/config/application.rb
         | 
| 272 | 
            -
            - spec/rails_app/config/boot.rb
         | 
| 273 | 
            -
            - spec/rails_app/config/database.yml
         | 
| 274 | 
            -
            - spec/rails_app/config/environment.rb
         | 
| 275 | 
            -
            - spec/rails_app/config/environments/development.rb
         | 
| 276 | 
            -
            - spec/rails_app/config/environments/production.rb
         | 
| 277 | 
            -
            - spec/rails_app/config/environments/test.rb
         | 
| 278 | 
            -
            - spec/rails_app/config/initializers/backtrace_silencers.rb
         | 
| 279 | 
            -
            - spec/rails_app/config/initializers/cookies_serializer.rb
         | 
| 280 | 
            -
            - spec/rails_app/config/initializers/devise.rb
         | 
| 281 | 
            -
            - spec/rails_app/config/initializers/inflections.rb
         | 
| 282 | 
            -
            - spec/rails_app/config/initializers/mime_types.rb
         | 
| 283 | 
            -
            - spec/rails_app/config/initializers/secret_token.rb
         | 
| 284 | 
            -
            - spec/rails_app/config/initializers/session_store.rb
         | 
| 285 | 
            -
            - spec/rails_app/config/initializers/wrap_parameters.rb
         | 
| 286 | 
            -
            - spec/rails_app/config/locales/devise.en.yml
         | 
| 287 | 
            -
            - spec/rails_app/config/locales/en.yml
         | 
| 288 | 
            -
            - spec/rails_app/config/routes.rb
         | 
| 289 | 
            -
            - spec/rails_app/db/migrate/20140403184646_devise_create_users.rb
         | 
| 290 | 
            -
            - spec/rails_app/db/migrate/20140407172619_two_factor_authentication_add_to_users.rb
         | 
| 291 | 
            -
            - spec/rails_app/db/migrate/20140407215513_add_nickanme_to_users.rb
         | 
| 292 | 
            -
            - spec/rails_app/db/schema.rb
         | 
| 293 | 
            -
            - spec/rails_app/lib/assets/.gitkeep
         | 
| 294 | 
            -
            - spec/rails_app/lib/sms_provider.rb
         | 
| 295 | 
            -
            - spec/rails_app/public/404.html
         | 
| 296 | 
            -
            - spec/rails_app/public/422.html
         | 
| 297 | 
            -
            - spec/rails_app/public/500.html
         | 
| 298 | 
            -
            - spec/rails_app/public/favicon.ico
         | 
| 299 | 
            -
            - spec/rails_app/script/rails
         | 
| 300 | 
            -
            - spec/spec_helper.rb
         | 
| 301 | 
            -
            - spec/support/authenticated_model_helper.rb
         | 
| 302 | 
            -
            - spec/support/capybara.rb
         | 
| 303 | 
            -
            - spec/support/features_spec_helper.rb
         | 
| 304 | 
            -
            - spec/support/sms_provider.rb
         | 
| 251 | 
            +
            test_files: []
         | 
| 305 252 | 
             
            has_rdoc: 
         |