问题
So this is the authorization code I wrote based on Railscast #386.
The problem is that the block works on all controllers except for user_controller
. In other words, any user can triger edit
and update
actions on any other user, even though the block given to it is the same as that of favors edit
and update
actions.
def initialize(user)
allow :users, [:new, :create, :show]
allow :sessions, [:new, :create, :destroy]
allow :favors, [:index, :show]
if user
allow :users, [:edit, :update] do |usr|
usr.id == user.id
end
allow :favors, [:new, :create]
allow :favors, [:edit, :update] do |favor|
favor.user_id == user.id
end
allow :acceptances, [:create, :update] do |acceptance|
!acceptance.has_accepted_acceptance?
end
end
end
Any help is highly appreciated :)
回答1:
You are already passing in the (user)
to the permission class. By calling it again in
if user... do |user|... end
you are re-initializing the passed-in user, making it nil
. You then try to give a nil user permissions on the controller#action, in this case anything involving the user's account.
The reason Ryan Bates includes a block in permissions involving other models is because the model instance hasn't been passed to the permission class. That is why you see the likes of:
allow_action :topics, [:new, :create, :index]
allow_action :topics, [:edit, :update, :show] do |topic|
topic.author_id == user.id
end
allow_attr :topic, [:title, :content]
This bit above grants permissions on all the topics the user may or has created.
SOLUTION Take out anything that re-initializes the (user)
and then try again.
allow_action :users, [:edit, :update]
allow_attr :users, [:email, :invite_token, :name, :surname, :password, :password_confirmation]
NOTE I have renamed the allow
action to allow_action
, as per Ryan's suggestion in the Railscast. I also renamed the allow_param
method to allow_attr
since we are used to using attr_accessible anyway.
来源:https://stackoverflow.com/questions/35120915/railscast-authorization-from-scratch-for-users