heimdallr-resource 1.0.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. data/.rspec +1 -2
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +9 -5
  4. data/heimdallr-resource.gemspec +4 -3
  5. data/lib/heimdallr-resource.rb +2 -0
  6. data/lib/heimdallr/resource.rb +21 -191
  7. data/lib/heimdallr/resource_implementation.rb +190 -0
  8. data/spec/{resource_spec.rb → controllers/entities_controller_spec.rb} +25 -7
  9. data/spec/controllers/fluffies_controller_spec.rb +20 -0
  10. data/spec/controllers/things_controller_spec.rb +31 -0
  11. data/spec/dummy/app/controllers/{entity_controller.rb → entities_controller.rb} +6 -2
  12. data/spec/dummy/app/controllers/things_controller.rb +29 -0
  13. data/spec/dummy/app/models/entity.rb +2 -0
  14. data/spec/dummy/app/models/thing.rb +16 -0
  15. data/spec/dummy/config/application.rb +1 -1
  16. data/spec/dummy/config/routes.rb +6 -5
  17. data/spec/dummy/db/schema.rb +5 -0
  18. data/spec/models/resource_implementation_spec.rb +382 -0
  19. data/spec/models/resource_spec.rb +91 -0
  20. data/spec/spec_helper.rb +1 -0
  21. metadata +44 -48
  22. data/spec/dummy/Rakefile +0 -7
  23. data/spec/dummy/app/helpers/application_helper.rb +0 -2
  24. data/spec/dummy/config/environments/development.rb +0 -23
  25. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  26. data/spec/dummy/config/initializers/inflections.rb +0 -10
  27. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  28. data/spec/dummy/config/initializers/secret_token.rb +0 -7
  29. data/spec/dummy/config/initializers/session_store.rb +0 -8
  30. data/spec/dummy/config/locales/en.yml +0 -5
  31. data/spec/dummy/public/404.html +0 -26
  32. data/spec/dummy/public/422.html +0 -26
  33. data/spec/dummy/public/500.html +0 -26
  34. data/spec/dummy/public/favicon.ico +0 -0
  35. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  36. data/spec/dummy/script/rails +0 -6
  37. data/spec/fluffies_spec.rb +0 -22
@@ -1,11 +1,16 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe EntityController, :type => :controller do
3
+ describe EntitiesController, :type => :controller do
4
4
  before(:all) do
5
+ User.destroy_all
6
+ Entity.destroy_all
7
+
5
8
  @john = User.create! :admin => false
6
9
  @maria = User.create! :admin => false
7
10
  @admin = User.create! :admin => true
11
+
8
12
  @private = Entity.create! :name => 'ent1', :public => false
13
+ @private_own = Entity.create! :name => 'ent1', :public => false, :owner_id => @john.id
9
14
  @public = Entity.create! :name => 'ent1', :public => true, :owner_id => @john.id
10
15
  end
11
16
 
@@ -14,14 +19,27 @@ describe EntityController, :type => :controller do
14
19
  User.mock @admin
15
20
  get :index
16
21
 
17
- assigns(:entities).count.should == 2
22
+ assigns(:entities).should have(3).items
18
23
  end
19
24
 
20
25
  it "hides non-public entities" do
21
26
  User.mock @john
22
27
  get :index
23
28
 
24
- assigns(:entities).count.should == 1
29
+ assigns(:entities).should have(2).items
30
+ end
31
+
32
+ it "shows private to owner" do
33
+ User.mock @john
34
+ get :show, {:id => @private_own.id}
35
+
36
+ assigns(:entity).insecure.should == @private_own
37
+ end
38
+
39
+ it "hides private from non-owner" do
40
+ User.mock @maria
41
+
42
+ expect { get :show, {:id => @private_own.id} }.to raise_error
25
43
  end
26
44
 
27
45
  it "allows creation for admin" do
@@ -33,7 +51,7 @@ describe EntityController, :type => :controller do
33
51
 
34
52
  it "disallows creation for non-admin" do
