11. Devise の設定(1)

devise のインストール

develop から configure_devise というブランチを切って作業する。以下、このブランチでの作業。まず、Gemfile を設定した。

# a flexible authentication solution for Rails based on Warden
gem 'devise', '~> 3.4.1'

bundle install する。

$ bundle install
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Installing bcrypt 3.1.9
Installing orm_adapter 0.5.0
Installing responders 2.0.2
Installing warden 1.2.3
Installing devise 3.4.1
Your bundle is complete!
It was installed into ./vendor/bundle

devise の設定

Generator を使って devise を設定する。

> bin/rails g devise:install
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================

Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

  4. If you are deploying on Heroku with Rails 3.2 only, you may want to set:

       config.assets.initialize_on_precompile = false

     On config/application.rb forcing your application to not access the DB
     or load models when precompiling your assets.

  5. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

===============================================================================

ここに書かれている手順通りに作業を進める。ここで、2 はすでにこれまでで実装済なのでスキップ。また、4 は Rails 3.2 の話なのでスキップ。

1 は default_url_options を設定することということで、development 環境であれば、config/environments/development.rb に

  # environment for devise  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

と設定するとのこと。production 環境については、実際の運用環境の URL を設定する。本システムは学生用と教職員用が別れているが、ソースは共通なので、判別用のファイルを見て切り替える必要がある。まだこの部分は実装していないので、ToDo としてコメントを残しておく。

3 は app/views/layouts/application.html.haml に notice と alert の表記を入れる。今回は、yield の前にこんなふうに入れてみた。

  %body
    -if notice
      .alert.alert-dismissable.alert-success
        %button.close{type:'button', 'data-dismiss' => 'alert'} ×
        %p= notice
    -if alert       
      .alert.alert-dismissable.alert-warning
        %button.close{type:'button', 'data-dismiss' => 'alert'} ×
        %p= alert
    = yield

5 は view を独自に持つ場合の設定。前回は作成したが、現状ではペンディングにしてみる。

devise モデルの作成

前回のシステムと同じで User モデルを作成する。ここでできるモデルと 4 年前に作成したモデルの属性が一致すれば、現在使っているデータがそのまま流用できることになる。ということで、さっそく作成。

$ bin/rails g devise User
      invoke  active_record
      create    db/migrate/20141225022729_devise_create_users.rb
      create    app/models/user.rb
      invoke    rspec
      create      spec/models/user_spec.rb
      invoke      factory_girl
      create        spec/factories/users.rb
      insert    app/models/user.rb
       route  devise_for :users

