-
Notifications
You must be signed in to change notification settings - Fork 67
Support NullUser pattern as well as AnonymousUser pattern. #32
Conversation
…ng NoMethodError for nil, but SecurityViolation instead.
@christhekeele - thanks for working on Authority with me! I'm super pumped to have your contributions. My only concern with this change is that the existing error (" My understanding of NullObject pattern is that there would be a specific object that knows how to quack like a user, but represents the absence of one. So instead of passing nil, you'd pass a If someone accidentally passes nil because they think I have a |
You're right, I suppose I meant I wanted to provide an option to people who don't want to touch the User interface at all, and just accept nil. I do like the Odds are that developers who want to use that pattern will do so themselves in their So re: nil current_users, I propose a configuration option--called something like I find the nil current_user pattern easier to maintain than a no-op user and very common in ruby apps, so I think we'd find the option heavily used. Re: the |
@adamhunter and I have been discussing this, and we thought of another problem. But we also came up with what I think is a nice solution. The other problem we see is that, even if we handle See, in my mind, to have the controller authorization deny a user permission to do something should be a very rare case. That's because any forbidden action should not be visible in the view. If somebody gets stopped at the controller level, either the developer forgot to do So, if the developer is taking care of this in the views, making the controller handle They can solve this by having What we can do is put the following line to the options file, with explanation, commented out by default: nil.extend(Authority::UserAbilities) Similarly, if the developer wants to have With this change, It may seem a bit extreme to modify Any objections? If not, would you update your pull request accordingly? |
By the way, thanks for being patient with my nitpicking. :) |
I've implemented Authority in some small test projects and a big project currently running in production. I love the simplicity and the overall logic that it provides. I've tackled the problem of authorizing some links / controller actions when I don't have a user, and I realized that those should be just handled by authentication, and not authorization in most cases. When authentication doesn't suffice, the developer can just implement the NullUser pattern, so the So, polluting NilClass is extreme in my opinion. Also making authority handle Something like UserMissing Exception, or whatever name and description seems more informative. |
I'm not sure there is a That's what this pull request was initially about, really: the Encouraging the developer to mixin authorization logic into every class that their On the other hand, I'd argue that |
Re: @shuriu
I agree this would be an obfuscation and confusing to a developer picking up Authority for the first time, if it were the default behavior. But if there was a configuration variable that had to get changed first, it would make this behavior explicit enough for me to sleep at night. It might be confusing to existing users of Authority on update, but disabling the configuration variable by default will maintain the current API. It might be confusing to an end user, but this is all under the assumption that they weren't logged in and were trying to find their way into other portions of the site regardless. Screw those guys. I'll update the pull request with a configuration variable implementation to further the discussion. Re: @nathanl Nitpicking is good! If you didn't care about your library's code, I wouldn't be using your library, let alone trying to contribute to it. :) |
I'm still thinking about this (and also trying to do my normal work). :) Will try to respond soon. (Sorry about the merge conflict - I saw you fixed a bunch of whitespace and I thought, "dang, what a mess! I'm just going to fix that everywhere", so I did that on master.) |
@christhekeele - I'd like to talk about this some more. Any chance you'd be able to do a Google Hangout or talk on Skype during business hours? (I'm in Eastern time.) |
I could do Skype in half an hour. (I'm in Central time, so that's 4:45 to me.) Hit me up @tireurroyale. |
OK! For the sake of anyone else reading this issue, Chris and I chatted and agreed about the best way to proceed. Here's the gist of it. Authority won't specially handle nil users or give a specific option to do so. We want to limit Authority to authorization and keep authentication totally separate. If there's no user signed in, that's an authentication concern; Authority can't meaningfully answer the question "can this user do X?" if it isn't given a user or something that quacks like one. Besides the philosophical point, having authentication handle this is a better user experience. If an admin has forgotten to sign in and attempts some admin-only action, it would be confusing to them to say "access denied". It would be much more helpful to say "please sign in". What developers using Authority can do is:
What Authority can do is improve the error it gives you if you pass Thanks to @christhekeele for working on this and to @shuriu for helping us think through it. |
@christhekeele - Still planning to make the nicer error? I don't mind doing it if you don't want to or have time. |
I was planning on doing it this weekend. Don't worry, hadn't forgotten! :) |
Hi I've just put this class ApplicationController < ActionController::Base
def current_or_null_user
if current_user == nil
User.new
else
current_user
end
end
end ... Authority.configure do |config|
config.user_method = :current_or_null_user
end |
@funkdified - Yep, that's a fine way to handle it in your app and will ensure that Authority gets handed an object it can work with. You could go further and have a specific You may also find that there are areas of your app that simply shouldn't be accessed by users who aren't logged in. In that case, the authentication layer should stop them and ask for credentials. |
Thanks for the tip Nathan.. I will try to implement this :) |
@christhekeele - no worries on the timeline. FYI, I'll be traveling this coming week, so if you send a pull request, I'll see it when I return. |
Allows
action_authorized?
to handle nilsend(Authority.configuration.user_method)
users without raisingundefined method 'can_#{action}?' for nil:NilClass
, butSecurityViolation
instead.This works well for lightweight authentication systems that don't mock out a user when unauthenticated.
I meant for this to be a one-liner fix, but my text editor must have trimmed off a trailing space somewhere. Darn.