35
53
  User.mock @john
36
- expect { post :create, {} }.should raise_error
54
+ expect { post :create, {} }.to raise_error
37
55
  end
38
56
 
39
57
  it "allows update for admin" do
@@ -46,7 +64,7 @@ describe EntityController, :type => :controller do
46
64
 
47
65
  it "disallows update for non-admin" do
48
66
  User.mock @john
49
- expect { post :update, {:id => @public.id} }.should raise_error
67
+ expect { post :update, {:id => @public.id} }.to raise_error
50
68
  end
51
69
 
52
70
  it "allows destroy for admin" do
@@ -67,7 +85,7 @@ describe EntityController, :type => :controller do
67
85
 
68
86
  it "disallows destroy for nobody" do
69
87
  User.mock @maria
70
- expect { post :destroy, {:id => @public.id} }.should raise_error
88
+ expect { post :destroy, {:id => @public.id} }.to raise_error
71
89
  end
72
90
 
73
91
  it "assigns the custom methods" do
@@ -78,4 +96,4 @@ describe EntityController, :type => :controller do
78
96
  assigns(:entity).id.should == @public.id
79
97
  end
80
98
  end
81
- end
99
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe FluffiesController, :type => :controller do
4
+ before(:all) do
5
+ User.destroy_all
6
+ Entity.destroy_all
7
+
8
+ @admin = User.create! :admin => true
9
+
10
+ @entity1 = Entity.create! :name => 'entity 1'
11
+ @entity2 = Entity.create! :name => 'entity 2'
12
+ end
13
+
14
+ it "loads entity resources and assigns to @entities" do
15
+ User.mock @admin
16
+ get :index
17
+
18
+ assigns(:entities).should have(2).items
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe ThingsController, :type => :controller do
4
+ before(:all) do
5
+ User.delete_all
6
+ Entity.delete_all
7
+
8
+ @admin = User.create! :admin => true
9
+
10
+ @entity1 = Entity.create! :name => 'entity 1'
11
+ @entity2 = Entity.create! :name => 'entity 2'
12
+
13
+ @thing1 = Thing.create! :name => 'thing 1', :entity_id => @entity1.id
14
+ @thing2 = Thing.create! :name => 'thing 2', :entity_id => @entity1.id
15
+ @thing3 = Thing.create! :name => 'thing 3', :entity_id => @entity2.id
16
+ end
17
+
18
+ it "loads entity resource and assigns to @entity" do
19
+ User.mock @admin
20
+ get :index, :entity_id => @entity1.id
21
+
22
+ assigns(:entity).id.should == @entity1.id
23
+ end
24
+
25
+ it "loads thing resources through @entity and assigns to @things" do
26
+ User.mock @admin
27
+ get :index, :entity_id => @entity1.id
28
+
29
+ assigns(:things).should have(2).items
30
+ end
31
+ end
@@ -1,4 +1,4 @@
1
- class EntityController < ApplicationController
1
+ class EntitiesController < ApplicationController
2
2
  include Heimdallr::Resource
3
3
 
4
4
  load_and_authorize_resource
@@ -7,6 +7,10 @@ class EntityController < ApplicationController
7
7
  render :nothing => true
8
8
  end
9
9
 
10
+ def show
11
+ render :nothing => true
12
+ end
13
+
10
14
  def new
11
15
  render :nothing => true
12
16
  end
@@ -30,4 +34,4 @@ class EntityController < ApplicationController
30
34
  def penetrate
31
35
  render :nothing => true
32
36
  end
33
- end
37
+ end
@@ -0,0 +1,29 @@
1
+ class ThingsController < ApplicationController
2
+ include Heimdallr::Resource
3
+
4
+ load_and_authorize_resource :through => :entity
5
+
6
+ def index
7
+ render :nothing => true
8
+ end
9
+
10
+ def new
11
+ render :nothing => true
12
+ end
13
+
14
+ def create
15
+ render :nothing => true
16
+ end
17
+
18
+ def edit
19
+ render :nothing => true
20
+ end
21
+
22
+ def update
23
+ render :nothing => true
24
+ end
25
+
26
+ def destroy
27
+ render :nothing => true
28
+ end
29
+ end
@@ -1,6 +1,8 @@
1
1
  class Entity < ActiveRecord::Base
