認証。acts_as_authenticatedとrole_requirementとopenid_login_generatorで、両対応な感じを目指す。

acts_as_authenticated

インスコ→じぇねる→migrate

$ ./script/plugin install acts_as_authenticated
$ ./script/generate authenticated user account
$ rake db:migrate

で、おk

role_requirement

インスコ→じぇねる→migrate

$ script/plugin install http://rolerequirement.googlecode.com/svn/tags/role_requirement/
$ script/generate roles Role User
$ rake db:migrate

モデル書く
app/models/role.rb

class Role < ActiveRecord::Base
  has_and_belongs_to_many :users
end

ロールの管理をscaffold

ruby script/generate scaffold role --skip-migration

migrationをskipしてるからか、スキーマ情報が
入ってないのでviewを直す。

(略)

openid_login_generator

既にgemでインスコしてあって、ジェネレータも直してる状態で、
generate
Userモデルはもうあるのでその辺はnで

$ ./script/generate openid_login openid
      create  lib/openid_login_system.rb
      create  app/controllers/openid_controller.rb
      create  test/functional/openid_controller_test.rb
      create  app/helpers/openid_helper.rb
overwrite app/models/user.rb? (enter "h" for help) [Ynaqdh] n
        skip  app/models/user.rb
overwrite test/unit/user_test.rb? (enter "h" for help) [Ynaqdh] n
        skip  test/unit/user_test.rb
overwrite test/fixtures/users.yml? (enter "h" for help) [Ynaqdh] n
        skip  test/fixtures/users.yml
      create  app/views/layouts/scaffold.html.erb
   identical  public/stylesheets/scaffold.css
      create  app/views/openid
      create  app/views/openid/welcome.rhtml
      create  app/views/openid/login.rhtml
      create  app/views/openid/logout.rhtml
      create  README_LOGIN

usersにopenid_urlカラムを追加

$ ruby script/generate migration add_column_users_openid_url
      exists  db/migrate
      create  db/migrate/003_add_column_users_openid_url.rb

migarate_fileを編集

class AddColumnUsersOpenidUrl < ActiveRecord::Migration
  def self.up
    add_column :users, :openid_url, :string
  end

  def self.down
    remove_column :users, :openid_url
  end
end

migrate

$ rake db:migrate
(in /home/coek/dev/rails/auth_and_open_id_test)
== 3 AddColumnUsersOpenidUrl: migrating =======================================
-- add_column(:users, :openid_url, :string)
   -> 0.0417s
== 3 AddColumnUsersOpenidUrl: migrated (0.0439s) ==============================

モデル書き足す

  def self.get(openid_url)
    find_by_openid_url(openid_url)
  end
  protected

  validates_uniqueness_of :openid_url, :on => :create
  validates_presence_of :openid_url

で、controllerとかを
http://d.hatena.ne.jp/crimaru/20080212/1202793189
http://d.hatena.ne.jp/crimaru/20080212/1202812083
とかでやったように全部直す。

validateでコケる

今回はopenidからのログイン(登録)の場合は、idとopenid_urlだけ入れるってのでいいかなと思ってる。
で、普通にサインアップしたときは、openid_urlがNULLでいいかな、と。
なので

validates_presence_of     :login, :email

だと、openidから使うときダメになるので

Userモデルに

  def openid?
    self.openid_url.blank? #入ってたらfalseが返る
  end

なのを書き足して、

  validates_presence_of     :login, :email, :if => :openid?
  validates_presence_of     :password,                   :if => :password_required?
  validates_presence_of     :password_confirmation,      :if => :password_required?
  validates_length_of       :password, :within => 4..40, :if => :password_required?
  validates_confirmation_of :password,                   :if => :password_required?
  validates_length_of       :login,    :within => 3..40, :if => :openid?
  validates_length_of       :email,    :within => 3..100, :if => :openid?
  validates_uniqueness_of   :login, :email, :case_sensitive => false, :if => :openid?
(中略)
  validates_uniqueness_of :openid_url, :on => :create, :unless => :openid?
  validates_presence_of   :openid_url, :unless => :openid?

な、感じでやればとりあえずよくなる。
とりあえずね。とりあえず。
あとpassword_required?もちょっとだけ手を入れる

    def password_required?
      if openid? then
        crypted_password.blank? || !password.blank? 
      else
        openid?
      end
    end

すんません。頑張ります><

これで一応両対応

http://localhost:3000/login/signup
から普通にサインアップ
http://localhost:3000/openid/
からOpenidログイン
usersに書かれる。

openid_controllerでのログイン処理

def complete

#中略

  when OpenID::Consumer::SUCCESS

  #中略
  #OpenID::Consumer::SUCCESSの最後で

      #サイト側の認証
      @user = User.get(oidresp.identity_url)
      if @user.blank? then
        @user = User.new(:openid_url => oidresp.identity_url)
        @user.save
      end
      self.current_user = @user
            
      redirect_to :action => 'mypage/top', :action => "index"