sorcery 0.1.4 → 0.3.1

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 (113) hide show
  1. data/Gemfile +4 -2
  2. data/Gemfile.lock +16 -13
  3. data/README.rdoc +149 -78
  4. data/Rakefile +5 -0
  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/activity_logging.rb +20 -7
  16. data/lib/sorcery/controller/submodules/brute_force_protection.rb +9 -2
  17. data/lib/sorcery/controller/submodules/email.rb +44 -0
  18. data/lib/sorcery/controller/submodules/external/protocols/oauth1.rb +35 -0
  19. data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +26 -0
  20. data/lib/sorcery/controller/submodules/external/providers/facebook.rb +82 -0
  21. data/lib/sorcery/controller/submodules/external/providers/twitter.rb +86 -0
  22. data/lib/sorcery/controller/submodules/external.rb +83 -0
  23. data/lib/sorcery/controller/submodules/http_basic_auth.rb +18 -9
  24. data/lib/sorcery/controller/submodules/oauth.rb +95 -0
  25. data/lib/sorcery/controller/submodules/remember_me.rb +14 -5
  26. data/lib/sorcery/controller/submodules/session_timeout.rb +6 -1
  27. data/lib/sorcery/controller.rb +30 -16
  28. data/lib/sorcery/engine.rb +9 -2
  29. data/lib/sorcery/model/submodules/activity_logging.rb +13 -8
  30. data/lib/sorcery/model/submodules/brute_force_protection.rb +11 -8
  31. data/lib/sorcery/model/submodules/external.rb +53 -0
  32. data/lib/sorcery/model/submodules/remember_me.rb +5 -3
  33. data/lib/sorcery/model/submodules/reset_password.rb +16 -13
  34. data/lib/sorcery/model/submodules/user_activation.rb +38 -19
  35. data/lib/sorcery/model/temporary_token.rb +22 -0
  36. data/lib/sorcery/model.rb +17 -7
  37. data/lib/sorcery/sinatra.rb +14 -0
  38. data/lib/sorcery/test_helpers/rails.rb +57 -0
  39. data/lib/sorcery/test_helpers/sinatra.rb +131 -0
  40. data/lib/sorcery/test_helpers.rb +40 -0
  41. data/lib/sorcery.rb +22 -0
  42. data/sorcery.gemspec +146 -41
  43. data/spec/Gemfile +3 -2
  44. data/spec/Gemfile.lock +15 -2
  45. data/spec/rails3/app_root/.rspec +1 -0
  46. data/spec/rails3/{Gemfile → app_root/Gemfile} +4 -4
  47. data/spec/rails3/{Gemfile.lock → app_root/Gemfile.lock} +23 -3
  48. data/spec/rails3/app_root/app/controllers/application_controller.rb +42 -1
  49. data/spec/rails3/app_root/app/models/authentication.rb +3 -0
  50. data/spec/rails3/app_root/app/models/user.rb +4 -1
  51. data/spec/rails3/app_root/config/application.rb +1 -3
  52. data/spec/rails3/app_root/config/routes.rb +1 -10
  53. data/spec/rails3/app_root/db/migrate/activation/20101224223622_add_activation_to_users.rb +6 -4
  54. data/spec/rails3/app_root/db/migrate/core/20101224223620_create_users.rb +4 -4
  55. data/spec/rails3/app_root/db/migrate/external/20101224223628_create_authentications.rb +14 -0
  56. data/spec/rails3/{controller_activity_logging_spec.rb → app_root/spec/controller_activity_logging_spec.rb} +13 -13
  57. data/spec/rails3/{controller_brute_force_protection_spec.rb → app_root/spec/controller_brute_force_protection_spec.rb} +16 -6
  58. data/spec/rails3/{controller_http_basic_auth_spec.rb → app_root/spec/controller_http_basic_auth_spec.rb} +3 -3
  59. data/spec/rails3/app_root/spec/controller_oauth2_spec.rb +119 -0
  60. data/spec/rails3/app_root/spec/controller_oauth_spec.rb +122 -0
  61. data/spec/rails3/{controller_remember_me_spec.rb → app_root/spec/controller_remember_me_spec.rb} +4 -4
  62. data/spec/rails3/{controller_session_timeout_spec.rb → app_root/spec/controller_session_timeout_spec.rb} +6 -6
  63. data/spec/rails3/{controller_spec.rb → app_root/spec/controller_spec.rb} +20 -13
  64. data/spec/rails3/app_root/spec/spec_helper.orig.rb +27 -0
  65. data/spec/rails3/app_root/spec/spec_helper.rb +62 -0
  66. data/spec/rails3/{user_activation_spec.rb → app_root/spec/user_activation_spec.rb} +60 -20
  67. data/spec/rails3/{user_activity_logging_spec.rb → app_root/spec/user_activity_logging_spec.rb} +4 -4
  68. data/spec/rails3/{user_brute_force_protection_spec.rb → app_root/spec/user_brute_force_protection_spec.rb} +7 -7
  69. data/spec/rails3/app_root/spec/user_oauth_spec.rb +39 -0
  70. data/spec/rails3/{user_remember_me_spec.rb → app_root/spec/user_remember_me_spec.rb} +4 -4
  71. data/spec/rails3/{user_reset_password_spec.rb → app_root/spec/user_reset_password_spec.rb} +21 -41
  72. data/spec/rails3/app_root/spec/user_spec.rb +317 -0
  73. data/spec/sinatra/Gemfile +12 -0
  74. data/spec/sinatra/Gemfile.lock +134 -0
  75. data/spec/sinatra/Rakefile +10 -0
  76. data/spec/sinatra/authentication.rb +3 -0
  77. data/spec/sinatra/db/migrate/activation/20101224223622_add_activation_to_users.rb +17 -0
  78. data/spec/sinatra/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +17 -0
  79. data/spec/sinatra/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +11 -0
  80. data/spec/sinatra/db/migrate/core/20101224223620_create_users.rb +16 -0
  81. data/spec/sinatra/db/migrate/external/20101224223628_create_authentications.rb +14 -0
  82. data/spec/sinatra/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +15 -0
  83. data/spec/sinatra/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
  84. data/spec/sinatra/filters.rb +21 -0
  85. data/spec/sinatra/myapp.rb +133 -0
  86. data/spec/sinatra/sorcery_mailer.rb +25 -0
  87. data/spec/sinatra/spec/controller_activity_logging_spec.rb +85 -0
  88. data/spec/sinatra/spec/controller_brute_force_protection_spec.rb +69 -0
  89. data/spec/sinatra/spec/controller_http_basic_auth_spec.rb +53 -0
  90. data/spec/sinatra/spec/controller_oauth2_spec.rb +119 -0
  91. data/spec/sinatra/spec/controller_oauth_spec.rb +121 -0
  92. data/spec/sinatra/spec/controller_remember_me_spec.rb +64 -0
  93. data/spec/sinatra/spec/controller_session_timeout_spec.rb +52 -0
  94. data/spec/sinatra/spec/controller_spec.rb +120 -0
  95. data/spec/sinatra/spec/spec.opts +4 -0
  96. data/spec/sinatra/spec/spec_helper.rb +44 -0
  97. data/spec/sinatra/spec/user_activation_spec.rb +188 -0
  98. data/spec/sinatra/spec/user_activity_logging_spec.rb +36 -0
  99. data/spec/sinatra/spec/user_brute_force_protection_spec.rb +76 -0
  100. data/spec/sinatra/spec/user_oauth_spec.rb +39 -0
  101. data/spec/sinatra/spec/user_remember_me_spec.rb +66 -0
  102. data/spec/sinatra/spec/user_reset_password_spec.rb +178 -0
  103. data/spec/{rails3 → sinatra/spec}/user_spec.rb +68 -38
  104. data/spec/sinatra/user.rb +6 -0
  105. data/spec/sinatra/views/test_login.erb +4 -0
  106. data/spec/untitled folder +18 -0
  107. metadata +203 -58
  108. data/spec/rails3/app_root/test/fixtures/users.yml +0 -9
  109. data/spec/rails3/app_root/test/performance/browsing_test.rb +0 -9
  110. data/spec/rails3/app_root/test/test_helper.rb +0 -13
  111. data/spec/rails3/app_root/test/unit/user_test.rb +0 -8
  112. data/spec/rails3/spec_helper.rb +0 -135
  113. /data/spec/rails3/{Rakefile → app_root/Rakefile} +0 -0
