ateam-merb-auth-old 0.0.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 (69) hide show
  1. data/LICENSE +44 -0
  2. data/README +212 -0
  3. data/Rakefile +50 -0
  4. data/TODO +14 -0
  5. data/activerecord_generators/ma_migration/ma_migration_generator.rb +41 -0
  6. data/activerecord_generators/ma_migration/templates/schema/migrations/%time_stamp%_add_ma_user.rb +21 -0
  7. data/app/controllers/application.rb +7 -0
  8. data/app/controllers/sessions.rb +3 -0
  9. data/app/controllers/users.rb +3 -0
  10. data/app/helpers/application_helper.rb +64 -0
  11. data/app/mailers/user_mailer.rb +24 -0
  12. data/app/mailers/views/user_mailer/activation.text.erb +1 -0
  13. data/app/mailers/views/user_mailer/forgot_password.text.erb +5 -0
  14. data/app/mailers/views/user_mailer/signup.text.erb +7 -0
  15. data/app/views/layout/merb_auth.html.erb +16 -0
  16. data/app/views/sessions/new.html.erb +13 -0
  17. data/app/views/users/new.html.erb +21 -0
  18. data/datamapper_generators/ma_migration/ma_migration_generator.rb +38 -0
  19. data/datamapper_generators/ma_migration/templates/schema/migrations/add_ma_user.rb +21 -0
  20. data/lib/ateam-merb-auth-old.rb +1 -0
  21. data/lib/merb-auth.rb +184 -0
  22. data/lib/merb-auth/adapters/activerecord/init.rb +26 -0
  23. data/lib/merb-auth/adapters/activerecord/map.rb +44 -0
  24. data/lib/merb-auth/adapters/activerecord/model.rb +81 -0
  25. data/lib/merb-auth/adapters/common.rb +161 -0
  26. data/lib/merb-auth/adapters/datamapper/init.rb +28 -0
  27. data/lib/merb-auth/adapters/datamapper/map.rb +35 -0
  28. data/lib/merb-auth/adapters/datamapper/model.rb +72 -0
  29. data/lib/merb-auth/adapters/map.rb +0 -0
  30. data/lib/merb-auth/adapters/sequel/init.rb +26 -0
  31. data/lib/merb-auth/adapters/sequel/map.rb +36 -0
  32. data/lib/merb-auth/adapters/sequel/model.rb +86 -0
  33. data/lib/merb-auth/controller/controller.rb +113 -0
  34. data/lib/merb-auth/controller/sessions_base.rb +41 -0
  35. data/lib/merb-auth/controller/users_base.rb +58 -0
  36. data/lib/merb-auth/initializer.rb +47 -0
  37. data/lib/merb-auth/merbtasks.rb +168 -0
  38. data/lib/merb-auth/slicetasks.rb +102 -0
  39. data/plugins/forgotten_password/app/controllers/passwords.rb +90 -0
  40. data/plugins/forgotten_password/app/models/user.rb +52 -0
  41. data/plugins/forgotten_password/app/views/passwords/edit.html.erb +9 -0
  42. data/plugins/forgotten_password/app/views/passwords/new.html.erb +4 -0
  43. data/plugins/forgotten_password/forgotten_password.rb +6 -0
  44. data/plugins/forgotten_password/init.rb +8 -0
  45. data/plugins/forgotten_password/spec/controller_spec.rb +236 -0
  46. data/plugins/forgotten_password/spec/model_spec.rb +52 -0
  47. data/plugins/forgotten_password/spec/spec_helper.rb +36 -0
  48. data/public/javascripts/master.js +0 -0
  49. data/public/stylesheets/master.css +2 -0
  50. data/spec/controllers/plugins/test_plugin.rb +17 -0
  51. data/spec/controllers/sessions_spec.rb +118 -0
  52. data/spec/controllers/users_spec.rb +119 -0
  53. data/spec/mailers/user_mailer_spec.rb +75 -0
  54. data/spec/merb_auth_spec.rb +231 -0
  55. data/spec/models/ar_model_spec.rb +50 -0
  56. data/spec/models/common_spec.rb +0 -0
  57. data/spec/models/model_spec.rb +23 -0
  58. data/spec/models/sq_model_spec.rb +50 -0
  59. data/spec/shared_specs/shared_model_spec.rb +445 -0
  60. data/spec/spec_helper.rb +114 -0
  61. data/spec/spec_helpers/helpers.rb +18 -0
  62. data/spec/spec_helpers/valid_model_hashes.rb +10 -0
  63. data/stubs/app/controllers/application.rb +2 -0
  64. data/stubs/app/controllers/main.rb +2 -0
  65. data/stubs/app/mailers/views/activation.text.erb +1 -0
  66. data/stubs/app/mailers/views/signup.text.erb +7 -0
  67. data/stubs/app/views/sessions/new.html.erb +14 -0
  68. data/stubs/app/views/users/new.html.erb +18 -0
  69. metadata +120 -0
