【问题标题】:Cancan restricting access to users when it shouldn't (Ruby on Rails)Cancan 在不应该的时候限制对用户的访问(Ruby on Rails)
【发布时间】:2013-05-31 16:09:30
【问题描述】:

我在只允许管理员用户查看和编辑他创建的用户时遇到了问题。 我有一个分层系统:超级用户 > 管理员 > 其他用户 我的超级用户可以编辑所有用户,但我的管理员用户只能编辑自己。为了解决这个问题,我有一个 creator_id 参数,它为新用户提供了一个与当前用户的 id 匹配的 creator_id。

我的用户控制器:

class UsersController < ApplicationController
  #CanCan resource will generate a 500 error if unauthorized
  load_and_authorize_resource :user
  # GET /users
  # GET /users.json
  def index
    @users = User.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @users }
    end
  end

  # GET /users/1
  # GET /users/1.json
  def show
    @user = User.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @user }
    end
  end

  # GET /users/new
  # GET /users/new.json
  def new
    @user = User.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @user }
    end
  end

  # GET /users/1/edit
  def edit
    @user = User.find(params[:id])
    #User.find(session[:user])
  end

  # POST /users
  # POST /users.json
  def create
    @user = User.new(params[:user])
    @user.creator = current_user

    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'Registration successful.' }
        format.json { render json: @user, status: :created, location: @user }
      else
        format.html { render action: "new" }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # PUT /users/1
  # PUT /users/1.json
  def update
    @user = User.find(params[:id])
    #@user = current_user

    respond_to do |format|
      if @user.update_attributes(params[:user])
        format.html { redirect_to @user, notice: 'Successfully updated profile.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1
  # DELETE /users/1.json
  def destroy
    @user = User.find(params[:id])
    @user.destroy

    respond_to do |format|
      format.html { redirect_to users_url }
      format.json { head :no_content }
    end
  end
end

还有我的ability.rb文件:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new  #Guest user w/o account

    #Permissions on what pages can be seen by which users, and what
    #Users can do with those pages
    if user.status == "Super User" 
      can :manage, :all
    elsif user.status == "Admin"
      can :manage, Book             
      can [:create,:new], User      
      can [:show, :update], User, :id => user.id 
      can :manage, User, :creator_id => user.id
    end
  end
end

我确实检查了数据库,它正确地将当前用户的 id 分配给了新用户的 creator_id。我只是卡住了。 Cancan 一直拒绝更新这些用户的权限,我不知道为什么。任何帮助表示赞赏!

编辑

我的用户模型:

class User < ActiveRecord::Base
  has_many :books
  has_many :listings
  has_many :orders
  belongs_to :organizations
  belongs_to :creator, class_name: 'User'
  attr_accessible :password, :email, :first_name, :last_name, :password_confirmation,   :status, :username
  acts_as_authentic
  validates :first_name, :presence => true
  validates :last_name, :presence => true
  validates :username, :presence => true, :uniqueness => true
  validates :email, :presence => true, :uniqueness => true
  validates :status, :presence => true
end

【问题讨论】:

  • 你有没有在你的应用程序中定义过roles
  • 我确实定义了角色。除了我将它作为用户的一个属性称为状态。所以 user.status 定义了用户的角​​色
  • 您是否在您的用户模型中定义了:status?这方面的一个例子可能是这样的 - gist.github.com/anonymous/5686257 进一步我建议看:starqle.com/articles/…
  • 编辑了我的原始问题以包含我的模型我觉得我应该添加我正在使用带有 Authlogic 的 CanCan,并且我确实有基本的用户身份验证工作。
  • 看看那个链接,试一试,设置应该能让你走上正轨。

标签: ruby-on-rails ruby permissions cancan


【解决方案1】:

好的,只是再次阅读您的问题,您似乎希望管理员拥有管理用户的权威访问权限。在这种情况下,您可以在 application_controller 中定义非常相似的内容

def correct_user
    if !params[:id].nil?
      @user.User.find_by_id(params[:id])
      if current_user.status :admin
        else
        access_denied unless current_user?(@user)
      end
    end
  end

这样做是允许管理员访问所有用户帐户,如果用户不是管理员,则他们被拒绝访问。您可以使用控制器中的before_filter 启用此功能,以便您可以执行before_filter :correct_user, :only =&gt; [:edit, :show] 之类的操作,这意味着只有正确的用户才能访问这些操作。所以你应该有一个UserController 像下面这样:

class UsersController < ApplicationController
  load_and_authorize_resource
  before_filter :correct_user, :only => [:edit, :show]
  ..
  ....
   .....
end 

此示例表明,作为正确的用户或管理员将有权编辑和显示操作。

【讨论】:

    【解决方案2】:
    Try this.
    
    def initialize(user)
      user ||= User.new
    
      if user.super_user?
        can :manage, :all
      elsif user.admin?
        can [:create, :new], User
        can [:show, :edit, :update], User do |usr|
          id == usr.id
        end
        can :manage, User do |usr|
          usr.creator_id == usr.id
        end
      end
    end
    
    In user model, add methods:
    
    def has_status?(given_status)
      status == given_status
    end
    
    def admin?
      has_status? 'Admin'
    end
    
    def super_user?
      has_status? 'Super User'
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多