2008年12月10日水曜日

あぁあ〜...

イヤなことに気が付いちゃった...

(略)
CURRENT FEATURES
(略)
  - Authentication Plugins 
    - restful_authentication, open_id_authentication, role_requirement, recaptcha
  - UI Plugins 
    - custom-err-msg, permalink_fu, uberkit, will_paginate
  - Debug Plugins 
    - exception_logger, rails-footnotes, query_analyzer, query_stats, rows_logger
  - Development and Performance Plugins
    - auto_migrations, pseudo_cursors
  - Testing 
    - rspec, rspec_rails
  - Gems
    - ruby-openid-2.1.2
(略)
え?
何それ?
ゴメン、云ってる意味が解らない。
聞きたくない。
聞きたくないったら、聞きたくないwww

あ゛あ゛あ゛ー解らないったら解らないっ

ああっ、もうっ
ちょっと気分転換するっ

ついでに、もう少しマシなブログ探すwww

コードのブラッシュ・アップ

まあ、職安行って、失業認定とやらを申請してきた訳ですが。
次回の受給金額が、年末年始の絡みもあり、21日分でして。

あの...家賃と光熱費とケータイ代で、消えちゃうんですがwww


まあ、そんなことは置いといて。

これまでのコードを、ちょっとキレイにしちゃおうかな、と。

まず、new_user_pathなんて形でリンク先のurlをせいせいしているところが幾つかあるんだけど、これを、signup_pathに書き換えた。
だって、sessions/newは、login_pathになってるんだよ?

だったら、users/newは、signup_pathだよねぇ?w

あと、アタシゃ古いタイプのコード書きのようでして、やっぱり、メソッドの後ろの引数には、括弧が付いていないと、気持ちが悪いのよ。
なんで、片っ端から、括弧付けw

なんて無駄なwww
つうか、restful_authenticationの制作者様も、コーディング・スタイルが一貫してないぞwww

もちろん、bells and whitslesの人もだwww

でも、基本的に、コーディング・スタイルは、Rubyコーディング規約に準ずることにしたよ。

他人の決めたルールに則るのって、ラクチンだよねw

だがしかし、外すところでは、外すよ。
例えば、ファイル名は、「-」じゃなくって、「_」繋ぎにするとか。
まあ、これも、railsがそうなってるから、なんだけどね;-p

メソッドの引数に関しても、宣言くさいもの、
  • include、require
  • belongs_to、has_many、has_one、has_and_belongs_to_many
  • validate_hogehoge
  • attr_hogehoge
なんかは、敢えて()を付けないことにした。
特に、validate_hogehogeは、付いてない方が、可読性が良い気がする。
良い気がすれば、おk。wwww


それから、user_controller.rbのnewアクションに付けてた、current_user?での分岐を外した。
before_filterでかかってるからね。
-    if logged_in?
-      redirect_to(:controller => "users", :action => "show", :id => current_user.id)
-    else
-      @user = User.new
-    end
+    @user = User.new

ん。

2008年12月9日火曜日

どうよ? じゃねえよwww

いきなりレイアウト崩れてんじゃねぇよwww->blogger.com
ホンキ、使えねえなwww

また引っ越しちゃうぞwwwww


で。
メソッド、全然足りてねえでやんのwww
lib/authentication_system.rb
+    def permission_denied
+      respond_to do |format|
+        format.html do
+          #Put your domain name here ex. http://www.example.com
+          domain_name = "http://localhost:3000"
+          http_referer = session[:refer_to]
+          if http_referer.nil?
+            store_referer
+            http_referer = ( session[:refer_to] || domain_name )
+          end
+          flash[:error] = "You don't have permission to complete that action."
+          #The [0..20] represents the 21 characters in http://localhost:3000
+          #You have to set that to the number of characters in your domain name
+          if http_referer[0..20] != domain_name  
+            session[:refer_to] = nil
+            redirect_to root_path
+          else
+            redirect_to_referer_or_default(root_path)  
+          end
+        end
+        format.xml do
+          headers["Status"]           = "Unauthorized"
+          headers["WWW-Authenticate"] = %(Basic realm="Web Password")
+          render :text => "You don't have permission to complete this action.", :status => '401 Unauthorized'
+        end
+      end
+    end

+    def store_referer
+      session[:refer_to] = request.env["HTTP_REFERER"]
+    end

+    def redirect_to_referer_or_default(default)
+      redirect_to(session[:refer_to] || default)
+      session[:refer_to] = nil
+    end

ん。
んで、http://localhost:3000/usersに行ってみると...

NoMethodError in Users#index
Showing app/views/users/_user.html.erb where line #4 raised:

undefined method `enabled' for #

!?
なんだよ? "enabled"って?
で、見てみたら、どうも、メソッドではなくって、スキーマくさい。
どうも、今のバージョンのrestrul_authentication --aasmだと、enabledじゃなくって、statusになってるっぽい。
んじゃあ、ってんで、書き換えよう。
app/views/users/_user.html.erb

-  <td><%= user.enabled ? 'yes' : 'no' %>
+  <td><%= user.state == "active"  ? 'yes' : 'no' %>

-      <% if user.enabled %>
+      <% if user.state == "active" %>
ん。動いた。
動いたことは動いたんだけど、ブラウザで表示して、「enable」のリンクをクリックしても、何の変化もなし。

んー...
っていうか、enableなんてメソッド、作ってないわwww
じゃあ、移植しましょう、ってことで。
でも、メソッド名は変えるよ。それっぽく。
app/controllers/users_controller.rb
+  def forcible_activate
+    @user = User.find(params[:id])
+    if @user.update_attribute(:state, "active")
+      flash[:notice] = "User activated"
+    else
+      flash[:error] = "There was a problem activating this user."
+    end
+      redirect_to :action => 'index'
+  end
あと、administrator_role_requiredの:enabelも書き換えなきゃな。
-before_filter :administrator_role_required, :only => [:index, :destroy, :enable]
+before_filter :administrator_role_required, :only => [:index, :destroy, :forcible_activate]

んで、ルーティングも変更。
config/routes.rb
+  map.forcible_activate '/forcible_activate/:id', :controller => "users", :action => "forcible_activate"

んで、viewも変更。
app/views/users/_user.html.erb
-  <td><%= user.enabled ? 'yes' : 'no' %>
-    <% unless user == current_user %>
-      <% if user.enabled %>
-        <%= link_to('disable', user_path(user.id), :method => :delete) %>
-      <% else %>
-        <%= link_to('enable', enable_user_path(user.id), :method => :put) %>
-      <% end %>
-    <% end %>
-  </td>

+  <td>
+    <%= h user.state %>
+    <% unless user == current_user %>
+      <% if user.state == "active" %>
+        <%= link_to('inactivate', user_path(user.id), :method=> :delete) %>
+      <% else %>
+        <%= link_to('activate', forcible_activate_path(user.id), :method => :put) %>
+      <% end %>
+    <% end %>
+  </td>
よし。これで、ユーザ管理画面チックなものが出来たよね?:-)

2008年12月8日月曜日

じゃあ、role機能でもやっちゃいますか。

職安にって、職業相談とやらを受けるも、なんか、ちょろっと話をしただけで終わったぞ?
大丈夫か? 俺www

んで、帰りにブックオフで「きのう何食べた? 2」と「不思議な少年 7」を買ってくる。
マンガ買うなんて、まだ余裕あるつもりなのか? 俺www


んじゃあ、もう一度、例のページの頭に戻って、roleに関するところのみピックアップして、やっていきますか。

で、ずうっと飛ばして、
$ script/generate scaffold Role rolename:string
$ script/generate model Permission
から。
つうか、scaffold、いるのか?www

んで、db/migrate/*数字*_create_permissions.rb。
...ん?
って、これ、adminのデータ、作ってるよね?
じゃあ、その部分、飛ばして、別に作ろう。
class CreatePermissions <>
def self.up
create_table :permissions do |t|
t.integer :role_id, :user_id, :null => false
t.timestamps
end
end

def self.down
drop_table :permissions
end
end
よし。

アレ?
*数字*_create_roles.rb、編集してないよね?
つうか、ここにも載ってないよね?
じゃあ、最新版restful_authentication_tutorialの方から拾ってくる方面で。
db/migrate/*数字*_create_roles.rb。
def self.up
create_table "roles" do |t|
t.string :name
end
# generate the join table
create_table "roles_users", :id => false do |t|
t.integer "role_id", "user_id"
end
add_index "roles_users", "role_id"
add_index "roles_users", "user_id"
end

def self.down
drop_table "roles"
drop_table "roles_users"
end
ありゃ?
scaffoldの時にはrolenameだったのに、こっちはnameになってるな...
まあ、いいやwww
こっちを採用。
Role.nameの方が、Role.rolenameより自然だよね?

混同しそうだけどwwwwww

んじゃあ、modelの関連付け、しましょうか。
app/models/role.rb
class Role <>
has_many :permissions
has_many :users, :through => :permissions
end
app/models/permission.rb
class Permission <>
belongs_to :user
belongs_to :role
end
んで、app/models/user.rbにも関連付けを。
+ has_many :permissions
+ has_many :roles, :through => :permissions
これで、userとroleとpermissionが結びついたよね?
ああ、あと、find_for_forget?とhas_role?メソッドも追加してるね。
+ def self.find_for_forget(email)
+ find :first, :conditions => ['email = ? and activated_at IS NOT NULL', email]
+ end
+
+ def has_role?(rolename)
+ self.roles.find_by_name(rolename) ? true : false
+ end
次は、filter用のメソッドの追加。
lib/authenticated_system.rb
+ def role_requiered(role)
+ unless logged_in? && @current_user.has_role?(role)
+ if logged_in?
+ permission_denied
+ else
+ store_referer
+ access_denied
+ end
+ end
+ end
+
+ def administrator_role_required
+ role_requiered('administrator')
+ end
メソッド名は、それぞれ、っぽく変えといた;-p

んで、app/controllers/users_controller.rbにbefore_filterする。
+ before_filter :administrator_role_required, :only => [:index, :destroy, :enable]

んじゃあ、app/controllers/roles_controller.rbまで飛ばして。
class RolesController <>
before_filter :administrator_role_required
def index
@user = User.find(params[:user_id])
@all_roles = Role.find(:all)
end
def update
@user = User.find(params[:user_id])
@role = Role.find(params[:id])
unless @user.has_role?(@role.name)
@user.roles << @role
end
redirect_to :action => 'index'
end
def destroy
@user = User.find(params[:user_id])
@role = Role.find(params[:id])
if @user.has_role?(@role.name)
@user.roles.delete(@role)
end
redirect_to :action => 'index'
end

end
そういえば、respond_toって、いままで付けてなかったな...

まあ、いいやwww
また今度。

次。roleのview。
scaffoldで生成したものの内、index以外はいらないんで、削除。
んで、partial作る。
app/views/roles/_role.html.erb
<li>
<%= role.name %>
<% if @user.has_role?(role.name) %>
<%= link_to 'remove role', user_role_url(:id => role.id, :user_id => @user.id), :method => :delete %>
<% else %>
<%= link_to 'assign role', user_role_url(:id => role.id, :user_id => @user.id), :method => :put %>
<% end %>
</li>
んで、app/views/roles/index.html.erb
<h2>Roles for <%=h @user.nickname %></h2>
<h3>Roles assigned:</h3>
<ul><%= render :partial => 'role', :collection => @user.roles %></ul>
<h3>Roles available:</h3>
<ul><%= render :partial => 'role', :collection => (@all_roles - @user.roles) %></ul>
おk。

で、今まで敢えて作ってこなかったviewを。
まず、app/users/_user.html.erb
<tr class="<%= cycle('odd', 'even') %>">
<td><%=h user.nickname %></td>
<td><%=h user.email %></td>
<td><%= user.enabled ? 'yes' : 'no' %>
<% unless user == current_user %>
<% if user.enabled %>
<%= link_to('disable', user_path(user.id), :method => :delete) %>
<% else %>
<%= link_to('enable', enable_user_path(user.id), :method => :put) %>
<% end %>
<% end %>
</td>
<td><%= link_to 'edit roles', user_roles_path(user) %>]</td>
</tr>
んで、app/views/users/index.html.erb。
<h2>All Users</h2>
<table>
<tr>
<th>Username</th>
<th>Email</th>
<th>Enabled?</th>
<th>Roles</th>
</tr>
<%= render :partial => 'user', :collection => @users %>
</table>
おk。

後は、adminユーザの初期データのマイグレーションですか。
これは、最新版restful_authentication_tutorialから持ってきたものを基にしよう。
$ script/generate migration AddAdminUserToUser
で、
db/migrate/*数字*_add_admin_user_to_user.rb
class AddAdminUserToUser <>
def self.up
#Be sure to change these settings for your initial admin user
unless User.find_by_email("email@hogehoge.com")
User.create(
:nickname => "admin",
:family_name => "管理者",
:middle_name => "ザ",
:given_name => "アドミン",
:password => "password",
:password_confirmation => "password",
:email => "email@hogehoge.com")
end
#Admin role name should be "admin" for convenience
unless Role.find_by_name("administrator")
Role.create(
:name => "administrator")
end

admin_user = User.find_by_email("email@hogehoge.com")
admin_role = Role.find_by_name("administrator")
admin_user.state = "active"
admin_user.activated_at = Time.now.utc
admin_user.roles <<>
admin_user.save(false)
end

def self.down
admin_user = User.find_by_email("email@hogehoge.com")
admin_role = Role.find_by_name("administrator")
admin_user.roles = []
admin_user.save
admin_user.destroy
admin_role.destroy
end
end
どうよ?


こんな感じじゃ良くなかったwww


いやいや、passwords_controller.rbの中で、



before_filter :not_logged_in_required, :only => [:new, :create]



ってしているけど、"not_logged_in_required"ってメソッド、どこかにあるのか? と思ってたら、lib/authenticated_system.rbに書くんだなwww


で、restful_authentication_tutorialの方を見てみたら、メソッドの名前を変えて、新たに作ってあったから、それ使った。


lib/authenticated_system.rb



# Prevents logged in users from accessing actions reserved for


# non-authenticated users such as the login or signup forms


# Make sure to redirect to a path they can access to avoid an infinite loop


def login_prohibited


!logged_in? || (redirect_to root_path)


end



んで、passwords_controller.rbとaccounts_controller.rbを変更した。



/app/controllers/passwords_controller.rb



- before_filter :not_logged_in_required, :only => [:new, :create]



+ before_filter :login_prohibited, :only => [:new, :create]


/app/controllers/accounts_controller.rb


- before_filter :not_logged_in_required, :only => :show


+ before_filter :login_prohibited, :only => :show






んじゃあ、sessions_controllerとusers_controllerも書き換えれるよね。


logged_in?で見ていたところも、login_prohibitedをbefore_filterしちゃえばいいんだもんな。


と思って、やってみたら、sessions_controllerは、ダメだwww


だって、root_pathを、sessions/newにしてるんだもんwww


app/controllers/sessions_controller.rb




- skip_before_filter :login_required


+ skip_before_filter :login_required, :only => [:new, :create]




後々、root_pathを変えることになったなら、その時は考えましょう;-p


app/controllers/users_controller.rb



skip_before_filter :login_required, :only => [:new, :create, :activate, :suspend, :unsuspend, :destoy, :purge]

+ before_filter :login_prohibited, :only => [:new, :create, :activate, :suspend, :unsuspend, :destoy, :purge]



おk。


あと、usersのview、全然作ってないじゃんwwww


とりあえず、内容はあまり考えずに、プレース・ホルダとして、ベタバリしましょうかwww


app/views/users/edit.html.erb




<h2>Edit Your Account</h2>


<p><%= link_to 'Show Profile', user_path(@user) %> | <%= link_to 'Change Password', change_password_path %></p>


<%= error_messages_for :user %>


<% form_for :user, :url => user_url(@user), :html => { :method => :put } do |f| %>


<p>Email:<br /><%= f.text_field :email, :size => 60 %></p>


<%= submit_tag 'Save' %>


<% end %>



って、これじゃあ、メールアドレスしか変更出来ねぇwww


ん、あとで考える。


index.html.erbと_user.html.erbは、また今度。


role絡みのロジック入れないと、エラー返ってくるし。


new.html.erbとshow.html.erbは、前に書いたヤツのほうが、イイ感じ;-p


あと、userモデルにpassword_reset_codeのカラム、追加するの忘れてたwww



$ script/generate migration AddColumnPassWordResetCodeToUser password_reset_code:string



で、




class AddColumnPassWordResetCodeToUser <>

def self.up


add_column :users, :password_reset_code, :string, :limit => 40


end


def self.down


remove_column :users, :password_reset_code


end


end





んな感じで。





2008年12月7日日曜日

とりあえず、パスワードを忘れた時の処理を追加(?)

とりあえず、Restful Authentication with all the bells and whistlesを、順番に追っかけてみましょうかね。

app/models/user.mailer.rbに、
  • forgot_password
  • reset_password
の、2つのメソッドを追加。
こんな感じ。
  def forgot_password(user)
    setup_email(user)
    @subject    += 'You have requested to change your password'
    @body[:url]  = "http://localhost:3000/reset_password/#{user.password_reset_code}"
  end

  def reset_password(user)
    setup_email(user)
    @subject    += 'Your password has been reset.'
  end
はい。
次に、app/models/user_observer.rbに追記。
UserMailer.deliver_forgot_password(user) if user.recently_forgot_password?
UserMailer.deliver_reset_password(user) if user.recently_reset_password?
で、次に、って、アレ?
permission云々って、書いてあるな...

んー、飛ばすwww

で、app/models/user.rbに
  • forgot_password
  • reset_password
  • recently_forgot_password?
  • recently_reset_password?
  • make_password_reset_code (protected)
を追加。
以下、コード。 
 # Forgot password
  def forgot_password
    @forgotten_password = true
    self.make_password_reset_code
  end
  # Reset password
  def reset_password
    # First update the password_reset_code before setting the
    # reset_password flag to avoid duplicate email notifications.
    update_attribute(:password_reset_code, nil)
    @reset_password = true
  end

  #used in user_observer
  def recently_forgot_password?
    @forgotten_password
  end
 
  def recently_reset_password?
    @reset_password
  end
(略)
protected
(略)
    def make_password_reset_code
        self.password_reset_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
    end
こんな感じですか。
次。lib/authenticated_system.rbを書き換えてるようですが、permission絡みみたいなんで、飛ばす。

次は、app/controller/users_controller.rb。
とりあえず、indexとeditとupdateのメソッドの追加。
  def index
    @users = User.find(:all)
  end

  # render edit.html.erb
  def edit
    @user = current_user
  end

  def update
    @user = User.find(current_user)
    if @user.update_attributes(params[:user])
      flash[:notice] = "User updated"
      redirect_to :action => 'show', :id => current_user
    else
      render :action => 'edit'
    end
  end
ほい。
updateは、viewが無いんだね。

そりゃそうだwww

次は、app/controllers/sessions_controller.rb。
...なんかいるか?
...飛ばすwww

次。
ん?
passwords_controller.rb?
accounts_controller.rb?
roles_controller.rb?

ん?
飛ばすwww

んで?
application.html.erbも、飛ばす。
なんか、role絡みのコードが入ってるし。後だね、後。

次は、app/views/passwords/edit.html.erb。
あれ?
app/views/passwords/new.html.erbとapp/views/accounts/edit.html.erbも、とりあえず、飛ばそう。

あ、そうか!
これ、password変更のロジックだな。

おk。後回しwww

んで、...
なんか、role関係のviewが続くんで、まとめて飛ばし。

次。
やっとだよwww
app/views/sesisons/new.html.erb。
まあ、別にどうでも良いんだけど、とりあえず、users_controllerのnewアクションへのリンクを足す。

new_user_pathなんて云う書き方、今、はじめて気が付いたwww
"アクション名_コントローラ名(単数系)_path"で、そのurlが生成できるんだな。
イヤ、便利っぽくない?www
後で書き換えよう:-)

app/views/user_mailer/activation.erb
<%= h @user.real_name %>, your account has been activated.  Welcome aboard!

  <%=h @url %>
@user.loginは、loginを削除してしまっているんで、real_nameメソッドを使って、本名を使うようにした。
後述のforgot_password.erbとreset_password.erbも一緒。

app/views/user_mailer/forgot_password.erb
<%= h @user.real_name %>, your account has been activated.  To visit the site, follow the link below:
<%= @url %> 
app/views/user_mailer/reset_password.erb
<%= h @user.real_name %>, Your password has been reset

こんな感じ?

app/views/user_mailer/signup_notification.html.erbは、real_nameとemailを使って、passwordは送らないようにしましょうか。再発行できるんだから、ね?
Your account has been created.

  Real Name: <%= h @user.real_name %>
  Email: <%= h @user.email %>
  Password: <%= h @user.password %>

Visit this url to activate your account:

  <%= h @url %>

って、あれ?
だとすると、さっき飛ばしたロジック、入れとかないと、マズいよね?
じゃあ、入れましょうか。
$ script/generate controller Passwords
$ script/generate controller Accounts
んで、
app/controllers/passwords_controller.rb
class PasswordsController <>
   skip_before_filter :login_required :only => [:new, :creat]
  :not_logged_in_required, :only => [:new, :create]
  
  # Enter email address to recover password 
  def new
  end
 
  # Forgot password action
  def create    
    return unless request.post?
  if @user = User.find_for_forget(params[:email])
      @user.forgot_password
      @user.save      
      flash[:notice] = "A password reset link has been sent to your email address."
      redirect_to login_path
    else
      flash[:notice] = "Could not find a user with that email address."
      render :action => 'new'
    end  
  end
  
  # Action triggered by clicking on the /reset_password/:id link recieved via email
  # Makes sure the id code is included
  # Checks that the id code matches a user in the database
  # Then if everything checks out, shows the password reset fields
  def edit
    if params[:id].nil?
      render :action => 'new'
      return
    end
    @user = User.find_by_password_reset_code(params[:id]) if params[:id]
    raise if @user.nil?
  rescue
    logger.error "Invalid Reset Code entered."
    flash[:notice] = "Sorry - That is an invalid password reset code. Please check your code and try again. (Perhaps your email client inserted a carriage return?)"
    #redirect_back_or_default('/')
    redirect_to new_user_path
  end
    
  # Reset password action /reset_password/:id
  # Checks once again that an id is included and makes sure that the password field isn't blank
  def update
    if params[:id].nil?
      render :action => 'new'
      return
    end
    if params[:password].blank?
      flash[:notice] = "Password field cannot be blank."
      render :action => 'edit', :id => params[:id]
      return
    end
    @user = User.find_by_password_reset_code(params[:id]) if params[:id]
    raise if @user.nil?
    return if @user unless params[:password]
      if (params[:password] == params[:password_confirmation])
      #Uncomment and comment lines with @user to have the user logged in after reset - not recommended
        #self.current_user = @user #for the next two lines to work
        #current_user.password_confirmation = params[:password_confirmation]
        #current_user.password = params[:password]
        #@user.reset_password
    #flash[:notice] = current_user.save ? "Password reset" : "Password not reset"
    @user.password_confirmation = params[:password_confirmation]
    @user.password = params[:password]
    @user.reset_password        
    flash[:notice] = @user.save ? "Password reset." : "Password not reset."
      else
        flash[:notice] = "Password mismatch."
        render :action => 'edit', :id => params[:id]
      return
      end  
      redirect_to login_path
  rescue
    logger.error "Invalid Reset Code entered"
    flash[:notice] = "Sorry - That is an invalid password reset code. Please check your code and try again. (Perhaps your email client inserted a carriage return?)"
    redirect_to new_user_path
  end
    
end
ほぼベタ張りwww
しっかし、長えな、これwww
ロジックがどう動いているのか、サッパリ理解してないぞwww

続いて、app/controllers/accounts_controller.rb。
class AccountsController <>
  skip_before_filter :login_required :only => [:show]
  before_filter :not_logged_in_required, :only => :show
 
  # Activate action
  def show
    # Uncomment and change paths to have user logged in after activation - not recommended
    #self.current_user = User.find_and_activate!(params[:id])
  User.find_and_activate!(params[:id])
    flash[:notice] = "Your account has been activated! You can now login."
    redirect_to login_path
  rescue User::ArgumentError
    flash[:notice] = 'Activation code not found. Please try creating a new account.'
    redirect_to new_user_path 
  rescue User::ActivationCodeNotFound
    flash[:notice] = 'Activation code not found. Please try creating a new account.'
    redirect_to new_user_path
  rescue User::AlreadyActivated
    flash[:notice] = 'Your account has already been activated. You can log in below.'
    redirect_to login_path
  end
 
  def edit
  end
  
  # Change password action  
  def update
  return unless request.post?
    if User.authenticate(current_user.email, params[:old_password])
      if ((params[:password] == params[:password_confirmation]) && !params[:password_confirmation].blank?)
        current_user.password_confirmation = params[:password_confirmation]
        current_user.password = params[:password]        
    if current_user.save
          flash[:notice] = "Password successfully updated."
          redirect_to root_path #profile_url(current_user.login)
        else
          flash[:error] = "An error occured, your password was not changed."
          render :action => 'edit'
        end
      else
        flash[:error] = "New password does not match the password confirmation."
        @old_password = params[:old_password]
        render :action => 'edit'      
      end
    else
      flash[:error] = "Your old password is incorrect."
      render :action => 'edit'
    end 
  end
  
end
つうか、ね?
newアクション、いるのか?www
あと、User.authenticateでcurrent_user.loginを放り込んでるから、current_user.emailに変更ね。

んじゃあ、viewも作りましょうか。
app/views/passwords/edit.html.erb
<% form_tag url_for(:action => "update", :id => params[:id]) do %>
    Password:<br />
    <%= password_field_tag :password %><br />
    Confirm Password:<br />
    <%= password_field_tag :password_confirmation %><br />
    <%= submit_tag "Reset Your Password" %>
<% end %>

app/views/passwords/new.html.erb
<h2>Forgot Password</h2>
<% form_tag url_for(:action => 'create') do %>
    What is the email address used to create your account?<br />
    <%= text_field_tag :email, "", :size => 50 %><br />
    <%= submit_tag 'Reset Password' %>
<% end %>

app/views/accounts/edit.html.erb
<% form_tag url_for(:action => "update") do %>
  <p><label for="old_password" class="block">Old Password</label><br />
  <%= password_field_tag 'old_password', @old_password, :size => 45 %></p>
 
  <p><label for="password" class="block">New Password</label><br />
  <%= password_field_tag 'password', {}, :size => 45 %><br />
  <small>Between 4 and 40 characters</small></p>
 
  <p><label for="password_confirmation"  class="block">Confirm new password</label><br />
  <%= password_field_tag 'password_confirmation', {}, :size => 45 %></p>
 
  <%= submit_tag 'Change password' %>
 
<% end %>
な感じで。
何も変えてないぞwwww

んで、config/routes.rbに以下を追記。
map.forgot_password '/forgot_password', :controller => 'passwords', :action => 'new'
map.reset_password '/reset_password/:id', :controller => 'passwords', :action => 'edit'
map.change_password '/change_password', :controller => 'accounts', :action => 'edit'

map.resources :users, :member => { :enable => :put } do |users|
 users.resource :account
 users.resources :roles
end

map.resource :password
こんな感じで、いいんじゃね?
ね?

じゃあ、restful_authenticationで作ったUserモデルの機能拡張をしようか。

参考にするのは、主に以下のページ。
後者は、前者の基になったページのようですな。
で、後者は、既にアップデートされているんだけども。
これが、また、もう、全く別物って云うくらいにいじられまくりwww
github.comに、restful_authentication_tutorialてな形で、プロジェクトが置いてあるんだけど。

イヤ、もう、全く別物www

そんなややこしいのの中を見てコードを理解するのなんか、イヤじゃwww

という訳で、上記のページを参考にしながら、徐々に機能をアップデートしていきましょうよ。