inossidabile / protector

Comfortable (seriously) white-list security restrictions for models on a field level
MIT License
270 stars 31 forks source link

conditions not working on object #15

Closed anazar closed 11 years ago

anazar commented 11 years ago

I have an issue where I'm setting cannot :view

If I do:

Article.restrict!(current_user).find 1

It works and I can't get the article.

If I do:

a = Article.find 1
a.restrict!(current_user).can? :view #returns true
a.restrict!(current_user).visible? #returns true

Shouldn't I be able to check accessiblity on an existing object?

inossidabile commented 11 years ago

What do you mean yo can not get the article? You can not select it, read particular field or what? You clearly seem to miss can and scope.

cannot rule controls if you can read fields of a model. So cannot :view means you can not read any attribute of a model. But you still can find it.

scope rule controls scope that your selection will be automatically restricted with. So unless you called scope or set paranoid mode you will be able to select any record from the database.

If that didn't clarify things to you – paste your protection block for further investigation.

anazar commented 11 years ago

Sorry for the confusion -- what I'm trying to figure out is how to check if a user can view an object that has been loaded without a scope.

    protect do |user|
      case user.role.name.to_sym
      when :vendor_manager, :vendor_staff
        scope { where(permission: [:public, :vendor]) }
        can :view, permission: ->(x) {%w(public vendor).include? x}
        can :create
      when :client_staff, :client_manager
        scope { where(permission: [:public, :client]) }
        can :view, permission: ->(x) {%w(public client).include? x}
        can :create         
      end
    end

So in this case I have an article with a permission of "private"

article = Article.find 1 #grabbing private article without a scope
article.restrict!(current_user).can? :view  #current user can't view private article but this is still returning true
article.restrict!(current_user).visible? #current user can't view private article but this is still returning true
inossidabile commented 11 years ago

It should be visible? what you are seeking for. Can you also dump current_user you pass to restrict! in the latter example to make visible? return true? Just to make sure it is a bug.

anazar commented 11 years ago

I figured out the issue...

2.0.0p0 :009 > history.restrict!(current_user).visible?
=> false 
2.0.0p0 :010 > history.permission = :public
=> :public 
2.0.0p0 :011 > history.restrict!(current_user).visible?
=> false 

I didn't realize that visible? was doing a db query. I was setting the attribute without saving while testing.

My bad. Thanks for the help. Is there a way to check visible on the current object without db lookup?

inossidabile commented 11 years ago

Unfortunately it's technically impossible. Scopes translate directly into SQL and there is no way to filter model instances through them.