minimalist_authentication 0.6.14 → 1.0.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 +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +56 -52
- data/Rakefile +27 -26
- data/{test/rails_root/lib/tasks/.gitkeep → app/assets/config/minimalist_authentication_manifest.js} +0 -0
- data/app/views/sessions/_form.html.erb +5 -0
- data/app/views/sessions/new.html.erb +1 -0
- data/config/routes.rb +2 -0
- data/lib/minimalist/authentication.rb +69 -79
- data/lib/minimalist/authorization.rb +30 -35
- data/lib/minimalist/sessions.rb +45 -49
- data/lib/minimalist/test_helper.rb +5 -5
- data/lib/minimalist_authentication.rb +3 -1
- data/lib/minimalist_authentication/engine.rb +4 -0
- data/lib/{minimalist → minimalist_authentication}/version.rb +1 -1
- metadata +24 -128
- data/.gitignore +0 -6
- data/Gemfile +0 -2
- data/Gemfile.lock +0 -101
- data/lib/app/views/sessions/_form.html.erb +0 -12
- data/lib/app/views/sessions/new.html.erb +0 -1
- data/minimalist_authentication.gemspec +0 -23
- data/test/.gitignore +0 -1
- data/test/authentication_test.rb +0 -103
- data/test/authorization_test.rb +0 -77
- data/test/factories.rb +0 -12
- data/test/jenkins.bash +0 -9
- data/test/rails_root/README +0 -256
- data/test/rails_root/Rakefile +0 -7
- data/test/rails_root/app/controllers/application_controller.rb +0 -5
- data/test/rails_root/app/controllers/sessions_controller.rb +0 -3
- data/test/rails_root/app/helpers/application_helper.rb +0 -2
- data/test/rails_root/app/models/user.rb +0 -4
- data/test/rails_root/app/views/layouts/application.html.erb +0 -14
- data/test/rails_root/config.ru +0 -4
- data/test/rails_root/config/application.rb +0 -42
- data/test/rails_root/config/boot.rb +0 -13
- data/test/rails_root/config/database.yml +0 -22
- data/test/rails_root/config/environment.rb +0 -5
- data/test/rails_root/config/environments/development.rb +0 -26
- data/test/rails_root/config/environments/production.rb +0 -49
- data/test/rails_root/config/environments/test.rb +0 -35
- data/test/rails_root/config/initializers/backtrace_silencers.rb +0 -7
- data/test/rails_root/config/initializers/inflections.rb +0 -10
- data/test/rails_root/config/initializers/mime_types.rb +0 -5
- data/test/rails_root/config/initializers/secret_token.rb +0 -7
- data/test/rails_root/config/initializers/session_store.rb +0 -8
- data/test/rails_root/config/locales/en.yml +0 -5
- data/test/rails_root/config/routes.rb +0 -5
- data/test/rails_root/db/.gitignore +0 -2
- data/test/rails_root/db/schema.rb +0 -21
- data/test/rails_root/db/seeds.rb +0 -7
- data/test/rails_root/doc/README_FOR_APP +0 -2
- data/test/rails_root/log/.gitignore +0 -1
- data/test/rails_root/log/.gitkeep +0 -0
- data/test/rails_root/script/rails +0 -6
- data/test/rails_root/test/performance/browsing_test.rb +0 -9
- data/test/rails_root/test/test_helper.rb +0 -13
- data/test/sessions_test.rb +0 -30
- data/test/test_helper.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d020d82d864706eb3048098a397f68a6dd1cbf7
|
4
|
+
data.tar.gz: 0ebabb35dda1683be51aff8132a84fbb851f1da7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb9ec1fde1bbf9d5ba15778b0b52b906b67cf2a76e5a5c44ed1159d72377b2fc313f81bde6d54423e4229111b14927ac3e7ef695dd0fc5c21b2631b0f4663a2a
|
7
|
+
data.tar.gz: 82e0db4943b2b1e4b8e0fe4320876079a5a38609a0add94598bc01f4d68e101560cf1e5569814076aa62918461374068c8ad5531cf3eb87dcd3e57f4d80bb893
|
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright
|
1
|
+
Copyright 2009-2017 Brightways Learning https://www.brightwayslearning.org
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
data/README.md
CHANGED
@@ -1,55 +1,59 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
MinimalistAuthentication
|
4
|
-
========================
|
5
|
-
|
1
|
+
# MinimalistAuthentication
|
6
2
|
A Rails authentication gem that takes a minimalist approach. It is designed to be simple to understand, use, and modify for your application.
|
7
3
|
|
8
|
-
This gem was largely inspired by the restful-authentication plugin (http://github.com/technoweenie/restful-authentication/tree/master). I selected the essential methods for password based authentication, reorganized them, trimmed them down when possible, added a couple of features, and resisted the urge to start adding more.
|
9
|
-
|
10
|
-
|
11
|
-
Installation
|
12
|
-
============
|
13
|
-
1) Add to your Gemfile:
|
14
|
-
|
15
|
-
gem 'minimalist_authentication'
|
16
|
-
|
17
|
-
2) Create a user model:
|
18
|
-
|
19
|
-
bin/rails generate model user active:boolean email:string crypted_password:string salt:string using_digest_version:integer last_logged_in_at:datetime
|
20
|
-
|
21
|
-
|
22
|
-
Example
|
23
|
-
=======
|
24
|
-
|
25
|
-
1) app/models/user.rb
|
26
|
-
|
27
|
-
class User < ActiveRecord::Base
|
28
|
-
include Minimalist::Authentication
|
29
|
-
end
|
30
|
-
|
31
|
-
2) app/controllers/application.rb
|
32
|
-
|
33
|
-
class ApplicationController < ActionController::Base
|
34
|
-
include Minimalist::Authorization
|
35
|
-
|
36
|
-
# Lock down everything by default
|
37
|
-
# use skip_before_filter to open up sepecific actions
|
38
|
-
prepend_before_filter :authorization_required
|
39
|
-
end
|
40
|
-
|
41
|
-
3) app/controllers/sessions_controller.rb
|
42
|
-
|
43
|
-
class SessionsController < ApplicationController
|
44
|
-
include Minimalist::Sessions
|
45
|
-
skip_before_filter :authorization_required, only: [:new, :create]
|
46
|
-
end
|
47
|
-
|
48
|
-
4) test/test_helper.rb
|
49
|
-
|
50
|
-
class ActiveSupport::TestCase
|
51
|
-
include Minimalist::TestHelper
|
52
|
-
end
|
53
|
-
|
54
4
|
|
55
|
-
|
5
|
+
## Installation
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'minimalist_authentication'
|
10
|
+
```
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
```bash
|
14
|
+
$ bundle
|
15
|
+
```
|
16
|
+
|
17
|
+
Create a user model:
|
18
|
+
```bash
|
19
|
+
bin/rails generate model user active:boolean email:string crypted_password:string salt:string using_digest_version:integer last_logged_in_at:datetime
|
20
|
+
```
|
21
|
+
|
22
|
+
|
23
|
+
## Example
|
24
|
+
Include Minimalist::Authentication in your user model (app/models/user.rb)
|
25
|
+
```ruby
|
26
|
+
class User < ApplicationRecord
|
27
|
+
include Minimalist::Authentication
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
Include Minimalist::Authorization in your ApplicationController (app/controllers/application.rb)
|
32
|
+
```ruby
|
33
|
+
class ApplicationController < ActionController::Base
|
34
|
+
include Minimalist::Authorization
|
35
|
+
|
36
|
+
# Lock down everything by default
|
37
|
+
# use skip_before_action to open up specific actions
|
38
|
+
before_action :authorization_required
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
Include Minimalist::Sessions in your SessionsController (app/controllers/sessions_controller.rb)
|
43
|
+
```ruby
|
44
|
+
class SessionsController < ApplicationController
|
45
|
+
include Minimalist::Sessions
|
46
|
+
skip_before_action :authorization_required, only: %i(new create)
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
Include Minimalist::TestHelper in your test helper (test/test_helper.rb)
|
51
|
+
```ruby
|
52
|
+
class ActiveSupport::TestCase
|
53
|
+
include Minimalist::TestHelper
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
|
58
|
+
## License
|
59
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,35 +1,36 @@
|
|
1
|
-
|
2
|
-
require '
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
3
7
|
require 'rdoc/task'
|
4
8
|
|
5
|
-
|
6
|
-
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'MinimalistAuthentication'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
load 'rails/tasks/statistics.rake'
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
require 'bundler/gem_tasks'
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
7
28
|
|
8
|
-
desc 'Test the minimalist_authentication plugin.'
|
9
29
|
Rake::TestTask.new(:test) do |t|
|
10
|
-
t.libs << 'lib'
|
11
30
|
t.libs << 'test'
|
12
31
|
t.pattern = 'test/**/*_test.rb'
|
13
|
-
t.verbose =
|
32
|
+
t.verbose = false
|
14
33
|
end
|
15
34
|
|
16
|
-
desc 'Generate documentation for the minimalist_authentication plugin.'
|
17
|
-
Rake::RDocTask.new(:rdoc) do |rdoc|
|
18
|
-
rdoc.rdoc_dir = 'rdoc'
|
19
|
-
rdoc.title = 'MinimalistAuthentication'
|
20
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
-
rdoc.rdoc_files.include('README')
|
22
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
-
end
|
24
35
|
|
25
|
-
|
26
|
-
task :rcov do
|
27
|
-
rm_f "coverage"
|
28
|
-
rcov = "rcov --rails --text-summary -Ilib --exclude /gems/,/app/,/Library/"
|
29
|
-
system("#{rcov} --html #{Dir.glob('test/**/*_test.rb').join(' ')}")
|
30
|
-
if PLATFORM['darwin'] #Mac
|
31
|
-
system("open coverage/index.html")
|
32
|
-
elsif PLATFORM[/linux/] #Ubuntu, etc.
|
33
|
-
system("/etc/alternatives/x-www-browser coverage/index.html")
|
34
|
-
end
|
35
|
-
end
|
36
|
+
task default: :test
|
data/{test/rails_root/lib/tasks/.gitkeep → app/assets/config/minimalist_authentication_manifest.js}
RENAMED
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render partial: 'form' %>
|
data/config/routes.rb
ADDED
@@ -3,33 +3,29 @@ require 'bcrypt'
|
|
3
3
|
|
4
4
|
module Minimalist
|
5
5
|
module Authentication
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
6
8
|
GUEST_USER_EMAIL = 'guest'
|
7
9
|
PREFERRED_DIGEST_VERSION = 3
|
8
10
|
|
9
11
|
# Recalibrates cost when class is loaded so that new user passwords
|
10
12
|
# can automatically take advantage of faster server hardware in the
|
11
13
|
# future for better encryption.
|
12
|
-
|
14
|
+
# sets cost to BCrypt::Engine::MIN_COST in the test environment
|
15
|
+
CALIBRATED_BCRYPT_COST = (::Rails.env.test? ? BCrypt::Engine::MIN_COST : BCrypt::Engine.calibrate(750))
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
include InstanceMethods
|
17
|
+
included do
|
18
|
+
attr_accessor :password
|
19
|
+
before_save :encrypt_password
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
+
validates_presence_of :email, if: :validate_email_presence?
|
22
|
+
validates_uniqueness_of :email, allow_blank: true, if: :validate_email_uniqueness?
|
23
|
+
validates_format_of :email, allow_blank: true, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, if: :validate_email_format?
|
24
|
+
validates_presence_of :password, if: :password_required?
|
25
|
+
validates_confirmation_of :password, if: :password_required?
|
26
|
+
validates_length_of :password, within: 6..40, if: :password_required?
|
21
27
|
|
22
|
-
|
23
|
-
validates_uniqueness_of :email, allow_blank: true, if: :validate_email_uniqueness?
|
24
|
-
validates_format_of :email, allow_blank: true, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, if: :validate_email_format?
|
25
|
-
validates_presence_of :password, if: :password_required?
|
26
|
-
validates_confirmation_of :password, if: :password_required?
|
27
|
-
validates_length_of :password, within: 6..40, if: :password_required?
|
28
|
-
|
29
|
-
scope :active, ->(active = true) { where active: active }
|
30
|
-
|
31
|
-
|
32
|
-
end
|
28
|
+
scope :active, ->(active = true) { where active: active }
|
33
29
|
end
|
34
30
|
|
35
31
|
module ClassMethods
|
@@ -40,7 +36,7 @@ module Minimalist
|
|
40
36
|
return user
|
41
37
|
end
|
42
38
|
|
43
|
-
def secure_digest(string, salt, version =
|
39
|
+
def secure_digest(string, salt, version = PREFERRED_DIGEST_VERSION)
|
44
40
|
case version
|
45
41
|
when 0 then Digest::MD5.hexdigest(string.to_s)
|
46
42
|
when 1 then Digest::SHA1.hexdigest("#{string}--#{salt}")
|
@@ -54,84 +50,78 @@ module Minimalist
|
|
54
50
|
end
|
55
51
|
|
56
52
|
def guest
|
57
|
-
new
|
58
|
-
user.email = GUEST_USER_EMAIL
|
59
|
-
end
|
53
|
+
new(email: GUEST_USER_EMAIL)
|
60
54
|
end
|
61
55
|
end
|
62
56
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
active
|
67
|
-
end
|
57
|
+
def active?
|
58
|
+
active
|
59
|
+
end
|
68
60
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
77
|
-
return true
|
78
|
-
else
|
79
|
-
return false
|
61
|
+
def authenticated?(password)
|
62
|
+
if crypted_password == encrypt(password)
|
63
|
+
if self.respond_to?(:using_digest_version) && (using_digest_version != PREFERRED_DIGEST_VERSION || salt_cost < CALIBRATED_BCRYPT_COST)
|
64
|
+
new_salt = self.class.make_token
|
65
|
+
self.update_attribute(:crypted_password, self.class.secure_digest(password, new_salt))
|
66
|
+
self.update_attribute(:salt, new_salt)
|
67
|
+
self.update_attribute(:using_digest_version, PREFERRED_DIGEST_VERSION)
|
80
68
|
end
|
69
|
+
return true
|
70
|
+
else
|
71
|
+
return false
|
81
72
|
end
|
73
|
+
end
|
82
74
|
|
83
|
-
|
84
|
-
|
85
|
-
|
75
|
+
def logged_in
|
76
|
+
update_column(:last_logged_in_at, Time.current) # use update_column to avoid updated_on trigger
|
77
|
+
end
|
86
78
|
|
87
|
-
|
88
|
-
|
89
|
-
|
79
|
+
def is_guest?
|
80
|
+
email == GUEST_USER_EMAIL
|
81
|
+
end
|
90
82
|
|
91
|
-
#######
|
92
|
-
private
|
93
|
-
#######
|
94
83
|
|
95
|
-
|
96
|
-
active? && (crypted_password.blank? || !password.blank?)
|
97
|
-
end
|
84
|
+
private
|
98
85
|
|
99
|
-
|
100
|
-
|
101
|
-
|
86
|
+
def password_required?
|
87
|
+
active? && (crypted_password.blank? || !password.blank?)
|
88
|
+
end
|
102
89
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
self.crypted_password = self.class.secure_digest(password, salt, (self.respond_to?(:using_digest_version) ? PREFERRED_DIGEST_VERSION : 1))
|
107
|
-
self.using_digest_version = PREFERRED_DIGEST_VERSION if self.respond_to?(:using_digest_version)
|
108
|
-
end
|
90
|
+
def encrypt(password)
|
91
|
+
self.class.secure_digest(password, salt, digest_version)
|
92
|
+
end
|
109
93
|
|
110
|
-
|
111
|
-
|
112
|
-
|
94
|
+
def encrypt_password
|
95
|
+
return if password.blank?
|
96
|
+
self.salt = self.class.make_token
|
97
|
+
self.crypted_password = self.class.secure_digest(password, salt)
|
98
|
+
self.using_digest_version = PREFERRED_DIGEST_VERSION if self.respond_to?(:using_digest_version)
|
99
|
+
end
|
113
100
|
|
114
|
-
|
115
|
-
|
116
|
-
|
101
|
+
def digest_version
|
102
|
+
self.respond_to?(:using_digest_version) ? (using_digest_version || 1) : 1
|
103
|
+
end
|
117
104
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
true
|
122
|
-
end
|
105
|
+
def salt_cost
|
106
|
+
BCrypt::Engine.valid_salt?(salt) ? salt.match(/\$[^\$]+\$([0-9]+)\$/)[1].to_i : 0
|
107
|
+
end
|
123
108
|
|
124
|
-
|
125
|
-
|
126
|
-
|
109
|
+
# email validation
|
110
|
+
def validate_email?
|
111
|
+
# allows applications to turn off email validation
|
112
|
+
true
|
113
|
+
end
|
127
114
|
|
128
|
-
|
129
|
-
|
130
|
-
|
115
|
+
def validate_email_presence?
|
116
|
+
validate_email? && active?
|
117
|
+
end
|
131
118
|
|
132
|
-
|
133
|
-
|
134
|
-
|
119
|
+
def validate_email_format?
|
120
|
+
validate_email? && active?
|
121
|
+
end
|
122
|
+
|
123
|
+
def validate_email_uniqueness?
|
124
|
+
validate_email? && active?
|
135
125
|
end
|
136
126
|
end
|
137
127
|
end
|
@@ -1,49 +1,44 @@
|
|
1
1
|
module Minimalist
|
2
2
|
module Authorization
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
end
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
helper_method :current_user, :logged_in?, :authorized?
|
8
7
|
end
|
9
8
|
|
10
|
-
|
11
|
-
#######
|
12
|
-
private
|
13
|
-
#######
|
9
|
+
private
|
14
10
|
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
def current_user
|
12
|
+
@current_user ||= (get_user_from_session || User.guest)
|
13
|
+
end
|
18
14
|
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
def get_user_from_session
|
16
|
+
User.find_by_id(session[:user_id]) if session[:user_id]
|
17
|
+
end
|
22
18
|
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
def authorization_required
|
20
|
+
authorized? || access_denied
|
21
|
+
end
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
def authorized?(action = action_name, resource = controller_name)
|
24
|
+
logged_in?
|
25
|
+
end
|
30
26
|
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
def logged_in?
|
28
|
+
!current_user.is_guest?
|
29
|
+
end
|
34
30
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
31
|
+
def access_denied
|
32
|
+
store_location if request.method.to_s.downcase == 'get' && !logged_in?
|
33
|
+
redirect_to new_session_path
|
34
|
+
end
|
39
35
|
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
def store_location
|
37
|
+
session['return_to'] = request.fullpath
|
38
|
+
end
|
43
39
|
|
44
|
-
|
45
|
-
|
46
|
-
end
|
40
|
+
def redirect_back_or_default(default)
|
41
|
+
redirect_to(session.delete('return_to') || default)
|
47
42
|
end
|
48
43
|
end
|
49
|
-
end
|
44
|
+
end
|