2
2
  include Heimdallr::Model
3
3
 
4
+ has_many :things, :dependent => :destroy
5
+
4
6
  restrict do |user, record|
5
7
  if user.admin
6
8
  scope :fetch
@@ -0,0 +1,16 @@
1
+ class Thing < ActiveRecord::Base
2
+ include Heimdallr::Model
3
+
4
+ belongs_to :entity
5
+
6
+ restrict do |user, record|
7
+ if user.admin
8
+ scope :fetch
9
+ scope :delete
10
+ can [:view, :create, :update]
11
+ else
12
+ scope :fetch, -> { where('public = ? or owner_id = ?', true, user.id) }
13
+ scope :delete, -> { where('owner_id = ?', user.id) }
14
+ end
15
+ end
16
+ end
@@ -5,7 +5,7 @@ require "rails/all"
5
5
  Bundler.require(:default, Rails.env)
6
6
 
7
7
  require "heimdallr"
8
- require "heimdallr/resource"
8
+ require "heimdallr-resource"
9
9
 
10
10
  module Dummy
11
11
  class Application < Rails::Application
@@ -1,8 +1,9 @@
1
1
  Dummy::Application.routes.draw do
2
- resources :entity do
3
- member do
4
- post :penetrate
5
- end
2
+ resources :entities do
3
+ resources :things
4
+
5
+ post :penetrate, :on => :member
6
6
  end
7
+
7
8
  resources :fluffies
8
- end
9
+ end
@@ -5,6 +5,11 @@ ActiveRecord::Schema.define(:version => 1) do
5
5
  t.boolean "public"
6
6
  end
7
7
 
8
+ create_table "things", :force => true do |t|
9
+ t.integer "entity_id"
10
+ t.string "name"
11
+ end
12
+
8
13
  create_table "users", :force => true do |t|
9
14
  t.boolean "admin"
10
15
  end
