sorcery 0.2.1 → 0.4.2

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. data/Gemfile +3 -2
  2. data/Gemfile.lock +13 -11
  3. data/README.rdoc +157 -61
  4. data/Rakefile +4 -4
  5. data/VERSION +1 -1
  6. data/lib/generators/sorcery_migration/sorcery_migration_generator.rb +24 -0
  7. data/lib/generators/sorcery_migration/templates/activity_logging.rb +17 -0
  8. data/lib/generators/sorcery_migration/templates/brute_force_protection.rb +11 -0
  9. data/lib/generators/sorcery_migration/templates/core.rb +16 -0
  10. data/lib/generators/sorcery_migration/templates/external.rb +14 -0
  11. data/lib/generators/sorcery_migration/templates/remember_me.rb +15 -0
  12. data/lib/generators/sorcery_migration/templates/reset_password.rb +13 -0
  13. data/lib/generators/sorcery_migration/templates/user_activation.rb +17 -0
  14. data/lib/sorcery/controller/adapters/sinatra.rb +97 -0
  15. data/lib/sorcery/controller/submodules/external/protocols/oauth1.rb +35 -0
  16. data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +26 -0
  17. data/lib/sorcery/controller/submodules/{oauth → external}/providers/facebook.rb +24 -6
  18. data/lib/sorcery/controller/submodules/{oauth → external}/providers/twitter.rb +31 -6
  19. data/lib/sorcery/controller/submodules/{oauth.rb → external.rb} +18 -27
  20. data/lib/sorcery/controller/submodules/http_basic_auth.rb +11 -7
  21. data/lib/sorcery/controller.rb +21 -21
  22. data/lib/sorcery/crypto_providers/bcrypt.rb +3 -5
  23. data/lib/sorcery/crypto_providers/common.rb +35 -0
  24. data/lib/sorcery/crypto_providers/md5.rb +3 -23
  25. data/lib/sorcery/crypto_providers/sha1.rb +4 -16
  26. data/lib/sorcery/crypto_providers/sha256.rb +3 -23
  27. data/lib/sorcery/crypto_providers/sha512.rb +3 -23
  28. data/lib/sorcery/engine.rb +4 -0
  29. data/lib/sorcery/initializers/initializer.rb +86 -0
  30. data/lib/sorcery/model/submodules/activity_logging.rb +2 -2
  31. data/lib/sorcery/model/submodules/brute_force_protection.rb +1 -5
  32. data/lib/sorcery/model/submodules/{oauth.rb → external.rb} +3 -3
  33. data/lib/sorcery/model/submodules/reset_password.rb +1 -1
  34. data/lib/sorcery/model.rb +34 -9
  35. data/lib/sorcery/railties/tasks.rake +10 -0
  36. data/lib/sorcery/sinatra.rb +5 -0
  37. data/lib/sorcery/test_helpers/internal/rails.rb +52 -0
  38. data/lib/sorcery/test_helpers/internal/sinatra.rb +122 -0
  39. data/lib/sorcery/test_helpers/internal.rb +55 -0
  40. data/lib/sorcery/test_helpers/rails.rb +16 -0
  41. data/lib/sorcery/test_helpers/sinatra.rb +85 -0
  42. data/lib/sorcery/test_helpers.rb +0 -79
  43. data/lib/sorcery.rb +25 -7
  44. data/sorcery.gemspec +207 -137
  45. data/spec/Gemfile +2 -2
  46. data/spec/Gemfile.lock +20 -12
  47. data/spec/Rakefile +1 -0
  48. data/spec/rails3/.rspec +1 -1
  49. data/spec/rails3/{app_root/Gemfile → Gemfile} +5 -7
  50. data/spec/rails3/{app_root/Gemfile.lock → Gemfile.lock} +20 -23
  51. data/spec/rails3/{app_root/Rakefile → Rakefile} +1 -0
  52. data/spec/rails3/{app_root/app → app}/controllers/application_controller.rb +11 -11
  53. data/spec/rails3/config/database.yml +27 -0
  54. data/spec/rails3/{app_root/spec → spec}/controller_activity_logging_spec.rb +2 -4
  55. data/spec/rails3/{app_root/spec → spec}/controller_brute_force_protection_spec.rb +3 -2
  56. data/spec/rails3/{app_root/spec → spec}/controller_oauth2_spec.rb +25 -22
  57. data/spec/rails3/{app_root/spec → spec}/controller_oauth_spec.rb +24 -19
  58. data/spec/rails3/spec/controller_session_timeout_spec.rb +55 -0
  59. data/spec/rails3/{app_root/spec → spec}/controller_spec.rb +6 -16
  60. data/spec/rails3/spec/spec.opts +2 -0
  61. data/spec/rails3/spec/spec_helper.rb +70 -0
  62. data/spec/rails3/{app_root/spec → spec}/user_activation_spec.rb +7 -13
  63. data/spec/rails3/{app_root/spec → spec}/user_brute_force_protection_spec.rb +2 -30
  64. data/spec/rails3/{app_root/spec → spec}/user_oauth_spec.rb +7 -7
  65. data/spec/rails3/{app_root/spec → spec}/user_remember_me_spec.rb +3 -11
  66. data/spec/rails3/{app_root/spec → spec}/user_reset_password_spec.rb +20 -17
  67. data/spec/rails3/{app_root/spec → spec}/user_spec.rb +21 -11
  68. data/spec/sinatra/Gemfile +12 -0
  69. data/spec/sinatra/Gemfile.lock +134 -0
  70. data/spec/sinatra/Rakefile +11 -0
  71. data/spec/sinatra/authentication.rb +3 -0
  72. data/spec/sinatra/db/migrate/activation/20101224223622_add_activation_to_users.rb +17 -0
  73. data/spec/sinatra/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +17 -0
  74. data/spec/sinatra/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +11 -0
  75. data/spec/sinatra/db/migrate/core/20101224223620_create_users.rb +16 -0
  76. data/spec/sinatra/db/migrate/external/20101224223628_create_authentications.rb +14 -0
  77. data/spec/sinatra/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +15 -0
  78. data/spec/sinatra/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
  79. data/spec/sinatra/filters.rb +21 -0
  80. data/spec/sinatra/myapp.rb +133 -0
  81. data/spec/sinatra/sorcery_mailer.rb +25 -0
  82. data/spec/sinatra/spec/controller_activity_logging_spec.rb +85 -0
  83. data/spec/sinatra/spec/controller_brute_force_protection_spec.rb +70 -0
  84. data/spec/sinatra/spec/controller_http_basic_auth_spec.rb +53 -0
  85. data/spec/sinatra/spec/controller_oauth2_spec.rb +120 -0
  86. data/spec/sinatra/spec/controller_oauth_spec.rb +121 -0
  87. data/spec/sinatra/spec/controller_remember_me_spec.rb +64 -0
  88. data/spec/sinatra/spec/controller_session_timeout_spec.rb +57 -0
  89. data/spec/sinatra/spec/controller_spec.rb +120 -0
  90. data/spec/sinatra/spec/spec.opts +2 -0
  91. data/spec/sinatra/spec/spec_helper.rb +46 -0
  92. data/spec/sinatra/user.rb +6 -0
  93. data/spec/sinatra/views/test_login.erb +4 -0
  94. data/spec/sorcery_crypto_providers_spec.rb +5 -4
  95. data/spec/spec.opts +2 -0
  96. data/spec/spec_helper.rb +3 -4
  97. data/spec/untitled folder +18 -0
  98. metadata +217 -139
  99. data/lib/sorcery/controller/submodules/oauth/oauth1.rb +0 -26
  100. data/lib/sorcery/controller/submodules/oauth/oauth2.rb +0 -24
  101. data/spec/rails3/app_root/.rspec +0 -1
  102. data/spec/rails3/app_root/config/database.yml +0 -27
  103. data/spec/rails3/app_root/spec/controller_session_timeout_spec.rb +0 -50
  104. data/spec/rails3/app_root/spec/spec_helper.rb +0 -61
  105. /data/spec/rails3/{app_root/.gitignore → .gitignore} +0 -0
  106. /data/spec/rails3/{app_root/README → README} +0 -0
  107. /data/spec/rails3/{app_root/Rakefile.unused → Rakefile.unused} +0 -0
  108. /data/spec/rails3/{app_root/app → app}/helpers/application_helper.rb +0 -0
  109. /data/spec/rails3/{app_root/app → app}/mailers/sorcery_mailer.rb +0 -0
  110. /data/spec/rails3/{app_root/app → app}/models/authentication.rb +0 -0
  111. /data/spec/rails3/{app_root/app → app}/models/user.rb +0 -0
  112. /data/spec/rails3/{app_root/app → app}/views/layouts/application.html.erb +0 -0
  113. /data/spec/rails3/{app_root/app → app}/views/sorcery_mailer/activation_email.html.erb +0 -0
  114. /data/spec/rails3/{app_root/app → app}/views/sorcery_mailer/activation_email.text.erb +0 -0
  115. /data/spec/rails3/{app_root/app → app}/views/sorcery_mailer/activation_success_email.html.erb +0 -0
  116. /data/spec/rails3/{app_root/app → app}/views/sorcery_mailer/activation_success_email.text.erb +0 -0
  117. /data/spec/rails3/{app_root/app → app}/views/sorcery_mailer/reset_password_email.html.erb +0 -0
  118. /data/spec/rails3/{app_root/app → app}/views/sorcery_mailer/reset_password_email.text.erb +0 -0
  119. /data/spec/rails3/{app_root/config → config}/application.rb +0 -0
  120. /data/spec/rails3/{app_root/config → config}/boot.rb +0 -0
  121. /data/spec/rails3/{app_root/config → config}/environment.rb +0 -0
  122. /data/spec/rails3/{app_root/config → config}/environments/development.rb +0 -0
  123. /data/spec/rails3/{app_root/config → config}/environments/in_memory.rb +0 -0
  124. /data/spec/rails3/{app_root/config → config}/environments/production.rb +0 -0
  125. /data/spec/rails3/{app_root/config → config}/environments/test.rb +0 -0
  126. /data/spec/rails3/{app_root/config → config}/initializers/backtrace_silencers.rb +0 -0
  127. /data/spec/rails3/{app_root/config → config}/initializers/inflections.rb +0 -0
  128. /data/spec/rails3/{app_root/config → config}/initializers/mime_types.rb +0 -0
  129. /data/spec/rails3/{app_root/config → config}/initializers/secret_token.rb +0 -0
  130. /data/spec/rails3/{app_root/config → config}/initializers/session_store.rb +0 -0
  131. /data/spec/rails3/{app_root/config → config}/locales/en.yml +0 -0
  132. /data/spec/rails3/{app_root/config → config}/routes.rb +0 -0
  133. /data/spec/rails3/{app_root/config.ru → config.ru} +0 -0
  134. /data/spec/rails3/{app_root/db → db}/migrate/activation/20101224223622_add_activation_to_users.rb +0 -0
  135. /data/spec/rails3/{app_root/db → db}/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +0 -0
  136. /data/spec/rails3/{app_root/db → db}/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +0 -0
  137. /data/spec/rails3/{app_root/db → db}/migrate/core/20101224223620_create_users.rb +0 -0
  138. /data/spec/rails3/{app_root/db/migrate/oauth → db/migrate/external}/20101224223628_create_authentications.rb +0 -0
  139. /data/spec/rails3/{app_root/db → db}/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +0 -0
  140. /data/spec/rails3/{app_root/db → db}/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +0 -0
  141. /data/spec/rails3/{app_root/db → db}/schema.rb +0 -0
  142. /data/spec/rails3/{app_root/db → db}/seeds.rb +0 -0
  143. /data/spec/rails3/{app_root/lib → lib}/tasks/.gitkeep +0 -0
  144. /data/spec/rails3/{app_root/public → public}/404.html +0 -0
  145. /data/spec/rails3/{app_root/public → public}/422.html +0 -0
  146. /data/spec/rails3/{app_root/public → public}/500.html +0 -0
  147. /data/spec/rails3/{app_root/public → public}/favicon.ico +0 -0
  148. /data/spec/rails3/{app_root/public → public}/images/rails.png +0 -0
  149. /data/spec/rails3/{app_root/public → public}/index.html +0 -0
  150. /data/spec/rails3/{app_root/public → public}/javascripts/application.js +0 -0
  151. /data/spec/rails3/{app_root/public → public}/javascripts/controls.js +0 -0
  152. /data/spec/rails3/{app_root/public → public}/javascripts/dragdrop.js +0 -0
  153. /data/spec/rails3/{app_root/public → public}/javascripts/effects.js +0 -0
  154. /data/spec/rails3/{app_root/public → public}/javascripts/prototype.js +0 -0
  155. /data/spec/rails3/{app_root/public → public}/javascripts/rails.js +0 -0
  156. /data/spec/rails3/{app_root/public → public}/robots.txt +0 -0
  157. /data/spec/rails3/{app_root/public → public}/stylesheets/.gitkeep +0 -0
  158. /data/spec/rails3/{app_root/script → script}/rails +0 -0
  159. /data/spec/rails3/{app_root/spec → spec}/controller_http_basic_auth_spec.rb +0 -0
  160. /data/spec/rails3/{app_root/spec → spec}/controller_remember_me_spec.rb +0 -0
  161. /data/spec/rails3/{app_root/spec → spec}/spec_helper.orig.rb +0 -0
  162. /data/spec/rails3/{app_root/spec → spec}/user_activity_logging_spec.rb +0 -0
  163. /data/spec/rails3/{app_root/vendor → vendor}/plugins/.gitkeep +0 -0
