sorcery 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sorcery might be problematic. Click here for more details.
- data/Gemfile +5 -2
- data/Gemfile.lock +12 -0
- data/README.rdoc +12 -7
- data/VERSION +1 -1
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +1 -1
- data/lib/sorcery/crypto_providers/common.rb +2 -2
- data/lib/sorcery/engine.rb +0 -4
- data/lib/sorcery/initializers/initializer.rb +1 -0
- data/lib/sorcery/model/adapters/active_record.rb +28 -0
- data/lib/sorcery/model/adapters/mongoid.rb +59 -0
- data/lib/sorcery/model/submodules/activity_logging.rb +12 -3
- data/lib/sorcery/model/submodules/brute_force_protection.rb +6 -1
- data/lib/sorcery/model/submodules/external.rb +1 -0
- data/lib/sorcery/model/submodules/remember_me.rb +15 -1
- data/lib/sorcery/model/submodules/reset_password.rb +10 -3
- data/lib/sorcery/model/submodules/user_activation.rb +11 -1
- data/lib/sorcery/model/temporary_token.rb +1 -1
- data/lib/sorcery/model.rb +15 -7
- data/lib/sorcery/sinatra.rb +0 -1
- data/lib/sorcery/test_helpers/internal/sinatra.rb +6 -54
- data/lib/sorcery/test_helpers/internal.rb +2 -1
- data/lib/sorcery/test_helpers/sinatra.rb +4 -1
- data/lib/sorcery.rb +22 -1
- data/sorcery.gemspec +107 -10
- data/spec/Gemfile.lock +1 -1
- data/spec/rails3/Gemfile.lock +5 -5
- data/spec/rails3/spec/user_reset_password_spec.rb +2 -2
- data/spec/rails3/spec/user_spec.rb +0 -1
- data/spec/rails3_mongoid/.gitignore +4 -0
- data/spec/rails3_mongoid/.rspec +1 -0
- data/spec/rails3_mongoid/Gemfile +14 -0
- data/spec/rails3_mongoid/Gemfile.lock +146 -0
- data/spec/rails3_mongoid/Rakefile +11 -0
- data/spec/rails3_mongoid/app/controllers/application_controller.rb +108 -0
- data/spec/rails3_mongoid/app/helpers/application_helper.rb +2 -0
- data/spec/rails3_mongoid/app/mailers/sorcery_mailer.rb +25 -0
- data/spec/rails3_mongoid/app/models/authentication.rb +7 -0
- data/spec/rails3_mongoid/app/models/user.rb +5 -0
- data/spec/rails3_mongoid/app/views/layouts/application.html.erb +14 -0
- data/spec/rails3_mongoid/app/views/sorcery_mailer/activation_email.html.erb +17 -0
- data/spec/rails3_mongoid/app/views/sorcery_mailer/activation_email.text.erb +9 -0
- data/spec/rails3_mongoid/app/views/sorcery_mailer/activation_success_email.html.erb +17 -0
- data/spec/rails3_mongoid/app/views/sorcery_mailer/activation_success_email.text.erb +9 -0
- data/spec/rails3_mongoid/app/views/sorcery_mailer/reset_password_email.html.erb +16 -0
- data/spec/rails3_mongoid/app/views/sorcery_mailer/reset_password_email.text.erb +8 -0
- data/spec/rails3_mongoid/config/application.rb +51 -0
- data/spec/rails3_mongoid/config/boot.rb +13 -0
- data/spec/rails3_mongoid/config/environment.rb +5 -0
- data/spec/rails3_mongoid/config/environments/development.rb +26 -0
- data/spec/rails3_mongoid/config/environments/in_memory.rb +0 -0
- data/spec/rails3_mongoid/config/environments/production.rb +49 -0
- data/spec/rails3_mongoid/config/environments/test.rb +35 -0
- data/spec/rails3_mongoid/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails3_mongoid/config/initializers/inflections.rb +10 -0
- data/spec/rails3_mongoid/config/initializers/mime_types.rb +5 -0
- data/spec/rails3_mongoid/config/initializers/secret_token.rb +7 -0
- data/spec/rails3_mongoid/config/initializers/session_store.rb +8 -0
- data/spec/rails3_mongoid/config/locales/en.yml +5 -0
- data/spec/rails3_mongoid/config/mongoid.yml +7 -0
- data/spec/rails3_mongoid/config/routes.rb +59 -0
- data/spec/rails3_mongoid/config.ru +4 -0
- data/spec/rails3_mongoid/db/schema.rb +23 -0
- data/spec/rails3_mongoid/db/seeds.rb +7 -0
- data/spec/rails3_mongoid/lib/tasks/.gitkeep +0 -0
- data/spec/rails3_mongoid/public/404.html +26 -0
- data/spec/rails3_mongoid/public/422.html +26 -0
- data/spec/rails3_mongoid/public/500.html +26 -0
- data/spec/rails3_mongoid/public/favicon.ico +0 -0
- data/spec/rails3_mongoid/public/images/rails.png +0 -0
- data/spec/rails3_mongoid/public/javascripts/application.js +2 -0
- data/spec/rails3_mongoid/public/javascripts/controls.js +965 -0
- data/spec/rails3_mongoid/public/javascripts/dragdrop.js +974 -0
- data/spec/rails3_mongoid/public/javascripts/effects.js +1123 -0
- data/spec/rails3_mongoid/public/javascripts/prototype.js +6001 -0
- data/spec/rails3_mongoid/public/javascripts/rails.js +175 -0
- data/spec/rails3_mongoid/public/robots.txt +5 -0
- data/spec/rails3_mongoid/public/stylesheets/.gitkeep +0 -0
- data/spec/rails3_mongoid/script/rails +6 -0
- data/spec/rails3_mongoid/spec/spec.opts +2 -0
- data/spec/rails3_mongoid/spec/spec_helper.orig.rb +27 -0
- data/spec/rails3_mongoid/spec/spec_helper.rb +55 -0
- data/spec/rails3_mongoid/spec/user_activation_spec.rb +178 -0
- data/spec/rails3_mongoid/spec/user_activity_logging_spec.rb +31 -0
- data/spec/rails3_mongoid/spec/user_brute_force_protection_spec.rb +41 -0
- data/spec/rails3_mongoid/spec/user_oauth_spec.rb +34 -0
- data/spec/rails3_mongoid/spec/user_remember_me_spec.rb +51 -0
- data/spec/rails3_mongoid/spec/user_reset_password_spec.rb +174 -0
- data/spec/rails3_mongoid/spec/user_spec.rb +329 -0
- data/spec/rails3_mongoid/vendor/plugins/.gitkeep +0 -0
- data/spec/sinatra/Gemfile.lock +5 -5
- data/spec/sinatra/spec/spec_helper.rb +0 -1
- metadata +150 -37
- data/spec/untitled folder +0 -18
data/Gemfile
CHANGED
@@ -2,13 +2,16 @@ source "http://rubygems.org"
|
|
2
2
|
# Add dependencies required to use your gem here.
|
3
3
|
# Example:
|
4
4
|
# gem "activesupport", ">= 2.3.5"
|
5
|
-
gem "rails", ">= 3.0.0"
|
6
|
-
gem 'json', ">= 1.5.1"
|
7
5
|
gem 'oauth', ">= 0.4.4"
|
8
6
|
gem 'oauth2', ">= 0.1.1"
|
7
|
+
|
9
8
|
# Add dependencies to develop your gem here.
|
10
9
|
# Include everything needed to run rake, tests, features, etc.
|
11
10
|
group :development do
|
11
|
+
gem "rails", ">= 3.0.0"
|
12
|
+
gem 'json', ">= 1.5.1"
|
13
|
+
gem "mongoid", "~> 2.0"
|
14
|
+
gem "bson_ext", "~> 1.3"
|
12
15
|
gem "rspec", "~> 2.5.0"
|
13
16
|
gem 'rspec-rails', "~> 2.5.0"
|
14
17
|
gem 'ruby-debug19'
|
data/Gemfile.lock
CHANGED
@@ -31,6 +31,8 @@ GEM
|
|
31
31
|
addressable (2.2.4)
|
32
32
|
archive-tar-minitar (0.5.2)
|
33
33
|
arel (2.0.6)
|
34
|
+
bson (1.3.0)
|
35
|
+
bson_ext (1.3.0)
|
34
36
|
builder (2.1.2)
|
35
37
|
columnize (0.3.2)
|
36
38
|
diff-lcs (1.1.2)
|
@@ -55,6 +57,13 @@ GEM
|
|
55
57
|
mime-types (~> 1.16)
|
56
58
|
treetop (~> 1.4.8)
|
57
59
|
mime-types (1.16)
|
60
|
+
mongo (1.3.0)
|
61
|
+
bson (>= 1.3.0)
|
62
|
+
mongoid (2.0.1)
|
63
|
+
activemodel (~> 3.0)
|
64
|
+
mongo (~> 1.3)
|
65
|
+
tzinfo (~> 0.3.22)
|
66
|
+
will_paginate (~> 3.0.pre)
|
58
67
|
multi_json (0.0.5)
|
59
68
|
multipart-post (1.1.0)
|
60
69
|
oauth (0.4.4)
|
@@ -113,15 +122,18 @@ GEM
|
|
113
122
|
treetop (1.4.9)
|
114
123
|
polyglot (>= 0.3.1)
|
115
124
|
tzinfo (0.3.23)
|
125
|
+
will_paginate (3.0.pre2)
|
116
126
|
yard (0.6.4)
|
117
127
|
|
118
128
|
PLATFORMS
|
119
129
|
ruby
|
120
130
|
|
121
131
|
DEPENDENCIES
|
132
|
+
bson_ext (~> 1.3)
|
122
133
|
bundler (~> 1.0.0)
|
123
134
|
jeweler (~> 1.5.2)
|
124
135
|
json (>= 1.5.1)
|
136
|
+
mongoid (~> 2.0)
|
125
137
|
oauth (>= 0.4.4)
|
126
138
|
oauth2 (>= 0.1.1)
|
127
139
|
rails (>= 3.0.0)
|
data/README.rdoc
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
= sorcery
|
2
2
|
Magical Authentication for Rails 3 and Sinatra.
|
3
|
+
Supports ActiveRecord and Mongoid.
|
3
4
|
|
4
5
|
Inspired by restful_authentication, Authlogic and Devise.
|
5
6
|
Crypto code taken almost unchanged from Authlogic.
|
@@ -15,7 +16,7 @@ It was built with a few goals in mind:
|
|
15
16
|
* Less is more - less than 20 public methods to remember for the entire feature-set make the lib easy to 'get'.
|
16
17
|
* No built-in or generated code - use the library's methods inside *your own* MVC structures, and don't fight to fix someone else's.
|
17
18
|
* Magic yes, Voodoo no - the lib should be easy to hack for most developers.
|
18
|
-
* Configuration over Confusion - Simple & short configuration as possible, not drowning in syntactic sugar.
|
19
|
+
* Configuration over Confusion - Centralized (1 file), Simple & short configuration as possible, not drowning in syntactic sugar.
|
19
20
|
* Keep MVC cleanly separated - DB is for models, sessions are for controllers. Models stay unaware of sessions.
|
20
21
|
|
21
22
|
Hopefully, I've achieved this. If not, let me know.
|
@@ -28,7 +29,7 @@ Example Rails 3 app using sorcery: https://github.com/NoamB/sorcery-example-app
|
|
28
29
|
|
29
30
|
Example Sinatra app using sorcery: https://github.com/NoamB/sorcery-example-app-sinatra
|
30
31
|
|
31
|
-
Documentation: http://rubydoc.info/gems/sorcery/0.
|
32
|
+
Documentation: http://rubydoc.info/gems/sorcery/0.5.0/frames
|
32
33
|
|
33
34
|
Check out the tutorials in the github wiki!
|
34
35
|
|
@@ -66,7 +67,7 @@ Below is a summary of the library methods. Most method names are self explaining
|
|
66
67
|
# reset password
|
67
68
|
User.load_from_reset_password_token(token)
|
68
69
|
@user.deliver_reset_password_instructions!
|
69
|
-
@user.
|
70
|
+
@user.change_password!(new_password)
|
70
71
|
|
71
72
|
# user activation
|
72
73
|
User.load_from_activation_token(token)
|
@@ -193,19 +194,23 @@ External (see lib/sorcery/controller/submodules/external.rb):
|
|
193
194
|
== Next Planned Features:
|
194
195
|
|
195
196
|
|
196
|
-
I've got
|
197
|
+
I've got some thoughts which include (unordered):
|
198
|
+
* Passing a block to encrypt, allowing the developer to define his own mix of salting and encrypting
|
197
199
|
* Forgot username, maybe as part of the reset_password module
|
198
200
|
* Scoping logins (to a subdomain or another arbitrary field)
|
199
|
-
*
|
201
|
+
* Allowing storing the salt and crypted password in the same DB field for extra security
|
200
202
|
* Other reset password strategies (security questions?)
|
201
203
|
* Other brute force protection strategies (captcha)
|
202
|
-
|
204
|
+
|
205
|
+
|
206
|
+
Have an idea? Let me know, and it might get into the gem!
|
207
|
+
|
203
208
|
|
204
209
|
Other stuff:
|
205
210
|
* Improve specs speed
|
206
211
|
* Provide an easy way to run specs after install
|
207
212
|
* Improve documentation
|
208
|
-
*
|
213
|
+
* Try to reduce the number of library methods, and find better names to some
|
209
214
|
|
210
215
|
|
211
216
|
== Backward compatibility
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
@@ -19,7 +19,7 @@ module Sorcery
|
|
19
19
|
# Increments the failed logins counter on every failed login.
|
20
20
|
# Runs as a hook after a failed login.
|
21
21
|
def update_failed_logins_count!(credentials)
|
22
|
-
user = Config.user_class.
|
22
|
+
user = Config.user_class.find_by_credentials(credentials)
|
23
23
|
user.register_failed_login! if user
|
24
24
|
end
|
25
25
|
|
@@ -13,14 +13,14 @@ module Sorcery
|
|
13
13
|
attr_writer :stretches
|
14
14
|
|
15
15
|
def encrypt(*tokens)
|
16
|
-
digest = tokens.flatten.join(join_token)
|
16
|
+
digest = tokens.flatten.compact.join(join_token)
|
17
17
|
stretches.times { digest = secure_digest(digest) }
|
18
18
|
digest
|
19
19
|
end
|
20
20
|
|
21
21
|
# Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
|
22
22
|
def matches?(crypted, *tokens)
|
23
|
-
encrypt(*tokens) == crypted
|
23
|
+
encrypt(*tokens.compact) == crypted
|
24
24
|
end
|
25
25
|
|
26
26
|
def reset!
|
data/lib/sorcery/engine.rb
CHANGED
@@ -7,10 +7,6 @@ module Sorcery
|
|
7
7
|
class Engine < Rails::Engine
|
8
8
|
config.sorcery = ::Sorcery::Controller::Config
|
9
9
|
|
10
|
-
initializer "extend Model with sorcery" do |app|
|
11
|
-
ActiveRecord::Base.send(:include, Sorcery::Model) if defined?(ActiveRecord)
|
12
|
-
end
|
13
|
-
|
14
10
|
initializer "extend Controller with sorcery" do |app|
|
15
11
|
ActionController::Base.send(:include, Sorcery::Controller)
|
16
12
|
ActionController::Base.helper_method :current_user
|
@@ -45,6 +45,7 @@ Rails.application.config.sorcery.configure do |config|
|
|
45
45
|
# user.encryption_key = nil # encryption key used to encrypt reversible encryptions such as AES256.
|
46
46
|
# user.custom_encryption_provider = nil # use an external encryption class.
|
47
47
|
# user.encryption_algorithm = :bcrypt # encryption algorithm name. See 'encryption_algorithm=' for available options.
|
48
|
+
# user.subclasses_inherit_config = false # make this configuration inheritable for subclasses. Useful for ActiveRecord's STI.
|
48
49
|
|
49
50
|
# -- user_activation --
|
50
51
|
# user.activation_state_attribute_name = :activation_state # the attribute name to hold activation state (active/pending).
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module Model
|
3
|
+
module Adapters
|
4
|
+
module ActiveRecord
|
5
|
+
def self.included(klass)
|
6
|
+
klass.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def find_by_credentials(credentials)
|
11
|
+
where("#{@sorcery_config.username_attribute_name} = ?", credentials[0]).first
|
12
|
+
end
|
13
|
+
|
14
|
+
def find_by_token(token_attr_name, token)
|
15
|
+
where("#{token_attr_name} = ?", token).first
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_current_users
|
19
|
+
config = sorcery_config
|
20
|
+
where("#{config.last_activity_at_attribute_name} IS NOT NULL") \
|
21
|
+
.where("#{config.last_logout_at_attribute_name} IS NULL OR #{config.last_activity_at_attribute_name} > #{config.last_logout_at_attribute_name}") \
|
22
|
+
.where("#{config.last_activity_at_attribute_name} > ? ", config.activity_timeout.seconds.ago.utc.to_s(:db))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module Model
|
3
|
+
module Adapters
|
4
|
+
module Mongoid
|
5
|
+
def self.included(klass)
|
6
|
+
klass.extend ClassMethods
|
7
|
+
klass.send(:include, InstanceMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module InstanceMethods
|
11
|
+
def increment(attr)
|
12
|
+
self.inc(attr,1)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def find_by_credentials(credentials)
|
18
|
+
where(@sorcery_config.username_attribute_name => credentials[0]).first
|
19
|
+
end
|
20
|
+
|
21
|
+
def find_by_provider_and_uid(provider, uid)
|
22
|
+
where(:provider => provider, :uid => uid).first
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_by_id(id)
|
26
|
+
find(id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_by_activation_token(token)
|
30
|
+
where(:activation_token => token).first
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_by_remember_me_token(token)
|
34
|
+
where(:remember_me_token => token).first
|
35
|
+
end
|
36
|
+
|
37
|
+
def find_by_username(username)
|
38
|
+
where(:username => username).first
|
39
|
+
end
|
40
|
+
|
41
|
+
def transaction(&blk)
|
42
|
+
tap(&blk)
|
43
|
+
end
|
44
|
+
|
45
|
+
def find_by_token(token_attr_name, token)
|
46
|
+
where(token_attr_name => token).first
|
47
|
+
end
|
48
|
+
|
49
|
+
def get_current_users
|
50
|
+
config = sorcery_config
|
51
|
+
where(config.last_activity_at_attribute_name.ne => nil) \
|
52
|
+
.any_of({config.last_logout_at_attribute_name => nil},{config.last_activity_at_attribute_name.gt => config.last_logout_at_attribute_name}) \
|
53
|
+
.and(config.last_activity_at_attribute_name.gt => config.activity_timeout.seconds.ago.utc.to_s(:db)).order_by([:_id,:asc])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -9,6 +9,7 @@ module Sorcery
|
|
9
9
|
module ActivityLogging
|
10
10
|
def self.included(base)
|
11
11
|
base.extend(ClassMethods)
|
12
|
+
|
12
13
|
base.sorcery_config.class_eval do
|
13
14
|
attr_accessor :last_login_at_attribute_name, # last login attribute name.
|
14
15
|
:last_logout_at_attribute_name, # last logout attribute name.
|
@@ -23,15 +24,23 @@ module Sorcery
|
|
23
24
|
:@activity_timeout => 10 * 60)
|
24
25
|
reset!
|
25
26
|
end
|
27
|
+
|
28
|
+
base.sorcery_config.after_config << :define_activity_logging_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
|
26
29
|
end
|
27
30
|
|
28
31
|
module ClassMethods
|
29
32
|
# get all users with last_activity within timeout
|
30
33
|
def current_users
|
31
34
|
config = sorcery_config
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
+
get_current_users
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def define_activity_logging_mongoid_fields
|
41
|
+
field sorcery_config.last_login_at_attribute_name, type: DateTime
|
42
|
+
field sorcery_config.last_logout_at_attribute_name, type: DateTime
|
43
|
+
field sorcery_config.last_activity_at_attribute_name, type: DateTime
|
35
44
|
end
|
36
45
|
end
|
37
46
|
end
|
@@ -21,13 +21,18 @@ module Sorcery
|
|
21
21
|
end
|
22
22
|
|
23
23
|
base.sorcery_config.before_authenticate << :prevent_locked_user_login
|
24
|
+
base.sorcery_config.after_config << :define_brute_force_protection_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
|
24
25
|
base.extend(ClassMethods)
|
25
26
|
base.send(:include, InstanceMethods)
|
26
27
|
end
|
27
28
|
|
28
29
|
module ClassMethods
|
29
30
|
protected
|
30
|
-
|
31
|
+
|
32
|
+
def define_brute_force_protection_mongoid_fields
|
33
|
+
field sorcery_config.failed_logins_count_attribute_name, type: Integer
|
34
|
+
field sorcery_config.lock_expires_at_attribute_name, type: DateTime
|
35
|
+
end
|
31
36
|
end
|
32
37
|
|
33
38
|
module InstanceMethods
|
@@ -21,8 +21,22 @@ module Sorcery
|
|
21
21
|
end
|
22
22
|
|
23
23
|
base.send(:include, InstanceMethods)
|
24
|
+
|
25
|
+
base.sorcery_config.after_config << :define_remember_me_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
|
26
|
+
|
27
|
+
base.extend(ClassMethods)
|
28
|
+
end
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
protected
|
32
|
+
|
33
|
+
def define_remember_me_mongoid_fields
|
34
|
+
field sorcery_config.remember_me_token_attribute_name, type: String
|
35
|
+
field sorcery_config.remember_me_token_expires_at_attribute_name, type: DateTime
|
36
|
+
end
|
37
|
+
|
24
38
|
end
|
25
|
-
|
39
|
+
|
26
40
|
module InstanceMethods
|
27
41
|
# You shouldn't really use this one yourself - it's called by the controller's 'remember_me!' method.
|
28
42
|
def remember_me!
|
@@ -34,10 +34,12 @@ module Sorcery
|
|
34
34
|
end
|
35
35
|
|
36
36
|
base.sorcery_config.after_config << :validate_mailer_defined
|
37
|
-
|
37
|
+
base.sorcery_config.after_config << :define_reset_password_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
|
38
|
+
|
38
39
|
base.extend(ClassMethods)
|
39
40
|
base.send(:include, TemporaryToken)
|
40
41
|
base.send(:include, InstanceMethods)
|
42
|
+
|
41
43
|
end
|
42
44
|
|
43
45
|
module ClassMethods
|
@@ -57,6 +59,11 @@ module Sorcery
|
|
57
59
|
raise ArgumentError, msg if @sorcery_config.reset_password_mailer == nil
|
58
60
|
end
|
59
61
|
|
62
|
+
def define_reset_password_mongoid_fields
|
63
|
+
field sorcery_config.reset_password_token_attribute_name, type: String
|
64
|
+
field sorcery_config.reset_password_token_expires_at_attribute_name, type: DateTime
|
65
|
+
field sorcery_config.reset_password_email_sent_at_attribute_name, type: DateTime
|
66
|
+
end
|
60
67
|
end
|
61
68
|
|
62
69
|
module InstanceMethods
|
@@ -75,9 +82,9 @@ module Sorcery
|
|
75
82
|
end
|
76
83
|
|
77
84
|
# Clears token and tries to update the new password for the user.
|
78
|
-
def
|
85
|
+
def change_password!(new_password)
|
79
86
|
clear_reset_password_token
|
80
|
-
update_attributes(
|
87
|
+
update_attributes(sorcery_config.password_attribute_name => new_password)
|
81
88
|
end
|
82
89
|
|
83
90
|
protected
|
@@ -38,12 +38,14 @@ module Sorcery
|
|
38
38
|
end
|
39
39
|
|
40
40
|
base.sorcery_config.after_config << :validate_mailer_defined
|
41
|
-
|
41
|
+
base.sorcery_config.after_config << :define_user_activation_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
|
42
42
|
base.sorcery_config.before_authenticate << :prevent_non_active_login
|
43
43
|
|
44
44
|
base.extend(ClassMethods)
|
45
45
|
base.send(:include, TemporaryToken)
|
46
46
|
base.send(:include, InstanceMethods)
|
47
|
+
|
48
|
+
|
47
49
|
end
|
48
50
|
|
49
51
|
module ClassMethods
|
@@ -62,6 +64,14 @@ module Sorcery
|
|
62
64
|
msg = "To use user_activation submodule, you must define a mailer (config.user_activation_mailer = YourMailerClass)."
|
63
65
|
raise ArgumentError, msg if @sorcery_config.user_activation_mailer == nil
|
64
66
|
end
|
67
|
+
|
68
|
+
def define_user_activation_mongoid_fields
|
69
|
+
self.class_eval do
|
70
|
+
field sorcery_config.activation_state_attribute_name, type: String
|
71
|
+
field sorcery_config.activation_token_attribute_name, type: String
|
72
|
+
field sorcery_config.activation_token_expires_at_attribute_name, type: DateTime
|
73
|
+
end
|
74
|
+
end
|
65
75
|
end
|
66
76
|
|
67
77
|
module InstanceMethods
|
@@ -10,7 +10,7 @@ module Sorcery
|
|
10
10
|
module ClassMethods
|
11
11
|
def load_from_token(token, token_attr_name, token_expiration_date_attr)
|
12
12
|
return nil if token.blank?
|
13
|
-
user =
|
13
|
+
user = find_by_token(token_attr_name,token)
|
14
14
|
if !user.blank? && !user.send(token_expiration_date_attr).nil?
|
15
15
|
return Time.now.utc < user.send(token_expiration_date_attr) ? user : nil
|
16
16
|
end
|
data/lib/sorcery/model.rb
CHANGED
@@ -26,10 +26,18 @@ module Sorcery
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
# This runs the options block set in the initializer on the model class.
|
31
31
|
::Sorcery::Controller::Config.user_config.tap{|blk| blk.call(@sorcery_config) if blk}
|
32
|
-
|
32
|
+
|
33
|
+
self.class_eval do
|
34
|
+
field sorcery_config.username_attribute_name, type: String
|
35
|
+
field sorcery_config.password_attribute_name, type: String
|
36
|
+
field sorcery_config.email_attribute_name, type: String unless sorcery_config.username_attribute_name == sorcery_config.email_attribute_name
|
37
|
+
field sorcery_config.crypted_password_attribute_name, type: String
|
38
|
+
field sorcery_config.salt_attribute_name, type: String
|
39
|
+
end if defined?(Mongoid) and self.ancestors.include?(Mongoid::Document)
|
40
|
+
|
33
41
|
# add virtual password accessor and ORM callbacks
|
34
42
|
self.class_eval do
|
35
43
|
attr_accessor @sorcery_config.password_attribute_name
|
@@ -38,7 +46,7 @@ module Sorcery
|
|
38
46
|
after_save :clear_virtual_password, :if => Proc.new { |record| record.send(sorcery_config.password_attribute_name).present? }
|
39
47
|
end
|
40
48
|
|
41
|
-
@sorcery_config.after_config << :
|
49
|
+
@sorcery_config.after_config << :add_config_inheritance if @sorcery_config.subclasses_inherit_config
|
42
50
|
@sorcery_config.after_config.each { |c| send(c) }
|
43
51
|
end
|
44
52
|
end
|
@@ -57,7 +65,7 @@ module Sorcery
|
|
57
65
|
# returns the user if success, nil otherwise.
|
58
66
|
def authenticate(*credentials)
|
59
67
|
raise ArgumentError, "at least 2 arguments required" if credentials.size < 2
|
60
|
-
user =
|
68
|
+
user = find_by_credentials(credentials)
|
61
69
|
_salt = user.send(@sorcery_config.salt_attribute_name) if user && !@sorcery_config.salt_attribute_name.nil? && !@sorcery_config.encryption_provider.nil?
|
62
70
|
user if user && @sorcery_config.before_authenticate.all? {|c| user.send(c)} && credentials_match?(user.send(@sorcery_config.crypted_password_attribute_name),credentials[1],_salt)
|
63
71
|
end
|
@@ -80,7 +88,7 @@ module Sorcery
|
|
80
88
|
@sorcery_config.encryption_provider.matches?(crypted, *tokens)
|
81
89
|
end
|
82
90
|
|
83
|
-
def
|
91
|
+
def add_config_inheritance
|
84
92
|
self.class_eval do
|
85
93
|
def self.inherited(subclass)
|
86
94
|
subclass.class_eval do
|
@@ -111,7 +119,7 @@ module Sorcery
|
|
111
119
|
protected
|
112
120
|
|
113
121
|
# creates new salt and saves it.
|
114
|
-
# encrypts password with salt and
|
122
|
+
# encrypts password with salt and saves it.
|
115
123
|
def encrypt_password
|
116
124
|
config = sorcery_config
|
117
125
|
new_salt = self.send(:"#{config.salt_attribute_name}=", generate_random_token) if !config.salt_attribute_name.nil?
|
@@ -135,7 +143,7 @@ module Sorcery
|
|
135
143
|
|
136
144
|
# Random code, used for salt and temporary tokens.
|
137
145
|
def generate_random_token
|
138
|
-
|
146
|
+
Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
|
139
147
|
end
|
140
148
|
end
|
141
149
|
|
data/lib/sorcery/sinatra.rb
CHANGED
@@ -2,6 +2,8 @@ module Sorcery
|
|
2
2
|
module TestHelpers
|
3
3
|
module Internal
|
4
4
|
module Sinatra
|
5
|
+
include ::Sorcery::TestHelpers::Sinatra::CookieSessionMethods
|
6
|
+
include ::Sorcery::TestHelpers::Sinatra::InstanceMethods
|
5
7
|
|
6
8
|
class ::Sinatra::Application
|
7
9
|
class << self
|
@@ -24,64 +26,14 @@ module Sorcery
|
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
27
|
-
def get_sinatra_app(app)
|
28
|
-
while app.class != ::Sinatra::Application do
|
29
|
-
app = app.instance_variable_get(:@app)
|
30
|
-
end
|
31
|
-
app
|
32
|
-
end
|
33
|
-
|
34
|
-
def login_user(user=nil)
|
35
|
-
user ||= @user
|
36
|
-
get_sinatra_app(subject).send(:login_user,user)
|
37
|
-
get_sinatra_app(subject).send(:after_login!,user,[user.username,'secret'])
|
38
|
-
end
|
39
|
-
|
40
|
-
def logout_user
|
41
|
-
get_sinatra_app(subject).send(:logout)
|
42
|
-
end
|
43
|
-
|
44
29
|
def clear_user_without_logout
|
45
|
-
get_sinatra_app(subject).instance_variable_set(:@current_user,nil)
|
30
|
+
get_sinatra_app(subject).instance_variable_set(:@current_user, nil)
|
46
31
|
end
|
47
32
|
|
48
33
|
def assigns
|
49
34
|
::Sinatra::Application.sorcery_vars
|
50
35
|
end
|
51
36
|
|
52
|
-
class SessionData
|
53
|
-
def initialize(cookies)
|
54
|
-
@cookies = cookies
|
55
|
-
@data = cookies['rack.session']
|
56
|
-
if @data
|
57
|
-
@data = @data.unpack("m*").first
|
58
|
-
@data = Marshal.load(@data)
|
59
|
-
else
|
60
|
-
@data = {}
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def [](key)
|
65
|
-
@data[key]
|
66
|
-
end
|
67
|
-
|
68
|
-
def []=(key, value)
|
69
|
-
@data[key] = value
|
70
|
-
session_data = Marshal.dump(@data)
|
71
|
-
session_data = [session_data].pack("m*")
|
72
|
-
@cookies.merge("rack.session=#{Rack::Utils.escape(session_data)}", URI.parse("//example.org//"))
|
73
|
-
raise "session variable not set" unless @cookies['rack.session'] == session_data
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def session
|
78
|
-
SessionData.new(rack_test_session.instance_variable_get(:@rack_mock_session).cookie_jar)
|
79
|
-
end
|
80
|
-
|
81
|
-
def cookies
|
82
|
-
rack_test_session.instance_variable_get(:@rack_mock_session).cookie_jar
|
83
|
-
end
|
84
|
-
|
85
37
|
def sorcery_reload!(submodules = [], options = {})
|
86
38
|
reload_user_class
|
87
39
|
|
@@ -90,9 +42,9 @@ module Sorcery
|
|
90
42
|
::Sorcery::Controller::Config.reset!
|
91
43
|
|
92
44
|
# clear all filters
|
93
|
-
::Sinatra::Application.instance_variable_set(:@filters,{:before => []
|
45
|
+
::Sinatra::Application.instance_variable_set(:@filters, {:before => [], :after => []})
|
94
46
|
::Sinatra::Application.class_eval do
|
95
|
-
load File.join(File.dirname(__FILE__),'..','..','..','..','spec','sinatra','filters.rb')
|
47
|
+
load File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec', 'sinatra', 'filters.rb')
|
96
48
|
end
|
97
49
|
|
98
50
|
# configure
|
@@ -102,7 +54,7 @@ module Sorcery
|
|
102
54
|
::Sinatra::Application.send(:include, Sorcery::Controller)
|
103
55
|
|
104
56
|
::Sorcery::Controller::Config.user_config do |user|
|
105
|
-
options.each do |property,value|
|
57
|
+
options.each do |property, value|
|
106
58
|
user.send(:"#{property}=", value)
|
107
59
|
end
|
108
60
|
end
|
@@ -30,9 +30,10 @@ module Sorcery
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def create_new_external_user(provider, attributes_hash = nil)
|
33
|
-
user_attributes_hash = attributes_hash || {:username => 'gizmo'
|
33
|
+
user_attributes_hash = attributes_hash || {:username => 'gizmo'}
|
34
34
|
@user = User.new(user_attributes_hash)
|
35
35
|
@user.save!
|
36
|
+
@user.authentications.create!({:provider => provider, :uid => 123})
|
36
37
|
@user
|
37
38
|
end
|
38
39
|
|
@@ -76,9 +76,12 @@ module Sorcery
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def session
|
79
|
-
SessionData.new(
|
79
|
+
SessionData.new(cookies)
|
80
80
|
end
|
81
81
|
|
82
|
+
def cookies
|
83
|
+
rack_test_session.instance_variable_get(:@rack_mock_session).cookie_jar
|
84
|
+
end
|
82
85
|
end
|
83
86
|
end
|
84
87
|
end
|
data/lib/sorcery.rb
CHANGED
@@ -2,6 +2,10 @@ module Sorcery
|
|
2
2
|
autoload :Model, 'sorcery/model'
|
3
3
|
module Model
|
4
4
|
autoload :TemporaryToken, 'sorcery/model/temporary_token'
|
5
|
+
module Adapters
|
6
|
+
autoload :ActiveRecord, 'sorcery/model/adapters/active_record'
|
7
|
+
autoload :Mongoid, 'sorcery/model/adapters/mongoid'
|
8
|
+
end
|
5
9
|
module Submodules
|
6
10
|
autoload :UserActivation, 'sorcery/model/submodules/user_activation'
|
7
11
|
autoload :ResetPassword, 'sorcery/model/submodules/reset_password'
|
@@ -56,7 +60,24 @@ module Sorcery
|
|
56
60
|
|
57
61
|
end
|
58
62
|
|
59
|
-
|
63
|
+
if defined?(ActiveRecord)
|
64
|
+
ActiveRecord::Base.send(:include, Sorcery::Model)
|
65
|
+
ActiveRecord::Base.send(:include, ::Sorcery::Model::Adapters::ActiveRecord)
|
66
|
+
end
|
67
|
+
|
68
|
+
if defined?(Mongoid)
|
69
|
+
Mongoid::Document.module_eval do
|
70
|
+
included do
|
71
|
+
attr_reader :new_record
|
72
|
+
include Sorcery::Model::Adapters::Mongoid
|
73
|
+
include Sorcery::Model
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
60
78
|
require 'sorcery/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
61
79
|
require 'sorcery/sinatra' if defined?(Sinatra)
|
80
|
+
|
81
|
+
|
82
|
+
|
62
83
|
end
|