Skip to content
This repository has been archived by the owner on Nov 19, 2019. It is now read-only.

Default corresponding authorizers #28

Merged
merged 4 commits into from Mar 21, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.markdown
Expand Up @@ -2,6 +2,10 @@


Authority does its best to use [semantic versioning](http://semver.org). Authority does its best to use [semantic versioning](http://semver.org).


## Unreleased

Models whose `authorizer_name` is not specified will now check for an authorizer with their own name before falling back to `ApplicationAuthorizer`. Eg, `Comment` will look for `CommentAuthorizer`. Namespacing is respected.

## v2.4.3 ## v2.4.3


Bugfix for Rails 3.1 - apparently its `class_attribute` method stepped on instance methods even when given `:instance_reader => false` Bugfix for Rails 3.1 - apparently its `class_attribute` method stepped on instance methods even when given `:instance_reader => false`
Expand Down
7 changes: 5 additions & 2 deletions README.markdown
Expand Up @@ -71,9 +71,12 @@ All you have to do is define the methods you need on your authorizers. You have


Authority encapsulates all authorization logic in `Authorizer` classes. Want to do something with a model? **Ask its authorizer**. Authority encapsulates all authorization logic in `Authorizer` classes. Want to do something with a model? **Ask its authorizer**.


Models that have the same authorization rules should use the same authorizer. In other words, if you would write the exact same methods on two models to determine who can create them, who can edit them, etc, then they should use the same authorizer. You can specify a model's authorizer using the class method `authorizer_name=`. If you don't specify it, it will:


Every model starts out assuming that its authorizer is `ApplicationAuthorizer`, but you can specify another one using the model's `authorizer_name=` method. Authorizers are just classes, so you can use any inheritance pattern you like. - Look for an authorizer with its name. Eg, `Comment` will look for `CommentAuthorizer`.
- If that's not found, it will use `ApplicationAuthorizer`.

**Models that have the same authorization rules should use the same authorizer**. In other words, if you would write the exact same methods on two models to determine who can create them, who can edit them, etc, then they should use the same authorizer.


Some example groupings: Some example groupings:


Expand Down
2 changes: 1 addition & 1 deletion TODO.markdown
Expand Up @@ -4,7 +4,7 @@


## Tests ## Tests


- Test with Rails 4 and Ruby 2.0 - Test with Rails 4
- Test `ActionController` integration - Test `ActionController` integration
- Add tests for the generators - Add tests for the generators


Expand Down
13 changes: 10 additions & 3 deletions lib/authority/abilities.rb
Expand Up @@ -11,10 +11,17 @@ module Abilities
extend ActiveSupport::Concern extend ActiveSupport::Concern
extend Forwardable extend Forwardable


# Assume authorizer is `ApplicationAuthorizer` (but let the user change that) included do |base|
included do
class_attribute :authorizer_name class_attribute :authorizer_name
self.authorizer_name = "ApplicationAuthorizer"
# Set the default authorizer for this model.
# - Look for an authorizer named like the model inside the model's namespace.
# - If there is none, use 'ApplicationAuthorizer'
self.authorizer_name = begin
"#{base.name}Authorizer".constantize.name
rescue NameError => e
"ApplicationAuthorizer"
end
end end


def authorizer def authorizer
Expand Down
34 changes: 28 additions & 6 deletions spec/authority/abilities_spec.rb
Expand Up @@ -3,23 +3,45 @@


describe Authority::Abilities do describe Authority::Abilities do


let(:user) { ExampleUser.new } let(:user) { ExampleUser.new }
let(:resource_class) { ExampleResource } let(:resource_class) { ExampleResource }
let(:namespaced_resource_class) { Namespaced::SampleResource }
let(:other_resource_class) { OtherResource }


describe "instance methods" do describe "instance methods" do


describe "authorizer_name" do describe "authorizer_name" do


it "has a class attribute getter for authorizer_name" do it "has a class attribute getter" do
expect(resource_class).to respond_to(:authorizer_name) expect(resource_class).to respond_to(:authorizer_name)
end end


it "has a class attribute setter for authorizer_name" do it "has a class attribute setter" do
expect(resource_class).to respond_to(:authorizer_name=) expect(resource_class).to respond_to(:authorizer_name=)
end end


it "has a default authorizer_name of 'ApplicationAuthorizer'" do describe "by default" do
expect(resource_class.authorizer_name).to eq("ApplicationAuthorizer")
context "when there is an authorizer with a name like the resource's" do

it "uses that authorizer" do
expect(resource_class.authorizer_name).to eq("ExampleResourceAuthorizer")
end

it "respects namespaces when it's looking" do
expect(namespaced_resource_class.authorizer_name).to eq("Namespaced::SampleResourceAuthorizer")
end

end

context "when there is no authorizer with a name like the resource's" do

it "uses 'ApplicationAuthorizer'" do
expect(other_resource_class.authorizer_name).to eq("ApplicationAuthorizer")
end

end

end end


end end
Expand Down
23 changes: 20 additions & 3 deletions spec/support/example_classes.rb
@@ -1,13 +1,30 @@
class ApplicationAuthorizer < Authority::Authorizer
def self.readable_by?(user)
true
end
end

class ExampleUser class ExampleUser
include Authority::UserAbilities include Authority::UserAbilities
end end


class ExampleResourceAuthorizer < ApplicationAuthorizer
end

class ExampleResource class ExampleResource
include Authority::Abilities include Authority::Abilities
end end


class ApplicationAuthorizer < Authority::Authorizer module Namespaced
def self.readable_by?(user) class SampleResourceAuthorizer < ApplicationAuthorizer
true end

class SampleResource
include Authority::Abilities
end end

end

class OtherResource
include Authority::Abilities
end end