Authorization with Pundit Discussion
It is really helpful. I've also seen CanCan. But I'm little bit confuse, which one should I use? Do you have any suggestion? Beside this I've a request that it'll be very helpful, if provide a video on angularjs with rails.
Use whichever one makes the most sense to you. I tend to prefer Pundit, but that's my preference.
Cancan is not really good for scaling. If your app grows larger later, Pundit will be much better.
Here is a good article explaining why.
Great video! I've been searching for a good intro to authorization and this was perfect. Thanks!
I have a couple of questions: When are you actually passing in user and record into the the Pundit class because you never explicitly call ApplicationPolicy.new or PostPolicy.new ? How does Pundit know to assign a post to record variable and a user to user variable? Lastly does pundit know to associate @post with the PostPolicy?
You're always calling PostPolicy.new but Pundit provides a helper that creates the new policy and sends in those objects.
Since we inherited from ApplicationPolicy, the initialize method there is the one that sets the user and record variables. We created that, not Pundit so you have full control there.
When you call "authorize @post" it looks at the @post.class which is Post. Then it makes that a string, adds "Policy" on the end and looks up that class which would be "PostPolicy". That's how it knows to grab the right policy.
Hey @excid3:disqus I'm getting a strange error towards the end of the video where we add user == post.user I don't understand why this is happening because I have Devise setup properly. Any suggestions?
The error is happening inside Pundit. Check line 11 in your category_policy.rb. You're calling ".user" on something there that isn't valid. :)
Very useful episode. Two things came into my mind while watching it regarding the best practice using pundit combined with devise:
- Since pundit policy is checking for user presence, devise before_action :authenticate_user! seems redundant. Is it good practice to keep it or delete it ?
- Another thing that seems interesting with pundit is scope, which let you avoid dealing with query starting with current_user.something. I tend to use the User class directly (instead of the current_user) on my queries, it allows me to let the user owning the object (address, avatar) or the admin editing the data simply by navigating on the users#edit page (or registrations#edit if devise). Is it a good practice or there is a better way ? Thank you in advance for your lights.
Hey Chris, thanks for the awesome video; however, I wonder how would you still use Pundit's provided helpers in an Angular raw html view?
For example, as you've explained in the video, you can use:
<% if policy(MyClass).new? %>
Do you know how I can leverage Pundit's helpers in a non erb view?
Thanks
Hi Chris, please could you do another podcast that goes deeper than this. I'm struggling big time (current issues outlined here: http://stackoverflow.com/qu... ). It would be great to see you set scopes based on who the current user is and the conditions attaching to the record. I've been trying for 2 years to figure this out now and need some help. Do you think you could show how to use the scope and resolve methods in detail. Thank you
Yea, I had to use: <% if policy(@post).edit? %> in the Show View. policy(Post).edit? wouldn't work.
Hi Chris,
I notice that you add:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
include Pundit
after_action :verify_authorized, unless: :devise_controller?
end
In other tutorials I have seen :
class ApplicationController < ActionController::Base
include Pundit
protect_from_forgery
after_action :verify_policy_scoped, unless: :devise_controller?
end
is there any difference with including things before or after the protect?
It shouldn't make any difference. Traditionally people do includes at the very top and that's what I generally do too, but in this case I just pasted below to make it a little more clear.
Hey guys, I'm hoping for some advice on how to set a role for a user when signing up. My signup page has 2 options (as images); music supervisor and artist. Both go to the User/new form. In my User model I added a :role column. My goal is to have a user click an image; either supervisor or artist and when they sign up it adds that role name to the database. I know I could use an option field in the form, but I would love to do it this way.
I added this to my Routes:
devise_scope :user do
get "/users/sign_up/:role", to: 'devise/registrations#new', as: 'new_user_with_role'
end
And each image has it's respected url like:
link_to new_user_with_role_path(role: 'supervisor')
So the url looks like: /users/sign_up/supervisor
I added a hidden field and unsuccessfully tried sucking the params through the field to the database, but I think that's an unsecure way to do this.
Any ideas on a good way to do this? Thanks!