@@ -13,7 +13,7 @@ describe "User with reset_password submodule" do
13
13
  describe User, "loaded plugin configuration" do
14
14
 
15
15
  before(:all) do
16
- plugin_model_configure([:reset_password], :reset_password_mailer => ::SorceryMailer)
16
+ sorcery_reload!([:reset_password], :reset_password_mailer => ::SorceryMailer)
17
17
  end
18
18
 
19
19
  after(:each) do
@@ -25,11 +25,6 @@ describe "User with reset_password submodule" do
25
25
  @user.should respond_to(:deliver_reset_password_instructions!)
26
26
  end
27
27
 
28
- it "should respond to 'reset_password_token_valid?'" do
29
- create_new_user
30
- @user.should respond_to(:reset_password_token_valid?)
31
- end
32
-
33
28
  it "should respond to 'reset_password!" do
34
29
  create_new_user
35
30
  @user.should respond_to(:reset_password!)
@@ -41,32 +36,32 @@ describe "User with reset_password submodule" do
41
36
  end
42
37
 
43
38
  it "should allow configuration option 'reset_password_token_attribute_name'" do
44
- plugin_set_model_config_property(:reset_password_token_attribute_name, :my_code)
39
+ sorcery_model_property_set(:reset_password_token_attribute_name, :my_code)
45
40
  User.sorcery_config.reset_password_token_attribute_name.should equal(:my_code)
