canard 0.2.7 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ .DS_Store
1
2
  *.gem
2
3
  .bundle
3
4
  pkg/*
data/TODO CHANGED
@@ -1,7 +1,6 @@
1
- * Test the ability class.
2
1
  * Test the generators.
3
2
  * Test the railtie
4
3
  * Expand the tests to produce all the standard abilities: index,show,read,new,create,edit,update,destroy.
5
4
  * Add test unit generator.
6
5
  * Add install generator to allow overriding of the default tests.
7
- * Add some rdocs.
6
+ * Make the Ability user referece configureable.
data/lib/ability.rb CHANGED
@@ -1,11 +1,39 @@
1
+ # Canard provides a CanCan Ability class for you. The Canard Ability class
2
+ # looks for and applies abilities for the object passed when a new Ability
3
+ # instance is initialized.
4
+ #
5
+ # If the passed object has a reference to user the user is set to that.
6
+ # Otherwise the passed object is assumed to be the user. This gives the
7
+ # flexibility to have a seperate model for authorization from the model used
8
+ # to authenticate the user.
9
+ #
10
+ # Abilities are applied in the order they are set with the acts_as_user method
11
+ # for example for the User model
12
+ #
13
+ # class User < ActiveRecord::Base
14
+ #
15
+ # acts_as_user :roles => :manager, :admin
16
+ #
17
+ # end
18
+ #
19
+ # the abilities would be applied in the order: users, managers, admins
20
+ # with each subsequent set of abilities building on or overriding the existing
21
+ # abilities.
22
+ #
23
+ # If there is no object passed to the Ability.new method a guest ability is
24
+ # created and Canard will look for a guests.rb amongst the ability definitions
25
+ # and give the guest those abilities.
1
26
  class Ability
2
27
 
3
28
  include CanCan::Ability
4
29
 
30
+ attr_reader :user
31
+
5
32
  def initialize(object=nil)
6
33
 
7
- # If a user was passed set the user from it.
8
- @user = object.is_a?(Account) ? object.user : object
34
+ # If object has a user attribute set the user from it otherwise assume
35
+ # this is the user.
36
+ @user = object.respond_to?(:user) ? object.user : object
9
37
 
10
38
  if @user
11
39
  # Add the base user abilities.
@@ -26,12 +54,8 @@ class Ability
26
54
 
27
55
  private
28
56
 
29
- def user
30
- @user
31
- end
32
-
33
57
  def ability_definitions
34
- Canard::Abilities.definitions
58
+ Canard.ability_definitions
35
59
  end
36
60
 
37
61
  def append_abilities(role)
@@ -4,7 +4,11 @@ module Canard
4
4
  # A string specifying the location that should be searched for ability
5
5
  # definitions. By default, Canard will attempt to load abilities from
6
6
  # Rails.root + /abilities/.
7
- attr_accessor :abilities_path
7
+ attr_writer :abilities_path
8
+
9
+ def abilities_path
10
+ @abilities_path ||= File.expand_path('abilities', Rails.root)
11
+ end
8
12
 
9
13
  def ability_definitions
10
14
  Abilities.definitions
@@ -18,7 +22,6 @@ module Canard
18
22
  end
19
23
 
20
24
  def self.find_abilities #:nodoc:
21
-
22
25
  absolute_abilities_path = File.expand_path(abilities_path)
23
26
 
24
27
  if File.directory? absolute_abilities_path
@@ -7,7 +7,6 @@ module Canard
7
7
  initializer "canard.active_record" do |app|
8
8
  ActiveSupport.on_load :active_record do
9
9
  extend Canard::UserModel
10
- Canard.abilities_path ||= File.expand_path('abilities', Rails.root)
11
10
  Canard.find_abilities
12
11
  end
13
12
  end
@@ -2,6 +2,43 @@ module Canard
2
2
 
3
3
  module UserModel
4
4
 
5
+ # Canard applies roles to a model using the acts_as_user class method. The following User model
6
+ # will be given the :manager and :admin roles
7
+ #
8
+ # class User < ActiveRecord::Base
9
+ #
10
+ # acts_as_user :roles => :manager, :admin
11
+ #
12
+ # end
13
+ #
14
+ # == Scopes
15
+ #
16
+ # Beyond applying the roles to model acts_as_user also creates some useful scopes on the User
17
+ # model;
18
+ #
19
+ # User.with_any_role(:manager, :admin)
20
+ #
21
+ # returns all the managers and admins
22
+ #
23
+ # User.with_all_roles(:manager, :admin)
24
+ #
25
+ # returns only the users with both the manager and admin roles
26
+ #
27
+ # User.admins
28
+ #
29
+ # returns all the admins as
30
+ #
31
+ # User.managers
32
+ #
33
+ # returns all the users with the maager role likewise
34
+ #
35
+ # User.non_admins
36
+ #
37
+ # returns all the users who don't have the admin role and
38
+ #
39
+ # User.non_managers
40
+ #
41
+ # returns all the users who don't have the manager role.
5
42
  def acts_as_user(*args)
6
43
  include RoleModel
7
44
 
@@ -1,3 +1,3 @@
1
1
  module Canard
2
- VERSION = "0.2.7"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -1,9 +1,5 @@
1
1
  abilities_for(:admin) do
2
-
3
- can :manage, [Activity, User, Variation, Year]
4
-
5
- cannot :destroy, User do |u|
6
- (user == u)
7
- end
8
-
2
+
3
+ can :manage, [Activity, User]
4
+
9
5
  end
@@ -39,7 +39,7 @@ describe 'Canard::Abilities' do
39
39
 
40
40
  end
41
41
 
42
- describe "define" do
42
+ describe "for" do
43
43
 
44
44
  it "adds the block to the definitions" do
45
45
  block = lambda { puts 'some block' }
@@ -0,0 +1,113 @@
1
+ require 'test_helper'
2
+
3
+ describe Ability do
4
+
5
+ before do
6
+ # reload abilities because the reloader will have removed them after the railtie ran
7
+ Canard.find_abilities
8
+ end
9
+
10
+ describe "new" do
11
+
12
+ describe "with a user" do
13
+
14
+ let(:user) { User.new }
15
+ subject { Ability.new(user) }
16
+
17
+ it "assign the user to Ability#user" do
18
+ subject.user.must_equal user
19
+ end
20
+
21
+ end
22
+
23
+ describe "with a model that references a user" do
24
+
25
+ let(:user) { User.create }
26
+ let(:member) { Member.new(:user => user) }
27
+
28
+ subject { Ability.new(member) }
29
+
30
+ it "assign the user to Ability#user" do
31
+ subject.user.must_equal user
32
+ end
33
+
34
+ end
35
+
36
+ describe "for a user with author role" do
37
+
38
+ let(:user) { User.create(:roles => [:author]) }
39
+ let(:member) { Member.create(:user => user) }
40
+ let(:other_member) { Member.new(:user => User.create) }
41
+ subject { Ability.new(user) }
42
+
43
+ it "has all the abilities of the base class" do
44
+ subject.can?(:edit, member).must_equal true
45
+ subject.can?(:update, member).must_equal true
46
+
47
+ subject.can?(:edit, other_member).wont_equal true
48
+ subject.can?(:update, other_member).wont_equal true
49
+ end
50
+
51
+ it "has all the abilities of an author" do
52
+ subject.can?(:new, Post).must_equal true
53
+ subject.can?(:create, Post).must_equal true
54
+ subject.can?(:edit, Post).must_equal true
55
+ subject.can?(:update, Post).must_equal true
56
+ subject.can?(:show, Post).must_equal true
57
+ subject.can?(:index, Post).must_equal true
58
+ end
59
+
60
+ it "has no admin abilities" do
61
+ subject.cannot?(:destroy, Post).must_equal true
62
+ end
63
+
64
+ end
65
+
66
+ describe "for a user with admin and author role" do
67
+
68
+ let(:user) { User.create(:roles => [:author, :admin]) }
69
+ let(:member) { Member.create(:user => user) }
70
+ let(:other_user) { User.create }
71
+ let(:other_member) { Member.new(:user => other_user) }
72
+ subject { Ability.new(user) }
73
+
74
+ it "has all the abilities of the base class" do
75
+ subject.can?(:edit, member).must_equal true
76
+ subject.can?(:update, member).must_equal true
77
+
78
+ subject.cannot?(:edit, other_member).must_equal true
79
+ subject.cannot?(:update, other_member).must_equal true
80
+ end
81
+
82
+ it "has all the abilities of an author" do
83
+ subject.can?(:new, Post).must_equal true
84
+ end
85
+
86
+ it "has the abilities of an admin" do
87
+ subject.can?(:manage, Post).must_equal true
88
+ subject.can?(:manage, other_user).must_equal true
89
+ subject.can?(:destroy, other_user).must_equal true
90
+ subject.cannot?(:destroy, user).must_equal true
91
+ end
92
+
93
+ end
94
+
95
+ describe "for a guest" do
96
+
97
+ subject { Ability.new }
98
+
99
+ it "applies the guest abilities" do
100
+ subject.can?(:index, Post)
101
+ subject.can?(:show, Post)
102
+
103
+ subject.cannot?(:create, Post)
104
+ subject.cannot?(:update, Post)
105
+ subject.cannot?(:destroy, Post)
106
+
107
+ subject.cannot?(:show, User)
108
+ subject.cannot?(:show, Member)
109
+ end
110
+ end
111
+ end
112
+
113
+ end
@@ -0,0 +1,9 @@
1
+ Canard::Abilities.for(:admin) do
2
+
3
+ can :manage, [Post, User]
4
+
5
+ cannot :destroy, User do |u|
6
+ (user == u)
7
+ end
8
+
9
+ end
@@ -0,0 +1,5 @@
1
+ Canard::Abilities.for(:author) do
2
+
3
+ can [:create, :update, :read], Post
4
+
5
+ end
@@ -0,0 +1,5 @@
1
+ Canard::Abilities.for(:guest) do
2
+
3
+ can :read, Post
4
+
5
+ end
@@ -0,0 +1,5 @@
1
+ Canard::Abilities.for(:user) do
2
+
3
+ can [:edit, :update], Member, :user_id => user.id
4
+
5
+ end
@@ -0,0 +1,2 @@
1
+ class Activity
2
+ end
@@ -0,0 +1,7 @@
1
+ class Member < ActiveRecord::Base
2
+
3
+ belongs_to :user
4
+
5
+ attr_accessible :user, :user_id
6
+
7
+ end
@@ -0,0 +1,2 @@
1
+ class Post < ActiveRecord::Base
2
+ end
@@ -1,7 +1,8 @@
1
1
  class User < ActiveRecord::Base
2
2
 
3
3
  extend Canard::UserModel
4
- acts_as_user :roles => [:admin, :author, :viewer]
4
+
5
+ acts_as_user :roles => [:viewer, :author, :admin]
5
6
 
6
7
  attr_accessible :roles
7
8
  end
@@ -0,0 +1,18 @@
1
+ class InitializeDb < ActiveRecord::Migration
2
+
3
+ def change
4
+ create_table :users, :force => true do |t|
5
+ t.string :roles_mask
6
+ end
7
+ create_table :user_without_roles, :force => true do |t|
8
+ t.string :roles_mask
9
+ end
10
+ create_table :user_without_role_masks, :force => true do |t|
11
+ end
12
+
13
+ create_table :members, :force => true do |t|
14
+ t.references :user
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended to check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(:version => 20120430083231) do
15
+
16
+ create_table "members", :force => true do |t|
17
+ t.integer "user_id"
18
+ end
19
+
20
+ create_table "user_without_role_masks", :force => true do |t|
21
+ end
22
+
23
+ create_table "user_without_roles", :force => true do |t|
24
+ t.string "roles_mask"
25
+ end
26
+
27
+ create_table "users", :force => true do |t|
28
+ t.string "roles_mask"
29
+ end
30
+
31
+ end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -23,7 +23,7 @@ describe Canard do
23
23
  it "finds the abilities with the new syntax" do
24
24
  Canard.find_abilities
25
25
 
26
- Canard.ability_definitions.keys.must_include :moderator
26
+ Canard.ability_definitions.keys.must_include :author
27
27
  end
28
28
 
29
29
  it "reloads existing abilities" do
@@ -31,7 +31,7 @@ describe Canard do
31
31
  Canard::Abilities.send(:instance_variable_set, '@definitions', {})
32
32
  Canard.find_abilities
33
33
 
34
- Canard.ability_definitions.keys.must_include :moderator
34
+ Canard.ability_definitions.keys.must_include :author
35
35
  Canard.ability_definitions.keys.must_include :admin
36
36
  end
37
37
 
@@ -41,7 +41,7 @@ describe Canard do
41
41
 
42
42
  it "raises a deprecation warning" do
43
43
  assert_deprecated do
44
- Canard.abilities_for(:this) { puts 'that' }
44
+ Canard.abilities_for(:this) { return 'that' }
45
45
  end
46
46
  end
47
47
 
data/test/test_helper.rb CHANGED
@@ -1,3 +1,4 @@
1
+ gem 'minitest'
1
2
  require 'minitest/autorun'
2
3
 
3
4
  # Configure Rails Environment
@@ -11,5 +12,6 @@ Rails.backtrace_cleaner.remove_silencers!
11
12
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
12
13
 
13
14
  ActiveRecord::Migration.verbose = false
14
- load(File.dirname(__FILE__) + '/schema.rb')
15
+ load(File.expand_path('../dummy/db/schema.rb', __FILE__))
16
+
15
17
 
@@ -29,7 +29,7 @@ describe Canard::UserModel do
29
29
  describe 'and :roles => [] specified' do
30
30
 
31
31
  it 'should set the valid_roles for the class' do
32
- User.valid_roles.must_equal [:admin, :author, :viewer]
32
+ User.valid_roles.must_equal [:viewer, :author, :admin]
33
33
  end
34
34
 
35
35
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.3.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-10 00:00:00.000000000Z
12
+ date: 2012-05-02 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
16
- requirement: &2152271020 !ruby/object:Gem::Requirement
16
+ requirement: &2152517180 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '2'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2152271020
24
+ version_requirements: *2152517180
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sqlite3
27
- requirement: &2152263860 !ruby/object:Gem::Requirement
27
+ requirement: &2152516180 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2152263860
35
+ version_requirements: *2152516180
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rails
38
- requirement: &2152261660 !ruby/object:Gem::Requirement
38
+ requirement: &2152514320 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 3.2.3
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2152261660
46
+ version_requirements: *2152514320
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: activesupport
49
- requirement: &2152259720 !ruby/object:Gem::Requirement
49
+ requirement: &2152512180 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *2152259720
57
+ version_requirements: *2152512180
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: cancan
60
- requirement: &2152258740 !ruby/object:Gem::Requirement
60
+ requirement: &2152511480 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *2152258740
68
+ version_requirements: *2152511480
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: role_model
71
- requirement: &2152256860 !ruby/object:Gem::Requirement
71
+ requirement: &2152510060 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '0'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *2152256860
79
+ version_requirements: *2152510060
80
80
  description: Wraps CanCan and RoleModel up to make role based authorisation really
81
81
  easy in Rails 3.x.
82
82
  email:
@@ -107,10 +107,17 @@ files:
107
107
  - lib/generators/rspec/ability/templates/abilities_spec.rb.erb
108
108
  - test/abilities/admins.rb
109
109
  - test/abilities_test.rb
110
+ - test/ability_test.rb
110
111
  - test/canard_test.rb
111
112
  - test/dummy/Rakefile
112
- - test/dummy/app/abilities/moderators.rb
113
+ - test/dummy/app/abilities/admins.rb
114
+ - test/dummy/app/abilities/authors.rb
115
+ - test/dummy/app/abilities/guests.rb
116
+ - test/dummy/app/abilities/users.rb
113
117
  - test/dummy/app/controllers/application_controller.rb
118
+ - test/dummy/app/models/activity.rb
119
+ - test/dummy/app/models/member.rb
120
+ - test/dummy/app/models/post.rb
114
121
  - test/dummy/app/models/user.rb
115
122
  - test/dummy/app/models/user_without_role.rb
116
123
  - test/dummy/app/models/user_without_role_mask.rb
@@ -126,10 +133,12 @@ files:
126
133
  - test/dummy/config/initializers/wrap_parameters.rb
127
134
  - test/dummy/config/locales/en.yml
128
135
  - test/dummy/config/routes.rb
136
+ - test/dummy/db/migrate/20120430083231_initialize_db.rb
137
+ - test/dummy/db/schema.rb
129
138
  - test/dummy/db/test.sqlite3
130
139
  - test/dummy/log/.gitkeep
140
+ - test/dummy/script/rails
131
141
  - test/find_abilities_test.rb
132
- - test/schema.rb
133
142
  - test/support/reloadable.rb
134
143
  - test/test_helper.rb
135
144
  - test/user_model_test.rb
@@ -160,10 +169,17 @@ summary: Adds role based authorisation to Rails by combining RoleModel and CanCa
160
169
  test_files:
161
170
  - test/abilities/admins.rb
162
171
  - test/abilities_test.rb
172
+ - test/ability_test.rb
163
173
  - test/canard_test.rb
164
174
  - test/dummy/Rakefile
165
- - test/dummy/app/abilities/moderators.rb
175
+ - test/dummy/app/abilities/admins.rb
176
+ - test/dummy/app/abilities/authors.rb
177
+ - test/dummy/app/abilities/guests.rb
178
+ - test/dummy/app/abilities/users.rb
166
179
  - test/dummy/app/controllers/application_controller.rb
180
+ - test/dummy/app/models/activity.rb
181
+ - test/dummy/app/models/member.rb
182
+ - test/dummy/app/models/post.rb
167
183
  - test/dummy/app/models/user.rb
168
184
  - test/dummy/app/models/user_without_role.rb
169
185
  - test/dummy/app/models/user_without_role_mask.rb
@@ -179,10 +195,12 @@ test_files:
179
195
  - test/dummy/config/initializers/wrap_parameters.rb
180
196
  - test/dummy/config/locales/en.yml
181
197
  - test/dummy/config/routes.rb
198
+ - test/dummy/db/migrate/20120430083231_initialize_db.rb
199
+ - test/dummy/db/schema.rb
182
200
  - test/dummy/db/test.sqlite3
183
201
  - test/dummy/log/.gitkeep
202
+ - test/dummy/script/rails
184
203
  - test/find_abilities_test.rb
185
- - test/schema.rb
186
204
  - test/support/reloadable.rb
187
205
  - test/test_helper.rb
188
206
  - test/user_model_test.rb
@@ -1,9 +0,0 @@
1
- Canard::Abilities.for(:moderator) do
2
-
3
- can :manage, [Post]
4
-
5
- cannot :destroy, User do |u|
6
- (user == u)
7
- end
8
-
9
- end
data/test/schema.rb DELETED
@@ -1,12 +0,0 @@
1
- ActiveRecord::Schema.define :version => 0 do
2
-
3
- create_table :users, :force => true do |t|
4
- t.string :roles_mask
5
- end
6
- create_table :user_without_roles, :force => true do |t|
7
- t.string :roles_mask
8
- end
9
- create_table :user_without_role_masks, :force => true do |t|
10
- end
11
-
12
- end