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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +56 -52
  4. data/Rakefile +27 -26
  5. data/{test/rails_root/lib/tasks/.gitkeep → app/assets/config/minimalist_authentication_manifest.js} +0 -0
  6. data/app/views/sessions/_form.html.erb +5 -0
  7. data/app/views/sessions/new.html.erb +1 -0
  8. data/config/routes.rb +2 -0
  9. data/lib/minimalist/authentication.rb +69 -79
  10. data/lib/minimalist/authorization.rb +30 -35
  11. data/lib/minimalist/sessions.rb +45 -49
  12. data/lib/minimalist/test_helper.rb +5 -5
  13. data/lib/minimalist_authentication.rb +3 -1
  14. data/lib/minimalist_authentication/engine.rb +4 -0
  15. data/lib/{minimalist → minimalist_authentication}/version.rb +1 -1
  16. metadata +24 -128
  17. data/.gitignore +0 -6
  18. data/Gemfile +0 -2
  19. data/Gemfile.lock +0 -101
  20. data/lib/app/views/sessions/_form.html.erb +0 -12
  21. data/lib/app/views/sessions/new.html.erb +0 -1
  22. data/minimalist_authentication.gemspec +0 -23
  23. data/test/.gitignore +0 -1
  24. data/test/authentication_test.rb +0 -103
  25. data/test/authorization_test.rb +0 -77
  26. data/test/factories.rb +0 -12
  27. data/test/jenkins.bash +0 -9
  28. data/test/rails_root/README +0 -256
  29. data/test/rails_root/Rakefile +0 -7
  30. data/test/rails_root/app/controllers/application_controller.rb +0 -5
  31. data/test/rails_root/app/controllers/sessions_controller.rb +0 -3
  32. data/test/rails_root/app/helpers/application_helper.rb +0 -2
  33. data/test/rails_root/app/models/user.rb +0 -4
  34. data/test/rails_root/app/views/layouts/application.html.erb +0 -14
  35. data/test/rails_root/config.ru +0 -4
  36. data/test/rails_root/config/application.rb +0 -42
  37. data/test/rails_root/config/boot.rb +0 -13
  38. data/test/rails_root/config/database.yml +0 -22
  39. data/test/rails_root/config/environment.rb +0 -5
  40. data/test/rails_root/config/environments/development.rb +0 -26
  41. data/test/rails_root/config/environments/production.rb +0 -49
  42. data/test/rails_root/config/environments/test.rb +0 -35
  43. data/test/rails_root/config/initializers/backtrace_silencers.rb +0 -7
  44. data/test/rails_root/config/initializers/inflections.rb +0 -10
  45. data/test/rails_root/config/initializers/mime_types.rb +0 -5
  46. data/test/rails_root/config/initializers/secret_token.rb +0 -7
  47. data/test/rails_root/config/initializers/session_store.rb +0 -8
  48. data/test/rails_root/config/locales/en.yml +0 -5
  49. data/test/rails_root/config/routes.rb +0 -5
  50. data/test/rails_root/db/.gitignore +0 -2
  51. data/test/rails_root/db/schema.rb +0 -21
  52. data/test/rails_root/db/seeds.rb +0 -7
  53. data/test/rails_root/doc/README_FOR_APP +0 -2
  54. data/test/rails_root/log/.gitignore +0 -1
  55. data/test/rails_root/log/.gitkeep +0 -0
  56. data/test/rails_root/script/rails +0 -6
  57. data/test/rails_root/test/performance/browsing_test.rb +0 -9
  58. data/test/rails_root/test/test_helper.rb +0 -13
  59. data/test/sessions_test.rb +0 -30
  60. data/test/test_helper.rb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a34456f10d23a888a02be9b3f641b98aa6cc80ef
4
- data.tar.gz: e8e0a2755308097c530c7e8680cc320ed963ab77
3
+ metadata.gz: 2d020d82d864706eb3048098a397f68a6dd1cbf7
4
+ data.tar.gz: 0ebabb35dda1683be51aff8132a84fbb851f1da7
5
5
  SHA512:
6
- metadata.gz: 12cb3f5a4d7eec151c4666e2f6268ef46a796554a2afcef5bc9065aee3e1b637ac5daeafe3654c6016df9e5cf1c140eb266dfdbf330796b584e96c7edd87a986
7
- data.tar.gz: 92b48a4cf0293909525d4042c1857bf1696750025918cbe6eaef61b9e2115e7f7e9203f7dc3f35ca6e0ee0aab4e6aa5bcbfa011e100ce9905dac95c3dcabd46e
6
+ metadata.gz: fb9ec1fde1bbf9d5ba15778b0b52b906b67cf2a76e5a5c44ed1159d72377b2fc313f81bde6d54423e4229111b14927ac3e7ef695dd0fc5c21b2631b0f4663a2a
7
+ data.tar.gz: 82e0db4943b2b1e4b8e0fe4320876079a5a38609a0add94598bc01f4d68e101560cf1e5569814076aa62918461374068c8ad5531cf3eb87dcd3e57f4d80bb893
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009-2013 WorldWide IDEA, Inc http://www.wwidea.org
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
- [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/wwidea/minimalist_authentication)
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
- Copyright (c) 2009 Aaron Baldwin, released under the MIT license
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
- require 'rake'
2
- require 'rake/testtask'
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
- desc 'Default: run unit tests.'
6
- task :default => :test
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 = true
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
- desc 'Measures test coverage using rcov'
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
@@ -0,0 +1,5 @@
1
+ <%= form_for :user, url: session_path do |form| %>
2
+ <%= form.text_field :email %>
3
+ <%= form.password_field :password %>
4
+ <%= form.submit 'Log in' %>
5
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= render partial: 'form' %>
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Rails.application.routes.draw do
2
+ end
@@ -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
- CALIBRATED_BCRYPT_COST = BCrypt::Engine.calibrate(750)
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
- def self.included( base )
15
- base.extend(ClassMethods)
16
- base.class_eval do
17
- include InstanceMethods
17
+ included do
18
+ attr_accessor :password
19
+ before_save :encrypt_password
18
20
 