46
41
  end
47
42
 
48
43
  it "should allow configuration option 'reset_password_mailer'" do
49
- plugin_set_model_config_property(:reset_password_mailer, TestUser)
44
+ sorcery_model_property_set(:reset_password_mailer, TestUser)
50
45
  User.sorcery_config.reset_password_mailer.should equal(TestUser)
51
46
  end
52
47
 
53
48
  it "should allow configuration option 'reset_password_email_method_name'" do
54
- plugin_set_model_config_property(:reset_password_email_method_name, :my_mailer_method)
49
+ sorcery_model_property_set(:reset_password_email_method_name, :my_mailer_method)
55
50
  User.sorcery_config.reset_password_email_method_name.should equal(:my_mailer_method)
56
51
  end
57
52
 
58
53
  it "should allow configuration option 'reset_password_expiration_period'" do
59
- plugin_set_model_config_property(:reset_password_expiration_period, 16)
54
+ sorcery_model_property_set(:reset_password_expiration_period, 16)
60
55
  User.sorcery_config.reset_password_expiration_period.should equal(16)
61
56
  end
62
57
 
63
58
  it "should allow configuration option 'reset_password_email_sent_at_attribute_name'" do
64
- plugin_set_model_config_property(:reset_password_email_sent_at_attribute_name, :blabla)
59
+ sorcery_model_property_set(:reset_password_email_sent_at_attribute_name, :blabla)
65
60
  User.sorcery_config.reset_password_email_sent_at_attribute_name.should equal(:blabla)
66
61
  end
67
62
 
68
63
  it "should allow configuration option 'reset_password_time_between_emails'" do
69
- plugin_set_model_config_property(:reset_password_time_between_emails, 16)
64
+ sorcery_model_property_set(:reset_password_time_between_emails, 16)
70
65
  User.sorcery_config.reset_password_time_between_emails.should equal(16)
71
66
  end
72
67
  end
@@ -75,7 +70,7 @@ describe "User with reset_password submodule" do
75
70
  describe User, "when activated with sorcery" do
76
71
 
77
72
  before(:all) do
78
- plugin_model_configure([:reset_password], :reset_password_mailer => ::SorceryMailer)
73
+ sorcery_reload!([:reset_password], :reset_password_mailer => ::SorceryMailer)
79
74
  end
80
75
 
81
76
  before(:each) do
@@ -96,19 +91,26 @@ describe "User with reset_password submodule" do
96
91
 
97
92
  it "load_from_reset_password_token should return user when token is found and not expired" do
98
93
  create_new_user
99
- plugin_set_model_config_property(:reset_password_expiration_period, 500)
94
+ sorcery_model_property_set(:reset_password_expiration_period, 500)
100
95
  @user.deliver_reset_password_instructions!
101
96
  User.load_from_reset_password_token(@user.reset_password_token).should == @user
102
97
  end
103
98
 
104
99
  it "load_from_reset_password_token should NOT return user when token is found and expired" do
105
100
  create_new_user
106
- plugin_set_model_config_property(:reset_password_expiration_period, 0.1)
101
+ sorcery_model_property_set(:reset_password_expiration_period, 0.1)
107
102
  @user.deliver_reset_password_instructions!
108
103
  sleep 0.5
109
104
  User.load_from_reset_password_token(@user.reset_password_token).should == nil
110
105
  end
111
106
 
107
+ it "load_from_reset_password_token should always be valid if expiration period is nil" do
108
+ create_new_user
109
+ sorcery_model_property_set(:reset_password_expiration_period, nil)
110
+ @user.deliver_reset_password_instructions!
111
+ User.load_from_reset_password_token(@user.reset_password_token).should == @user
112
+ end
113
+
112
114
  it "load_from_reset_password_token should return nil if token is blank" do
113
115
  User.load_from_reset_password_token(nil).should == nil
114
116
  User.load_from_reset_password_token("").should == nil
@@ -123,7 +125,7 @@ describe "User with reset_password submodule" do
123
125
 
124
126
  it "the reset_password_token should be random" do
125
127
  create_new_user
126
- plugin_set_model_config_property(:reset_password_time_between_emails, 0)
128
+ sorcery_model_property_set(:reset_password_time_between_emails, 0)
127
129
  @user.deliver_reset_password_instructions!
128
130
  old_password_code = @user.reset_password_token
129
131
  @user.deliver_reset_password_instructions!
