lib/authority.rb in authority-2.9.0 vs lib/authority.rb in authority-2.10.0

- old
+ new

@@ -35,14 +35,14 @@ # @return [Model] resource instance def self.enforce(action, resource, user, options = {}) unless action_authorized?(action, resource, user, options) raise SecurityViolation.new(user, action, resource) end - resource end def self.action_authorized?(action, resource, user, options = {}) + raise MissingUser if user.nil? resource_and_maybe_options = [resource, options].tap {|args| args.pop if args.last == {}} user.send("can_#{action}?", *resource_and_maybe_options) end class << self @@ -65,9 +65,33 @@ def self.require_authority_internals! require 'authority/abilities' require 'authority/authorizer' require 'authority/user_abilities' + end + + class MissingUser < StandardError + def message + "You tried to check authorization on `nil`. Authority doesn't know what + `nil` is allowed to do. There are two ways you can fix this. + + 1. Authenticate before authorizing. If the user isn't signed in, force + them to sign in before they can attempt any action that requires + authorization. + + 2. When the user is not signed in, return a Null Object instead of + `nil`. (You could create an AnonymousUser class, for example.) It should + respond to the normal methods Authority will call (like `can_delete?`), + possibly by including `Authority::UserAbilities` and teaching your authorizers + what an anonymous user can do. + + The downside of solution #2 is that a user who forgot to sign in will be + told they are not authorized for an action they could normally do. This might + be confusing. + + However, you might use both strategies in different parts of your application. + " + end end end require 'authority/configuration'