sorcery 0.8.5 → 0.9.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 (163) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.travis.yml +122 -5
  4. data/CHANGELOG.md +37 -1
  5. data/Gemfile +10 -18
  6. data/README.md +159 -88
  7. data/gemfiles/active_record-rails40.gemfile +7 -0
  8. data/gemfiles/active_record-rails41.gemfile +7 -0
  9. data/gemfiles/mongo_mapper-rails40.gemfile +9 -0
  10. data/gemfiles/mongo_mapper-rails41.gemfile +9 -0
  11. data/gemfiles/mongoid-rails40.gemfile +9 -0
  12. data/gemfiles/mongoid-rails41.gemfile +9 -0
  13. data/gemfiles/mongoid3-rails32.gemfile +9 -0
  14. data/lib/generators/sorcery/USAGE +1 -1
  15. data/lib/generators/sorcery/install_generator.rb +19 -5
  16. data/lib/generators/sorcery/templates/initializer.rb +34 -9
  17. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +3 -1
  18. data/lib/generators/sorcery/templates/migration/core.rb +2 -2
  19. data/lib/generators/sorcery/templates/migration/external.rb +3 -1
  20. data/lib/sorcery/adapters/active_record_adapter.rb +120 -0
  21. data/lib/sorcery/adapters/base_adapter.rb +30 -0
  22. data/lib/sorcery/adapters/data_mapper_adapter.rb +176 -0
  23. data/lib/sorcery/adapters/mongo_mapper_adapter.rb +110 -0
  24. data/lib/sorcery/adapters/mongoid_adapter.rb +97 -0
  25. data/lib/sorcery/controller/config.rb +65 -0
  26. data/lib/sorcery/controller/submodules/activity_logging.rb +16 -21
  27. data/lib/sorcery/controller/submodules/brute_force_protection.rb +6 -6
  28. data/lib/sorcery/controller/submodules/external.rb +35 -40
  29. data/lib/sorcery/controller/submodules/remember_me.rb +4 -4
  30. data/lib/sorcery/controller/submodules/session_timeout.rb +10 -6
  31. data/lib/sorcery/controller.rb +10 -74
  32. data/lib/sorcery/model/config.rb +96 -0
  33. data/lib/sorcery/model/submodules/activity_logging.rb +30 -13
  34. data/lib/sorcery/model/submodules/brute_force_protection.rb +21 -21
  35. data/lib/sorcery/model/submodules/external.rb +53 -9
  36. data/lib/sorcery/model/submodules/remember_me.rb +15 -19
  37. data/lib/sorcery/model/submodules/reset_password.rb +33 -34
  38. data/lib/sorcery/model/submodules/user_activation.rb +36 -47
  39. data/lib/sorcery/model/temporary_token.rb +4 -4
  40. data/lib/sorcery/model.rb +73 -173
  41. data/lib/sorcery/protocols/oauth.rb +42 -0
  42. data/lib/sorcery/protocols/oauth2.rb +47 -0
  43. data/lib/sorcery/providers/base.rb +38 -0
  44. data/lib/sorcery/providers/facebook.rb +63 -0
  45. data/lib/sorcery/providers/github.rb +51 -0
  46. data/lib/sorcery/providers/google.rb +51 -0
  47. data/lib/sorcery/providers/heroku.rb +57 -0
  48. data/lib/sorcery/providers/jira.rb +77 -0
  49. data/lib/sorcery/providers/linkedin.rb +66 -0
  50. data/lib/sorcery/providers/liveid.rb +53 -0
  51. data/lib/sorcery/providers/salesforce.rb +50 -0
  52. data/lib/sorcery/providers/twitter.rb +59 -0
  53. data/lib/sorcery/providers/vk.rb +63 -0
  54. data/lib/sorcery/providers/xing.rb +64 -0
  55. data/lib/sorcery/test_helpers/internal/rails.rb +14 -3
  56. data/lib/sorcery/test_helpers/internal.rb +7 -3
  57. data/lib/sorcery/test_helpers/rails/controller.rb +21 -0
  58. data/lib/sorcery/test_helpers/rails/integration.rb +26 -0
  59. data/lib/sorcery/version.rb +3 -0
  60. data/lib/sorcery.rb +82 -58
  61. data/sorcery.gemspec +19 -19
  62. data/spec/active_record/user_activation_spec.rb +1 -1
  63. data/spec/active_record/user_activity_logging_spec.rb +10 -1
  64. data/spec/active_record/user_brute_force_protection_spec.rb +1 -1
  65. data/spec/active_record/user_oauth_spec.rb +1 -1
  66. data/spec/active_record/user_remember_me_spec.rb +1 -1
  67. data/spec/active_record/user_reset_password_spec.rb +1 -1
  68. data/spec/active_record/user_spec.rb +7 -8
  69. data/spec/controllers/controller_activity_logging_spec.rb +124 -0
  70. data/spec/controllers/controller_brute_force_protection_spec.rb +43 -0
  71. data/spec/controllers/controller_http_basic_auth_spec.rb +68 -0
  72. data/spec/controllers/controller_oauth2_spec.rb +414 -0
  73. data/spec/controllers/controller_oauth_spec.rb +240 -0
  74. data/spec/controllers/controller_remember_me_spec.rb +117 -0
  75. data/spec/controllers/controller_session_timeout_spec.rb +80 -0
  76. data/spec/controllers/controller_spec.rb +218 -0
  77. data/spec/data_mapper/user_activation_spec.rb +10 -0
  78. data/spec/data_mapper/user_activity_logging_spec.rb +14 -0
  79. data/spec/data_mapper/user_brute_force_protection_spec.rb +9 -0
  80. data/spec/data_mapper/user_oauth_spec.rb +9 -0
  81. data/spec/data_mapper/user_remember_me_spec.rb +8 -0
  82. data/spec/data_mapper/user_reset_password_spec.rb +8 -0
  83. data/spec/data_mapper/user_spec.rb +27 -0
  84. data/spec/mongo_mapper/user_activation_spec.rb +1 -2
  85. data/spec/mongo_mapper/user_activity_logging_spec.rb +1 -1
  86. data/spec/mongo_mapper/user_brute_force_protection_spec.rb +1 -1
  87. data/spec/mongo_mapper/user_oauth_spec.rb +1 -1
  88. data/spec/mongo_mapper/user_remember_me_spec.rb +1 -1
  89. data/spec/mongo_mapper/user_reset_password_spec.rb +1 -1
  90. data/spec/mongo_mapper/user_spec.rb +7 -8
  91. data/spec/mongoid/user_activation_spec.rb +1 -2
  92. data/spec/mongoid/user_activity_logging_spec.rb +1 -2
  93. data/spec/mongoid/user_brute_force_protection_spec.rb +1 -2
  94. data/spec/mongoid/user_oauth_spec.rb +1 -2
  95. data/spec/mongoid/user_remember_me_spec.rb +1 -2
  96. data/spec/mongoid/user_reset_password_spec.rb +1 -2
  97. data/spec/mongoid/user_spec.rb +21 -9
  98. data/spec/orm/active_record.rb +14 -0
  99. data/spec/orm/data_mapper.rb +48 -0
  100. data/spec/orm/mongo_mapper.rb +1 -1
  101. data/spec/orm/mongoid.rb +5 -0
  102. data/spec/rails_app/app/controllers/sorcery_controller.rb +125 -59
  103. data/spec/rails_app/app/data_mapper/authentication.rb +8 -0
  104. data/spec/rails_app/app/data_mapper/user.rb +7 -0
  105. data/spec/rails_app/app/mongo_mapper/user.rb +2 -0
  106. data/spec/rails_app/config/routes.rb +27 -13
  107. data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +2 -2
  108. data/spec/shared_examples/user_activation_shared_examples.rb +108 -91
  109. data/spec/shared_examples/user_activity_logging_shared_examples.rb +83 -15
  110. data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +140 -21
  111. data/spec/shared_examples/user_oauth_shared_examples.rb +21 -16
  112. data/spec/shared_examples/user_remember_me_shared_examples.rb +36 -24
  113. data/spec/shared_examples/user_reset_password_shared_examples.rb +138 -117
  114. data/spec/shared_examples/user_shared_examples.rb +297 -150
  115. data/spec/sorcery_crypto_providers_spec.rb +28 -28
  116. data/spec/spec_helper.rb +12 -18
  117. metadata +99 -165
  118. data/Gemfile.rails4 +0 -24
  119. data/VERSION +0 -1
  120. data/lib/sorcery/controller/submodules/external/protocols/oauth1.rb +0 -46
  121. data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +0 -50
  122. data/lib/sorcery/controller/submodules/external/providers/base.rb +0 -21
  123. data/lib/sorcery/controller/submodules/external/providers/facebook.rb +0 -99
  124. data/lib/sorcery/controller/submodules/external/providers/github.rb +0 -93
  125. data/lib/sorcery/controller/submodules/external/providers/google.rb +0 -92
  126. data/lib/sorcery/controller/submodules/external/providers/linkedin.rb +0 -103
  127. data/lib/sorcery/controller/submodules/external/providers/liveid.rb +0 -93
  128. data/lib/sorcery/controller/submodules/external/providers/twitter.rb +0 -94
  129. data/lib/sorcery/controller/submodules/external/providers/vk.rb +0 -101
  130. data/lib/sorcery/controller/submodules/external/providers/xing.rb +0 -98
  131. data/lib/sorcery/model/adapters/active_record.rb +0 -49
  132. data/lib/sorcery/model/adapters/mongo_mapper.rb +0 -56
  133. data/lib/sorcery/model/adapters/mongoid.rb +0 -88
  134. data/lib/sorcery/test_helpers/rails.rb +0 -16
  135. data/lib/sorcery/test_helpers.rb +0 -5
  136. data/spec/active_record/controller_activity_logging_spec.rb +0 -140
  137. data/spec/active_record/controller_brute_force_protection_spec.rb +0 -136
  138. data/spec/active_record/controller_http_basic_auth_spec.rb +0 -59
  139. data/spec/active_record/controller_oauth2_spec.rb +0 -417
  140. data/spec/active_record/controller_oauth_spec.rb +0 -212
  141. data/spec/active_record/controller_remember_me_spec.rb +0 -96
  142. data/spec/active_record/controller_session_timeout_spec.rb +0 -55
  143. data/spec/active_record/controller_spec.rb +0 -182
  144. data/spec/active_record/integration_spec.rb +0 -23
  145. data/spec/mongo_mapper/controller_spec.rb +0 -175
  146. data/spec/mongoid/controller_activity_logging_spec.rb +0 -111
  147. data/spec/mongoid/controller_spec.rb +0 -186
  148. data/spec/rails_app/public/404.html +0 -26
  149. data/spec/rails_app/public/422.html +0 -26
  150. data/spec/rails_app/public/500.html +0 -26
  151. data/spec/rails_app/public/favicon.ico +0 -0
  152. data/spec/rails_app/public/images/rails.png +0 -0
  153. data/spec/rails_app/public/javascripts/application.js +0 -2
  154. data/spec/rails_app/public/javascripts/controls.js +0 -965
  155. data/spec/rails_app/public/javascripts/dragdrop.js +0 -974
  156. data/spec/rails_app/public/javascripts/effects.js +0 -1123
  157. data/spec/rails_app/public/javascripts/prototype.js +0 -6001
  158. data/spec/rails_app/public/javascripts/rails.js +0 -175
  159. data/spec/rails_app/public/robots.txt +0 -5
  160. data/spec/rails_app/public/stylesheets/.gitkeep +0 -0
  161. data/spec/shared_examples/controller_oauth2_shared_examples.rb +0 -56
  162. data/spec/shared_examples/controller_oauth_shared_examples.rb +0 -69
  163. /data/lib/sorcery/{controller/submodules/external/protocols → protocols}/certs/ca-bundle.crt +0 -0
