authkit 0.5.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +12 -0
- data/README.md +11 -3
- data/Rakefile +15 -8
- data/authkit.gemspec +2 -2
- data/lib/authkit/version.rb +1 -1
- data/lib/generators/authkit/install_generator.rb +8 -1
- data/lib/generators/authkit/templates/app/controllers/application_controller.rb +23 -20
- data/lib/generators/authkit/templates/app/controllers/auths_controller.rb +4 -4
- data/lib/generators/authkit/templates/app/controllers/email_confirmation_controller.rb +3 -6
- data/lib/generators/authkit/templates/app/controllers/password_change_controller.rb +4 -5
- data/lib/generators/authkit/templates/app/controllers/signup_controller.rb +4 -1
- data/lib/generators/authkit/templates/app/controllers/upload_controller.rb +3 -3
- data/lib/generators/authkit/templates/app/controllers/users_controller.rb +1 -3
- data/lib/generators/authkit/templates/app/forms/signup.rb +10 -2
- data/lib/generators/authkit/templates/app/models/user.rb +2 -22
- data/lib/generators/authkit/templates/app/models/user_session.rb +55 -0
- data/lib/generators/authkit/templates/app/views/password_reset/show.html.erb +0 -2
- data/lib/generators/authkit/templates/db/migrate/add_authkit_fields_to_users.rb +1 -10
- data/lib/generators/authkit/templates/db/migrate/create_auths.rb +6 -2
- data/lib/generators/authkit/templates/db/migrate/create_avatars.rb +3 -2
- data/lib/generators/authkit/templates/db/migrate/create_user_sessions.rb +27 -0
- data/lib/generators/authkit/templates/db/migrate/create_users.rb +2 -2
- data/lib/generators/authkit/templates/spec/controllers/application_controller_spec.rb +40 -47
- data/lib/generators/authkit/templates/spec/controllers/email_confirmation_controller_spec.rb +11 -11
- data/lib/generators/authkit/templates/spec/controllers/password_change_controller_spec.rb +21 -26
- data/lib/generators/authkit/templates/spec/controllers/password_reset_controller_spec.rb +11 -16
- data/lib/generators/authkit/templates/spec/controllers/sessions_controller_spec.rb +17 -23
- data/lib/generators/authkit/templates/spec/controllers/signup_controller_spec.rb +21 -29
- data/lib/generators/authkit/templates/spec/controllers/users_controller_spec.rb +14 -18
- data/lib/generators/authkit/templates/spec/factories/user_session.rb +6 -0
- data/lib/generators/authkit/templates/spec/forms/signup_spec.rb +1 -1
- data/lib/generators/authkit/templates/spec/models/user_session_spec.rb +81 -0
- data/lib/generators/authkit/templates/spec/models/user_spec.rb +18 -45
- data/lib/generators/authkit/templates/spec/support/factory_girl.rb +5 -0
- data/lib/generators/authkit/templates/spec/support/shoulda_matchers.rb +6 -0
- metadata +13 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c20d323000029539b3db935d5f81a0b315feff5
|
4
|
+
data.tar.gz: 31f3cb08d1e680b4000ba21c227ad7277d24a4cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0aac938938939b71b495b3e5c261bead4f72a126f623f6be637658b0960e506725f89262050dd9a2b30c72bbd7db253e9e98de71d8893e26812fd861ddac83c0
|
7
|
+
data.tar.gz: 62b3808da27f4c5c90c9047743e730a7669c2fb77a24a2e6e1fcd00a636c2eac02405e8f72905d4bc486e33f021a246d240e76e7370d8c23f031133159c96a8b
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
## 0.6.0
|
2
|
+
|
3
|
+
* Rails 4.2 compatibility
|
4
|
+
* Removed unneeded development dependencies
|
5
|
+
* Updated sample application to invoke out of process
|
6
|
+
* `UserSession` all session based code has moved into the user session so that all sessions are maintained separately for each device.
|
7
|
+
- This fixes a problem where multiple logins would override the remember token
|
8
|
+
- This provides the groundwork to allow users to revoke sessions
|
9
|
+
* Remember tokens no longer expire
|
10
|
+
* Every access is recorded per session
|
11
|
+
- This means a significant number of writes to the database but this behavior also facilitates updating the remember token for each access
|
12
|
+
* Factory Girl syntax methods moved to support per RSpec recommendation
|
data/README.md
CHANGED
@@ -4,11 +4,11 @@ A gem for installing auth into you app.
|
|
4
4
|
|
5
5
|
## Why?
|
6
6
|
|
7
|
-
There are lots of great authentication gems out there; devise? clearance? restful_auth? All of these seek to solve the problem of adding authentication to your application but they all share one philosophy: you shouldn't need to think about authentication to build your app.
|
7
|
+
There are lots of great authentication gems out there; devise? clearance? restful_auth? All of these seek to solve the problem of adding authentication to your application but they all share one philosophy: you shouldn't need to think about authentication to build your app. Because of this, the developer may spend more time trying to customize the tools for the few cases when the application needs to do something different.
|
8
8
|
|
9
9
|
Authkit takes the opposite stance: auth belongs in your app. It is important and it is specific to your app. It only includes generators and installs itself with some specs. You customize it. Everything is right where you would expect it to be.
|
10
10
|
|
11
|
-
Of course, this stance can be very dangerous
|
11
|
+
Of course, this stance can be very dangerous as it relies on the application developer to not interfere with the authentication mechanisms, and it makes introducing security patches difficult. This is the trade-off. Generally speaking the approaches taken within authkit are designed for the early life-cycle of a small to medium application. It can support much larger platforms, but it is likely that larger platforms will need centralized authentication mechanisms that go beyond the scope of this project.
|
12
12
|
|
13
13
|
## Features
|
14
14
|
|
@@ -22,6 +22,7 @@ Authkit supports Ruby down to version 1.9 but targets 2.0. It is built for Rails
|
|
22
22
|
* One time password / Two factor authentication
|
23
23
|
* Token support
|
24
24
|
* Remember me
|
25
|
+
* User sessions per device
|
25
26
|
* Account page
|
26
27
|
* Time zones
|
27
28
|
* Do not track (DNT) support
|
@@ -248,6 +249,13 @@ In the case of API access, storing a digest of the token is not practical. Bcryp
|
|
248
249
|
|
249
250
|
Additionally, storing only the digest means that a user cannot login to see their API tokens. They would need to be regenerated. This might be considered a feature.
|
250
251
|
|
252
|
+
## User session expiry
|
253
|
+
|
254
|
+
Users sessions and the remember tokens attached to them do not expire by default. For most sites this type of behavior is fine. If the user chooses to remember their session on the current device then that shouldn't change based on an arbitrary timeout, but only if the user revokes the session or logs out. However on some sensitive sites you may want to change this behavior. You can do this by making the cookie expire after a specific amount of time or by making the token or session expire based on a rolling time window:
|
255
|
+
|
256
|
+
scope :active, -> { where('(accessed_at IS NULL OR accessed_at >= ?)', 2.weeks.ago).where(revoked_at: nil, logged_out_at: nil) }
|
257
|
+
|
258
|
+
|
251
259
|
## What's missing
|
252
260
|
|
253
261
|
There is a significant amount of functionality that is currently unimplemented:
|
@@ -262,10 +270,10 @@ There is a significant amount of functionality that is currently unimplemented:
|
|
262
270
|
* One time password support completed
|
263
271
|
* Add Authy or Google Authenticator support
|
264
272
|
* Avatars (possibly this should be within uploadkit)
|
265
|
-
* User session tracking and revoking
|
266
273
|
* Audit logs
|
267
274
|
* No internationalization (i18n)
|
268
275
|
* JavaScript validation for username and email availability and password complexity
|
276
|
+
* Reset all sessions on password change
|
269
277
|
|
270
278
|
## Testing
|
271
279
|
|
data/Rakefile
CHANGED
@@ -5,13 +5,14 @@ gem_name = :authkit
|
|
5
5
|
|
6
6
|
RSpec::Core::RakeTask.new(spec: ["generator:cleanup", "generator:prepare", "generator:#{gem_name}"]) do |task|
|
7
7
|
task.pattern = "spec/**/*_spec.rb"
|
8
|
-
task.rspec_opts = "--color
|
8
|
+
task.rspec_opts = "--color"
|
9
9
|
task.verbose = true
|
10
10
|
end
|
11
11
|
|
12
12
|
namespace :spec do
|
13
13
|
RSpec::Core::RakeTask.new(database: ["generator:cleanup", "generator:prepare", "generator:database", "generator:#{gem_name}"]) do |task|
|
14
14
|
task.pattern = "spec/**/*_spec.rb"
|
15
|
+
task.rspec_opts = "--color"
|
15
16
|
task.verbose = true
|
16
17
|
end
|
17
18
|
end
|
@@ -34,19 +35,25 @@ namespace :generator do
|
|
34
35
|
FileUtils.mkdir_p("spec/tmp")
|
35
36
|
|
36
37
|
system "cd spec/tmp && rails new sample --skip-spring"
|
38
|
+
system "cp .ruby-version spec/tmp/sample"
|
37
39
|
|
38
40
|
# bundle
|
39
41
|
gem_root = File.expand_path(File.dirname(__FILE__))
|
40
42
|
system "echo \"gem 'rspec-rails'\" >> spec/tmp/sample/Gemfile"
|
41
43
|
system "echo \"gem '#{gem_name}', :path => '#{gem_root}'\" >> spec/tmp/sample/Gemfile"
|
42
|
-
|
43
|
-
system "cd spec/tmp/sample
|
44
|
+
|
45
|
+
system "cd spec/tmp/sample; bundle install"
|
46
|
+
system "cd spec/tmp/sample; bin/rails g rspec:install"
|
47
|
+
|
48
|
+
# Make sure rails helper loads the factory girl support file
|
49
|
+
sed("s/# Dir/Dir/", "spec/tmp/sample/spec/rails_helper.rb")
|
44
50
|
|
45
51
|
# Open up the root route for specs
|
46
|
-
sed("s
|
52
|
+
sed("s/#/root to: \"sessions#new\" #/", "spec/tmp/sample/config/routes.rb")
|
47
53
|
|
48
54
|
# Make a thing
|
49
|
-
system "cd spec/tmp/sample
|
55
|
+
# system "cd spec/tmp/sample; bin/rails g scaffold thing name:string mood:string --no-controller-specs --no-view-specs --no-helper-specs --no-routing-specs"
|
56
|
+
# system "rm spec/tmp/sample/spec/models/thing_spec.rb"
|
50
57
|
end
|
51
58
|
|
52
59
|
# This task is not used unless you need to test the generator with an alternate database
|
@@ -55,13 +62,13 @@ namespace :generator do
|
|
55
62
|
task :database do
|
56
63
|
puts "== Configuring the database =================================================="
|
57
64
|
system "cp config/database.yml.example spec/tmp/sample/config/database.yml"
|
58
|
-
system "cd spec/tmp/sample && rake db:migrate:reset"
|
65
|
+
system "cd spec/tmp/sample && bundle exec rake db:migrate:reset"
|
59
66
|
end
|
60
67
|
|
61
68
|
desc "Run the #{gem_name} generator"
|
62
69
|
task gem_name do
|
63
|
-
system "cd spec/tmp/sample && rails g #{gem_name}:install --force #{'--oauth --google' if ENV['SKIP_OAUTH'].nil?} #{'--skip-username' unless ENV['SKIP_USERNAME'].nil?} && rake db:migrate"
|
64
|
-
system "cd spec/tmp/sample && rake db:migrate RAILS_ENV=test"
|
70
|
+
system "cd spec/tmp/sample && rails g #{gem_name}:install --force #{'--oauth --google' if ENV['SKIP_OAUTH'].nil?} #{'--skip-username' unless ENV['SKIP_USERNAME'].nil?} && bundle exec rake db:migrate"
|
71
|
+
system "cd spec/tmp/sample && bundle exec rake db:migrate RAILS_ENV=test"
|
65
72
|
end
|
66
73
|
|
67
74
|
end
|
data/authkit.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
22
|
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
23
24
|
spec.add_development_dependency "rspec-rails"
|
24
|
-
spec.add_development_dependency "
|
25
|
-
spec.add_development_dependency "active_model_otp"
|
25
|
+
spec.add_development_dependency "rails"
|
26
26
|
end
|
data/lib/authkit/version.rb
CHANGED
@@ -45,6 +45,7 @@ module Authkit
|
|
45
45
|
def generate_migrations
|
46
46
|
generate_migration("create_users")
|
47
47
|
generate_migration("add_authkit_fields_to_users")
|
48
|
+
generate_migration("create_user_sessions")
|
48
49
|
generate_migration("create_auths") if oauth?
|
49
50
|
end
|
50
51
|
|
@@ -61,6 +62,7 @@ module Authkit
|
|
61
62
|
"app/views/password_reset",
|
62
63
|
"app/views/password_change",
|
63
64
|
"spec",
|
65
|
+
"spec/support",
|
64
66
|
"spec/factories",
|
65
67
|
"spec/models",
|
66
68
|
"spec/controllers",
|
@@ -74,6 +76,7 @@ module Authkit
|
|
74
76
|
|
75
77
|
# Fill out some templates (for now, this is just straight copy)
|
76
78
|
template "app/models/user.rb", "app/models/user.rb"
|
79
|
+
template "app/models/user_session.rb", "app/models/user_session.rb"
|
77
80
|
template "app/controllers/users_controller.rb", "app/controllers/users_controller.rb"
|
78
81
|
template "app/controllers/signup_controller.rb", "app/controllers/signup_controller.rb"
|
79
82
|
template "app/controllers/sessions_controller.rb", "app/controllers/sessions_controller.rb"
|
@@ -89,8 +92,12 @@ module Authkit
|
|
89
92
|
|
90
93
|
template "app/forms/signup.rb", "app/forms/signup.rb"
|
91
94
|
|
95
|
+
template "spec/support/shoulda_matchers.rb", "spec/support/shoulda_matchers.rb"
|
96
|
+
template "spec/support/factory_girl.rb", "spec/support/factory_girl.rb"
|
92
97
|
template "spec/factories/user.rb", "spec/factories/user.rb"
|
98
|
+
template "spec/factories/user_session.rb", "spec/factories/user_session.rb"
|
93
99
|
template "spec/models/user_spec.rb", "spec/models/user_spec.rb"
|
100
|
+
template "spec/models/user_session_spec.rb", "spec/models/user_session_spec.rb"
|
94
101
|
template "spec/forms/signup_spec.rb", "spec/forms/signup_spec.rb"
|
95
102
|
template "spec/controllers/application_controller_spec.rb", "spec/controllers/application_controller_spec.rb"
|
96
103
|
template "spec/controllers/users_controller_spec.rb", "spec/controllers/users_controller_spec.rb"
|
@@ -171,7 +178,7 @@ module Authkit
|
|
171
178
|
|
172
179
|
# Support for google client apis
|
173
180
|
if provider?(:google)
|
174
|
-
gem 'google-api-client'
|
181
|
+
gem 'google-api-client'
|
175
182
|
gem 'faraday', '~> 0.9.0'
|
176
183
|
gem 'faraday_middleware'
|
177
184
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
before_action :set_time_zone
|
3
3
|
|
4
4
|
helper_method :logged_in?, :current_user
|
5
5
|
|
@@ -16,15 +16,20 @@
|
|
16
16
|
# The user is fetched using id or remember token but these come from a
|
17
17
|
# verified cookie (verified using secure compare) so these database calls do
|
18
18
|
# not need to protect against timing attacks.
|
19
|
-
def
|
20
|
-
return @
|
21
|
-
@
|
22
|
-
|
23
|
-
|
24
|
-
session[:
|
19
|
+
def current_user_session
|
20
|
+
return @current_user_session if defined?(@current_user_session)
|
21
|
+
@current_user_session ||= UserSession.active.where(id: session[:user_session_id]).first if session[:user_session_id]
|
22
|
+
set_current_user_session_from_remember_token unless @current_user_session
|
23
|
+
@current_user_session.access(request, allow_tracking?) if @current_user_session
|
24
|
+
session[:user_session_id] = @current_user_session.id if @current_user_session
|
25
|
+
session[:time_zone] = @current_user_session.user.time_zone if @current_user_session
|
25
26
|
set_time_zone
|
26
27
|
|
27
|
-
@
|
28
|
+
@current_user_session
|
29
|
+
end
|
30
|
+
|
31
|
+
def current_user
|
32
|
+
current_user_session && current_user_session.user
|
28
33
|
end
|
29
34
|
|
30
35
|
def allow_tracking?
|
@@ -46,38 +51,36 @@
|
|
46
51
|
|
47
52
|
def login(user, remember=false)
|
48
53
|
reset_session
|
49
|
-
@
|
54
|
+
@current_user_session = UserSession.create(user: user)
|
50
55
|
current_user.track_sign_in(request.remote_ip) if allow_tracking?
|
51
|
-
current_user.set_remember_token if remember
|
52
56
|
set_remember_cookie if remember
|
53
|
-
session[:
|
57
|
+
session[:user_session_id] = current_user_session.id
|
54
58
|
session[:time_zone] = current_user.time_zone
|
55
59
|
set_time_zone
|
56
|
-
|
60
|
+
current_user_session
|
57
61
|
end
|
58
62
|
|
59
63
|
def logout
|
60
|
-
|
64
|
+
current_user_session.logout if current_user_session
|
61
65
|
cookies.delete(:remember)
|
62
66
|
reset_session
|
63
|
-
@
|
67
|
+
@current_user_session = nil
|
64
68
|
end
|
65
69
|
|
66
70
|
def set_time_zone
|
67
71
|
Time.zone = session[:time_zone] if session[:time_zone].present?
|
68
72
|
end
|
69
73
|
|
70
|
-
def
|
74
|
+
def set_current_user_session_from_remember_token
|
71
75
|
token = cookies.signed[:remember]
|
72
76
|
return if token.blank?
|
73
|
-
@
|
74
|
-
@
|
75
|
-
@current_user
|
77
|
+
@current_user_session = UserSession.active.where(remember_token: "#{token}").first
|
78
|
+
@current_user_session
|
76
79
|
end
|
77
80
|
|
78
81
|
def set_remember_cookie
|
79
82
|
cookies.permanent.signed[:remember] = {
|
80
|
-
value:
|
83
|
+
value: current_user_session.remember_token,
|
81
84
|
secure: Rails.env.production?
|
82
85
|
}
|
83
86
|
end
|
@@ -91,7 +94,7 @@
|
|
91
94
|
|
92
95
|
session[:return_url] = request.fullpath
|
93
96
|
respond_to do |format|
|
94
|
-
format.json {
|
97
|
+
format.json { head :forbidden }
|
95
98
|
format.text { redirect_to(location) }
|
96
99
|
format.html do
|
97
100
|
flash[:error] = message || "Sorry, you must be logged in to do that"
|
@@ -2,10 +2,10 @@
|
|
2
2
|
# in for the connection to work. This controller is not used for creating a new
|
3
3
|
# session.
|
4
4
|
class AuthsController < ApplicationController
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
before_action :require_login, only: [:connect]
|
6
|
+
before_action :require_login_when_connecting, only: [:callback]
|
7
|
+
before_action :require_completed_login, only: [:disconnect]
|
8
|
+
before_action :require_auth_hash, only: [:callback]
|
9
9
|
|
10
10
|
# Adjust scope here for particular sets of user using the session
|
11
11
|
#
|
@@ -1,8 +1,6 @@
|
|
1
1
|
class EmailConfirmationController < ApplicationController
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
respond_to :html
|
2
|
+
before_action :require_login
|
3
|
+
before_action :require_token
|
6
4
|
|
7
5
|
def show
|
8
6
|
if current_user.email_confirmed
|
@@ -33,9 +31,8 @@ class EmailConfirmationController < ApplicationController
|
|
33
31
|
# It is possible to consider failed confirmation tokens failed attempts and
|
34
32
|
# lock the account.
|
35
33
|
def require_token
|
36
|
-
verifier = ActiveSupport::MessageVerifier.new(Rails.application.config.secret_key_base)
|
37
34
|
valid = params[:token].present? && current_user.confirmation_token.present?
|
38
|
-
valid = valid &&
|
35
|
+
valid = valid && ActiveSupport::SecurityUtils.secure_compare(params[:token], current_user.confirmation_token)
|
39
36
|
valid = valid && !current_user.confirmation_token_expired?
|
40
37
|
deny_user("Invalid token", root_path) unless valid
|
41
38
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class PasswordChangeController < ApplicationController
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
before_action :require_no_user
|
3
|
+
before_action :require_email_user
|
4
|
+
before_action :require_token
|
5
5
|
|
6
6
|
def show
|
7
7
|
respond_to do |format|
|
@@ -51,9 +51,8 @@ class PasswordChangeController < ApplicationController
|
|
51
51
|
|
52
52
|
# Reset password tokens expire after 1 day
|
53
53
|
def require_token
|
54
|
-
verifier = ActiveSupport::MessageVerifier.new(Rails.application.config.secret_key_base)
|
55
54
|
valid = params[:token].present?
|
56
|
-
valid = valid &&
|
55
|
+
valid = valid && ActiveSupport::SecurityUtils.secure_compare(params[:token], email_user.reset_password_token)
|
57
56
|
valid = valid && !email_user.reset_password_token_expired?
|
58
57
|
deny_user("Invalid token", root_path) unless valid
|
59
58
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
class SignupController < ApplicationController
|
2
2
|
<% if oauth? %>include AuthsHelper
|
3
3
|
<% end %>
|
4
|
-
respond_to :html, :json
|
5
4
|
|
6
5
|
# Create a new Signup form model (found in app/forms/signup.rb)
|
7
6
|
def new
|
@@ -31,6 +30,10 @@ class SignupController < ApplicationController
|
|
31
30
|
|
32
31
|
protected
|
33
32
|
|
33
|
+
def signup
|
34
|
+
@signup
|
35
|
+
end
|
36
|
+
|
34
37
|
def signup_params
|
35
38
|
params.require(:signup).permit(
|
36
39
|
:email,
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class UploadController < ApplicationController
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
before_action :require_login
|
3
|
+
before_action :require_advertiser, only: [:audio, :cover]
|
4
|
+
before_action :aws_key_to_remote_url, only: [:avatar]
|
5
5
|
|
6
6
|
respond_to :json
|
7
7
|
|
@@ -45,6 +45,10 @@ class Signup
|
|
45
45
|
false
|
46
46
|
end
|
47
47
|
|
48
|
+
def save!
|
49
|
+
raise ActiveRecord::RecordNotSaved unless save
|
50
|
+
end
|
51
|
+
|
48
52
|
def save
|
49
53
|
if valid?
|
50
54
|
persist!
|
@@ -56,6 +60,10 @@ class Signup
|
|
56
60
|
end
|
57
61
|
end
|
58
62
|
|
63
|
+
def save!
|
64
|
+
raise ActiveRecord::RecordNotSaved.new(nil, self.user) unless save
|
65
|
+
end
|
66
|
+
|
59
67
|
def user
|
60
68
|
return @user if @user
|
61
69
|
@user = User.new(user_params)
|
@@ -91,11 +99,11 @@ class Signup
|
|
91
99
|
private
|
92
100
|
|
93
101
|
def validate_models
|
94
|
-
self.user.errors.each { |k, v| errors
|
102
|
+
self.user.errors.each { |k, v| errors.add(k, v) } unless self.user.valid?
|
95
103
|
|
96
104
|
<% if oauth? %>
|
97
105
|
if self.auth.present?
|
98
|
-
self.auth.errors.each { |k, v| errors
|
106
|
+
self.auth.errors.each { |k, v| errors.add(k, v) } unless self.auth.valid?
|
99
107
|
end
|
100
108
|
<% end %>
|
101
109
|
end
|
@@ -2,7 +2,8 @@ require 'email_format_validator'
|
|
2
2
|
require 'full_name_splitter'
|
3
3
|
<% if username? %>require 'username_format_validator'
|
4
4
|
<% end %>
|
5
|
-
class User <
|
5
|
+
class User < ApplicationRecord
|
6
|
+
has_many :sessions, class_name: 'UserSession'
|
6
7
|
<% if oauth? %>
|
7
8
|
has_many :auths
|
8
9
|
<% end %>
|
@@ -56,22 +57,6 @@ class User < ActiveRecord::Base
|
|
56
57
|
self.save
|
57
58
|
end
|
58
59
|
|
59
|
-
# The tokens created by this method have unique indexes but collisions are very
|
60
|
-
# unlikely (1/64^32). Because of this there shouldn't be a conflict. If one occurs
|
61
|
-
# the ActiveRecord::StatementInvalid or ActiveRecord::RecordNotUnique exeception
|
62
|
-
# should bubble up.
|
63
|
-
def set_remember_token
|
64
|
-
self.remember_token = SecureRandom.urlsafe_base64(32)
|
65
|
-
self.remember_token_created_at = Time.now
|
66
|
-
self.save!
|
67
|
-
end
|
68
|
-
|
69
|
-
def clear_remember_token
|
70
|
-
self.remember_token = nil
|
71
|
-
self.remember_token_created_at = nil
|
72
|
-
self.save!
|
73
|
-
end
|
74
|
-
|
75
60
|
def reset_password_token_expired?
|
76
61
|
# TODO reset password tokens expire in 1 day by default
|
77
62
|
self.reset_password_token_created_at.blank? || self.reset_password_token_created_at <= 1.day.ago
|
@@ -82,11 +67,6 @@ class User < ActiveRecord::Base
|
|
82
67
|
self.confirmation_token_created_at.blank? || self.confirmation_token_created_at <= 3.days.ago
|
83
68
|
end
|
84
69
|
|
85
|
-
def remember_token_expired?
|
86
|
-
# TODO remember tokens expire in 1 year by default
|
87
|
-
self.remember_token_created_at.blank? || self.remember_token_created_at <= 1.year.ago
|
88
|
-
end
|
89
|
-
|
90
70
|
def send_welcome
|
91
71
|
# TODO insert your mailer logic here
|
92
72
|
true
|