簡體   English   中英

可以不可以授權管理員

[英]CanCanCan not authorizing admin

我將cancancanrails_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 我是否需要在數據庫中同時使用roleroles_mask

  1. 我不完全了解User#roles但是在任意分配一個role_mask為0(admin的索引)之后,我得到了一個空數組。 我懷疑這是您預期的行為。

  2. 我看到檢查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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM