minimalist_authentication 0.6.14 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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