@@ -20,7 +20,7 @@ module Sorcery
20
20
  @defaults.merge!(:@last_login_at_attribute_name => :last_login_at,
21
21
  :@last_logout_at_attribute_name => :last_logout_at,
22
22
  :@last_activity_at_attribute_name => :last_activity_at,
23
- :@activity_timeout => 10.minutes)
23
+ :@activity_timeout => 10 * 60)
24
24
  reset!
25
25
  end
26
26
  end
@@ -31,7 +31,7 @@ module Sorcery
31
31
  config = sorcery_config
32
32
  where("#{config.last_activity_at_attribute_name} IS NOT NULL") \
33
33
  .where("#{config.last_logout_at_attribute_name} IS NULL OR #{config.last_activity_at_attribute_name} > #{config.last_logout_at_attribute_name}") \
34
- .where("#{config.last_activity_at_attribute_name} > ? ", config.activity_timeout.seconds.ago)
34
+ .where("#{config.last_activity_at_attribute_name} > ? ", config.activity_timeout.seconds.ago.utc.to_s(:db))
35
35
  end
36
36
  end
37
37
  end
@@ -16,14 +16,10 @@ module Sorcery
16
16
  @defaults.merge!(:@failed_logins_count_attribute_name => :failed_logins_count,
17
17
  :@lock_expires_at_attribute_name => :lock_expires_at,
18
18
  :@consecutive_login_retries_amount_limit => 50,
19
- :@login_lock_time_period => 3600)
19
+ :@login_lock_time_period => 60 * 60)
20
20
  reset!