@@ -0,0 +1,382 @@
1
+ require 'spec_helper'
2
+
3
+ describe Heimdallr::ResourceImplementation do
4
+ let(:controller) { Object.new }
5
+ let(:params) { HashWithIndifferentAccess.new :controller => :entities }
6
+ let(:entity) { stub!.id{1}.subject }
7
+ before do
8
+ stub(controller).params { params }
9
+ stub(controller).skip_authorization_check? { false }
10
+ end
11
+
12
+ describe '#load_resource' do
13
+ it "loads and assigns the resource to an instance variable for show action" do
14
+ params.merge! :action => 'show', :id => entity.id
15
+ stub(Entity).scoped.mock!.find(entity.id) { entity }
16
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
17
+ resource.load_resource
18
+ controller.instance_variable_get(:@entity).should == entity
19
+ end
20
+
21
+ it "loads and assigns the resource to an instance variable for edit action" do
22
+ params.merge! :action => 'edit', :id => entity.id
23
+ stub(Entity).scoped.mock!.find(entity.id) { entity }
24
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
25
+ resource.load_resource
26
+ controller.instance_variable_get(:@entity).should == entity
27
+ end
28
+
29
+ it "loads and assigns the resource to an instance variable for update action" do
30
+ params.merge! :action => 'edit', :id => entity.id
31
+ stub(Entity).scoped.mock!.find(entity.id) { entity }
32
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
33
+ resource.load_resource
34
+ controller.instance_variable_get(:@entity).should == entity
35
+ end
36
+
37
+ it "loads and assigns the resource to an instance variable for destroy action" do
38
+ params.merge! :action => 'destroy', :id => entity.id
39
+ stub(Entity).scoped.mock!.find(entity.id) { entity }
40
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
41
+ resource.load_resource
42
+ controller.instance_variable_get(:@entity).should == entity
43
+ end
44
+
45
+ it "builds and assigns a new resource for new action" do
46
+ params.merge! :action => 'new'
47
+ mock(Entity).new({}) { :new_entity }
48
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
49
+ resource.load_resource
50
+ controller.instance_variable_get(:@entity).should == :new_entity
51
+ end
52
+
53
+ it "builds and assigns a new resource for create action" do
54
+ params.merge! :action => 'create', :entity => {:name => 'foo'}
55
+ mock(Entity).new('name' => 'foo') { :new_entity }
56
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
57
+ resource.load_resource
58
+ controller.instance_variable_get(:@entity).should == :new_entity
59
+ end
60
+
61
+ it "loads and assigns a resource collection for index action" do
62
+ params.merge! :action => 'index'
63
+ mock(Entity).scoped { :entity_collection }
64
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
65
+ resource.load_resource
66
+ controller.instance_variable_get(:@entities).should == :entity_collection
67
+ end
68
+
69
+ it "loads and assigns a namespaced resource" do
70
+ params.merge! :action => 'show', :id => entity.id
71
+ module SomeProject
72
+ class Entity < ::Entity; end
73
+ end
74
+ stub(SomeProject::Entity).scoped.mock!.find(entity.id) { entity }
75
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'some_project/entity'
76
+ resource.load_resource
77
+ controller.instance_variable_get(:@some_project_entity).should == entity
78
+ end
79
+
80
+ it "loads the resource with a custom finder" do
81
+ params.merge! :action => 'show', :id => entity.id
82
+ stub(Entity).scoped.mock!.find_by_name(entity.id) { entity }
83
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity', :finder => :find_by_name
84
+ resource.load_resource
85
+ controller.instance_variable_get(:@entity).should == entity
86
+ end
87
+
88
+ it "loads and assigns a single resource for custom action by default" do
89
+ params.merge! :action => 'fetch', :id => entity.id
90
+ stub(Entity).scoped.mock!.find(entity.id) { entity }
91
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
92
+ resource.load_resource
93
+ controller.instance_variable_get(:@entity).should == entity
94
+ end
95
+
96
+ it "loads and assigns a collection for custom action if specified in options" do
97
+ params.merge! :action => 'sort'
98
+ mock(Entity).scoped { :entity_collection }
99
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity', :collection => [:sort]
100
+ resource.load_resource
101
+ controller.instance_variable_get(:@entities).should == :entity_collection
102
+ end
103
+
104
+ it "builds and assigns a new resource for custom action if specified in options" do
105
+ params.merge! :action => 'generate', :entity => {:name => 'foo'}
106
+ mock(Entity).new('name' => 'foo') { :new_entity }
107
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity', :new_record => [:generate]
108
+ resource.load_resource
109
+ controller.instance_variable_get(:@entity).should == :new_entity
110
+ end
111
+
112
+ it "doesn't assign the resource to an instance variable if it is already assigned" do
113
+ params.merge! :action => 'show', :id => entity.id
114
+ controller.instance_variable_set :@entity, :different_entity
115
+ stub(Entity).scoped.stub!.find(entity.id) { entity }
116
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
117
+ resource.load_resource
118
+ controller.instance_variable_get(:@entity).should == :different_entity
119
+ end
120
+
121
+ it "loads and assigns a resource through the association of another parent resource" do
122
+ thing = stub!.id{1}.subject
123
+ params.merge! :controller => :things, :action => 'show', :entity_id => entity.id, :id => thing.id
124
+ controller.instance_variable_set(:@entity, entity)
125
+ stub(entity).things.mock!.find(thing.id) { thing }
126
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity'
127
+ resource.load_resource
128
+ controller.instance_variable_get(:@thing).should == thing
129
+ end
130
+
131
+ it "loads and assigns the parent resource if :through option is provided" do
132
+ params.merge! :controller => :things, :action => 'index', :entity_id => entity.id
133
+ stub(Entity).scoped.mock!.find(entity.id) { entity }
134
+ stub(entity).things
135
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity'
136
+ resource.load_resource
137
+ controller.instance_variable_get(:@entity).should == entity
138
+ end
139
+
140
+ it "loads the resource directly if the parent isn't found and :shallow option is true" do
141
+ thing = stub!.id{1}.subject
142
+ params.merge! :controller => :things, :action => 'show', :id => thing.id
143
+ stub(Thing).scoped.mock!.find(thing.id) { thing }
144
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :shallow => true
145
+ resource.load_resource
146
+ controller.instance_variable_get(:@thing).should == thing
147
+ end
148
+
149
+ it "raises an error when the parent's id is not provided" do
150
+ params.merge! :controller => :things, :action => 'show', :id => 1
151
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity'
152
+ expect { resource.load_resource }.to raise_error(RuntimeError)
153
+ end
154
+
155
+ it "loads through the first parent found when multiple are given" do
156
+ thing = stub!.id{1}.subject
157
+ params.merge! :controller => :things, :action => 'show', :id => thing.id
158
+ class Nothing; end
159
+ stub(Nothing).scoped
160
+ controller.instance_variable_set(:@entity, entity)
161
+ controller.instance_variable_set(:@user, Object.new)
162
+ stub(entity).things.mock!.find(thing.id) { thing }
163
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => [:nothing, :entity, :user]
164
+ resource.load_resource
165
+ controller.instance_variable_get(:@thing).should == thing
166
+ end
167
+
168
+ it "loads through has_one association with :singleton option" do
169
+ thing = stub!.id{1}.subject
170
+ params.merge! :controller => :things, :action => 'show'
171
+ controller.instance_variable_set(:@entity, entity)
172
+ mock(entity).thing { thing }
173
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true
174
+ resource.load_resource
175
+ controller.instance_variable_get(:@thing).should == thing
176
+ end
177
+
178
+ it "builds a record through has_one association with :singleton option" do
179
+ params.merge! :controller => :things, :action => 'create', :thing => {:name => 'foo'}
180
+ controller.instance_variable_set(:@entity, entity)
181
+ thing = stub!.id{1}.subject
182
+ stub(entity).thing { nil }
183
+ mock(entity).build_thing('name' => 'foo') { thing }
184
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true
185
+ resource.load_resource
186
+ controller.instance_variable_get(:@thing).should == thing
187
+ end
188
+
189
+ it "builds a record with correct method name with :singleton and :through_association options" do
190
+ params.merge! :controller => :things, :action => 'create', :thing => {:name => 'foo'}
191
+ controller.instance_variable_set(:@entity, entity)
192
+ thing = stub!.id{1}.subject
193
+ stub(entity).stuff { nil }
194
+ mock(entity).build_stuff('name' => 'foo') { thing }
195
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true, :through_association => :stuff
196
+ resource.load_resource
197
+ controller.instance_variable_get(:@thing).should == thing
198
+ end
199
+
200
+ it "doesn't build a record through has_one association with :singleton option if one already exists because it can cause it to delete it in the database" do
201
+ params.merge! :controller => :things, :action => 'create', :thing => {:name => 'foo'}
202
+ controller.instance_variable_set(:@entity, entity)
203
+ thing = stub!.id{1}.subject
204
+ mock(entity).thing { thing }
205
+ mock(thing).assign_attributes 'name' => 'foo'
206
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true
207
+ resource.load_resource
208
+ controller.instance_variable_get(:@thing).should == thing
209
+ end
210
+
211
+ it "loads through has_one association with :singleton and :shallow options" do
212
+ thing = stub!.id{1}.subject
213
+ params.merge! :controller => :things, :action => 'show', :id => thing.id
214
+ stub(Thing).scoped.mock!.find(thing.id) { thing }
215
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true, :shallow => :true
216
+ resource.load_resource
217
+ controller.instance_variable_get(:@thing).should == thing
218
+ end
219
+
220
+ it "builds a record through has_one association with :singleton and :shallow options" do
221
+ params.merge! :controller => :things, :action => 'create', :thing => {:name => 'foo'}
222
+ stub(Thing).scoped.mock!.new('name' => 'foo') { :new_thing }
223
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true, :shallow => :true
224
+ resource.load_resource
225
+ controller.instance_variable_get(:@thing).should == :new_thing
226
+ end
227
+
228
+ it "builds a record through has_one association with :singleton and :shallow options even if the parent is present" do
229
+ params.merge! :controller => :things, :action => 'create', :thing => {:name => 'foo'}
230
+ controller.instance_variable_set(:@entity, entity)
231
+ stub(entity).thing { nil }
232
+ mock(entity).build_thing('name' => 'foo') { :new_thing }
233
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true, :shallow => :true
234
+ resource.load_resource
235
+ controller.instance_variable_get(:@thing).should == :new_thing
236
+ end
237
+
238
+ it "loads through custom association if :through_association option is provided" do
239
+ thing = stub!.id{1}.subject
240
+ params.merge! :controller => :things, :action => 'show', :entity_id => entity.id, :id => thing.id
241
+ controller.instance_variable_set(:@entity, entity)
242
+ stub(entity).stuff.mock!.find(thing.id) { thing }
243
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :through_association => :stuff
244
+ resource.load_resource
245
+ controller.instance_variable_get(:@thing).should == thing
246
+ end
247
+
248
+ it "loads through custom association if both :through_association and :singleton options are provided" do
249
+ thing = stub!.id{1}.subject
250
+ params.merge! :controller => :things, :action => 'show', :entity_id => entity.id, :id => thing.id
251
+ controller.instance_variable_set(:@entity, entity)
252
+ mock(entity).stuff { thing }
253
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :through_association => :stuff, :singleton => true
254
+ resource.load_resource
255
+ controller.instance_variable_get(:@thing).should == thing
256
+ end
257
+
258
+ it "loads and assigns a resource using custom instance name" do
259
+ params.merge! :action => 'show', :id => entity.id
260
+ stub(Entity).scoped.mock!.find(entity.id) { entity }
261
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity', :instance_name => :something
262
+ resource.load_resource
263
+ controller.instance_variable_get(:@something).should == entity
264
+ end
265
+
266
+ it "loads and assigns a resource collection using custom instance name" do
267
+ params.merge! :action => 'index'
268
+ mock(Entity).scoped { :entity_collection }
269
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity', :instance_name => :something
270
+ resource.load_resource
271
+ controller.instance_variable_get(:@somethings).should == :entity_collection
272
+ end
273
+ end
274
+
275
+ describe '#load_and_authorize_resource' do
276
+ let(:user) { stub!.id{1}.subject }
277
+ before do
278
+ stub(user).admin { false }
279
+ stub(controller).security_context { user }
280
+ end
281
+
282
+ it "calls #restrict on the loaded resource" do
283
+ params.merge! :action => 'show', :id => entity.id
284
+ mock(Entity).restrict(controller.security_context).stub!.find(entity.id) { entity }
285
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
286
+ resource.load_and_authorize_resource
287
+ end
288
+
289
+ it "raises AccessDenied when calling :new action for resource that can't be created" do
290
+ params.merge! :action => 'new'
291
+ mock(Entity).new.mock!.restrict(controller.security_context, {}) { entity }
292
+ stub(entity).assign_attributes
293
+ mock(entity).creatable? { false }
294
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
295
+ expect { resource.load_and_authorize_resource }.to raise_error(Heimdallr::AccessDenied)
296
+ end
297
+
298
+ it "raises AccessDenied when creating a resource that can't be created" do
299
+ params.merge! :action => 'create'
300
+ mock(Entity).new.mock!.restrict(controller.security_context, {}) { entity }
301
+ stub(entity).assign_attributes
302
+ mock(entity).creatable? { false }
303
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
304
+ expect { resource.load_and_authorize_resource }.to raise_error(Heimdallr::AccessDenied)
305
+ end
306
+
307
+ it "raises AccessDenied when calling :edit action for resource that can't be updated" do
308
+ params.merge! :action => 'edit', :id => entity.id
309
+ mock(Entity).restrict(controller.security_context).stub!.find(entity.id) { entity }
310
+ mock(entity).modifiable? { false }
311
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
312
+ expect { resource.load_and_authorize_resource }.to raise_error(Heimdallr::AccessDenied)
313
+ end
314
+
315
+ it "raises AccessDenied when updating a resource that can't be updated" do
316
+ params.merge! :action => 'update', :id => entity.id
317
+ mock(Entity).restrict(controller.security_context).stub!.find(entity.id) { entity }
318
+ mock(entity).modifiable? { false }
319
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
320
+ expect { resource.load_and_authorize_resource }.to raise_error(Heimdallr::AccessDenied)
321
+ end
322
+
323
+ it "raises AccessDenied when destroying a resource that can't be destroyed" do
324
+ params.merge! :action => 'destroy', :id => entity.id
325
+ mock(Entity).restrict(controller.security_context).stub!.find(entity.id) { entity }
326
+ mock(entity).destroyable? { false }
327
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
328
+ expect { resource.load_and_authorize_resource }.to raise_error(Heimdallr::AccessDenied)
329
+ end
330
+
331
+ it "fixates certain attributes of a new resource" do
332
+ params.merge! :action => 'new', :entity => {:name => 'foo'}
333
+ mock(Entity).new.mock!.restrict(controller.security_context, {}) { entity }
334
+ mock(entity).creatable? { true }
335
+ fixtures = {:create => {:name => 'bar'}}
336
+ stub(entity).reflect_on_security { {:restrictions => stub!.fixtures{fixtures}.subject} }
337
+ stub(entity).assign_attributes('name' => 'foo')
338
+ mock(entity).assign_attributes(fixtures[:create])
339
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
340
+ resource.load_and_authorize_resource
341
+ controller.instance_variable_get(:@entity) == entity
342
+ end
343
+
344
+ it "fixates certain attributes of an updating resource" do
345
+ params.merge! :action => 'update', :id => entity.id, :entity => {:name => 'foo'}
346
+ mock(Entity).restrict(controller.security_context).stub!.find(entity.id) { entity }
347
+ mock(entity).modifiable? { true }
348
+ fixtures = {:update => {:name => 'bar'}}
349
+ stub(entity).reflect_on_security { {:restrictions => stub!.fixtures{fixtures}.subject} }
350
+ stub(entity).assign_attributes('name' => 'foo')
351
+ mock(entity).assign_attributes(fixtures[:update])
352
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
353
+ resource.load_and_authorize_resource
354
+ controller.instance_variable_get(:@entity) == entity
355
+ end
356
+
357
+ context "when controller.skip_authorization_check? is true" do
358
+ before { stub(controller).skip_authorization_check? { true } }
359
+
360
+ it "doesn't raise AccessDenied" do
361
+ params.merge! :action => 'destroy', :id => entity.id
362
+ mock(Entity).restrict(controller.security_context).stub!.find(entity.id) { entity }
363
+ stub(entity).destroyable? { false }
364
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
365
+ expect { resource.load_and_authorize_resource }.not_to raise_error(Heimdallr::AccessDenied)
366
+ end
367
+
368
+ it "doesn't fixate attributes" do
369
+ params.merge! :action => 'new', :entity => {:name => 'foo'}
370
+ mock(Entity).new.mock!.restrict(controller.security_context, {}) { entity }
371
+ stub(entity).creatable? { true }
372
+ fixtures = {:create => {:name => 'bar'}}
373
+ stub(entity).reflect_on_security { {:restrictions => stub!.fixtures{fixtures}.subject} }
374
+ stub(entity).assign_attributes('name' => 'foo')
375
+ dont_allow(entity).assign_attributes(fixtures[:create])
376
+ resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
377
+ resource.load_and_authorize_resource
378
+ controller.instance_variable_get(:@entity) == entity
379
+ end
380
+ end
381
+ end
382
+ end