Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: CI

on:
push:
pull_request:

permissions:
contents: read

jobs:
test:
name: Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }}
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.rails == 'main' }}
timeout-minutes: 20

strategy:
fail-fast: false
matrix:
include:
- ruby: "2.2"
rails: "4.2"
bundler: "1.17.3"
- ruby: "2.3"
rails: "4.2"
bundler: "1.17.3"
- ruby: "2.4"
rails: "4.2"
bundler: "1.17.3"
- ruby: "2.5"
rails: "4.2"
bundler: "1.17.3"
- ruby: "2.3"
rails: "5.2"
- ruby: "2.4"
rails: "5.2"
- ruby: "2.5"
rails: "5.2"
- ruby: "2.5"
rails: "6.0"
- ruby: "2.7"
rails: "6.0"
- ruby: "2.5"
rails: "6.1"
- ruby: "3.1"
rails: "6.1"
- ruby: "2.7"
rails: "7.0"
- ruby: "3.2"
rails: "7.0"
- ruby: "2.7"
rails: "7.1"
- ruby: "3.3"
rails: "7.1"
- ruby: "3.1"
rails: "7.2"
- ruby: "4.0"
rails: "7.2"
- ruby: "3.2"
rails: "8.0"
- ruby: "4.0"
rails: "8.0"
- ruby: "3.2"
rails: "8.1"
- ruby: "4.0"
rails: "8.1"
- ruby: "4.0"
rails: main

env:
RAILS_VERSION: ${{ matrix.rails }}

steps:
- name: Check out repository
uses: actions/checkout@v7
with:
persist-credentials: false

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler: ${{ matrix.bundler || 'default' }}
bundler-cache: true

- name: Set up test database
run: bundle exec rake app:db:setup

- name: Run specs
run: bundle exec rake spec
28 changes: 0 additions & 28 deletions .travis.yml

This file was deleted.

33 changes: 28 additions & 5 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,45 @@ gemspec
rails_version = ENV["RAILS_VERSION"] || "default"

rails = case rails_version
when "master"
{github: "rails/rails"}
when "main"
{github: "rails/rails", branch: "main"}
when "default"
"~> 5.2"
else
"~> #{rails_version}"
requirement = rails_version.split('.').length == 2 ? "#{rails_version}.0" : rails_version
"~> #{requirement}"
end

gem "rails", rails

if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.2.0')
ruby_version = Gem::Version.new(RUBY_VERSION)

if ruby_version >= Gem::Version.new('2.2.0')
gem "test-unit", "~> 3.0"
end

if ruby_version < Gem::Version.new('2.3.0')
gem 'nokogiri', '~> 1.8.5'
elsif ruby_version < Gem::Version.new('2.5.0')
gem 'nokogiri', '~> 1.10.10'
elsif ruby_version < Gem::Version.new('2.6.0')
gem 'nokogiri', '~> 1.12.5'
end

gem 'loofah', '< 2.21' if ruby_version < Gem::Version.new('2.5.0')
gem 'psych', '< 5' if rails_version == '7.1' && ruby_version < Gem::Version.new('3.0.0')

group :test, :development do
gem 'sqlite3'
gem 'ostruct' if ruby_version >= Gem::Version.new('4.0.0')
case rails_version
when '4.2'
gem 'sqlite3', '~> 1.3.6'
when 'default', '5.2', '6.0', '6.1', '7.0'
gem 'sqlite3', '~> 1.4'
else
gem 'sqlite3'
end
gem 'sprockets-rails'
end

group :test do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def authenticate_totp(code, options = {})
drift_ahead: drift, drift_behind: drift, after: totp_timestamp
)
return false unless new_timestamp
self.totp_timestamp = new_timestamp
self.totp_timestamp = Time.at(new_timestamp).utc
true
end