21
21
  end
22
22
 
23
- base.class_eval do
24
-
25
- end
26
-
27
23
  base.sorcery_config.before_authenticate << :prevent_locked_user_login
28
24
  base.extend(ClassMethods)
29
25
  base.send(:include, InstanceMethods)
@@ -1,9 +1,9 @@
1
1
  module Sorcery
2
2
  module Model
3
3
  module Submodules
4
- # This submodule helps you login users from OAuth providers such as Twitter.
4
+ # This submodule helps you login users from external providers such as Twitter.
5
5
  # This is the model part which handles finding the user using access tokens.
6
- # For the controller options see Sorcery::Controller::Oauth.
6
+ # For the controller options see Sorcery::Controller::External.
7
7
  #
8
8
  # Socery assumes (read: requires) you will create external users in the same table where you keep your regular users,
9
9
  # but that you will have a separate table for keeping their external authentication data,
@@ -11,7 +11,7 @@ module Sorcery
11
11
  #
12
12
  # External users will have a null crypted_password field, since we do not hold their password.
13
13
  # They will not be sent activation emails on creation.
14
- module Oauth
14
+ module External
15
15
  def self.included(base)
16
16
  base.sorcery_config.class_eval do
17
17
  attr_accessor :authentications_class,
@@ -28,7 +28,7 @@ module Sorcery
28
28
  :@reset_password_mailer => nil,
