authenticate 0.1.0
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 +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +21 -0
- data/Gemfile.lock +154 -0
- data/LICENSE +20 -0
- data/README.md +240 -0
- data/Rakefile +6 -0
- data/app/assets/config/authenticate_manifest.js +0 -0
- data/app/assets/images/authenticate/.keep +0 -0
- data/app/assets/javascripts/authenticate/.keep +0 -0
- data/app/assets/stylesheets/authenticate/.keep +0 -0
- data/app/controllers/.keep +0 -0
- data/app/helpers/.keep +0 -0
- data/app/mailers/.keep +0 -0
- data/app/models/.keep +0 -0
- data/app/views/.keep +0 -0
- data/authenticate.gemspec +38 -0
- data/bin/rails +12 -0
- data/config/routes.rb +2 -0
- data/lib/authenticate.rb +12 -0
- data/lib/authenticate/callbacks/authenticatable.rb +4 -0
- data/lib/authenticate/callbacks/brute_force.rb +31 -0
- data/lib/authenticate/callbacks/lifetimed.rb +5 -0
- data/lib/authenticate/callbacks/timeoutable.rb +15 -0
- data/lib/authenticate/callbacks/trackable.rb +8 -0
- data/lib/authenticate/configuration.rb +144 -0
- data/lib/authenticate/controller.rb +110 -0
- data/lib/authenticate/crypto/bcrypt.rb +30 -0
- data/lib/authenticate/debug.rb +10 -0
- data/lib/authenticate/engine.rb +21 -0
- data/lib/authenticate/lifecycle.rb +120 -0
- data/lib/authenticate/login_status.rb +27 -0
- data/lib/authenticate/model/brute_force.rb +51 -0
- data/lib/authenticate/model/db_password.rb +71 -0
- data/lib/authenticate/model/email.rb +76 -0
- data/lib/authenticate/model/lifetimed.rb +48 -0
- data/lib/authenticate/model/timeoutable.rb +47 -0
- data/lib/authenticate/model/trackable.rb +43 -0
- data/lib/authenticate/model/username.rb +45 -0
- data/lib/authenticate/modules.rb +61 -0
- data/lib/authenticate/session.rb +123 -0
- data/lib/authenticate/token.rb +7 -0
- data/lib/authenticate/user.rb +50 -0
- data/lib/authenticate/version.rb +3 -0
- data/lib/tasks/authenticate_tasks.rake +4 -0
- data/spec/configuration_spec.rb +60 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/models/user.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +26 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/authenticate.rb +7 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +56 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20160120003910_create_users.rb +18 -0
- data/spec/dummy/db/schema.rb +31 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/users.rb +23 -0
- data/spec/model/session_spec.rb +86 -0
- data/spec/model/token_spec.rb +11 -0
- data/spec/model/user_spec.rb +12 -0
- data/spec/orm/active_record.rb +17 -0
- data/spec/spec_helper.rb +148 -0
- metadata +255 -0
data/Rakefile
ADDED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/app/helpers/.keep
ADDED
File without changes
|
data/app/mailers/.keep
ADDED
File without changes
|
data/app/models/.keep
ADDED
File without changes
|
data/app/views/.keep
ADDED
File without changes
|
@@ -0,0 +1,38 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
2
|
+
# $:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
require 'authenticate/version'
|
5
|
+
require 'date'
|
6
|
+
|
7
|
+
# Describe your gem and declare its dependencies:
|
8
|
+
Gem::Specification.new do |s|
|
9
|
+
s.name = 'authenticate'
|
10
|
+
s.version = Authenticate::VERSION
|
11
|
+
s.authors = ['Justin Tomich']
|
12
|
+
s.email = ['justin@tomich.org']
|
13
|
+
s.homepage = 'http://github.com/tomichj/authenticate'
|
14
|
+
s.summary = 'Rails authentication with email & password'
|
15
|
+
s.description = 'Rails authentication with email & password'
|
16
|
+
s.license = 'MIT'
|
17
|
+
|
18
|
+
# s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
# s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
21
|
+
s.test_files = Dir['spec/**/*_spec.rb']
|
22
|
+
|
23
|
+
s.extra_rdoc_files = %w(LICENSE README.md)
|
24
|
+
s.rdoc_options = ['--charset=UTF-8']
|
25
|
+
|
26
|
+
s.require_paths = ['lib']
|
27
|
+
|
28
|
+
s.add_dependency 'bcrypt'
|
29
|
+
s.add_dependency 'email_validator', '~> 1.6'
|
30
|
+
s.add_dependency 'rails', '>= 4.0', '< 5.1'
|
31
|
+
s.add_development_dependency 'sqlite3'
|
32
|
+
s.add_development_dependency 'rspec'
|
33
|
+
s.add_development_dependency 'rspec-rails'
|
34
|
+
# s.add_development_dependency 'capybara'
|
35
|
+
s.add_development_dependency 'factory_girl_rails'
|
36
|
+
|
37
|
+
s.required_ruby_version = Gem::Requirement.new('>= 2.0')
|
38
|
+
end
|
data/bin/rails
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
|
3
|
+
|
4
|
+
ENGINE_ROOT = File.expand_path('../..', __FILE__)
|
5
|
+
ENGINE_PATH = File.expand_path('../../lib/authenticate/engine', __FILE__)
|
6
|
+
|
7
|
+
# Set up gems listed in the Gemfile.
|
8
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
9
|
+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
10
|
+
|
11
|
+
require 'rails/all'
|
12
|
+
require 'rails/engine/commands'
|
data/config/routes.rb
ADDED
data/lib/authenticate.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'authenticate/debug'
|
2
|
+
require 'authenticate/configuration'
|
3
|
+
require 'authenticate/lifecycle'
|
4
|
+
require 'authenticate/controller'
|
5
|
+
require 'authenticate/session'
|
6
|
+
require 'authenticate/user'
|
7
|
+
require 'authenticate/engine'
|
8
|
+
require 'authenticate/modules'
|
9
|
+
|
10
|
+
module Authenticate
|
11
|
+
# Your code goes here...
|
12
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Prevents a locked user from logging in, and unlocks users that expired their lock time.
|
2
|
+
# Runs as a hook after authentication.
|
3
|
+
Authenticate.lifecycle.prepend_after_authentication name: 'brute force protection' do |user, session, options|
|
4
|
+
include ActionView::Helpers::DateHelper
|
5
|
+
|
6
|
+
# puts 'bf: about to check authentication'
|
7
|
+
unless session.authenticated?
|
8
|
+
# puts 'bf: session not authenticated'
|
9
|
+
|
10
|
+
user_credentials = User.credentials(session.request.params)
|
11
|
+
# puts "brute force protection user_credentials: #{user_credentials}"
|
12
|
+
user ||= User.find_by_credentials(user_credentials)
|
13
|
+
|
14
|
+
# puts 'bf: looked up user by credentials, found:' + user.inspect
|
15
|
+
if user
|
16
|
+
# puts 'found user, about to register failed attempt'
|
17
|
+
user.register_failed_login!
|
18
|
+
user.save!
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
if user && user.locked? && Authenticate.configuration.bad_login_lockout_period != nil
|
23
|
+
user.unlock! if user.lock_expires_at <= Time.now.utc
|
24
|
+
end
|
25
|
+
|
26
|
+
if user && user.locked?
|
27
|
+
remaining = time_ago_in_words(user.lock_expires_at)
|
28
|
+
throw(:failure, "Your account is locked, will unlock in #{remaining.to_s}")
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
Authenticate.lifecycle.after_set_user name: 'lifetimed after set_user', except: :authentication do |user, session, options|
|
2
|
+
if user && user.respond_to?(:max_session_timedout?)
|
3
|
+
throw(:failure, "Your session has reached it's maximum allowed lifetime, you must log in again") if user.max_session_timedout?
|
4
|
+
end
|
5
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Authenticate.lifecycle.after_authentication name: 'timeoutable after authentication' do |user, session, options|
|
2
|
+
if user && user.respond_to?(:last_access_at)
|
3
|
+
user.last_access_at = Time.now.utc
|
4
|
+
user.save!
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
Authenticate.lifecycle.after_set_user name: 'timeoutable after set_user', except: :authentication do |user, session, options|
|
9
|
+
puts "user.respond_to?(:timedout?) #{user.respond_to?(:timedout?).inspect}" if user
|
10
|
+
if user && user.respond_to?(:timedout?)
|
11
|
+
throw(:failure, 'Your session has expired') if user.timedout?
|
12
|
+
user.last_access_at = Time.now.utc
|
13
|
+
user.save!
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# After each sign in: ”update sign in time, sign in count and sign in IP.
|
2
|
+
# This is only triggered when the user is explicitly set (with set_user)
|
3
|
+
# and on authentication.
|
4
|
+
Authenticate.lifecycle.after_authentication name: 'trackable' do |user, session, options|
|
5
|
+
if user.respond_to?(:update_tracked_fields!)
|
6
|
+
user.update_tracked_fields!(session.request)
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
module Authenticate
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
# ActiveRecord model class name that represents your user.
|
5
|
+
# Specify as a String. Defaults to '::User'.
|
6
|
+
# To set to a different class:
|
7
|
+
#
|
8
|
+
# Authenticate.configure do |config|
|
9
|
+
# config.user_model = 'BlogUser'
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
attr_accessor :user_model
|
14
|
+
|
15
|
+
# Name of the session cookie Authenticate will send to client browser.
|
16
|
+
# Defaults to 'authenticate_session_token'.
|
17
|
+
# @return [String]
|
18
|
+
attr_accessor :cookie_name
|
19
|
+
|
20
|
+
# A lambda called to set the remember token cookie expires attribute. Defaults to 1 year expiration.
|
21
|
+
# Note this is NOT the session's max lifetime, see #max_session_lifetime.
|
22
|
+
# To set cookie expiration yourself:
|
23
|
+
#
|
24
|
+
# Authenticate.configure do |config|
|
25
|
+
# config.cookie_expiration = { 1.month.from_now.utc }
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @return [Lambda]
|
29
|
+
attr_accessor :cookie_expiration
|
30
|
+
|
31
|
+
# The domain to set for the Authenticate session cookie.
|
32
|
+
# Defaults to nil, which will cause the cookie domain to set
|
33
|
+
# to the domain of the request.
|
34
|
+
# @return [String]
|
35
|
+
attr_accessor :cookie_domain
|
36
|
+
|
37
|
+
# Crypto used when authenticating and setting passwords.
|
38
|
+
# Defaults to {Authenticate::Model::BCrypt}.
|
39
|
+
# Crypto implementations must provide:
|
40
|
+
# * match?(secret, encrypted)
|
41
|
+
# * encrypt(secret)
|
42
|
+
#
|
43
|
+
# @return [Module #match? #encrypt]
|
44
|
+
attr_accessor :crypto_provider
|
45
|
+
|
46
|
+
# Invalidate the session after the specified period of idle time.
|
47
|
+
# Defaults to nil, which is no idle timeout.
|
48
|
+
#
|
49
|
+
# Authenticate.configure do |config|
|
50
|
+
# config.timeout_in = 45.minutes
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# @return [ActiveSupport::CoreExtensions::Numeric::Time]
|
54
|
+
attr_accessor :timeout_in
|
55
|
+
|
56
|
+
# Allow a session to 'live' for no more than the given elapsed time, e.g. 8.hours.
|
57
|
+
# Defaults to nil, or no max session time.
|
58
|
+
# @return [ActiveSupport::CoreExtensions::Numeric::Time]
|
59
|
+
attr_accessor :max_session_lifetime
|
60
|
+
|
61
|
+
# Number of consecutive bad login attempts allowed.
|
62
|
+
# Default is nil, which disables this feature.
|
63
|
+
# @return [Integer]
|
64
|
+
attr_accessor :max_consecutive_bad_logins_allowed
|
65
|
+
|
66
|
+
# Time period to lock an account for if the user exceeds
|
67
|
+
# max_consecutive_bad_logins_allowed (and it's set to nonzero).
|
68
|
+
# If set to nil, account is locked out indefinitely.
|
69
|
+
# @return [ActiveSupport::CoreExtensions::Numeric::Time]
|
70
|
+
attr_accessor :bad_login_lockout_period
|
71
|
+
|
72
|
+
# Strategy for authentication.
|
73
|
+
#
|
74
|
+
# Available strategies:
|
75
|
+
# :email - requires user have attribute :email
|
76
|
+
# :username - requires user have attribute :username
|
77
|
+
# Defaults to :email. To set to :username:
|
78
|
+
# Configuration.configure do |config|
|
79
|
+
# config.authentication_strategy = :username
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# Or, you can plug in your own authentication class, eg:
|
83
|
+
# Configuration.configure do |config|
|
84
|
+
# config.authentication_strategy = MyFunkyAuthClass
|
85
|
+
# end
|
86
|
+
# @return [Symbol or Class]
|
87
|
+
attr_accessor :authentication_strategy
|
88
|
+
|
89
|
+
|
90
|
+
# Enable debugging messages.
|
91
|
+
# @private
|
92
|
+
# @return [Boolean]
|
93
|
+
attr_accessor :debug
|
94
|
+
|
95
|
+
# An array of additional modules to load into the User module.
|
96
|
+
# Defaults to an empty array.
|
97
|
+
# @return [Array]
|
98
|
+
attr_accessor :modules
|
99
|
+
|
100
|
+
|
101
|
+
def initialize
|
102
|
+
# Defaults
|
103
|
+
@debug = false
|
104
|
+
@cookie_name = 'authenticate_session_token'
|
105
|
+
@cookie_expiration = -> { 1.year.from_now.utc }
|
106
|
+
@modules = []
|
107
|
+
@user_model = '::User'
|
108
|
+
@authentication_strategy = :email
|
109
|
+
end
|
110
|
+
|
111
|
+
def user_model_class
|
112
|
+
@user_model_class ||= user_model.constantize
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
# List of symbols naming modules to load.
|
117
|
+
def modules
|
118
|
+
modules = @modules.dup # in case the user pushes any on
|
119
|
+
modules << @authentication_strategy
|
120
|
+
modules << :db_password
|
121
|
+
modules << :trackable # needs configuration
|
122
|
+
modules << :timeoutable if @timeout_in
|
123
|
+
modules << :lifetimed if @max_session_lifetime
|
124
|
+
modules << :brute_force if @max_consecutive_bad_logins_allowed
|
125
|
+
modules
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
end # end of Configuration class
|
130
|
+
|
131
|
+
|
132
|
+
def self.configuration
|
133
|
+
@configuration ||= Configuration.new
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.configuration=(config)
|
137
|
+
@configuration = config
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.configure
|
141
|
+
yield configuration
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Authenticate
|
2
|
+
module Controller
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
include Debug
|
5
|
+
|
6
|
+
included do
|
7
|
+
helper_method :current_user, :authenticated?
|
8
|
+
attr_writer :authenticate_session
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
# Validate a user's identity with (typically) email/ID & password, and return the User if valid, or nil.
|
13
|
+
# After calling this, call login(user) to complete the process.
|
14
|
+
def authenticate(params)
|
15
|
+
# todo: get params from User model
|
16
|
+
user_credentials = Authenticate.configuration.user_model_class.credentials(params)
|
17
|
+
puts "Controller::user_credentials: #{user_credentials.inspect}"
|
18
|
+
Authenticate.configuration.user_model_class.authenticate(user_credentials)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
# Complete the user's sign in process: after calling authenticate, or after user creates account.
|
23
|
+
# Runs all valid callbacks and sends the user a session token.
|
24
|
+
def login(user, &block)
|
25
|
+
authenticate_session.login user, &block
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
# Log the user out. Typically used in session controller.
|
30
|
+
#
|
31
|
+
# class SessionsController < ActionController::Base
|
32
|
+
# include Authenticate::Controller
|
33
|
+
#
|
34
|
+
# def destroy
|
35
|
+
# logout
|
36
|
+
# redirect_to '/', notice: 'You logged out successfully'
|
37
|
+
# end
|
38
|
+
def logout
|
39
|
+
authenticate_session.deauthenticate
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
# Use this as a before_action to restrict controller actions to authenticated users.
|
44
|
+
# Consider using in application_controller to restrict access to all controllers.
|
45
|
+
#
|
46
|
+
# Example:
|
47
|
+
#
|
48
|
+
# class ApplicationController < ActionController::Base
|
49
|
+
# before_action :require_authentication
|
50
|
+
#
|
51
|
+
# def index
|
52
|
+
# # ...
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
def require_authentication
|
57
|
+
d 'Controller::require_authentication'
|
58
|
+
unless authenticated?
|
59
|
+
unauthorized
|
60
|
+
end
|
61
|
+
|
62
|
+
message = catch(:failure) do
|
63
|
+
current_user = authenticate_session.current_user
|
64
|
+
Authenticate.lifecycle.run_callbacks(:after_set_user, current_user, authenticate_session, {event: :set_user })
|
65
|
+
end
|
66
|
+
unauthorized(message) if message
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# Has the user been logged in? Exposed as a helper, can be called from views.
|
71
|
+
#
|
72
|
+
# <% if authenticated? %>
|
73
|
+
# <%= link_to logout_path, "Sign out" %>
|
74
|
+
# <% else %>
|
75
|
+
# <%= link_to login_path, "Sign in" %>
|
76
|
+
# <% end %>
|
77
|
+
#
|
78
|
+
def authenticated?
|
79
|
+
authenticate_session.authenticated?
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# Get the current user from the current Authenticate session.
|
84
|
+
# Exposed as a helper , can be called from controllers, views, and other helpers.
|
85
|
+
#
|
86
|
+
# <p>Your email address: <%= current_user.email %></p>
|
87
|
+
#
|
88
|
+
def current_user
|
89
|
+
authenticate_session.current_user
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def authenticate_session
|
95
|
+
@authenticate_session ||= Authenticate::Session.new(request, cookies)
|
96
|
+
end
|
97
|
+
|
98
|
+
def unauthorized(msg = 'You must sign in')
|
99
|
+
respond_to do |format|
|
100
|
+
format.any(:js, :json, :xml) { head :unauthorized }
|
101
|
+
format.any {
|
102
|
+
flash[:notice] = msg # TODO use locales
|
103
|
+
redirect_to '/authenticate' #TODO something better baby
|
104
|
+
}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Authenticate
|
2
|
+
module Crypto
|
3
|
+
|
4
|
+
# All crypto providers must implement encrypt(secret) and match?(secret, encrypted)
|
5
|
+
module BCrypt
|
6
|
+
require 'bcrypt'
|
7
|
+
|
8
|
+
def encrypt(secret)
|
9
|
+
::BCrypt::Password.create secret, cost: cost
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?(secret, encrypted)
|
13
|
+
return false unless encrypted.present?
|
14
|
+
::BCrypt::Password.new(encrypted) == secret
|
15
|
+
end
|
16
|
+
|
17
|
+
def cost
|
18
|
+
@cost ||= ::BCrypt::Engine::DEFAULT_COST
|
19
|
+
end
|
20
|
+
|
21
|
+
def cost=(val)
|
22
|
+
if val < ::BCrypt::Engine::MIN_COST
|
23
|
+
raise ArgumentError.new("bcrypt cost cannot be set below the engine's min cost (#{::BCrypt::Engine::MIN_COST})")
|
24
|
+
end
|
25
|
+
@cost = val
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|