[英]CanCanCan not authorizing admin
I'm using cancancan
with rails_admin
and devise
gems. 我将
cancancan
与rails_admin
使用,并devise
gems。 Even though the user has the role admin
cancan shows the error You are not authorized to access this page.
即使用户具有
admin
角色也可以显示错误, You are not authorized to access this page.
when trying to go to /admin
route after logging in. 登录后尝试进入
/admin
路由时。
Here's my ability.rb
这是我的
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
Here's my user model 这是我的用户模型
#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
Here's the rails_admin.rb
这是
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
Here's the user in my schema.rb
这是我的
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
I created a regular user and changed it's role attribute to admin
using User.first.update_attribute :role, 'admin'
我创建了一个普通用户,并使用
User.first.update_attribute :role, 'admin'
将它的角色属性更改为admin
User.first.update_attribute :role, 'admin'
I don't exactly understand the use of roles_mask
. 我不完全了解
roles_mask
。 Do I need to use both role
and roles_mask
in my database? 我是否需要在数据库中同时使用
role
和roles_mask
?
I don't fully understand what's going on in the User#roles
but after arbitrarily assigning a role_mask of 0(the index of admin), I got an empty array. 我不完全了解
User#roles
但是在任意分配一个role_mask为0(admin的索引)之后,我得到了一个空数组。 I doubt that this is the behaviour you anticipated. 我怀疑这是您预期的行为。
I see that the check for roles( has_role?
) uses the role_mask which you may not have assigned after the creation of your users. 我看到检查role(
has_role?
)使用的是您创建用户后可能尚未分配的role_mask。
To reduce some of these boilerplate code, I think it would be convenient to use ActiveRecord.enum
. 为了减少其中的一些样板代码,我认为使用
ActiveRecord.enum
会很方便。
#models/user.rb
class User < AR::Base
enum roles: %i[admin moderator banned]
end
note that to assign a default role, you could set that on your db or after_create
. 请注意,要分配默认角色,可以在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
You can also assign role to a particular user by user.admin!
您还可以通过
user.admin!
将角色分配给特定用户user.admin!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.