29
29
  :@reset_password_email_method_name => :reset_password_email,
30
30
  :@reset_password_expiration_period => nil,
31
- :@reset_password_time_between_emails => 5.minutes )
31
+ :@reset_password_time_between_emails => 5 * 60 )
32
32
 
33
33
  reset!
34
34
  end
data/lib/sorcery/model.rb CHANGED
@@ -9,30 +9,36 @@ module Sorcery
9
9
  def self.included(klass)
10
10
  klass.class_eval do
11
11
  class << self
12
- def activate_sorcery!
12
+ def authenticates_with_sorcery!
13
13
  @sorcery_config = Config.new
14
14
  self.class_eval do
15
15
  extend ClassMethods # included here, before submodules, so they can be overriden by them.
16
16
  include InstanceMethods
17
+
18
+ # set the user_class for the controller methods which call it
17
19
  ::Sorcery::Controller::Config.user_class = self
18
20
  @sorcery_config.submodules = ::Sorcery::Controller::Config.submodules
19
21
  @sorcery_config.submodules.each do |mod|
20
22
  begin
21
23
  include Submodules.const_get(mod.to_s.split("_").map {|p| p.capitalize}.join(""))
22
24
  rescue NameError
23
- # don't stop on a missing submodule.
25
+ # don't stop on a missing submodule. Needed because some submodules are only defined in the controller side.
24
26
  end
25
27
  end
26
28
  end
27
29
 
28
- yield @sorcery_config if block_given?
30
+ # This runs the options block set in the initializer on the model class.
31
+ ::Sorcery::Controller::Config.user_config.tap{|blk| blk.call(@sorcery_config) if blk}
29
32
 
33
+ # add virtual password accessor and ORM callbacks
30
34
  self.class_eval do
31
35
  attr_accessor @sorcery_config.password_attribute_name
32
36
  attr_protected @sorcery_config.crypted_password_attribute_name, @sorcery_config.salt_attribute_name
33
37
  before_save :encrypt_password, :if => Proc.new { |record| record.send(sorcery_config.password_attribute_name).present? }
34
38
  after_save :clear_virtual_password, :if => Proc.new { |record| record.send(sorcery_config.password_attribute_name).present? }
35
39
  end
40
+
41
+ @sorcery_config.after_config << :add_config_inheritence if @sorcery_config.subclasses_inherit_config
36
42
  @sorcery_config.after_config.each { |c| send(c) }
37
43
  end
38
44
  end
@@ -56,12 +62,6 @@ module Sorcery
56
62
  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)