@@ -2,9 +2,9 @@ module Sorcery
2
2
  module TestHelpers
3
3
  module Internal
4
4
  module Rails
5
- include ::Sorcery::TestHelpers::Rails
5
+ include ::Sorcery::TestHelpers::Rails::Controller
6
6
 
7
- SUBMODUELS_AUTO_ADDED_CONTROLLER_FILTERS = [
7
+ SUBMODULES_AUTO_ADDED_CONTROLLER_FILTERS = [
8
8
  :register_last_activity_time_to_db,
9
9
  :deny_banned_user,
10
10
  :validate_session
@@ -20,7 +20,13 @@ module Sorcery
20
20
  # remove all plugin before_filters so they won't fail other tests.
21
21
  # I don't like this way, but I didn't find another.
22
22
  # hopefully it won't break until Rails 4.
23
- SorceryController._process_action_callbacks.delete_if {|c| SUBMODUELS_AUTO_ADDED_CONTROLLER_FILTERS.include?(c.filter) }
23
+ chain = if Gem::Version.new(::Rails::VERSION::STRING) >= Gem::Version.new("4.1.0")
24
+ SorceryController._process_action_callbacks.send :chain
25
+ else
26
+ SorceryController._process_action_callbacks
27
+ end
28
+
29
+ chain.delete_if {|c| SUBMODULES_AUTO_ADDED_CONTROLLER_FILTERS.include?(c.filter) }
24
30
 
25
31
  # configure
26
32
  ::Sorcery::Controller::Config.submodules = submodules
@@ -34,6 +40,11 @@ module Sorcery
34
40
  end
35
41
  end
36
42
  User.authenticates_with_sorcery!
43
+ if defined?(DataMapper) and User.ancestors.include?(DataMapper::Resource)
44
+ DataMapper.auto_migrate!
45
+ User.finalize
46
+ Authentication.finalize
47
+ end
37
48
  end
38
49
 
39
50
  def sorcery_controller_property_set(property, value)
@@ -30,14 +30,14 @@ module Sorcery
30
30
 
31
31
  def create_new_user(attributes_hash = nil)
32
32
  @user = build_new_user(attributes_hash)
33
- @user.save!
33
+ @user.sorcery_adapter.save(:raise_on_failure => true)
34
34
  @user
35
35
  end
36
36
 
37
37
  def create_new_external_user(provider, attributes_hash = nil)
38
38
  user_attributes_hash = attributes_hash || {:username => 'gizmo'}
39
39
  @user = User.new(user_attributes_hash)
40
- @user.save!
40
+ @user.sorcery_adapter.save(:raise_on_failure => true)
41
41
  @user.authentications.create!({:provider => provider, :uid => 123})
42
42
  @user
43
43
  end
@@ -47,7 +47,7 @@ module Sorcery
47
47
 
48
48
  user_attributes_hash = attributes_hash || {:username => 'gizmo'}
49
49
  @user = User.new(user_attributes_hash)
50
- @user.save!
50
+ @user.sorcery_adapter.save(:raise_on_failure => true)
51
51
  @user.send(authentication_association).create!({:provider => provider, :uid => 123})
52
52
  @user
53
53
  end
@@ -58,6 +58,10 @@ module Sorcery
58
58
  end
59
59
  end
60
60
 
61
+ def update_model(&block)
62
+ User.class_exec(&block)
63
+ end
64
+
61
65
  private
62
66
 
63
67
  # reload user class between specs
@@ -0,0 +1,21 @@
1
+ module Sorcery
2
+ module TestHelpers
3
+ module Rails
4
+ module Controller
5
+ def login_user(user = nil, test_context = {})
6
+ user ||= @user
7
+ @controller.send(:auto_login, user)
8
+ @controller.send(:after_login!, user, [user.send(user.sorcery_config.username_attribute_names.first), 'secret'])
9
+ end
10
+
11
+ def logout_user
12
+ @controller.send(:logout)
13
+ end
14
+
15
+ def logged_in?
16
+ @controller.send(:logged_in?)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ module Sorcery
2
+ module TestHelpers
3
+ module Rails
4
+ module Integration
5
+
6
+ #Accepts arguments for user to login, route to use and HTTP method
7
+ #Defaults - @user, 'sessions_url' and POST
8
+ def login_user(user = nil, route = nil, http_method = :post)
9
+ user ||= @user
10
+ route ||= sessions_url
11
+
12
+ username_attr = user.sorcery_config.username_attribute_names.first
13
+ username = user.send(username_attr)
14
+ page.driver.send(http_method, route, { :"#{username_attr}" => username, :password => 'secret' })
15
+ end
16
+
17
+ #Accepts route and HTTP method arguments
18
+ #Default - 'logout_url' and GET
19
+ def logout_user(route = nil, http_method = :get)
20
+ route ||= logout_url
21
+ page.driver.send(http_method, route)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module Sorcery
2
+ VERSION = "0.9.0"
3
+ end
data/lib/sorcery.rb CHANGED
@@ -1,86 +1,110 @@
1
+ require 'sorcery/version'
2
+
1
3
  module Sorcery
2
- autoload :Model, 'sorcery/model'
4
+
5
+ require 'sorcery/model'
6
+
7
+ module Adapters
8
+ require 'sorcery/adapters/base_adapter'
9
+ end
10
+
3
11
  module Model
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
- autoload :MongoMapper, 'sorcery/model/adapters/mongo_mapper'
9
- end
12
+ require 'sorcery/model/temporary_token'
13
+ require 'sorcery/model/config'
14
+
15
+
10
16
  module Submodules
11
- autoload :UserActivation, 'sorcery/model/submodules/user_activation'
12
- autoload :ResetPassword, 'sorcery/model/submodules/reset_password'
13
- autoload :RememberMe, 'sorcery/model/submodules/remember_me'
14
- autoload :ActivityLogging, 'sorcery/model/submodules/activity_logging'
15
- autoload :BruteForceProtection, 'sorcery/model/submodules/brute_force_protection'
16
- autoload :External, 'sorcery/model/submodules/external'
17
+ require 'sorcery/model/submodules/user_activation'
18
+ require 'sorcery/model/submodules/reset_password'
19
+ require 'sorcery/model/submodules/remember_me'
20
+ require 'sorcery/model/submodules/activity_logging'
21
+ require 'sorcery/model/submodules/brute_force_protection'
22
+ require 'sorcery/model/submodules/external'
17
23
  end
18
24
  end
19
- autoload :Controller, 'sorcery/controller'
25
+
26
+ require 'sorcery/controller'
27
+
20
28
  module Controller
29
+ autoload :Config, 'sorcery/controller/config'
21
30
  module Submodules
22
- autoload :RememberMe, 'sorcery/controller/submodules/remember_me'
23
- autoload :SessionTimeout, 'sorcery/controller/submodules/session_timeout'
24
- autoload :BruteForceProtection, 'sorcery/controller/submodules/brute_force_protection'
25
- autoload :HttpBasicAuth, 'sorcery/controller/submodules/http_basic_auth'
26
- autoload :ActivityLogging, 'sorcery/controller/submodules/activity_logging'
27
- autoload :External, 'sorcery/controller/submodules/external'
28
- module External
29
- module Protocols
30
- autoload :Oauth1, 'sorcery/controller/submodules/external/protocols/oauth1'
31
- autoload :Oauth2, 'sorcery/controller/submodules/external/protocols/oauth2'
32
- end
33
- module Providers
34
- autoload :Base, 'sorcery/controller/submodules/external/providers/base'
35
- autoload :Twitter, 'sorcery/controller/submodules/external/providers/twitter'
36
- autoload :Facebook, 'sorcery/controller/submodules/external/providers/facebook'
37
- autoload :Github, 'sorcery/controller/submodules/external/providers/github'
38
- autoload :Google, 'sorcery/controller/submodules/external/providers/google'
39
- autoload :Liveid, 'sorcery/controller/submodules/external/providers/liveid'
40
- autoload :Linkedin, 'sorcery/controller/submodules/external/providers/linkedin'
41
- autoload :Vk, 'sorcery/controller/submodules/external/providers/vk'
42
- autoload :Xing, 'sorcery/controller/submodules/external/providers/xing'
43
- end
44
- end
31
+ require 'sorcery/controller/submodules/remember_me'
32
+ require 'sorcery/controller/submodules/session_timeout'
33
+ require 'sorcery/controller/submodules/brute_force_protection'
34
+ require 'sorcery/controller/submodules/http_basic_auth'
35
+ require 'sorcery/controller/submodules/activity_logging'
36
+ require 'sorcery/controller/submodules/external'
45
37
  end
46
38
  end
39
+
40
+ module Protocols
41
+ require 'sorcery/protocols/oauth'
42
+ require 'sorcery/protocols/oauth2'
43
+ end
44
+
47
45
  module CryptoProviders
48
- autoload :Common, 'sorcery/crypto_providers/common'
49
- autoload :AES256, 'sorcery/crypto_providers/aes256'
50
- autoload :BCrypt, 'sorcery/crypto_providers/bcrypt'
51
- autoload :MD5, 'sorcery/crypto_providers/md5'
52
- autoload :SHA1, 'sorcery/crypto_providers/sha1'
53
- autoload :SHA256, 'sorcery/crypto_providers/sha256'
54
- autoload :SHA512, 'sorcery/crypto_providers/sha512'
46
+ require 'sorcery/crypto_providers/common'
47
+ require 'sorcery/crypto_providers/aes256'
48
+ require 'sorcery/crypto_providers/bcrypt'
49
+ require 'sorcery/crypto_providers/md5'
50
+ require 'sorcery/crypto_providers/sha1'
51
+ require 'sorcery/crypto_providers/sha256'
52
+ require 'sorcery/crypto_providers/sha512'
55
53
  end
56
- autoload :TestHelpers, 'sorcery/test_helpers'
54
+
57
55
  module TestHelpers
58
- autoload :Rails, 'sorcery/test_helpers/rails'
59
- autoload :Internal, 'sorcery/test_helpers/internal'
56
+ require 'sorcery/test_helpers/internal'
57
+
58
+ module Rails
59
+ require 'sorcery/test_helpers/rails/controller'
60
+ require 'sorcery/test_helpers/rails/integration'
61
+ end
62
+
60
63
  module Internal
61
- autoload :Rails, 'sorcery/test_helpers/internal/rails'
64
+ require 'sorcery/test_helpers/internal/rails'
62
65
  end
63
66
 
64
67
  end
65
68
 
69
+ require 'sorcery/adapters/base_adapter'
70
+
66
71
  if defined?(ActiveRecord)
67
- ActiveRecord::Base.send(:include, Sorcery::Model)
68
- ActiveRecord::Base.send(:include, Sorcery::Model::Adapters::ActiveRecord)
72
+ require 'sorcery/adapters/active_record_adapter'
73
+ ActiveRecord::Base.extend Sorcery::Model
74
+
75
+ ActiveRecord::Base.send :define_method, :sorcery_adapter do
76
+ @sorcery_adapter ||= Sorcery::Adapters::ActiveRecordAdapter.new(self)
77
+ end
78
+
79
+ ActiveRecord::Base.send :define_singleton_method, :sorcery_adapter do
80
+ Sorcery::Adapters::ActiveRecordAdapter.from(self)
81
+ end
69
82
  end
70
83
 
71
84
  if defined?(Mongoid)
72
- Mongoid::Document.module_eval do
73
- included do
74
- attr_reader :new_record
75
- include Sorcery::Model
76
- include Sorcery::Model::Adapters::Mongoid
77
- end
85
+ require 'sorcery/adapters/mongoid_adapter'
86
+ Mongoid::Document::ClassMethods.send :include, Sorcery::Model
87
+
88
+ Mongoid::Document.send :define_method, :sorcery_adapter do
89
+ @sorcery_adapter ||= Sorcery::Adapters::MongoidAdapter.new(self)
90
+ end
91
+
92
+ Mongoid::Document::ClassMethods.send :define_method, :sorcery_adapter do
93
+ Sorcery::Adapters::MongoidAdapter.from(self)
78
94
  end
79
95
  end
80
96
 
81
97
  if defined?(MongoMapper)
82
- MongoMapper::Document.send(:plugin, Sorcery::Model::Adapters::MongoMapper)
98
+ require 'sorcery/adapters/mongo_mapper_adapter'
99
+ MongoMapper::Document.send(:plugin, Sorcery::Adapters::MongoMapperAdapter::Wrapper)
100
+ end
101
+
102
+ if defined?(DataMapper)
103
+ require 'sorcery/adapters/data_mapper_adapter'
104
+ DataMapper::Model.append_extensions(Sorcery::Model)
105
+
106
+ DataMapper::Model.append_inclusions(Sorcery::Adapters::DataMapperAdapter::Wrapper)
83
107
  end
84
108
 
85
- require 'sorcery/engine' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
109
+ require 'sorcery/engine' if defined?(Rails)
86
110
  end
data/sorcery.gemspec CHANGED
@@ -1,10 +1,14 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'sorcery/version'
4
+
1
5
  Gem::Specification.new do |s|
2
6
  s.name = "sorcery"
3
- s.version = "0.8.5"
4
- s.authors = ["Noam Ben Ari", "Kir Shatrov"]
7
+ s.version = Sorcery::VERSION
8
+ s.authors = ["Noam Ben Ari", "Kir Shatrov", "Grzegorz Witek"]
5
9
  s.email = "nbenari@gmail.com"
6
10
  s.description = "Provides common authentication needs such as signing in/out, activating by email and resetting password."
7
- s.summary = "Magical authentication for Rails 3 applications"
11
+ s.summary = "Magical authentication for Rails 3 & 4 applications"
8
12
  s.homepage = "http://github.com/NoamB/sorcery"
9
13
 
10
14
  s.files = `git ls-files`.split($/)
@@ -14,21 +18,17 @@ Gem::Specification.new do |s|
14
18
 
15
19
  s.required_ruby_version = '>= 1.9.3'
16
20
 
17
- s.add_dependency("oauth", "~> 0.4.4")
18
- s.add_dependency("oauth2", ">= 0.8.0", "< 1.0.0")
19
- s.add_dependency("bcrypt-ruby", ">= 3.0")
20
-
21
- s.add_development_dependency("abstract", ">= 1.0.0")
22
- s.add_development_dependency("rails", ">= 3.2.15")
23
- s.add_development_dependency("json", ">= 1.7.7")
24
- s.add_development_dependency("rspec", "~> 2.5.0")
25
- s.add_development_dependency("rspec-rails", "~> 2.5.0")
26
- s.add_development_dependency("sqlite3", ">= 0")
27
- s.add_development_dependency("yard", "~> 0.6.0")
28
- s.add_development_dependency("bundler", ">= 1.1.0")
29
- s.add_development_dependency("simplecov", ">= 0.3.8")
30
- s.add_development_dependency("timecop", ">= 0")
31
- s.add_development_dependency("mongo_mapper", ">= 0")
32
- s.add_development_dependency("mongoid", "~> 2.4.4")
21
+ s.add_dependency "oauth", "~> 0.4", ">= 0.4.4"
22
+ s.add_dependency "oauth2", ">= 0.8.0"
23
+ s.add_dependency "bcrypt", "~> 3.1"
24
+
25
+ s.add_development_dependency "abstract", ">= 1.0.0"
26
+ s.add_development_dependency "json", ">= 1.7.7"
27
+ s.add_development_dependency "yard", "~> 0.6.0"
28
+
29
+ s.add_development_dependency "timecop"
30
+ s.add_development_dependency "simplecov", ">= 0.3.8"
31
+ s.add_development_dependency "rspec", "~> 3.0.0"
32
+ s.add_development_dependency "rspec-rails", "~> 3.0.0"
33
33
  end
34
34
 
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  require 'rails_app/app/mailers/sorcery_mailer'
4
4
  require 'shared_examples/user_activation_shared_examples'
5
5
 
6
- describe "User with activation submodule" do
6
+ describe User, "with activation submodule", :active_record => true do
7
7
  before(:all) do
8
8
  ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activation")
9
9
  User.reset_column_information
@@ -1,7 +1,16 @@
1
1
  require 'spec_helper'
2
2
  require 'shared_examples/user_activity_logging_shared_examples'
3
3
 
4
- describe "User with activity logging submodule" do
4
+ describe User, "with activity logging submodule", :active_record => true do
5
+
6
+ before(:all) do
7
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activity_logging")
8
+ User.reset_column_information
9
+ end
10
+
11
+ after(:all) do
12
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activity_logging")
13
+ end
5
14
 
6
15
  it_behaves_like "rails_3_activity_logging_model"
7
16
 
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'shared_examples/user_brute_force_protection_shared_examples'
3
3
 
4
- describe "User with brute_force_protection submodule" do
4
+ describe User, "with brute_force_protection submodule", :active_record => true do
5
5
  before(:all) do
6
6
  ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/brute_force_protection")
7
7
  User.reset_column_information
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'shared_examples/user_oauth_shared_examples'
3
3
 
4
- describe "User with oauth submodule" do
4
+ describe User, "with oauth submodule", :active_record => true do
5
5
  before(:all) do
6
6
  ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
7
7
  User.reset_column_information
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'shared_examples/user_remember_me_shared_examples'
3
3
 
4
- describe "User with remember_me submodule" do
4
+ describe User, "with remember_me submodule", :active_record => true do
5
5
  before(:all) do
6
6
  ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/remember_me")
7
7
  User.reset_column_information
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'shared_examples/user_reset_password_shared_examples'
3
3
 
4
- describe "User with reset_password submodule" do
4
+ describe User, "with reset_password submodule", :active_record => true do
5
5
  before(:all) do
6
6
  ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/reset_password")
7
7
  User.reset_column_information
@@ -1,20 +1,19 @@
1
1
  require 'spec_helper'
2
-
3
2
  require 'rails_app/app/mailers/sorcery_mailer'
4
3
  require 'shared_examples/user_shared_examples'
5
4
 
6
- describe "User with no submodules (core)" do
5
+ describe User, "with no submodules (core)", :active_record => true do
7
6
  before(:all) do
8
7
  sorcery_reload!
9
8
  end
10
9
 
11
- describe User, "when app has plugin loaded" do
12
- it "should respond to the plugin activation class method" do
13
- ActiveRecord::Base.should respond_to(:authenticates_with_sorcery!)
10
+ context "when app has plugin loaded" do
11
+ it "responds to the plugin activation class method" do
12
+ expect(ActiveRecord::Base).to respond_to :authenticates_with_sorcery!
14
13
  end
15
14
 
16
- it "User should respond_to .authenticates_with_sorcery!" do
17
- User.should respond_to(:authenticates_with_sorcery!)
15
+ it "User responds to .authenticates_with_sorcery!" do
16
+ expect(User).to respond_to :authenticates_with_sorcery!
18
17
  end
19
18
  end
20
19
 
@@ -22,7 +21,7 @@ describe "User with no submodules (core)" do
22
21
 
23
22
  it_should_behave_like "rails_3_core_model"
24
23
 
25
- describe User, "external users" do
24
+ describe "external users" do
26
25
  before(:all) do
27
26
  ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
28
27
  User.reset_column_information
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ # require 'shared_examples/controller_activity_logging_shared_examples'
4
+
5
+ describe SorceryController do
6
+ after(:all) do
7
+ sorcery_controller_property_set(:register_login_time, true)
8
+ sorcery_controller_property_set(:register_logout_time, true)
9
+ sorcery_controller_property_set(:register_last_activity_time, true)
10
+ # sorcery_controller_property_set(:last_login_from_ip_address_name, true)
11
+ end
12
+
13
+ # ----------------- ACTIVITY LOGGING -----------------------
14
+ context "with activity logging features" do
15
+
16
+ let(:adapter) { double('sorcery_adapter') }
17
+ let(:user) { double('user', id: 42, sorcery_adapter: adapter) }
18
+
19
+ before(:all) do
20
+ sorcery_reload!([:activity_logging])
21
+ end
22
+
23
+ specify { expect(subject).to respond_to(:current_users) }
24
+
25
+ before(:each) do
26
+ allow(user).to receive(:username)
27
+ allow(user).to receive_message_chain(:sorcery_config, :username_attribute_names, :first) { :username }
28
+ allow(User.sorcery_config).to receive(:last_login_at_attribute_name) { :last_login_at }
29
+ allow(User.sorcery_config).to receive(:last_login_from_ip_address_name) { :last_login_from_ip_address }
30
+
31
+ sorcery_controller_property_set(:register_login_time, false)
32
+ sorcery_controller_property_set(:register_last_ip_address, false)
33
+ sorcery_controller_property_set(:register_last_activity_time, false)
34
+ end
35
+
36
+ it "'current_users' should proxy to User.current_users" do
37
+ expect(User).to receive(:current_users).with(no_args)
38
+
39
+ subject.current_users
40
+ end
41
+
42
+
43
+ it "logs login time on login" do
44
+ now = Time.now.in_time_zone
45
+ Timecop.freeze(now)
46
+
47
+ sorcery_controller_property_set(:register_login_time, true)
48
+ expect(user).to receive(:set_last_login_at).with(be_within(0.1).of(now))
49
+ login_user(user)
50
+
51
+ Timecop.return
52
+ end
53
+
54
+ it "logs logout time on logout" do
55
+ login_user(user)
56
+ now = Time.now.in_time_zone
57
+ Timecop.freeze(now)
58
+ expect(user).to receive(:set_last_logout_at).with(be_within(0.1).of(now))
59
+
60
+ logout_user
61
+
62
+ Timecop.return
63
+ end
64
+
65
+ it "logs last activity time when logged in" do
66
+ sorcery_controller_property_set(:register_last_activity_time, true)
67
+
68
+ login_user(user)
69
+ now = Time.now.in_time_zone
70
+ Timecop.freeze(now)
71
+ expect(user).to receive(:set_last_activity_at).with(be_within(0.1).of(now))
72
+
73
+ get :some_action
74
+
75
+ Timecop.return
76
+ end
77
+
78
+ it "logs last IP address when logged in" do
79
+ sorcery_controller_property_set(:register_last_ip_address, true)
80
+ expect(user).to receive(:set_last_ip_addess).with('0.0.0.0')
81
+
82
+ login_user(user)
83
+ end
84
+
85
+ it "updates nothing but activity fields" do
86
+ pending 'Move to model'
87
+ original_user_name = User.last.username
88
+ login_user(user)
89
+ get :some_action_making_a_non_persisted_change_to_the_user
90
+
91
+ expect(User.last.username).to eq original_user_name
92
+ end
93
+
94
+ it "does not register login time if configured so" do
95
+ sorcery_controller_property_set(:register_login_time, false)
96
+
97
+ expect(user).to receive(:set_last_login_at).never
98
+ login_user(user)
99
+ end
100
+
101
+ it "does not register logout time if configured so" do
102
+ sorcery_controller_property_set(:register_logout_time, false)
103
+ login_user(user)
104
+
105
+ expect(user).to receive(:set_last_logout_at).never
106
+ logout_user
107
+ end
108
+
109
+ it "does not register last activity time if configured so" do
110
+ sorcery_controller_property_set(:register_last_activity_time, false)
111
+
112
+ expect(user).to receive(:set_last_activity_at).never
113
+ login_user(user)
114
+ end
115
+
116
+ it "does not register last IP address if configured so" do
117
+ sorcery_controller_property_set(:register_last_ip_address, false)
118
+ expect(user).to receive(:set_last_ip_addess).never
119
+
120
+ login_user(user)
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe SorceryController do
4
+
5
+ let(:user) { double('user', id: 42, email: 'bla@bla.com') }
6
+
7
+ def request_test_login
8
+ get :test_login, email: 'bla@bla.com', password: 'blabla'
9
+ end
10
+
11
+ # ----------------- SESSION TIMEOUT -----------------------
12
+ describe "brute force protection features" do
13
+
14
+ before(:all) do
15
+ sorcery_reload!([:brute_force_protection])
16
+ end
17
+
18
+ after(:each) do
19
+ Sorcery::Controller::Config.reset!
20
+ sorcery_controller_property_set(:user_class, User)
21
+ Timecop.return
22
+ end
23
+
24
+ it "counts login retries" do
25
+ allow(User).to receive(:authenticate)
26
+ allow(User.sorcery_adapter).to receive(:find_by_credentials).with(['bla@bla.com', 'blabla']).and_return(user)
27
+
28
+ expect(user).to receive(:register_failed_login!).exactly(3).times
29
+
30
+ 3.times { request_test_login }
31
+ end
32
+
33
+ it "resets the counter on a good login" do
34
+ # dirty hack for rails 4
35
+ allow(@controller).to receive(:register_last_activity_time_to_db)
36
+
37
+ allow(User).to receive(:authenticate).and_return(user)
38
+ expect(user).to receive_message_chain(:sorcery_adapter, :update_attribute).with(:failed_logins_count, 0)
39
+
40
+ get :test_login, email: 'bla@bla.com', password: 'secret'
41
+ end
42
+ end
43
+ end