Administrative users

我們要在 User model 中增加一個 admin 屬性,類型是 boolean,然後可以用 admin? 來判斷使用者是否為管理員,User model 欄位如下:

建立 admin 屬性,類型是 boolean:

$ rails generate migration add_admin_to_users admin:boolean

產生的遷移檔案如下:

db/migrate/[timestamp]_add_admin_to_users.rb

class AddAdminToUsers < ActiveRecord::Migration
  def change
    add_column :users, :admin, :boolean, default: false
  end
end

注意,我們加了一個參數 default: false,表示預設中,使用者不是管理員的狀態。

如果不加上 default: falseadmin 會預設為 nil,不過仍然是 false,所以並不是一定要這麼做。只是加上去之後可以讓程式碼的意圖更明顯。

然後執行遷移:

$ bundle exec rake db:migrate

Rails 會自動辨識 admin 屬性的類型是 boolean,然後自動產生 admin? 方法:

$ rails console --sandbox
>> user = User.first
>> user.admin?
=> false
>> user.toggle!(:admin)
=> true
>> user.admin?
=> true

上面使用了 toogle! 方法,把 admin 屬性值 false 翻轉成 true

接著我們要更新 seed data,把第一個使用者設定成預設的管理員:

db/seeds.rb

User.create!(name:  "Example User",
             email: "[email protected]",
             password:              "foobar",
             password_confirmation: "foobar",
             admin: true)

99.times do |n|
  name  = Faker::Name.name
  email = "example-#{n+1}@railstutorial.org"
  password = "password"
  User.create!(name:  name,
               email: email,
               password:              password,
               password_confirmation: password)
end

然後重設資料庫:

$ bundle exec rake db:migrate:reset
$ bundle exec rake db:seed

Revisiting strong parameters

前面我們在初始化的 hash 中,使用了 admin: true 參數來設定使用者為管理員,但這其實有安全顧慮,這會導致把使用者物件曝露在網路上,如果在請求中提供初始化的參數,惡意使用者就可以透過傳送如下的 PATCH 請求:

patch /users/17?admin=1

這個請求會讓 17 號使用者成為管理員,這對安全性來說是個潛藏的風險。

因為有這樣的安全顧慮,我們只允許能安全編輯的屬性通過請求,也就是使用 strong parameters,透過在 params hash 上呼叫 requirepermit

def user_params
  params.require(:user).permit(:name, :email, :password,
                               :password_confirmation)
end

注意,admin 並沒有在允許的清單之中,因為這樣才能預防任意使用者透過應用程式來為自己增加管理權限。因為這是蠻重要的安全議題,所以可以寫個測試來檢查那些不被允許編輯的屬性,這個測試留在練習題。