57
63
  end
58
64
 
59
- # Calls the configured encryption provider to compare the supplied password with the encrypted one.
60
- def credentials_match?(crypted, *tokens)
61
- return crypted == tokens.join if @sorcery_config.encryption_provider.nil?
62
- @sorcery_config.encryption_provider.matches?(crypted, *tokens)
63
- end
64
-
65
65
  # encrypt tokens using current encryption_provider.
66
66
  def encrypt(*tokens)
67
67
  return tokens.first if @sorcery_config.encryption_provider.nil?
@@ -71,6 +71,29 @@ module Sorcery
71
71
  CryptoProviders::AES256.key = @sorcery_config.encryption_key if @sorcery_config.encryption_algorithm == :aes256
72
72
  @sorcery_config.encryption_provider.encrypt(*tokens)
73
73
  end
74
+
75
+ protected
76
+
77
+ # Calls the configured encryption provider to compare the supplied password with the encrypted one.
78
+ def credentials_match?(crypted, *tokens)
79
+ return crypted == tokens.join if @sorcery_config.encryption_provider.nil?
80
+ @sorcery_config.encryption_provider.matches?(crypted, *tokens)
81
+ end
82
+
83
+ def add_config_inheritence
84
+ self.class_eval do
85
+ def self.inherited(subclass)
86
+ subclass.class_eval do
87
+ class << self
88
+ attr_accessor :sorcery_config
89
+ end
90
+ end
91
+ subclass.sorcery_config = sorcery_config
92
+ super
93
+ end
94
+ end
95
+ end
96
+
74
97
  end
75
98
 
76
99
  module InstanceMethods
@@ -128,6 +151,7 @@ module Sorcery
128
151
  :salt_attribute_name, # change default salt attribute.
129
152
  :stretches, # how many times to apply encryption to the password.
130
153
  :encryption_key, # encryption key used to encrypt reversible encryptions such as AES256.
154
+ :subclasses_inherit_config, # make this configuration inheritable for subclasses. Useful for ActiveRecord's STI.
131
155
 
132
156
  :submodules, # configured in config/application.rb
133
157
  :before_authenticate, # an array of method names to call before authentication completes. used internally.
@@ -151,6 +175,7 @@ module Sorcery
151
175
  :@salt_join_token => "",
152
176
  :@salt_attribute_name => :salt,
153
177
  :@stretches => nil,
178
+ :@subclasses_inherit_config => false,
154
179
  :@before_authenticate => [],
155
180
  :@after_config => []
156
181
  }
