authenticate 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -5
- data/README.md +149 -78
- data/app/controllers/authenticate/passwords_controller.rb +130 -0
- data/app/controllers/authenticate/sessions_controller.rb +46 -0
- data/app/controllers/authenticate/users_controller.rb +46 -0
- data/app/mailers/authenticate_mailer.rb +13 -0
- data/app/views/authenticate_mailer/change_password.html.erb +8 -0
- data/app/views/authenticate_mailer/change_password.text.erb +5 -0
- data/app/views/layouts/application.html.erb +25 -0
- data/app/views/passwords/edit.html.erb +20 -0
- data/app/views/passwords/new.html.erb +19 -0
- data/app/views/sessions/new.html.erb +28 -0
- data/app/views/users/new.html.erb +24 -0
- data/authenticate.gemspec +1 -2
- data/config/locales/authenticate.en.yml +57 -0
- data/config/routes.rb +14 -1
- data/lib/authenticate/callbacks/brute_force.rb +5 -9
- data/lib/authenticate/callbacks/lifetimed.rb +1 -0
- data/lib/authenticate/callbacks/timeoutable.rb +2 -1
- data/lib/authenticate/callbacks/trackable.rb +1 -3
- data/lib/authenticate/configuration.rb +94 -5
- data/lib/authenticate/controller.rb +69 -9
- data/lib/authenticate/debug.rb +1 -0
- data/lib/authenticate/engine.rb +4 -11
- data/lib/authenticate/model/brute_force.rb +22 -3
- data/lib/authenticate/model/db_password.rb +12 -7
- data/lib/authenticate/model/email.rb +8 -10
- data/lib/authenticate/model/password_reset.rb +76 -0
- data/lib/authenticate/model/timeoutable.rb +9 -3
- data/lib/authenticate/model/trackable.rb +1 -1
- data/lib/authenticate/model/username.rb +21 -8
- data/lib/authenticate/modules.rb +19 -1
- data/lib/authenticate/session.rb +3 -1
- data/lib/authenticate/user.rb +6 -1
- data/lib/authenticate/version.rb +1 -1
- data/lib/generators/authenticate/controllers/USAGE +12 -0
- data/lib/generators/authenticate/controllers/controllers_generator.rb +21 -0
- data/lib/generators/authenticate/install/USAGE +7 -0
- data/lib/generators/authenticate/install/install_generator.rb +140 -0
- data/lib/generators/authenticate/install/templates/authenticate.rb +22 -0
- data/lib/generators/authenticate/install/templates/db/migrate/add_authenticate_brute_force_to_users.rb +6 -0
- data/lib/generators/authenticate/install/templates/db/migrate/add_authenticate_password_reset_to_users.rb +7 -0
- data/lib/generators/authenticate/install/templates/db/migrate/add_authenticate_timeoutable_to_users.rb +5 -0
- data/lib/generators/authenticate/install/templates/db/migrate/add_authenticate_to_users.rb +21 -0
- data/lib/generators/authenticate/install/templates/db/migrate/create_users.rb +14 -0
- data/lib/generators/authenticate/install/templates/user.rb +3 -0
- data/lib/generators/authenticate/routes/USAGE +8 -0
- data/lib/generators/authenticate/routes/routes_generator.rb +32 -0
- data/lib/generators/authenticate/routes/templates/routes.rb +10 -0
- data/lib/generators/authenticate/views/USAGE +13 -0
- data/lib/generators/authenticate/views/views_generator.rb +21 -0
- data/spec/dummy/app/controllers/application_controller.rb +1 -0
- data/spec/dummy/config/initializers/authenticate.rb +12 -5
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20160130192728_create_users.rb +18 -0
- data/spec/dummy/db/migrate/20160130192729_add_authenticate_brute_force_to_users.rb +6 -0
- data/spec/dummy/db/migrate/20160130192730_add_authenticate_timeoutable_to_users.rb +5 -0
- data/spec/dummy/db/migrate/20160130192731_add_authenticate_password_reset_to_users.rb +7 -0
- data/spec/dummy/db/schema.rb +14 -10
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/factories/users.rb +5 -8
- data/spec/model/brute_force_spec.rb +63 -0
- data/spec/model/session_spec.rb +4 -0
- data/spec/model/user_spec.rb +15 -5
- data/spec/spec_helper.rb +2 -1
- metadata +41 -9
- data/app/controllers/.keep +0 -0
- data/app/mailers/.keep +0 -0
- data/app/views/.keep +0 -0
- data/spec/dummy/db/migrate/20160120003910_create_users.rb +0 -18
data/lib/authenticate/session.rb
CHANGED
@@ -100,7 +100,9 @@ module Authenticate
|
|
100
100
|
|
101
101
|
def write_cookie
|
102
102
|
cookie_hash = {
|
103
|
-
|
103
|
+
path: Authenticate.configuration.cookie_path,
|
104
|
+
secure: Authenticate.configuration.secure_cookie,
|
105
|
+
httponly: Authenticate.configuration.cookie_http_only,
|
104
106
|
value: @current_user.session_token,
|
105
107
|
expires: Authenticate.configuration.cookie_expiration.call
|
106
108
|
}
|
data/lib/authenticate/user.rb
CHANGED
@@ -35,16 +35,21 @@ module Authenticate
|
|
35
35
|
load_modules
|
36
36
|
end
|
37
37
|
|
38
|
+
# Generate a new session token for the user, overwriting the existing session token, if any.
|
39
|
+
# This is not automatically persisted; call {#reset_session_token!} to automatically
|
40
|
+
# generate and persist the session token update.
|
38
41
|
def generate_session_token
|
39
42
|
self.session_token = Authenticate::Token.new
|
40
|
-
# puts 'User.generate_session_token session_token:' + self.session_token.to_s
|
41
43
|
end
|
42
44
|
|
45
|
+
# Generate a new session token and persist the change, ignoring validations.
|
46
|
+
# This effectively signs out all existing sessions. Called as part of logout.
|
43
47
|
def reset_session_token!
|
44
48
|
generate_session_token
|
45
49
|
save validate: false
|
46
50
|
end
|
47
51
|
|
52
|
+
|
48
53
|
end
|
49
54
|
end
|
50
55
|
|
data/lib/authenticate/version.rb
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
Description:
|
2
|
+
Override the default authentication controllers and mailers. This generator will copy all of the
|
3
|
+
base authenticate controllers and mailers into your project.
|
4
|
+
|
5
|
+
Examples:
|
6
|
+
rails generate authenticate:controllers
|
7
|
+
|
8
|
+
View: app/controllers/authenticate/passwords_controller.rb
|
9
|
+
View: app/controllers/authenticate/sessions_controller.rb
|
10
|
+
View: app/controllers/authenticate/users_controller.rb
|
11
|
+
View: app/mailers/authenticate_mailer.rb
|
12
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
#
|
4
|
+
# deploy view and locale assets
|
5
|
+
#
|
6
|
+
module Authenticate
|
7
|
+
module Generators
|
8
|
+
class ControllersGenerator < Rails::Generators::Base
|
9
|
+
source_root File.expand_path("../../../../..", __FILE__)
|
10
|
+
|
11
|
+
def create_views
|
12
|
+
directory 'app/controllers'
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_mailers
|
16
|
+
directory 'app/mailers'
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
|
4
|
+
module Authenticate
|
5
|
+
module Generators
|
6
|
+
class InstallGenerator < Rails::Generators::Base
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
source_root File.expand_path('../templates', __FILE__)
|
9
|
+
|
10
|
+
def create_initializer
|
11
|
+
copy_file 'authenticate.rb', 'config/initializers/authenticate.rb'
|
12
|
+
end
|
13
|
+
|
14
|
+
def inject_into_application_controller
|
15
|
+
inject_into_class(
|
16
|
+
"app/controllers/application_controller.rb",
|
17
|
+
ApplicationController,
|
18
|
+
" include Authenticate::Controller\n"
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_or_inject_into_user_model
|
23
|
+
if File.exist? "app/models/user.rb"
|
24
|
+
inject_into_file(
|
25
|
+
'app/models/user.rb',
|
26
|
+
' include Authenticate::User\n\n',
|
27
|
+
after: 'class User < ActiveRecord::Base\n'
|
28
|
+
)
|
29
|
+
else
|
30
|
+
copy_file 'user.rb', 'app/models/user.rb'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_authenticate_user_migration
|
35
|
+
if users_table_exists?
|
36
|
+
create_add_columns_migration
|
37
|
+
else
|
38
|
+
create_new_users_migration
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def copy_migration_files
|
43
|
+
copy_migration 'add_authenticate_brute_force_to_users.rb'
|
44
|
+
copy_migration 'add_authenticate_timeoutable_to_users.rb'
|
45
|
+
copy_migration 'add_authenticate_password_reset_to_users.rb'
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def create_new_users_migration
|
51
|
+
config = {
|
52
|
+
new_columns: new_columns,
|
53
|
+
new_indexes: new_indexes
|
54
|
+
}
|
55
|
+
copy_migration 'create_users.rb', config
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_add_columns_migration
|
59
|
+
if migration_needed?
|
60
|
+
config = {
|
61
|
+
new_columns: new_columns,
|
62
|
+
new_indexes: new_indexes
|
63
|
+
}
|
64
|
+
copy_migration('add_authenticate_to_users.rb', config)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def copy_migration(migration_name, config = {})
|
69
|
+
unless migration_exists?(migration_name)
|
70
|
+
migration_template(
|
71
|
+
"db/migrate/#{migration_name}",
|
72
|
+
"db/migrate/#{migration_name}",
|
73
|
+
config
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def migration_needed?
|
79
|
+
new_columns.any? || new_indexes.any?
|
80
|
+
end
|
81
|
+
|
82
|
+
def new_columns
|
83
|
+
@new_columns ||= {
|
84
|
+
email: 't.string :email',
|
85
|
+
encrypted_password: 't.string :encrypted_password, limit: 128',
|
86
|
+
session_token: 't.string :session_token, limit: 128',
|
87
|
+
|
88
|
+
# trackable, lifetimed
|
89
|
+
current_sign_in_at: 't.datetime :current_sign_in_at',
|
90
|
+
current_sign_in_ip: 't.string :current_sign_in_ip, limit: 128',
|
91
|
+
last_sign_in_at: 't.datetime :last_sign_in_at',
|
92
|
+
last_sign_in_ip: 't.string :last_sign_in_ip, limit: 128',
|
93
|
+
sign_in_count: 't.integer :sign_in_count'
|
94
|
+
}.reject { |column| existing_users_columns.include?(column.to_s) }
|
95
|
+
end
|
96
|
+
|
97
|
+
def new_indexes
|
98
|
+
@new_indexes ||= {
|
99
|
+
index_users_on_email: 'add_index :users, :email',
|
100
|
+
index_users_on_session_token: 'add_index :users, :session_token'
|
101
|
+
}.reject { |index| existing_users_indexes.include?(index.to_s) }
|
102
|
+
end
|
103
|
+
|
104
|
+
def migration_exists?(name)
|
105
|
+
existing_migrations.include?(name)
|
106
|
+
end
|
107
|
+
|
108
|
+
def existing_migrations
|
109
|
+
@existing_migrations ||= Dir.glob("db/migrate/*.rb").map do |file|
|
110
|
+
migration_name_without_timestamp(file)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def migration_name_without_timestamp(file)
|
115
|
+
file.sub(%r{^.*(db/migrate/)(?:\d+_)?}, '')
|
116
|
+
end
|
117
|
+
|
118
|
+
def users_table_exists?
|
119
|
+
ActiveRecord::Base.connection.table_exists?(:users)
|
120
|
+
end
|
121
|
+
|
122
|
+
def existing_users_columns
|
123
|
+
return [] unless users_table_exists?
|
124
|
+
ActiveRecord::Base.connection.columns(:users).map(&:name)
|
125
|
+
end
|
126
|
+
|
127
|
+
def existing_users_indexes
|
128
|
+
return [] unless users_table_exists?
|
129
|
+
ActiveRecord::Base.connection.indexes(:users).map(&:name)
|
130
|
+
end
|
131
|
+
|
132
|
+
# for generating a timestamp when using `create_migration`
|
133
|
+
def self.next_migration_number(dir)
|
134
|
+
ActiveRecord::Generators::Base.next_migration_number(dir)
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Authenticate.configure do |config|
|
2
|
+
# config.user_model = 'User'
|
3
|
+
# config.cookie_name = 'authenticate_session_token'
|
4
|
+
# config.cookie_expiration = { 1.month.from_now.utc }
|
5
|
+
# config.cookie_domain = nil
|
6
|
+
# config.cookie_path = '/'
|
7
|
+
# config.secure_cookie = false # set to true in production https environments
|
8
|
+
# config.cookie_http_only = false # set to true if you can
|
9
|
+
|
10
|
+
# config.mailer_sender = 'reply@example.com'
|
11
|
+
# config.crypto_provider = Authenticate::Model::BCrypt
|
12
|
+
# config.timeout_in = 45.minutes
|
13
|
+
# config.max_session_lifetime = 8.hours
|
14
|
+
# config.max_consecutive_bad_logins_allowed = 4
|
15
|
+
# config.bad_login_lockout_period = 10.minutes
|
16
|
+
# config.authentication_strategy = :email
|
17
|
+
# config.redirect_url = '/'
|
18
|
+
# config.allow_sign_up = true
|
19
|
+
# config.routes = true
|
20
|
+
# config.reset_password_within = 2.days
|
21
|
+
# config.modules = []
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class AddAuthenticateToUsers < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
change_table :users do |t|
|
4
|
+
<% config[:new_columns].values.each do |column| -%>
|
5
|
+
<%= column %>
|
6
|
+
<% end -%>
|
7
|
+
end
|
8
|
+
|
9
|
+
<% config[:new_indexes].values.each do |index| -%>
|
10
|
+
<%= index %>
|
11
|
+
<% end -%>
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.down
|
15
|
+
change_table :users do |t|
|
16
|
+
<% if config[:new_columns].any? -%>
|
17
|
+
t.remove <%= new_columns.keys.map { |column| ":#{column}" }.join(", ") %>
|
18
|
+
<% end -%>
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateUsers < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
|
4
|
+
create_table :users do |t|
|
5
|
+
<% config[:new_columns].values.each do |column| -%>
|
6
|
+
<%= column %>
|
7
|
+
<% end -%>
|
8
|
+
end
|
9
|
+
|
10
|
+
<% config[:new_indexes].values.each do |index| -%>
|
11
|
+
<%= index %>
|
12
|
+
<% end -%>
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
module Authenticate
|
4
|
+
module Generators
|
5
|
+
class RoutesGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path('../templates', __FILE__)
|
7
|
+
|
8
|
+
def add_authenticate_routes
|
9
|
+
route(authenticate_routes)
|
10
|
+
end
|
11
|
+
|
12
|
+
def disable_authenticate_internal_routes
|
13
|
+
inject_into_file(
|
14
|
+
'config/initializers/authenticate.rb',
|
15
|
+
" config.routes = false \n",
|
16
|
+
after: "Authenticate.configure do |config|\n",
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def authenticate_routes
|
23
|
+
File.read(routes_file_path)
|
24
|
+
end
|
25
|
+
|
26
|
+
def routes_file_path
|
27
|
+
File.expand_path(find_in_source_paths('routes.rb'))
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
resource :session, controller: 'authenticate/sessions', only: [:create, :new, :destroy]
|
2
|
+
resources :passwords, controller: 'authenticate/passwords', only: [:new, :create]
|
3
|
+
|
4
|
+
resource :users, controller: 'authenticate/users', only: [:new, :create] do
|
5
|
+
resources :passwords, controller: 'authenticate/passwords', only: [:edit, :update]
|
6
|
+
end
|
7
|
+
|
8
|
+
get '/sign_up', to: 'authenticate/users#new', as: 'sign_up'
|
9
|
+
get '/sign_in', to: 'authenticate/sessions#new', as: 'sign_in'
|
10
|
+
get '/sign_out', to: 'authenticate/sessions#destroy', as: 'sign_out'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Description:
|
2
|
+
Override the default authenticate views. This generator will copy all of the
|
3
|
+
base authenticate views into your project.
|
4
|
+
|
5
|
+
Examples:
|
6
|
+
rails generate authenticate:views
|
7
|
+
|
8
|
+
View: app/views/authenticate_mailer/change_password.html.erb
|
9
|
+
View: app/views/layouts/application.html.erb
|
10
|
+
View: app/views/passwords/edit.html.erb
|
11
|
+
View: app/views/passwords/new.html.erb
|
12
|
+
View: app/views/sessions/new.html.erb
|
13
|
+
View: app/views/users/new.html.erb
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
#
|
4
|
+
# deploy view and locale assets
|
5
|
+
#
|
6
|
+
module Authenticate
|
7
|
+
module Generators
|
8
|
+
class ViewsGenerator < Rails::Generators::Base
|
9
|
+
source_root File.expand_path("../../../../..", __FILE__)
|
10
|
+
|
11
|
+
def create_views
|
12
|
+
directory 'app/views'
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_locales
|
16
|
+
directory 'config/locales'
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,7 +1,14 @@
|
|
1
|
-
puts '************************** initializer start'
|
2
1
|
Authenticate.configure do |config|
|
3
|
-
config.
|
4
|
-
config.
|
5
|
-
config.
|
2
|
+
# config.user_model = 'User'
|
3
|
+
# config.cookie_name = 'authenticate_session_token'
|
4
|
+
# config.cookie_expiration = { 1.month.from_now.utc }
|
5
|
+
# config.cookie_domain = nil
|
6
|
+
# config.cookie_path = '/'
|
7
|
+
# config.secure_cookie = false # set to true in production https environments
|
8
|
+
# config.http_only = false # set to true if you can
|
9
|
+
# config.timeout_in = 45.minutes
|
10
|
+
# config.max_session_lifetime = 8.hours
|
11
|
+
config.max_consecutive_bad_logins_allowed = 1
|
12
|
+
config.bad_login_lockout_period = 2.minutes
|
13
|
+
# config.authentication_strategy = :email
|
6
14
|
end
|
7
|
-
puts '************************** initializer finished'
|
Binary file
|