ateam-merb-auth-old 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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