@@ -0,0 +1,10 @@
1
+ require 'fileutils'
2
+
3
+ namespace :sorcery do
4
+ desc "Adds sorcery's initializer file"
5
+ task :bootstrap do
6
+ src = File.join(File.dirname(__FILE__), '..', 'initializers', 'initializer.rb')
7
+ target = File.join(Rails.root, "config", "initializers", "sorcery.rb")
8
+ FileUtils.cp(src, target)
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ ActiveRecord::Base.send(:include, Sorcery::Model) if defined?(ActiveRecord)
2
+ if defined?(Sinatra::Base)
3
+ Sinatra::Base.send(:include, Sorcery::Controller::Adapters::Sinatra)
4
+ Sinatra::Base.send(:include, Sorcery::Controller)
5
+ end
@@ -0,0 +1,52 @@
1
+ module Sorcery
2
+ module TestHelpers
3
+ module Internal
4
+ module Rails
5
+ include ::Sorcery::TestHelpers::Rails
6
+
7
+ SUBMODUELS_AUTO_ADDED_CONTROLLER_FILTERS = [:register_last_activity_time_to_db, :deny_banned_user, :validate_session]
8
+
9
+ def sorcery_reload!(submodules = [], options = {})
10
+ reload_user_class
11
+
12
+ # return to no-module configuration
13
+ ::Sorcery::Controller::Config.init!
14
+ ::Sorcery::Controller::Config.reset!
15
+
16
+ # remove all plugin before_filters so they won't fail other tests.
17
+ # I don't like this way, but I didn't find another.
18
+ # hopefully it won't break until Rails 4.
19
+ ApplicationController._process_action_callbacks.delete_if {|c| SUBMODUELS_AUTO_ADDED_CONTROLLER_FILTERS.include?(c.filter) }
20
+
21
+ # configure
22
+ ::Sorcery::Controller::Config.submodules = submodules
23
+ ::Sorcery::Controller::Config.user_class = nil
24
+ ActionController::Base.send(:include,::Sorcery::Controller)
25
+
26
+ ::Sorcery::Controller::Config.user_config do |user|
27
+ options.each do |property,value|
28
+ user.send(:"#{property}=", value)
29
+ end
30
+ end
31
+ User.authenticates_with_sorcery!
32
+ end
33
+
34
+ def sorcery_controller_property_set(property, value)
35
+ ::Sorcery::Controller::Config.send(:"#{property}=", value)
36
+ end
37
+
38
+ def sorcery_controller_external_property_set(provider, property, value)
39
+ ::Sorcery::Controller::Config.send(provider).send(:"#{property}=", value)
40
+ end
41
+
42
+ # This helper is used to fake multiple users signing in in tests.
43
+ # It does so by clearing @current_user, thus allowing a new user to login,
44
+ # all this without calling the :logout action explicitly.
45
+ # A dirty dirty hack.
46
+ def clear_user_without_logout
47
+ subject.instance_variable_set(:@current_user,nil)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,122 @@
1
+ module Sorcery
2
+ module TestHelpers
3
+ module Internal
4
+ module Sinatra
5
+
6
+ class ::Sinatra::Application
7
+ class << self
8
+ attr_accessor :sorcery_vars
9
+ end
10
+ @sorcery_vars = {}
11
+
12
+ # NOTE: see before and after test filters in filters.rb
13
+
14
+ def save_instance_vars
15
+ instance_variables.each do |var|
16
+ self.class.sorcery_vars[:"#{var.to_s.delete("@")}"] = instance_variable_get(var)
17
+ end
18
+ end
19
+ end
20
+
21
+ ::RSpec::Matchers.define :redirect_to do |expected|
22
+ match do |actual|
23
+ actual.status == 302 && actual.location == expected
24
+ end
25
+ end
26
+
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
+ def clear_user_without_logout
45
+ get_sinatra_app(subject).instance_variable_set(:@current_user,nil)
46
+ end
47
+
48
+ def assigns
49
+ ::Sinatra::Application.sorcery_vars
50
+ end
51
+
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
+ def sorcery_reload!(submodules = [], options = {})
86
+ reload_user_class
87
+
88
+ # return to no-module configuration
89
+ ::Sorcery::Controller::Config.init!
90
+ ::Sorcery::Controller::Config.reset!
91
+
92
+ # clear all filters
93
+ ::Sinatra::Application.instance_variable_set(:@filters,{:before => [],:after => []})
94
+ ::Sinatra::Application.class_eval do
95
+ load File.join(File.dirname(__FILE__),'..','..','..','..','spec','sinatra','filters.rb')
96
+ end
97
+
98
+ # configure
99
+ ::Sorcery::Controller::Config.submodules = submodules
100
+ ::Sorcery::Controller::Config.user_class = nil
101
+ ::Sinatra::Application.send(:include, Sorcery::Controller::Adapters::Sinatra)
102
+ ::Sinatra::Application.send(:include, Sorcery::Controller)
103
+
104
+ ::Sorcery::Controller::Config.user_config do |user|
105
+ options.each do |property,value|
106
+ user.send(:"#{property}=", value)
107
+ end
108
+ end
109
+ User.authenticates_with_sorcery!
110
+ end
111
+
112
+ def sorcery_controller_property_set(property, value)
113
+ ::Sorcery::Controller::Config.send(:"#{property}=", value)
114
+ end
115
+
116
+ def sorcery_controller_external_property_set(provider, property, value)
117
+ ::Sorcery::Controller::Config.send(provider).send(:"#{property}=", value)
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,55 @@
1
+ module Sorcery
2
+ module TestHelpers
3
+ # Internal TestHelpers are used to test the gem, internally, and should not be used to test apps *using* sorcery.
4
+ # This file will be included in the spec_helper file.
5
+ module Internal
6
+ def self.included(base)
7
+ # reducing default cost for specs speed
8
+ CryptoProviders::BCrypt.class_eval do
9
+ class << self
10
+ def cost
11
+ 1
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ # a patch to fix a bug in testing that happens when you 'destroy' a session twice.
18
+ # After the first destroy, the session is an ordinary hash, and then when destroy is called again there's an exception.
19
+ class ::Hash
20
+ def destroy
21
+ clear
22
+ end
23
+ end
24
+
25
+ def create_new_user(attributes_hash = nil)
26
+ user_attributes_hash = attributes_hash || {:username => 'gizmo', :email => "bla@bla.com", :password => 'secret'}
27
+ @user = User.new(user_attributes_hash)
28
+ @user.save!
29
+ @user
30
+ end
31
+
32
+ def create_new_external_user(provider, attributes_hash = nil)
33
+ user_attributes_hash = attributes_hash || {:username => 'gizmo', :authentications_attributes => [{:provider => provider, :uid => 123}]}
34
+ @user = User.new(user_attributes_hash)
35
+ @user.save!
36
+ @user
37
+ end
38
+
39
+ def sorcery_model_property_set(property, *values)
40
+ User.class_eval do
41
+ sorcery_config.send(:"#{property}=", *values)
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ # reload user class between specs
48
+ # so it will be possible to test the different submodules in isolation
49
+ def reload_user_class
50
+ Object.send(:remove_const,:User)
51
+ load 'user.rb'
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,16 @@
1
+ module Sorcery
2
+ module TestHelpers
3
+ module Rails
4
+ # logins a user and calls all callbacks
5
+ def login_user(user = nil)
6
+ user ||= @user
7
+ @controller.send(:login_user,user)
8
+ @controller.send(:after_login!,user,[user.send(user.sorcery_config.username_attribute_name),'secret'])
9
+ end
10
+
11
+ def logout_user
12
+ @controller.send(:logout)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,85 @@
1
+ module Sorcery
2
+ module TestHelpers
3
+ module Sinatra
4
+ def self.included(base)
5
+ base.send(:include, InstanceMethods)
6
+ base.send(:include, CookieSessionMethods)
7
+ ::Sinatra::Base.class_eval do
8
+ class << self
9
+ attr_accessor :rack_test_session
10
+ end
11
+
12
+ def self.inherited(subclass)
13
+ super
14
+ subclass.class_eval do
15
+ class << self
16
+ attr_accessor :rack_test_session
17
+ end
18
+ end
19
+ end
20
+
21
+ include CookieSessionMethods
22
+
23
+ def rack_test_session
24
+ self.class.rack_test_session
25
+ end
26
+ end
27
+ end
28
+
29
+ module InstanceMethods
30
+ def get_sinatra_app(app)
31
+ while !app.kind_of? ::Sinatra::Base do
32
+ app = app.instance_variable_get(:@app)
33
+ end
34
+ app
35
+ end
36
+
37
+ def login_user(user=nil)
38
+ user ||= @user
39
+ get_sinatra_app(app).send(:login_user, user)
40
+ get_sinatra_app(app).send(:after_login!, user, [user.send(user.sorcery_config.username_attribute_name), 'secret'])
41
+ end
42
+
43
+ def logout_user
44
+ get_sinatra_app(app).send(:logout)
45
+ end
46
+ end
47
+
48
+ module CookieSessionMethods
49
+ class SessionData
50
+ def initialize(cookies)
51
+ @cookies = cookies
52
+ @data = cookies['rack.session']
53
+ if @data
54
+ @data = @data.unpack("m*").first
55
+ @data = Marshal.load(@data)
56
+ else
57
+ @data = {}
58
+ end
59
+ end
60
+
61
+ def [](key)
62
+ @data[key]
63
+ end
64
+
65
+ def []=(key, value)
66
+ @data[key] = value
67
+ session_data = Marshal.dump(@data)
68
+ session_data = [session_data].pack("m*")
69
+ @cookies.merge("rack.session=#{Rack::Utils.escape(session_data)}", URI.parse("//example.org//"))
70
+ raise "session variable not set" unless @cookies['rack.session'] == session_data
71
+ end
72
+
73
+ def clear
74
+ @data = {}
75
+ end
76
+ end
77
+
78
+ def session
79
+ SessionData.new(rack_test_session.instance_variable_get(:@rack_mock_session).cookie_jar)
80
+ end
81
+
82
+ end
83
+ end
84
+ end
85
+ end
@@ -1,84 +1,5 @@
1
1
  module Sorcery
