[英]CanCanCan not authorizing admin
我將cancancan
與rails_admin
使用,並devise
gems。 即使用戶具有admin
角色也可以顯示錯誤, You are not authorized to access this page.
登錄后嘗試進入/admin
路由時。
這是我的ability.rb
#models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
can :read, :all # allow everyone to read everything
if user && user.has_role?(:admin)
can :access, :rails_admin # only allow admin users to access Rails Admin
can :dashboard # allow access to dashboard
if user.role? :admin
can :manage, :all # allow superadmins to do anything
end
end
end
end
這是我的用戶模型
#models/user.rb
class User < ActiveRecord::Base
ROLES = %i[admin moderator banned]
def roles=(roles)
roles = [*roles].map { |r| r.to_sym }
self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.inject(0, :+)
end
def roles
ROLES.reject do |r|
((roles_mask.to_i || 0) & 2**ROLES.index(r)).zero?
end
end
def has_role?(role)
roles.include?(role)
end
def role?(base_role)
ROLES.index(base_role.to_s) <= ROLES.index(role)
end
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
else
if conditions[:username].nil?
where(conditions).first
else
where(username: conditions[:username]).first
end
end
end
validate :validate_username
def validate_username
if User.where(email: username).exists?
errors.add(:username, :invalid)
end
end
validates_format_of :username, with: /^[a-zA-Z0-9_\.]*$/, :multiline => true
# Include default devise modules. Others available are:
# , :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :confirmable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :authentication_keys => [:login]
attr_accessor :login
def login=(login)
@login = login
end
def login
@login || self.username || self.email
end
end
這是rails_admin.rb
#config/initializers/rails_admin.rb
RailsAdmin.config do |config|
## == Devise ==
config.authenticate_with do
warden.authenticate! scope: :user
end
config.current_user_method(&:current_user)
## == Cancan ==
config.authorize_with :cancan
config.actions do
dashboard # mandatory
index # mandatory
new
export
bulk_delete
show
edit
delete
show_in_app
## With an audit adapter, you can add:
# history_index
# history_show
end
end
這是我的schema.rb
的用戶
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
t.string "username"
t.string "role"
t.integer "roles_mask"
end
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
add_index "users", ["username"], name: "index_users_on_username", unique: true
我創建了一個普通用戶,並使用User.first.update_attribute :role, 'admin'
將它的角色屬性更改為admin
User.first.update_attribute :role, 'admin'
我不完全了解roles_mask
。 我是否需要在數據庫中同時使用role
和roles_mask
?
我不完全了解User#roles
但是在任意分配一個role_mask為0(admin的索引)之后,我得到了一個空數組。 我懷疑這是您預期的行為。
我看到檢查role( has_role?
)使用的是您創建用戶后可能尚未分配的role_mask。
為了減少其中的一些樣板代碼,我認為使用ActiveRecord.enum
會很方便。
#models/user.rb
class User < AR::Base
enum roles: %i[admin moderator banned]
end
請注意,要分配默認角色,可以在db或after_create
。
#models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
can :read, :all # allow everyone to read everything
if user && user.admin?
can :access, :rails_admin # only allow admin users to access Rails Admin
can :dashboard # allow access to dashboard
if user.admin?
can :manage, :all # allow superadmins to do anything
end
end
end
end
您還可以通過user.admin!
將角色分配給特定用戶user.admin!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.