@@ -146,31 +148,9 @@ describe "User with reset_password submodule" do
146
148
  @user.reset_password_token.should be_nil
147
149
  end
148
150
 
149
- it "code isn't valid if expiration passed" do
150
- create_new_user
151
- plugin_set_model_config_property(:reset_password_expiration_period, 0.1)
152
- @user.deliver_reset_password_instructions!
153
- sleep 0.5
154
- @user.reset_password_token_valid?.should == false
155
- end
156
-
157
- it "code is valid if it's the same code and expiration period did not pass" do
158
- create_new_user
159
- plugin_set_model_config_property(:reset_password_expiration_period, 300)
160
- @user.deliver_reset_password_instructions!
161
- @user.reset_password_token_valid?.should == true
162
- end
163
-
164
- it "code is valid if it's the same code and expiration period is nil" do
165
- create_new_user
166
- plugin_set_model_config_property(:reset_password_expiration_period, nil)
167
- @user.deliver_reset_password_instructions!
168
- @user.reset_password_token_valid?.should == true
169
- end
170
-
171
151
  it "should not send an email if time between emails has not passed since last email" do
172
152
  create_new_user
173
- plugin_set_model_config_property(:reset_password_time_between_emails, 10000)
153
+ sorcery_model_property_set(:reset_password_time_between_emails, 10000)
174
154
  old_size = ActionMailer::Base.deliveries.size
175
155
  @user.deliver_reset_password_instructions!
176
156
  ActionMailer::Base.deliveries.size.should == old_size + 1
@@ -180,7 +160,7 @@ describe "User with reset_password submodule" do
180
160
 
181
161
  it "should send an email if time between emails has passed since last email" do
182
162
  create_new_user
183
- plugin_set_model_config_property(:reset_password_time_between_emails, 0.5)
163
+ sorcery_model_property_set(:reset_password_time_between_emails, 0.5)
184
164
  old_size = ActionMailer::Base.deliveries.size
185
165
  @user.deliver_reset_password_instructions!
186
166
  ActionMailer::Base.deliveries.size.should == old_size + 1
@@ -190,7 +170,7 @@ describe "User with reset_password submodule" do
190
170
  end
191
171
 
192
172
  it "if mailer is nil on activation, throw exception!" do
193
- expect{plugin_model_configure([:reset_password])}.to raise_error(ArgumentError)
173
+ expect{sorcery_reload!([:reset_password])}.to raise_error(ArgumentError)
194
174
  end
195
175
 
196
176
  end