2
2
  module TestHelpers
3
- SUBMODUELS_AUTO_ADDED_CONTROLLER_FILTERS = [:register_last_activity_time_to_db, :deny_banned_user, :validate_session]
4
3
 
5
- def create_new_user(attributes_hash = nil)
6
- user_attributes_hash = attributes_hash || {:username => 'gizmo', :email => "bla@bla.com", :password => 'secret'}
7
- @user = User.new(user_attributes_hash)
8
- @user.save!
9
- @user
10
- end
11
-
12
- def create_new_external_user(provider, attributes_hash = nil)
13
- user_attributes_hash = attributes_hash || {:username => 'gizmo', :authentications_attributes => [{:provider => provider, :uid => 123}]}
14
- @user = User.new(user_attributes_hash)
15
- @user.save!
16
- @user
17
- end
18
-
19
- def login_user(user = nil)
20
- user ||= @user
21
- subject.send(:login_user,user)
22
- subject.send(:after_login!,user,[user.username,'secret'])
23
- end
24
-
25
- def logout_user
26
- subject.send(:logout)
27
- end
28
-
29
- def clear_user_without_logout
30
- subject.instance_variable_set(:@current_user,nil)
31
- end
32
-
33
- def sorcery_reload!(submodules = [], options = {})
34
- reload_user_class
35
-
36
- # return to no-module configuration
37
- ::Sorcery::Controller::Config.init!
38
- ::Sorcery::Controller::Config.reset!
39
-
40
- # remove all plugin before_filters so they won't fail other tests.
41
- # I don't like this way, but I didn't find another.
42
- # hopefully it won't break until Rails 4.
43
- ApplicationController._process_action_callbacks.delete_if {|c| SUBMODUELS_AUTO_ADDED_CONTROLLER_FILTERS.include?(c.filter) }
44
-
45
- # configure
46
- ::Sorcery::Controller::Config.submodules = submodules
47
- ::Sorcery::Controller::Config.user_class = nil
48
- ActionController::Base.send(:include,::Sorcery::Controller)
49
-
50
- User.activate_sorcery! do |config|
51
- options.each do |property,value|
52
- config.send(:"#{property}=", value)
53
- end
54
- end
55
- end
56
-
57
- def sorcery_model_property_set(property, *values)
58
- User.class_eval do
59
- sorcery_config.send(:"#{property}=", *values)
60
- end
61
- end
62
-
63
- def sorcery_controller_property_set(property, value)
64
- ApplicationController.activate_sorcery! do |config|
65
- config.send(:"#{property}=", value)
66
- end
67
- end
68
-
69
- def sorcery_controller_oauth_property_set(provider, property, value)
70
- ApplicationController.activate_sorcery! do |config|
71
- config.send(provider).send(:"#{property}=", value)
72
- end
73
- end
74
-
75
- private
76
-
77
- # reload user class between specs
78
- # so it will be possible to test the different submodules in isolation
79
- def reload_user_class
80
- Object.send(:remove_const,:User)
81
- load 'user.rb'
82
- end
83
4
  end