Expand Down Expand Up @@ -101,7 +101,7 @@ def generate_totp_secret
def create_direct_otp(options = {})
# Create a new random OTP and store it in the database
digits = options[:length] || self.class.direct_otp_length || 6
update_attributes(
update(
direct_otp: random_base10(digits),
direct_otp_sent_at: Time.now.utc
)
Expand All @@ -122,7 +122,7 @@ def direct_otp_expired?
end

def clear_direct_otp
update_attributes(direct_otp: nil, direct_otp_sent_at: nil)
update(direct_otp: nil, direct_otp_sent_at: nil)
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/two_factor_authentication/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ class Mapper
protected

def devise_two_factor_authentication(mapping, controllers)
resource :two_factor_authentication, :only => [:show, :update, :resend_code], :path => mapping.path_names[:two_factor_authentication], :controller => controllers[:two_factor_authentication] do
resource :two_factor_authentication, :only => [:show, :update], :path => mapping.path_names[:two_factor_authentication], :controller => controllers[:two_factor_authentication] do
collection { get "resend_code" }
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
require 'spec_helper'
require 'tmpdir'

require 'generators/active_record/two_factor_authentication_generator'

describe ActiveRecord::Generators::TwoFactorAuthenticationGenerator, type: :generator do
destination File.expand_path('../../../../../tmp', __FILE__)
destination File.join(Dir.tmpdir, 'two_factor_authentication_generator')

before do
prepare_destination
Expand All @@ -23,7 +24,7 @@
describe 'the migration' do
subject { migration_file('db/migrate/two_factor_authentication_add_to_users.rb') }

it { is_expected.to exist }
it { is_expected.to satisfy { |path| File.exist?(path) } }
it { is_expected.to be_a_migration }
it { is_expected.to contain /def change/ }
it { is_expected.to contain /add_column :users, :second_factor_attempts_count, :integer, default: 0/ }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,13 @@ def instance.send_two_factor_authentication_code(code)
end

it "returns uri with user's email" do
expect(instance.provisioning_uri).
to match(%r{otpauth://totp/houdini@example.com\?secret=\w{32}})
uri = URI.parse(instance.provisioning_uri)
params = URI.decode_www_form(uri.query).to_h

expect(uri.scheme).to eq('otpauth')
expect(uri.host).to eq('totp')
expect(URI.decode_www_form_component(uri.path)).to eq('/houdini@example.com')
expect(params['secret']).to match(/\w{32}/)
end

it 'returns uri with issuer option' do
Expand All @@ -147,15 +152,14 @@ def instance.send_two_factor_authentication_code(code)
end

it 'returns uri with issuer option' do
require 'cgi'
uri = URI.parse(instance.provisioning_uri('houdini', issuer: 'Magic'))
params = CGI.parse(uri.query)
params = URI.decode_www_form(uri.query).to_h

expect(uri.scheme).to eq('otpauth')
expect(uri.host).to eq('totp')
expect(uri.path).to eq('/Magic:houdini')
expect(params['issuer'].shift).to eq('Magic')
expect(params['secret'].shift).to match(/\w{32}/)
expect(URI.decode_www_form_component(uri.path)).to eq('/Magic:houdini')
expect(params['issuer']).to eq('Magic')
expect(params['secret']).to match(/\w{32}/)
end
end
end
Expand Down
2 changes: 2 additions & 0 deletions spec/rails_app/app/assets/config/manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
2 changes: 1 addition & 1 deletion spec/rails_app/app/models/guest_user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class GuestUser
attr_accessor :direct_otp, :direct_otp_sent_at, :otp_secret_key, :email,
:second_factor_attempts_count, :totp_timestamp

def update_attributes(attrs)
def update(attrs)
attrs.each do |key, value|
send(key.to_s + '=', value)
end
Expand Down
2 changes: 1 addition & 1 deletion spec/rails_app/config/application.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'logger'
require File.expand_path('../boot', __FILE__)

require "active_record/railtie"
Expand Down Expand Up @@ -60,4 +61,3 @@ class Application < Rails::Application
config.secret_key_base = 'secretvalue'
end
end

4 changes: 4 additions & 0 deletions spec/rails_app/config/initializers/inflections.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@
# ActiveSupport::Inflector.inflections do |inflect|
# inflect.acronym 'RESTful'
# end

ActiveSupport::Inflector.inflections do |inflect|
inflect.acronym 'SMS'
end
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
ENV["RAILS_ENV"] ||= "test"
require File.expand_path("../rails_app/config/environment.rb", __FILE__)
require File.expand_path("../rails_app/lib/sms_provider.rb", __FILE__)

require 'rspec/rails'
require 'timecop'
Expand Down
2 changes: 1 addition & 1 deletion two_factor_authentication.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Gem::Specification.new do |s|
s.add_development_dependency 'bundler'
s.add_development_dependency 'rake'
s.add_development_dependency 'rspec-rails', '>= 3.0.1'
s.add_development_dependency 'capybara', '~> 2.5'
s.add_development_dependency 'capybara', '>= 2.5', '< 4'
s.add_development_dependency 'pry'
s.add_development_dependency 'timecop'
end