Commit 85d66ac6bcc8e33755cfa997a5d20149a63fd967

reset password functionality

Commit diff

TODO.txt

 
11(in no particular order)
22
3> If you do `git archive --format=tar --prefix=myproject/ HEAD | gzip >
4> myproject.tar.gz`, when .gitattributes specifies files that have
5> export-subst, it will expand keywords such as $Format:%cd$. Gitorious'
6> "Download as gzipped tarball" apparently does not do this and I think
7> it'd be pretty nice if it did.
8
39* Deal gracefully with markdown errors (and/or look into using the other markdown libary instead)
410* Don't generate graphs with big "No Data", text even if there's no data
511* Markdownify atom feed body for projects.atom
2020* expire fragment caches for project+repos on deletion
2121*a Tone down the "owner" of a repository, or implement a proper "mirror" project type.
2222*b be able to mark a project as a "mirror"
23* reset password functionality
2423* Nicer diff stats
2524* more interesting project stats on frontpage
2625* parse git submodule data and link to project if submodule is in gitorious
toggle raw diff

app/controllers/users_controller.rb

 
3636 end
3737 redirect_back_or_default('/')
3838 end
39
40 def forgot_password
41 end
42
43 def reset_password
44 if params[:user] && user = User.find_by_email(params[:user][:email])
45 # FIXME: should really be a two-step process: receive link, visiting it resets password
46 generated_password = user.reset_password!
47 Mailer.deliver_forgotten_password(user, generated_password)
48 flash[:notice] = "A new password has been sent to your email"
49 redirect_to(root_path)
50 else
51 flash[:error] = "Invalid email"
52 redirect_to forgot_password_users_path
53 end
54 end
3955end
toggle raw diff

app/models/mailer.rb

 
3232 @body[:url] = url
3333 end
3434
35 def forgotten_password(user, password)
36 setup_email(user)
37 @subject += "Your new password"
38 @body[:password] = password
39 end
40
3541 protected
3642 def setup_email(user)
3743 @recipients = "#{user.email}"
toggle raw diff

app/models/user.rb

 
4141 Digest::SHA1.hexdigest("--#{salt}--#{password}--")
4242 end
4343
44 def self.generate_random_password(password_size = 12)
45 characters = (("a".."z").to_a + ("0".."9").to_a) - %w[0 o i l 1]
46 (0...password_size).collect do |char|
47 characters[rand(characters.length)]
48 end.join
49 end
50
4451 # Activates the user in the database.
4552 def activate
4653 @activated = true
9999 save(false)
100100 end
101101
102 def reset_password!
103 generated = User.generate_random_password
104 self.password = generated
105 self.password_confirmation = generated
106 self.save!
107 generated
108 end
109
102110 def can_write_to?(repository)
103111 !!committerships.find_by_repository_id(repository.id)
104112 end
toggle raw diff

app/views/mailer/forgotten_password.rhtml

 
1Hello <%= @user.login -%>,
2
3Your new password is: <%= @password %>
4
5If you did not request a new password, then please do report this incident.
6
7Thank you
8
9http://<%= GitoriousConfig['gitorious_host'] %>
toggle raw diff

app/views/sessions/new.html.erb

 
2020 <p><%= submit_tag 'Log in' %></p>
2121<% end -%>
2222
23<% content_for(:submenu) do -%>
24 <ul>
25 <li><%= link_to "Register", new_user_path -%></li>
26 </ul>
27<% end -%>
23<p>
24 <small>
25 <%= link_to "Register", new_user_path -%>
26 | <%= link_to "Forgotten your password?", forgot_password_users_path -%>
27 </small>
28</p>
toggle raw diff

app/views/users/forgot_password.html.erb

 
1<h1>Forgot your password?</h1>
2
3
4<% form_for :user, :url => reset_password_users_path do |f| -%>
5 <p>
6 <%= f.label :email -%><br/>
7 <%= f.text_field :email, :class => "text" -%>
8 </p>
9
10 <p><%= f.submit 'Send me a new password' %></p>
11<% end -%>
toggle raw diff

config/routes.rb

 
2424 account.resources :keys
2525 end
2626 map.connect "users/activate/:activation_code", :controller => "users", :action => "activate"
27 map.resources :users, :requirements => {:id => /.+/}
27 map.resources :users, :requirements => {:id => /.+/}, :collection => {
28 :forgot_password => :get,
29 :reset_password => :post,
30 }
2831 map.resource :sessions
2932 map.with_options(:controller => "projects", :action => "category") do |project_cat|
3033 project_cat.projects_category "projects/category/:id"
toggle raw diff

spec/controllers/users_controller_spec.rb

 
9797 assigns[:commits_last_week].kind_of?(Fixnum).should == true
9898 (assigns[:commits_last_week] >= 0).should == true
9999 end
100
101 describe "#forgot_password" do
102 it "GETs the page fine for everyone" do
103 get :forgot_password
104 response.should be_success
105 response.should render_template("forgot_password")
106 end
107 end
108
109 describe "#reset_password" do
110 it "redirects to forgot_password if nothing was found" do
111 post :reset_password, :user => {:email => "xxx"}
112 response.should redirect_to(forgot_password_users_path)
113 flash[:error].should match(/invalid email/i)
114 end
115
116 it "sends a new password if email was found" do
117 u = users(:johan)
118 User.should_receive(:generate_random_password).and_return("secret")
119 Mailer.should_receive(:deliver_forgotten_password).with(u, "secret")
120 post :reset_password, :user => {:email => u.email}
121 response.should redirect_to(root_path)
122 flash[:notice].should == "A new password has been sent to your email"
123
124 User.authenticate(u.email, "secret").should_not be_nil
125 end
126 end
100127end
toggle raw diff

spec/models/mailer_spec.rb

 
5757 Mailer.deliver(mail)
5858 Mailer.deliveries.should == [mail]
5959 end
60
61 it "sends forgotten_password" do
62 user = users(:johan)
63 mail = Mailer.create_forgotten_password(user, "newpassword")
64
65 mail.to.should == [user.email]
66 mail.subject.should == "[Gitorious] Your new password"
67 mail.body.should match(/your new password is: newpassword/i)
68
69 Mailer.deliver(mail)
70 Mailer.deliveries.should == [mail]
71 end
6072
6173end
toggle raw diff

spec/models/user_spec.rb

 
141141 }.should raise_error(ActiveRecord::RecordNotFound)
142142 end
143143
144 it "generates some randomly password" do
145 User.generate_random_password.should match(/\w+/)
146 User.generate_random_password.length.should == 12
147 User.generate_random_password(16).length.should == 16
148 User.generate_random_password(5).length.should == 5
149 end
150
151 it "resets a password to something" do
152 u = users(:johan)
153 password = u.reset_password!
154 User.authenticate(u.email, password).should_not be_nil
155 end
156
144157 protected
145158 def create_user(options = {})
146159 u = User.new({
toggle raw diff