84
5
  end
data/lib/sorcery.rb CHANGED
@@ -8,7 +8,7 @@ module Sorcery
8
8
  autoload :RememberMe, 'sorcery/model/submodules/remember_me'
9
9
  autoload :ActivityLogging, 'sorcery/model/submodules/activity_logging'
10
10
  autoload :BruteForceProtection, 'sorcery/model/submodules/brute_force_protection'
11
- autoload :Oauth, 'sorcery/model/submodules/oauth'
11
+ autoload :External, 'sorcery/model/submodules/external'
12
12
  end
13
13
  end
14
14
  autoload :Controller, 'sorcery/controller'
@@ -19,18 +19,24 @@ module Sorcery
19
19
  autoload :BruteForceProtection, 'sorcery/controller/submodules/brute_force_protection'
20
20
  autoload :HttpBasicAuth, 'sorcery/controller/submodules/http_basic_auth'
21
21
  autoload :ActivityLogging, 'sorcery/controller/submodules/activity_logging'
22
- autoload :Oauth, 'sorcery/controller/submodules/oauth'
23
- module Oauth
24
- autoload :Oauth1, 'sorcery/controller/submodules/oauth/oauth1'
25
- autoload :Oauth2, 'sorcery/controller/submodules/oauth/oauth2'
22
+ autoload :External, 'sorcery/controller/submodules/external'
23
+ module External
24
+ module Protocols
25
+ autoload :Oauth1, 'sorcery/controller/submodules/external/protocols/oauth1'
26
+ autoload :Oauth2, 'sorcery/controller/submodules/external/protocols/oauth2'
27
+ end
26
28
  module Providers
27
- autoload :Twitter, 'sorcery/controller/submodules/oauth/providers/twitter'
28
- autoload :Facebook, 'sorcery/controller/submodules/oauth/providers/facebook'
29
+ autoload :Twitter, 'sorcery/controller/submodules/external/providers/twitter'
30
+ autoload :Facebook, 'sorcery/controller/submodules/external/providers/facebook'
29
31
  end
30
32
  end
31
33
  end
34
+ module Adapters
35
+ autoload :Sinatra, 'sorcery/controller/adapters/sinatra'
36
+ end
32
37
  end
33
38
  module CryptoProviders
39
+ autoload :Common, 'sorcery/crypto_providers/common'
34
40
  autoload :AES256, 'sorcery/crypto_providers/aes256'
35
41
  autoload :BCrypt, 'sorcery/crypto_providers/bcrypt'
36
42
  autoload :MD5, 'sorcery/crypto_providers/md5'
@@ -39,6 +45,18 @@ module Sorcery
39
45
  autoload :SHA512, 'sorcery/crypto_providers/sha512'
40
46
  end
41
47
  autoload :TestHelpers, 'sorcery/test_helpers'
48
+ module TestHelpers
49
+ autoload :Rails, 'sorcery/test_helpers/rails'
50
+ autoload :Sinatra, 'sorcery/test_helpers/sinatra'
51
+ autoload :Internal, 'sorcery/test_helpers/internal'
52
+ module Internal
53
+ autoload :Rails, 'sorcery/test_helpers/internal/rails'
54
+ autoload :Sinatra, 'sorcery/test_helpers/internal/sinatra'
55
+ end
56
+
57
+ end
58
+
42
59
 
43
60
  require 'sorcery/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
61
+ require 'sorcery/sinatra' if defined?(Sinatra)
44
62
  end