今回作成された db/migrate/*_devise_create_users.rb はこんな形。

class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.inet     :current_sign_in_ip
      t.inet     :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

旧システムは devise 1.1.2 の頃に作ったものであった。今回導入したものが 3.4.1 ということで、メジャーアップデートがすでに 2 回起こっている。旧システムは、当初ローカル認証だったものを LDAP 認証に変更したため、一部の属性は使わずに残っているものが多い。今回もデータベースの共有を目指しているので、属性を同一に設定したい。そこを踏まえて導入にあたる。旧のテーブルと新のテーブルを比較したところ、以下の属性は同じであった。

encrypted_password, reset_password_token, remember_created_at, sign_in_count, current_sign_in_at, last_sign_in_at, current_sign_in_ip, last_sign_in_ip

1.1.2 側にあって、3.4.1 側になくなった属性はこちら。

password_salt, remember_token, name, 他のモデルの関連ID

これらについて、調べてみた。password_salt については、1.2 の時に deprecated になっているとのこと。もともと、LDAP 認証にしているので、この部分は影響がないはずなので、テーブルに属性だけを挿入してしまう。

remember_token については、こちらで確認した。
Devise3.2.2 のデフォルト設定では、Rememberable の remember_token のカラムがないのでソースを解読してみた。remember_token フィールドを作成しない場合には、encrypted_password フィールドの値が使われるとのこと。今回は、LDAP 認証であるため、encrypted_password フィールドは使わない。こちらも、テーブルに属性を追加してみる。

name はシステムで設定した認証キーである。これも追加する。他のモデルについては後で設定するが、データの同期を確かめたいので属性だけ先に追加しておく。

一方、3.4.1 側にあって、1.1.2 側にない属性はこちら。

reset_password_sent_at

これは、Recoverable を設定したときに必要だが、LDAP 認証のため使わない。devise の設定で Recoverable を設定しなければ必要ないので、今回は登録しない。

最終的にはこんな感じになった。

class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
      ## Database authenticatable
      t.string :name,               null: false, default: ""
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
      t.string :password_salt       # unused field
      
      ## Recoverable
      t.string   :reset_password_token      # unused field
      # t.datetime :reset_password_sent_at  # remove field for compatible
      
      ## Rememberable
      t.string   :remember_token    # unused field
      t.datetime :remember_created_at
      
      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.inet     :current_sign_in_ip
      t.inet     :last_sign_in_ip 
    
      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable
  
      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at
    
      # link to other models
      t.integer :kyouin_id
      t.integer :shokuin_id
      t.integer :gakusei_id

      t.timestamps
    end

    add_index :users, :name,                unique: true
    add_index :users, :kyouin_id,           unique: true
    add_index :users, :shokuin_id,          unique: true
    add_index :users, :gakusei_id,          unique: true
    # add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end 
end 

migrate してテーブルを作成する。

$ bin/rake db:migrate
== 20141225022729 DeviseCreateUsers: migrating ================================
-- create_table(:users)
   -> 0.0451s
-- add_index(:users, :name, {:unique=>true})
   -> 0.0028s
-- add_index(:users, :kyouin_id, {:unique=>true})
   -> 0.0020s
-- add_index(:users, :shokuin_id, {:unique=>true})
   -> 0.0021s
-- add_index(:users, :gakusei_id, {:unique=>true})
   -> 0.0018s
== 20141225022729 DeviseCreateUsers: migrated (0.0540s) =======================

Devise の LDAP 連携

次に devise の LDAP 連携を設定する。前回のシステムでは、devise_ldap_authenticatable の 0.4.6 であった。現在の最新は、0.8.1 である。まず、Gemfile を設定した。

# a LDAP based authentication strategy for the Devise authentication framework
gem 'devise_ldap_authenticatable', '~> 0.8.1'

続いて、bundle install する。

$ bundle install
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Installing net-ldap 0.5.1
Installing devise_ldap_authenticatable 0.8.1
Your bundle is complete!
It was installed into ./vendor/bundle

次にシステムに devise_ldap_authenticatable をインストールする。

$ bin/rails g devise_ldap_authenticatable:install
      create  config/ldap.yml
      insert  config/initializers/devise.rb
        gsub  app/models/user.rb
      insert  app/controllers/application_controller.rb

システムがいろいろとファイルを修正したようなので、作業ツリーの差分を見ながら確認してみる(上記で自分が設定した部分は除く)。

app/controllers/applicatoin_controller.rb
LdapException が起こったときの例外処理が追加された
app/models/user.rb
LDAP だとほとんど設定が必要なくなる。最終的に以下のようになった
# @!attribute encrypted_password
#   @return [String] 暗号化されたパスワード(LDAP のため未使用。互換性のために維持)
# @!attribute password_salt
#   @return [String] パスワードの付加文字列 (devise 1.2 からは削除。互換性のために維持)
# @!attribute reset_password_token
#   @return [String] パスワードリセットのためのトークン(LDAP のため未使用。互換性のために維持)
# @!attribute remember_token
#   @return [String] パスワード記憶のためのトークン(デフォルトで削除されているが、互換性のために維持)
# @!attribute remember_created_at
#   @return [DateTime] パスワード記憶の日付
# @!attribute sign_in_count
#   @return [FixNum] サインイン数
# @!attribute current_sign_in_at
#   @return [DateTime] 現在のサインイン日付
# @!attribute last_sign_in_at
#   @return [DateTime] 最後にサインインした日付
# @!attribute current_sign_in_ip
#   @return [IPAddr] 現在のサインインIP
# @!attribute last_sign_in_ip
#   @return [IPAddr] 最後にサインインしたIP
# @!attribute kyouin_id
#   @return [FixNum] 教員ID
# @!attribute gakusei_id
#   @return [FixNum] 学生ID
# @!attribute shokuin_id
#   @return [FixNum] 職員ID
# @!attribute name
#   @return [String] ログイン名
# @!attribute email'
#   @return [String] 電子メールアドレス
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable, :registerable, :recoverable, :validatable
  devise :ldap_authenticatable, :rememberable, :trackable
end
config/ldap.yml
テストサーバが設定されたものが作成されているので、旧システムと同じく、学内の LDAP サーバを設定した
config/routes.rb
「devise_for :users」の行が追加された
config/initializers/devise.rb
旧システムの設定と見比べて以下の部分を修正
Devise.setup do |config|
  config.ldap_logger = true
  config.ldap_create_user = false
  config.authentication_keys = [ :name ]
  config.case_insensitive_keys = [ :name ]
  config.strip_whitespace_keys = [ :name ]
config/locales/devise.en.yml
英語用の locale ファイルが追加された。せっかくなので、日本語用の locale ファイルを取得して設置した。

とりあえずここまでを configure_devise リポジトリにコミットした。

今日はここまで。

written by iHatenaSync