19
- attr_accessor :password
20
- before_save :encrypt_password
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
- validates_presence_of :email, if: :validate_email_presence?
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 = 1)
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.tap do |user|
58
- user.email = GUEST_USER_EMAIL
59
- end
53
+ new(email: GUEST_USER_EMAIL)
60
54
  end
61
55
  end
62
56
 
63
- module InstanceMethods
64
-
65
- def active?
66
- active
67
- end
57
+ def active?
58
+ active
59
+ end
68
60
 
69
- def authenticated?(password)
70
- if crypted_password == encrypt(password)
71
- if self.respond_to?(:using_digest_version) and (using_digest_version != PREFERRED_DIGEST_VERSION or salt_cost < CALIBRATED_BCRYPT_COST)
72
- new_salt = self.class.make_token
73
- self.update_attribute(:crypted_password,self.class.secure_digest(password, new_salt, PREFERRED_DIGEST_VERSION))
74
- self.update_attribute(:salt, new_salt)
75
- self.update_attribute(:using_digest_version, PREFERRED_DIGEST_VERSION)
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
- def logged_in
84
- update_column(:last_logged_in_at, Time.current) # use update_column to avoid updated_on trigger
85
- end
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
- def is_guest?
88
- email == GUEST_USER_EMAIL
89
- end
79
+ def is_guest?
80
+ email == GUEST_USER_EMAIL
81
+ end
90
82
 
91
- #######
92
- private
93
- #######
94
83
 
95
- def password_required?
96
- active? && (crypted_password.blank? || !password.blank?)
97
- end
84
+ private
98
85
 
99
- def encrypt(password)
100
- self.class.secure_digest(password, salt, digest_version)
101
- end
86
+ def password_required?
87
+ active? && (crypted_password.blank? || !password.blank?)
88
+ end
102
89
 
103
- def encrypt_password
104
- return if password.blank?
105
- self.salt = self.class.make_token
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
- def digest_version
111
- self.respond_to?(:using_digest_version) ? (using_digest_version || 1) : 1
112
- end
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
- def salt_cost
115
- BCrypt::Engine.valid_salt?(salt) ? salt.match(/\$[^\$]+\$([0-9]+)\$/)[1].to_i : 0
116
- end
101
+ def digest_version
102
+ self.respond_to?(:using_digest_version) ? (using_digest_version || 1) : 1
103
+ end
117
104
 
118
- # email validation
119
- def validate_email?
120
- # allows applications to turn off email validation
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
- def validate_email_presence?
125
- validate_email? && active?
126
- end
109
+ # email validation
110
+ def validate_email?
111
+ # allows applications to turn off email validation
112
+ true
113
+ end
127
114
 
128
- def validate_email_format?
129
- validate_email? && active?
130
- end
115
+ def validate_email_presence?
116
+ validate_email? && active?
117
+ end
131
118
 
132
- def validate_email_uniqueness?
133
- validate_email? && active?
134
- end
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
- def self.included( base )
4
- base.class_eval do
5
- include InstanceMethods
6
- helper_method :current_user, :logged_in?, :authorized?
7
- end
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ helper_method :current_user, :logged_in?, :authorized?
8
7
  end
9
8
 
10
- module InstanceMethods
11
- #######
12
- private
13
- #######
9
+ private
14
10
 
15
- def current_user
16
- @current_user ||= (get_user_from_session || User.guest)
17
- end
11
+ def current_user
12
+ @current_user ||= (get_user_from_session || User.guest)
13
+ end
18
14
 
19
- def get_user_from_session
20
- User.find_by_id(session[:user_id]) if session[:user_id]
21
- end
15
+ def get_user_from_session
16
+ User.find_by_id(session[:user_id]) if session[:user_id]
17
+ end
22
18
 
23
- def authorization_required
24
- authorized? || access_denied
25
- end
19
+ def authorization_required
20
+ authorized? || access_denied
21
+ end
26
22
 
27
- def authorized?(action = action_name, resource = controller_name)
28
- logged_in?
29
- end
23
+ def authorized?(action = action_name, resource = controller_name)
24
+ logged_in?
25
+ end
30
26
 
31
- def logged_in?
32
- !current_user.is_guest?
33
- end
27
+ def logged_in?
28
+ !current_user.is_guest?
29
+ end
34
30
 
35
- def access_denied
36
- store_location if request.method.to_s.downcase == 'get' && !logged_in?
37
- redirect_to new_session_path
38
- end
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
- def store_location
41
- session['return_to'] = request.fullpath
42
- end
36
+ def store_location
37
+ session['return_to'] = request.fullpath
38
+ end
43
39
 
44
- def redirect_back_or_default(default)
45
- redirect_to(session.delete('return_to') || default)
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