@@ -0,0 +1,317 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../app/mailers/sorcery_mailer')
3
+
4
+ describe "User with no submodules (core)" do
5
+ before(:all) do
6
+ sorcery_reload!
7
+ end
8
+
9
+ describe User, "when app has plugin loaded" do
10
+ it "should respond to the plugin activation class method" do
11
+ ActiveRecord::Base.should respond_to(:activate_sorcery!)
12
+ User.should respond_to(:activate_sorcery!)
13
+ end
14
+
15
+ it "plugin activation should yield config to block" do
16
+ User.activate_sorcery! do |config|
17
+ config.class.should == ::Sorcery::Model::Config
18
+ end
19
+ end
20
+ end
21
+
22
+ # ----------------- PLUGIN ACTIVATION -----------------------
23
+ describe TestUser, "Testing activated class self-registration" do
24
+ it "should register itself as user_class if activated" do
25
+ TestUser.class_eval do
26
+ activate_sorcery!
27
+ end
28
+ ::Sorcery::Controller::Config.user_class.should == TestUser
29
+ end
30
+ end
31
+
32
+ # ----------------- PLUGIN CONFIGURATION -----------------------
33
+ describe User, "loaded plugin configuration" do
34
+ after(:each) do
35
+ User.sorcery_config.reset!
36
+ end
37
+
38
+ it "should enable configuration option 'username_attribute_name'" do
39
+ sorcery_model_property_set(:username_attribute_name, :email)
40
+ User.sorcery_config.username_attribute_name.should equal(:email)
41
+ end
42
+
43
+ it "should enable configuration option 'password_attribute_name'" do
44
+ sorcery_model_property_set(:password_attribute_name, :mypassword)
45
+ User.sorcery_config.password_attribute_name.should equal(:mypassword)
46
+ end
47
+
48
+ it "should enable configuration option 'email_attribute_name'" do
49
+ sorcery_model_property_set(:email_attribute_name, :my_email)
50
+ User.sorcery_config.email_attribute_name.should equal(:my_email)
51
+ end
52
+
53
+ it "should enable configuration option 'crypted_password_attribute_name'" do
54
+ sorcery_model_property_set(:crypted_password_attribute_name, :password)
55
+ User.sorcery_config.crypted_password_attribute_name.should equal(:password)
56
+ end
57
+
58
+ it "should enable configuration option 'salt_attribute_name'" do
59
+ sorcery_model_property_set(:salt_attribute_name, :my_salt)
60
+ User.sorcery_config.salt_attribute_name.should equal(:my_salt)
61
+ end
62
+
63
+ it "should enable configuration option 'encryption_algorithm'" do
64
+ sorcery_model_property_set(:encryption_algorithm, :none)
65
+ User.sorcery_config.encryption_algorithm.should equal(:none)
66
+ end
67
+
68
+ it "should enable configuration option 'encryption_key'" do
69
+ sorcery_model_property_set(:encryption_key, 'asdadas424234242')
70
+ User.sorcery_config.encryption_key.should == 'asdadas424234242'
71
+ end
72
+
73
+ it "should enable configuration option 'custom_encryption_provider'" do
74
+ sorcery_model_property_set(:encryption_algorithm, :custom)
75
+ sorcery_model_property_set(:custom_encryption_provider, Array)
76
+ User.sorcery_config.custom_encryption_provider.should equal(Array)
77
+ end
78
+
79
+ it "should enable configuration option 'salt_join_token'" do
80
+ salt_join_token = "--%%*&-"
81
+ sorcery_model_property_set(:salt_join_token, salt_join_token)
82
+ User.sorcery_config.salt_join_token.should equal(salt_join_token)
83
+ end
84
+
85
+ it "should enable configuration option 'stretches'" do
86
+ stretches = 15
87
+ sorcery_model_property_set(:stretches, stretches)
88
+ User.sorcery_config.stretches.should equal(stretches)
89
+ end
90
+
91
+ end
92
+
93
+ # ----------------- PLUGIN ACTIVATED -----------------------
94
+ describe User, "when activated with sorcery" do
95
+ before(:all) do
96
+ sorcery_reload!()
97
+ end
98
+
99
+ before(:each) do
100
+ User.delete_all
101
+ end
102
+
103
+ it "should respond to class method authenticate" do
104
+ ActiveRecord::Base.should_not respond_to(:authenticate)
105
+ User.should respond_to(:authenticate)
106
+ end
107
+
108
+ it "authenticate should return true if credentials are good" do
109
+ create_new_user
110
+ User.authenticate(@user.send(User.sorcery_config.username_attribute_name), 'secret').should be_true
111
+ end
112
+
113
+ it "authenticate should return false if credentials are bad" do
114
+ create_new_user
115
+ User.authenticate(@user.send(User.sorcery_config.username_attribute_name), 'wrong!').should be_false
116
+ end
117
+
118
+ it "should respond to the class method encrypt" do
119
+ User.should respond_to(:encrypt)
120
+ end
121
+ end
122
+
123
+ # ----------------- REGISTRATION -----------------------
124
+ describe User, "registration" do
125
+
126
+ before(:all) do
127
+ sorcery_reload!()
128
+ end
129
+
130
+ before(:each) do
131
+ User.delete_all
132
+ end
133
+
134
+ it "by default, encryption_provider should not be nil" do
135
+ User.sorcery_config.encryption_provider.should_not be_nil
136
+ end
137
+
138
+ it "should encrypt password when a new user is saved" do
139
+ create_new_user
140
+ User.sorcery_config.encryption_provider.matches?(@user.send(User.sorcery_config.crypted_password_attribute_name),'secret',@user.salt).should be_true
141
+ end
142
+
143
+ it "should clear the virtual password field if the encryption process worked" do
144
+ create_new_user
145
+ @user.password.should be_nil
146
+ end
147
+
148
+ it "should not clear the virtual password field if save failed due to validity" do
149
+ create_new_user
150
+ User.class_eval do
151
+ validates_format_of :email, :with => /^(.)+@(.)+$/, :if => Proc.new {|r| r.email}, :message => "is invalid"
152
+ end
153
+ @user.password = 'blupush'
154
+ @user.email = 'asd'
155
+ @user.save
156
+ @user.password.should_not be_nil
157
+ end
158
+
159
+ it "should not clear the virtual password field if save failed due to exception" do
160
+ create_new_user
161
+ @user.password = 'blupush'
162
+ @user.username = nil
163
+ begin
164
+ @user.save # triggers SQL exception since username field is defined not null.
165
+ rescue
166
+ end
167
+ @user.password.should_not be_nil
168
+ end
169
+
170
+ it "should not encrypt the password twice when a user is updated" do
171
+ create_new_user
172
+ @user.email = "blup@bla.com"
173
+ @user.save!
174
+ User.sorcery_config.encryption_provider.matches?(@user.send(User.sorcery_config.crypted_password_attribute_name),'secret',@user.salt).should be_true
175
+ end
176
+
177
+ it "should replace the crypted_password in case a new password is set" do
178
+ create_new_user
179
+ @user.password = 'new_secret'
180
+ @user.save!
181
+ User.sorcery_config.encryption_provider.matches?(@user.send(User.sorcery_config.crypted_password_attribute_name),'secret',@user.salt).should be_false
182
+ end
183
+
184
+ end
185
+
186
+ # ----------------- PASSWORD ENCRYPTION -----------------------
187
+ describe User, "special encryption cases" do
188
+ before(:all) do
189
+ sorcery_reload!()
190
+ @text = "Some Text!"
191
+ end
192
+
193
+ before(:each) do
194
+ User.delete_all
195
+ end
196
+
197
+ after(:each) do
198
+ User.sorcery_config.reset!
199
+ end
200
+
201
+ it "should work with no password encryption" do
202
+ sorcery_model_property_set(:encryption_algorithm, :none)
203
+ create_new_user
204
+ User.authenticate(@user.send(User.sorcery_config.username_attribute_name), 'secret').should be_true
205
+ end
206
+
207
+ it "should work with custom password encryption" do
208
+ class MyCrypto
209
+ def self.encrypt(*tokens)
210
+ tokens.flatten.join('').gsub(/e/,'A')
211
+ end
212
+
213
+ def self.matches?(crypted,*tokens)
214
+ crypted = encrypt(*tokens)
215
+ end
216
+ end
217
+ sorcery_model_property_set(:encryption_algorithm, :custom)
218
+ sorcery_model_property_set(:custom_encryption_provider, MyCrypto)
219
+ create_new_user
220
+ User.authenticate(@user.send(User.sorcery_config.username_attribute_name), 'secret').should be_true
221
+ end
222
+
223
+ it "if encryption algo is aes256, it should set key to crypto provider" do
224
+ sorcery_model_property_set(:encryption_algorithm, :aes256)
225
+ sorcery_model_property_set(:encryption_key, nil)
226
+ expect{User.encrypt(@text)}.to raise_error(ArgumentError)
227
+ sorcery_model_property_set(:encryption_key, "asd234dfs423fddsmndsflktsdf32343")
228
+ expect{User.encrypt(@text)}.to_not raise_error(ArgumentError)
229
+ end
230
+
231
+ it "if encryption algo is aes256, it should set key to crypto provider, even if attributes are set in reverse" do
232
+ sorcery_model_property_set(:encryption_key, nil)
233
+ sorcery_model_property_set(:encryption_algorithm, :none)
234
+ sorcery_model_property_set(:encryption_key, "asd234dfs423fddsmndsflktsdf32343")
235
+ sorcery_model_property_set(:encryption_algorithm, :aes256)
236
+ expect{User.encrypt(@text)}.to_not raise_error(ArgumentError)
237
+ end
238
+
239
+ it "if encryption algo is md5 it should work" do
240
+ sorcery_model_property_set(:encryption_algorithm, :md5)
241
+ User.encrypt(@text).should == Sorcery::CryptoProviders::MD5.encrypt(@text)
242
+ end
243
+
244
+ it "if encryption algo is sha1 it should work" do
245
+ sorcery_model_property_set(:encryption_algorithm, :sha1)
246
+ User.encrypt(@text).should == Sorcery::CryptoProviders::SHA1.encrypt(@text)
247
+ end
248
+
249
+ it "if encryption algo is sha256 it should work" do
250
+ sorcery_model_property_set(:encryption_algorithm, :sha256)
251
+ User.encrypt(@text).should == Sorcery::CryptoProviders::SHA256.encrypt(@text)
252
+ end
253
+
254
+ it "if encryption algo is sha512 it should work" do
255
+ sorcery_model_property_set(:encryption_algorithm, :sha512)
256
+ User.encrypt(@text).should == Sorcery::CryptoProviders::SHA512.encrypt(@text)
257
+ end
258
+
259
+ it "salt should be random for each user and saved in db" do
260
+ sorcery_model_property_set(:salt_attribute_name, :salt)
261
+ create_new_user
262
+ @user.salt.should_not be_nil
263
+ end
264
+
265
+ it "if salt is set should use it to encrypt" do
266
+ sorcery_model_property_set(:salt_attribute_name, :salt)
267
+ sorcery_model_property_set(:encryption_algorithm, :sha512)
268
+ create_new_user
269
+ @user.crypted_password.should_not == Sorcery::CryptoProviders::SHA512.encrypt('secret')
270
+ @user.crypted_password.should == Sorcery::CryptoProviders::SHA512.encrypt('secret',@user.salt)
271
+ end
272
+
273
+ it "if salt_join_token is set should use it to encrypt" do
274
+ sorcery_model_property_set(:salt_attribute_name, :salt)
275
+ sorcery_model_property_set(:salt_join_token, "-@=>")
276
+ sorcery_model_property_set(:encryption_algorithm, :sha512)
277
+ create_new_user
278
+ @user.crypted_password.should_not == Sorcery::CryptoProviders::SHA512.encrypt('secret')
279
+ Sorcery::CryptoProviders::SHA512.join_token = ""
280
+ @user.crypted_password.should_not == Sorcery::CryptoProviders::SHA512.encrypt('secret',@user.salt)
281
+ Sorcery::CryptoProviders::SHA512.join_token = User.sorcery_config.salt_join_token
282
+ @user.crypted_password.should == Sorcery::CryptoProviders::SHA512.encrypt('secret',@user.salt)
283
+ end
284
+
285
+ end
286
+
287
+ describe User, "external users" do
288
+ before(:all) do
289
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
290
+ sorcery_reload!()
291
+ end
292
+
293
+ after(:all) do
294
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
295
+ end
296
+
297
+ before(:each) do
298
+ User.delete_all
299
+ end
300
+
301
+ it "should respond to 'external?'" do
302
+ create_new_user
303
+ @user.should respond_to(:external?)
304
+ end
305
+
306
+ it "external? should be false for regular users" do
307
+ create_new_user
308
+ @user.external?.should be_false
309
+ end
310
+
311
+ it "external? should be true for external users" do
312
+ create_new_external_user(:twitter)
313
+ @user.external?.should be_true
314
+ end
315
+ end
316
+
317
+ end
@@ -0,0 +1,12 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'sinatra', '>= 1.2.0'
4
+ gem 'sqlite3-ruby', :require => 'sqlite3'
5
+ gem "sorcery", '0.3.1', :path => '../../'
6
+
7
+ group :development, :test do
8
+ gem 'rspec'
9
+ gem 'ruby-debug19'
10
+ gem 'simplecov', '>= 0.3.8', :require => false # Will install simplecov-html as a dependency
11
+ gem 'spork', '~> 0.9.0.rc'
12
+ end
@@ -0,0 +1,134 @@
1
+ PATH
2
+ remote: ../../
3
+ specs:
4
+ sorcery (0.3.1)
5
+ bcrypt-ruby (~> 2.1.4)
6
+ json (>= 1.5.1)
7
+ oauth (>= 0.4.4)
8
+ oauth (>= 0.4.4)
9
+ oauth2 (>= 0.1.1)
10
+ oauth2 (>= 0.1.1)
11
+ rails (>= 3.0.0)
12
+
13
+ GEM
14
+ remote: http://rubygems.org/
15
+ specs:
16
+ abstract (1.0.0)
17
+ actionmailer (3.0.3)
18
+ actionpack (= 3.0.3)
19
+ mail (~> 2.2.9)
20
+ actionpack (3.0.3)
21
+ activemodel (= 3.0.3)
22
+ activesupport (= 3.0.3)
23
+ builder (~> 2.1.2)
24
+ erubis (~> 2.6.6)
25
+ i18n (~> 0.4)
26
+ rack (~> 1.2.1)
27
+ rack-mount (~> 0.6.13)
28
+ rack-test (~> 0.5.6)
29
+ tzinfo (~> 0.3.23)
30
+ activemodel (3.0.3)
31
+ activesupport (= 3.0.3)
32
+ builder (~> 2.1.2)
33
+ i18n (~> 0.4)
34
+ activerecord (3.0.3)
35
+ activemodel (= 3.0.3)
36
+ activesupport (= 3.0.3)
37
+ arel (~> 2.0.2)
38
+ tzinfo (~> 0.3.23)
39
+ activeresource (3.0.3)
40
+ activemodel (= 3.0.3)
41
+ activesupport (= 3.0.3)
42
+ activesupport (3.0.3)
43
+ addressable (2.2.4)
44
+ archive-tar-minitar (0.5.2)
45
+ arel (2.0.7)
46
+ bcrypt-ruby (2.1.4)
47
+ builder (2.1.2)
48
+ columnize (0.3.2)
49
+ diff-lcs (1.1.2)
50
+ erubis (2.6.6)
51
+ abstract (>= 1.0.0)
52
+ faraday (0.5.5)
53
+ addressable (~> 2.2.4)
54
+ multipart-post (~> 1.1.0)
55
+ rack (< 2, >= 1.1.0)
56
+ i18n (0.5.0)
57
+ json (1.5.1)
58
+ linecache19 (0.5.11)
59
+ ruby_core_source (>= 0.1.4)
60
+ mail (2.2.15)
61
+ activesupport (>= 2.3.6)
62
+ i18n (>= 0.4.0)
63
+ mime-types (~> 1.16)
64
+ treetop (~> 1.4.8)
65
+ mime-types (1.16)
66
+ multi_json (0.0.5)
67
+ multipart-post (1.1.0)
68
+ oauth (0.4.4)
69
+ oauth2 (0.1.1)
70
+ faraday (~> 0.5.0)
71
+ multi_json (~> 0.0.4)
72
+ polyglot (0.3.1)
73
+ rack (1.2.1)
74
+ rack-mount (0.6.13)
75
+ rack (>= 1.0.0)
76
+ rack-test (0.5.7)
77
+ rack (>= 1.0)
78
+ rails (3.0.3)
79
+ actionmailer (= 3.0.3)
80
+ actionpack (= 3.0.3)
81
+ activerecord (= 3.0.3)
82
+ activeresource (= 3.0.3)
83
+ activesupport (= 3.0.3)
84
+ bundler (~> 1.0)
85
+ railties (= 3.0.3)
86
+ railties (3.0.3)
87
+ actionpack (= 3.0.3)
88
+ activesupport (= 3.0.3)
89
+ rake (>= 0.8.7)
90
+ thor (~> 0.14.4)
91
+ rake (0.8.7)
92
+ rspec (2.4.0)
93
+ rspec-core (~> 2.4.0)
94
+ rspec-expectations (~> 2.4.0)
95
+ rspec-mocks (~> 2.4.0)
96
+ rspec-core (2.4.0)
97
+ rspec-expectations (2.4.0)
98
+ diff-lcs (~> 1.1.2)
99
+ rspec-mocks (2.4.0)
100
+ ruby-debug-base19 (0.11.24)
101
+ columnize (>= 0.3.1)
102
+ linecache19 (>= 0.5.11)
103
+ ruby_core_source (>= 0.1.4)
104
+ ruby-debug19 (0.11.6)
105
+ columnize (>= 0.3.1)
106
+ linecache19 (>= 0.5.11)
107
+ ruby-debug-base19 (>= 0.11.19)
108
+ ruby_core_source (0.1.4)
109
+ archive-tar-minitar (>= 0.5.2)
110
+ simplecov (0.3.9)
111
+ simplecov-html (>= 0.3.7)
112
+ simplecov-html (0.3.9)
113
+ sinatra (1.2.0)
114
+ rack (~> 1.1)
115
+ tilt (< 2.0, >= 1.2.2)
116
+ spork (0.9.0.rc3)
117
+ sqlite3-ruby (1.3.2)
118
+ thor (0.14.6)
119
+ tilt (1.2.2)
120
+ treetop (1.4.9)
121
+ polyglot (>= 0.3.1)
122
+ tzinfo (0.3.24)
123
+
124
+ PLATFORMS
125
+ ruby
126
+
127
+ DEPENDENCIES
128
+ rspec
129
+ ruby-debug19
130
+ simplecov (>= 0.3.8)
131
+ sinatra (>= 1.2.0)
132
+ sorcery (= 0.3.1)!
133
+ spork (~> 0.9.0.rc)
134
+ sqlite3-ruby
@@ -0,0 +1,10 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc 'Default: Run all specs.'
5
+ task :default => :spec
6
+
7
+ desc "Run all specs"
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ t.pattern = '**/*_spec.rb'
10
+ end
@@ -0,0 +1,3 @@
1
+ class Authentication < ActiveRecord::Base
2
+ belongs_to :user
3
+ end
@@ -0,0 +1,17 @@
1
+ class AddActivationToUsers < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :users, :activation_state, :string, :default => nil
4
+ add_column :users, :activation_token, :string, :default => nil
5
+ add_column :users, :activation_token_expires_at, :datetime, :default => nil
6
+
7
+ add_index :users, :activation_token
8
+ end
9
+
10
+ def self.down
11
+ remove_index :users, :activation_token
12
+
13
+ remove_column :users, :activation_token_expires_at
14
+ remove_column :users, :activation_token
15
+ remove_column :users, :activation_state
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ class AddActivityLoggingToUsers < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :users, :last_login_at, :datetime, :default => nil
4
+ add_column :users, :last_logout_at, :datetime, :default => nil
5
+ add_column :users, :last_activity_at, :datetime, :default => nil
6
+
7
+ add_index :users, [:last_logout_at, :last_activity_at]
8
+ end
9
+
10
+ def self.down
11
+ remove_index :users, [:last_logout_at, :last_activity_at]
12
+
13
+ remove_column :users, :last_activity_at
14
+ remove_column :users, :last_logout_at
15
+ remove_column :users, :last_login_at
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ class AddBruteForceProtectionToUsers < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :users, :failed_logins_count, :integer, :default => 0
4
+ add_column :users, :lock_expires_at, :datetime, :default => nil
5
+ end
6
+
7
+ def self.down
8
+ remove_column :users, :lock_expires_at
9
+ remove_column :users, :failed_logins_count
10
+ end
11
+ end