@@ -0,0 +1,90 @@
1
+ module MerbAuth
2
+ class Passwords < Application
3
+
4
+ controller_for_slice :MerbAuth
5
+
6
+ def _template_location(context, type = nil, controller = controller_name)
7
+ if controller.nil? || controller != "merb_auth/passwords"
8
+ "#{controller}/#{context}.#{type}"
9
+ else
10
+ "passwords/#{context}.#{type}"
11
+ end
12
+ end
13
+
14
+ before :login_required, :only => [:edit, :update]
15
+
16
+ # NEW shows the html form to initiate the forgotten password request
17
+ def new
18
+ render
19
+ end
20
+
21
+ # Edit shows the reset password form for a currently logged in person
22
+ def edit
23
+ @ivar = current_ma_user
24
+ set_ivar
25
+ render
26
+ end
27
+
28
+ # Initiates a password reset for forgoten password
29
+ def create
30
+ email = params[:email]
31
+ @ivar = MA[:user].find_with_conditions(:email => email)
32
+ raise NotFound if @ivar.nil?
33
+ raise Unauthorized if logged_in? && @ivar != current_ma_user
34
+ @ivar.forgot_password!
35
+ set_ivar
36
+ redirect_back_or_default("/", "We've sent you a link to reset your password. Keep an eye on your inbox.")
37
+ end
38
+
39
+ # Reset is the link given in the email with the reset password code attached
40
+ # This action at best should be a 1 hit wonder link to log in the user, reset the code and
41
+ # redirect to edit. If There's an error send them to the new action
42
+ def show
43
+ id = params[:id]
44
+ @ivar = MA[:user].find_with_conditions(:password_reset_key => id)
45
+ if @ivar.nil?
46
+ redirect_back_or_default "/"
47
+ else
48
+ self.current_ma_user = @ivar
49
+ set_ivar
50
+ redirect url(:merb_auth_edit_password_form)
51
+ end
52
+ end
53
+
54
+
55
+ # Performs a password change for an existing user. This is nice and big to ensure that we're only dealing with
56
+ # Changes to passwords. Not arbitrary stuff.
57
+ def update
58
+ @ivar = current_ma_user
59
+ set_ivar
60
+ if params[MA[:single_resource]][:password].nil?
61
+ message[:notice] = "You must enter a password"
62
+ return render(:edit)
63
+ end
64
+
65
+ if !@ivar.has_forgotten_password?
66
+ if @ivar != MA[:user].authenticate(@ivar.email, params[:current_password])
67
+ message[:notice] = "Your current password is incorrect"
68
+ return render(:edit)
69
+ end
70
+ end
71
+
72
+ @ivar.password = params[MA[:single_resource]][:password]
73
+ @ivar.password_confirmation = params[MA[:single_resource]][:password_confirmation]
74
+
75
+ if @ivar.save
76
+ @ivar.clear_forgot_password!
77
+ redirect_back_or_default("/", "Password Changed")
78
+ else
79
+ redirect url(:merb_auth_edit_password_form), "Password Not Changed"
80
+ end
81
+ end
82
+
83
+ private
84
+ # sets the instance variable for the developer to use eg. @user
85
+ def set_ivar
86
+ instance_variable_set("@#{MA[:single_resource]}", @ivar)
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,52 @@
1
+ module MerbAuth
2
+ module ForgottenPassword
3
+ module Model
4
+
5
+ def self.included(base)
6
+ base.send(:extend, ClassMethods)
7
+ base.send(:include, InstanceMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ def make_key
12
+ Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
13
+ end
14
+
15
+ def authenticate(email, password)
16
+ super(email, password)
17
+ return if @u.nil?
18
+ return @u unless @u.has_forgotten_password?
19
+ @u.clear_forgot_password!
20
+ puts @u.inspect
21
+ @u
22
+ end
23
+ end
24
+
25
+ module InstanceMethods
26
+ def forgot_password! # Must be a unique password key before it goes in the database
27
+ pwreset_key_success = false
28
+ until pwreset_key_success
29
+ self.password_reset_key = self.class.make_key
30
+ self.save
31
+ pwreset_key_success = self.errors.on(:password_reset_key).nil? ? true : false
32
+ end
33
+ send_forgot_password
34
+ end
35
+
36
+ def has_forgotten_password?
37
+ !self.password_reset_key.nil?
38
+ end
39
+
40
+ def clear_forgot_password!
41
+ self.password_reset_key = nil
42
+ self.save
43
+ end
44
+
45
+
46
+ end # InstanceMethods
47
+
48
+ end
49
+ end
50
+ end
51
+
52
+ MA[:user].send(:include, MerbAuth::ForgottenPassword::Model)
@@ -0,0 +1,9 @@
1
+ <%= @message %>
2
+ <% form_for @ivar, :action => url(:merb_auth_passwords), :method => :put do %>
3
+ <% unless @ivar.has_forgotten_password? %>
4
+ <%= password_field :name => "current_password", :label => "Current Password" %>
5
+ <% end %>
6
+ <%= password_control :password, :label => "Password" %>
7
+ <%= password_control :password_confirmation, :label => "Password Confirmation" %>
8
+ <%= submit_button "Save" %>
9
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <% form_tag :action => url(:merb_auth_passwords), :method => :post do %>
2
+ <%= text_field :name => "email", :label => "Email" %>
3
+ <%= submit_button "Reset Password" %>
4
+ <% end %>
@@ -0,0 +1,6 @@
1
+ if MerbAuth[:forgotten_password] && MerbAuth[:user]
2
+ dir = File.expand_path(File.dirname(__FILE__))
3
+ Dir[File.join(dir, "app", "**/*.rb")].each{ |f| require f }
4
+ end
5
+
6
+ ######################### Include it into the module man
@@ -0,0 +1,8 @@
1
+ MerbAuth.plugins[:forgotten_password] = File.join(File.expand_path(File.dirname(__FILE__)) / "forgotten_password.rb")
2
+
3
+ MA.add_routes do |r|
4
+ if MerbAuth[:forgotten_password] && MerbAuth[:user]
5
+ r.match("/passwords/edit").to(:controller => "Passwords", :action => "edit").name(:merb_auth_edit_password_form)
6
+ r.resources :passwords
7
+ end
8
+ end
@@ -0,0 +1,236 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
2
+
3
+ describe "Passwords controller" do
4
+
5
+ before(:each) do
6
+ User.clear_database_table
7
+ @user = User.create(valid_user_hash.with(
8
+ :password => "test",
9
+ :password_confirmation => "test",
10
+ :login => "gary",
11
+ :email => "gary@example.com"
12
+ ))
13
+ @user.activate
14
+ @user.reload
15
+ @deliveries = Merb::Mailer.deliveries
16
+ end
17
+
18
+ after(:each) do
19
+ Merb::Mailer.deliveries.clear
20
+ end
21
+
22
+ describe "new" do
23
+
24
+ it "should render a form to create a reset password" do
25
+ c = dispatch_to(MA::Passwords, :new)
26
+ c.body.should have_tag(:form, :action => url(:merb_auth_passwords), :method => "post")
27
+ end
28
+ end
29
+
30
+ describe "edit" do
31
+
32
+ def dispatch_edit(opts = {})
33
+ dispatch_to(MA::Passwords, :edit, opts = {}) do |c|
34
+ c.stub!(:current_ma_user).and_return(@user)
35
+ end
36
+ end
37
+
38
+ it "should require the user to be logged in" do
39
+ c = dispatch_to(MA::Passwords, :edit)
40
+ c.should redirect_to(url(:login))
41
+ end
42
+
43
+ it "should have a form that is posted to url(:passwords)" do
44
+ c = dispatch_edit
45
+ c.body.should have_tag(:form, :action => url(:merb_auth_passwords), :method => "post")
46
+ end
47
+
48
+ it "the form should have password and confirmation password fields" do
49
+ c = dispatch_edit
50
+ c.body.should have_tag(:form, :action => url(:merb_auth_passwords), :method => "post") do |d|
51
+ d.should have_tag(:input, :type => "hidden", :name => "_method")
52
+ d.should have_tag(:input, :type => "password", :id => "user_password")
53
+ d.should have_tag(:input, :type => "password", :id => "user_password_confirmation")
54
+ end
55
+ end
56
+
57
+ it "should show the old password confirmation box if the user does not have a forgotten password" do
58
+ @user.clear_forgot_password!
59
+ @user.reload!
60
+ @user.should_not have_forgotten_password
61
+
62
+ c = dispatch_edit
63
+ c.body.should have_tag(:form, :action => url(:merb_auth_passwords), :method => "post") do |d|
64
+ d.should have_tag(:input, :type => "hidden", :name => "_method")
65
+ d.should have_tag(:input, :type => "password", :id => "user_password")
66
+ d.should have_tag(:input, :type => "password", :id => "user_password_confirmation")
67
+ d.should have_tag(:input, :type => "password", :name => "current_password")
68
+ end
69
+ end
70
+
71
+ it "should not show the old password ocnfirmation box if the user does have a forgotten password" do
72
+ @user.forgot_password!
73
+ @user.reload!
74
+
75
+ c = dispatch_edit
76
+ c.body.should have_tag(:form, :action => url(:merb_auth_passwords), :method => "post") do |d|
77
+ d.should have_tag(:input, :type => "hidden", :name => "_method")
78
+ d.should have_tag(:input, :type => "password", :id => "user_password")
79
+ d.should have_tag(:input, :type => "password", :id => "user_password_confirmation")
80
+ d.should_not have_tag(:input, :type => "password", :name => "current_password")
81
+ end
82
+ end
83
+ end
84
+
85
+ describe "create" do
86
+ def dispatch_create(opts = {})
87
+ dispatch_to(MA::Passwords, :create, {:email => @user.email}.merge!(opts) )
88
+ end
89
+
90
+ it "should set the users password to forgotten" do
91
+ @user.should_not have_forgotten_password
92
+ dispatch_create
93
+ @user.reload!
94
+ @user.should have_forgotten_password
95
+ end
96
+
97
+ it "should only change the user who's email was sent" do
98
+ user = User.create(valid_user_hash)
99
+ user.should_not be_new_record
100
+
101
+ @user.should_not have_forgotten_password
102
+ user.should_not have_forgotten_password
103
+
104
+ dispatch_create(:email => user.email)
105
+
106
+ user.reload!
107
+ @user.reload!
108
+
109
+ @user.should_not have_forgotten_password
110
+ user.should have_forgotten_password
111
+ end
112
+
113
+ it "should redirect" do
114
+ c = dispatch_create
115
+ c.should redirect
116
+ end
117
+
118
+ it "should raise an unauthorized if the user is logged in, and not the owner of the email" do
119
+ user = User.create(valid_user_hash)
120
+ lambda do
121
+ c = dispatch_to(MA::Passwords, :create, :email => user.email) do |c|
122
+ c.stub!(:current_ma_user).and_return(@user)
123
+ end
124
+ end.should raise_error(Merb::Controller::Unauthorized)
125
+ end
126
+
127
+ it "should raise a NotFound error if the users email does not exist" do
128
+ lambda do
129
+ c = dispatch_create(:email => "does_not_exist@blah.com")
130
+ end.should raise_error(Merb::Controller::NotFound)
131
+ end
132
+
133
+ it "should send a notification email that the password is to be resent" do
134
+ c = dispatch_create
135
+ c.should redirect_to("/")
136
+ @user.reload!
137
+ @deliveries.last.should_not be_nil
138
+ @deliveries.last.text.should include(url(:merb_auth_passwords, @user.password_reset_key))
139
+ end
140
+ end
141
+
142
+ describe "show" do
143
+
144
+ def dispatch_show(opts = {})
145
+ dispatch_to(MA::Passwords, :show, opts)
146
+ end
147
+
148
+ it "should redirect to edit if given a valid reset key" do
149
+ @user.forgot_password!
150
+ c = dispatch_show(:id => @user.password_reset_key)
151
+ c.should redirect_to(url(:merb_auth_edit_password_form))
152
+ end
153
+
154
+ it "should redirect to home if given an invalid reset key" do
155
+ c = dispatch_show(:id => "11234")
156
+ c.should redirect_to("/")
157
+ end
158
+
159
+ it "should log the user in" do
160
+ @user.forgot_password!
161
+ c = dispatch_show(:id => @user.password_reset_key)
162
+ @user.reload!
163
+ c.should be_logged_in
164
+ c.send(:current_ma_user).should == @user
165
+ end
166
+ end
167
+
168
+ describe "update" do
169
+
170
+ def dispatch_update(opts = {})
171
+ dispatch_to(MA::Passwords, :update, opts){|c| c.stub!(:current_ma_user).and_return(@user)}
172
+ end
173
+
174
+ it "should require the user to be logged in" do
175
+ c = dispatch_to(MA::Passwords, :update)
176
+ c.should redirect_to(url(:login))
177
+ end
178
+
179
+ it "should update the current_users password with pw and pw conf if there is a password_reset_key present" do
180
+ @user.forgot_password!
181
+ @user.password_reset_key.should_not be_nil
182
+ c = dispatch_update(:user => {:password => "gahh", :password_confirmation => "gahh"})
183
+ @user.reload!
184
+ User.authenticate(@user.email, "gahh").should == @user
185
+ end
186
+
187
+ it "should change the password when given a current password if there is no password_reset_key present" do
188
+ @user.should_not have_forgotten_password
189
+ c = dispatch_update(:user => {:password => "gahh", :password_confirmation => "gahh"}, :current_password => "test")
190
+ @user.reload!
191
+ User.authenticate(@user.email, "gahh").should == @user
192
+ end
193
+
194
+ it "should not change the password when not given a current password if there is no password_reset_key present" do
195
+ @user.should_not have_forgotten_password
196
+ c = dispatch_update(:user => {:password => "gahh", :password_confirmation => "gahh"})
197
+ @user.reload!
198
+ User.authenticate(@user.email, "gahh").should be_nil
199
+ User.authenticate(@user.email, "test").should == @user
200
+ end
201
+
202
+ it "should not change the password when the current password is wrong" do
203
+ @user.should_not have_forgotten_password
204
+ c = dispatch_update(:user => {:password => "gahh", :password_confirmation => "gahh"}, :current_password => "wrong")
205
+ @user.reload!
206
+ User.authenticate(@user.email, "wrong").should be_nil
207
+ User.authenticate(@user.email, "test").should == @user
208
+ end
209
+
210
+ it "should clear the password_reset_key" do
211
+ @user.forgot_password!
212
+ @user.should have_forgotten_password
213
+ dispatch_update(:user => {:password => "gahh", :password_confirmation => "gahh"})
214
+ @user.reload!
215
+ @user.should_not have_forgotten_password
216
+ end
217
+
218
+ it "should redirect to edit back to edit if the passwords do not match and not delete the forgotten password" do
219
+ @user.forgot_password!
220
+ c = dispatch_update(:user => {:password => "blah", :password_confirmation => "foo"})
221
+ @user.reload!
222
+ User.authenticate(@user.email, "blah").should be_nil
223
+ c.should redirect_to(url(:merb_auth_edit_password_form))
224
+ @user.should have_forgotten_password
225
+ end
226
+
227
+ it "should redirect to home if the password was changed" do
228
+ @user.forgot_password!
229
+ c = dispatch_update(:user => {:password => "blah", :password_confirmation =>"blah"})
230
+ @user.reload!
231
+ User.authenticate(@user.email, "blah").should_not be_nil
232
+ c.should redirect_to("/")
233
+ end
234
+ end
235
+
236
+ end
@@ -0,0 +1,52 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
2
+
3
+ describe "Forgotten password for models" do
4
+
5
+ before(:each) do
6
+ User.clear_database_table
7
+ @user = User.new(valid_user_hash.with(:password => "test", :password_confirmation => "test"))
8
+ @user.save
9
+ end
10
+
11
+ it "should not have a forgotten password" do
12
+ @user.should_not have_forgotten_password
13
+ end
14
+
15
+ it "should have a forgotten password" do
16
+ @user.forgot_password!
17
+ @user.should have_forgotten_password
18
+ end
19
+
20
+ it "should have a forgotten password key 40 chars long when the password is forgotten" do
21
+ @user.password_reset_key.should be_nil
22
+ @user.forgot_password!
23
+ @user.password_reset_key.should_not be_nil
24
+ end
25
+
26
+ it "should not allow duplicates of the key but should regenerate until it has a good one" do
27
+ key1 = @user.class.make_key
28
+ key2 = @user.class.make_key
29
+ key1.should_not == key2
30
+ @user.forgot_password!
31
+ @user.send(:password_reset_key=, key1)
32
+ @user.save
33
+ @user.reload!
34
+ @user.password_reset_key.should == key1
35
+
36
+ user = User.create(valid_user_hash)
37
+
38
+ User.should_receive(:make_key).exactly(3).times.and_return(key1,key1,key2)
39
+ user.forgot_password!
40
+ end
41
+
42
+ it "should remove the forgotten password key if present when it is authenticated with the password" do
43
+ # If the user remembers to log in then the password is no longer forgotten and this should be reset
44
+ @user.forgot_password!
45
+ @user.reload!
46
+ @user.password_reset_key.should_not be_nil
47
+ User.authenticate(@user.email, "test")
48
+ @user.reload!
49
+ @user.password_reset_key.should be_nil
50
+ end
51
+
52
+ end