rspec-authorization 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/.travis.yml +5 -0
- data/.yardopts +3 -0
- data/Gemfile +7 -0
- data/Guardfile +2 -1
- data/HISTORY.md +32 -0
- data/README.md +60 -7
- data/lib/rspec/authorization/adapters/example.rb +32 -9
- data/lib/rspec/authorization/adapters/example_group.rb +78 -0
- data/lib/rspec/authorization/adapters/request.rb +129 -14
- data/lib/rspec/authorization/adapters/route.rb +99 -16
- data/lib/rspec/authorization/adapters.rb +2 -2
- data/lib/rspec/authorization/matchers/have_permission_for.rb +126 -11
- data/lib/rspec/authorization/matchers.rb +1 -1
- data/lib/rspec/authorization/version.rb +2 -2
- data/lib/rspec/authorization.rb +2 -2
- data/rspec-authorization.gemspec +2 -2
- data/spec/controllers/articles_controller_spec.rb +21 -0
- data/spec/lib/rspec/authorization/adapters/example_group_spec.rb +28 -0
- data/spec/lib/rspec/authorization/adapters/example_spec.rb +6 -16
- data/spec/lib/rspec/authorization/adapters/request_spec.rb +3 -3
- data/spec/spec_helper.rb +3 -0
- data/spec/tools/rails_test_app_spec.rb +3 -1
- data/tools/rails_test_app/template.rb +18 -7
- metadata +15 -11
- data/lib/rspec/authorization/adapters/group.rb +0 -14
- data/spec/controllers/posts_controller_spec.rb +0 -11
- data/spec/lib/rspec/authorization/adapters/group_spec.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79650ca2e93b08c5ebd9008fa9e6f51e59d5245c
|
4
|
+
data.tar.gz: 64f6364b28ef24e98d203b764165201ac2c32a33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f28d44b4dec4e86ade6980070bebcbfdb0b35a9daded58db14e539c086ba380959ab81aee49a09e30839cfb1d2fcc16138c05ebc4588d1b6ea9cde4d00971262
|
7
|
+
data.tar.gz: f026a6b7e065e16d10e53bad7bfdaf66838abe3952cf421739d113b3334ba76bc077529b2f5d6788f56491fa3e3aa32520f5db42f123b63e1c20ed4652129da8
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/Gemfile
CHANGED
@@ -8,7 +8,14 @@ group :development, :test do
|
|
8
8
|
gem 'guard-rspec'
|
9
9
|
gem 'pry'
|
10
10
|
gem 'terminal-notifier-guard' if `uname` =~ /Darwin/
|
11
|
+
gem "codeclimate-test-reporter", require: nil
|
11
12
|
|
12
13
|
gem 'jquery-rails'
|
13
14
|
gem 'turbolinks'
|
14
15
|
end
|
16
|
+
|
17
|
+
group :docs do
|
18
|
+
gem "inch"
|
19
|
+
gem "rdoc"
|
20
|
+
gem "yard"
|
21
|
+
end
|
data/Guardfile
CHANGED
@@ -4,6 +4,7 @@ guard :rspec, cmd: 'bundle exec rspec' do
|
|
4
4
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
5
5
|
watch(%r{^tools/(.+)\.rb$}) { |m| "spec/tools/#{m[1]}_spec.rb" }
|
6
6
|
|
7
|
-
watch(%r{^
|
7
|
+
watch(%r{^lib/.+/matchers/.+\.rb$}) { "spec/controllers" }
|
8
|
+
watch(%r{^controllers/(.+)\.rb$}) { |m| "spec/controllers/#{m[1]}_spec.rb" }
|
8
9
|
end
|
9
10
|
|
data/HISTORY.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
[v0.0.2 / 2014-11-11] (https://github.com/hendrauzia/rspec-authorization/tree/v0.0.2)
|
3
|
+
=====================
|
4
|
+
|
5
|
+
* Add RESTful methods matcher chaining
|
6
|
+
* Add object, callback and controller action stub
|
7
|
+
* Add documentation to have_permission_for matcher
|
8
|
+
* Add request documentation
|
9
|
+
* Refactor and add documentation to example
|
10
|
+
* Refactor and add documentation to example group
|
11
|
+
* Add documentation to gem requirement
|
12
|
+
* Add documentation to route
|
13
|
+
* Add yard as documentation generator
|
14
|
+
* Add documentation badge
|
15
|
+
* Add coverage, dependencies and security badges
|
16
|
+
* Fix rails test app spec
|
17
|
+
* Fix travis build
|
18
|
+
* Add travis badge and config
|
19
|
+
* Add gem version badge and usage
|
20
|
+
|
21
|
+
[v0.0.1 / 2014-11-05] (https://github.com/hendrauzia/rspec-authorization/tree/v0.0.1)
|
22
|
+
=====================
|
23
|
+
|
24
|
+
* Add have_permission_for matcher for restful actions
|
25
|
+
* Add rails test app template
|
26
|
+
* Add clean and reset rake task
|
27
|
+
* Update dependency to ruby 2.1.4
|
28
|
+
* Add rails test app for spec to run against
|
29
|
+
* Add rspec-rails for specs
|
30
|
+
* Add rspec-authorization gem scaffold using bundler
|
31
|
+
* Initial commit
|
32
|
+
|
data/README.md
CHANGED
@@ -1,22 +1,75 @@
|
|
1
|
-
#
|
1
|
+
# RSpec::Authorization
|
2
2
|
|
3
|
-
|
3
|
+
[](http://github.com/hendrauzia/rspec-authorization)
|
4
|
+
[](http://rubydoc.org/github/hendrauzia/rspec-authorization)
|
5
|
+
|
6
|
+
[](http://badge.fury.io/rb/rspec-authorization)
|
7
|
+
[](https://travis-ci.org/hendrauzia/rspec-authorization)
|
8
|
+
[](https://codeclimate.com/github/hendrauzia/rspec-authorization)
|
9
|
+
[](https://codeclimate.com/github/hendrauzia/rspec-authorization)
|
10
|
+
[](https://gemnasium.com/hendrauzia/rspec-authorization)
|
11
|
+
[](https://hakiri.io/github/hendrauzia/rspec-authorization/master)
|
12
|
+
[](http://inch-ci.org/github/hendrauzia/rspec-authorization)
|
13
|
+
|
14
|
+
RSpec matcher for declarative_authorization. A neat way of asserting
|
15
|
+
declarative_authorization's rules inside controller using RSpec matcher.
|
4
16
|
|
5
17
|
## Installation
|
6
18
|
|
7
19
|
Add this line to your application's Gemfile:
|
8
20
|
|
9
|
-
|
10
|
-
gem 'rspec-authorization'
|
11
|
-
|
21
|
+
|
22
|
+
gem 'rspec-authorization', group: :test
|
23
|
+
|
12
24
|
|
13
25
|
And then execute:
|
14
26
|
|
15
|
-
|
27
|
+
bundle
|
16
28
|
|
17
29
|
Or install it yourself as:
|
18
30
|
|
19
|
-
|
31
|
+
gem install rspec-authorization
|
32
|
+
|
33
|
+
## Requirement
|
34
|
+
|
35
|
+
Current development focus is as follows, future development may support other
|
36
|
+
dependencies, following are requirements for this gem:
|
37
|
+
|
38
|
+
- declarative_authorization 1.0.0.pre
|
39
|
+
- rails 4.x
|
40
|
+
- rspec-rails 3.x
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
|
44
|
+
In your controller spec:
|
45
|
+
|
46
|
+
describe ArticlesController do
|
47
|
+
it { is_expected.to have_permission_for(:a_role).to(:restful_action_name) }
|
48
|
+
|
49
|
+
it { is_expected.to have_permission_for(:writer).to(:index) }
|
50
|
+
it { is_expected.to have_permission_for(:writer).to(:show) }
|
51
|
+
it { is_expected.to have_permission_for(:writer).to(:new) }
|
52
|
+
it { is_expected.to have_permission_for(:writer).to(:create) }
|
53
|
+
it { is_expected.not_to have_permission_for(:writer).to(:edit) }
|
54
|
+
it { is_expected.not_to have_permission_for(:writer).to(:update) }
|
55
|
+
it { is_expected.not_to have_permission_for(:writer).to(:destroy) }
|
56
|
+
end
|
57
|
+
|
58
|
+
You can also use convenience RESTful methods matcher:
|
59
|
+
|
60
|
+
describe ArticlesController do
|
61
|
+
it { is_expected.to have_permission_for(:user).to_read }
|
62
|
+
it { is_expected.not_to have_permission_for(:user).to_create }
|
63
|
+
it { is_expected.not_to have_permission_for(:user).to_update }
|
64
|
+
it { is_expected.not_to have_permission_for(:user).to_delete }
|
65
|
+
|
66
|
+
it { is_expected.to have_permission_for(:writer).to_read }
|
67
|
+
it { is_expected.to have_permission_for(:writer).to_create }
|
68
|
+
it { is_expected.to have_permission_for(:writer).to_update }
|
69
|
+
it { is_expected.not_to have_permission_for(:writer).to_delete }
|
70
|
+
|
71
|
+
it { is_expected.to have_permission_for(:editor).to_manage }
|
72
|
+
end
|
20
73
|
|
21
74
|
## Contributing
|
22
75
|
|
@@ -1,27 +1,50 @@
|
|
1
1
|
module RSpec::Authorization
|
2
2
|
module Adapters
|
3
|
+
# Wrapper to generate and immediately run example from +RSpec::Core::Example+.
|
4
|
+
# The purpose of this class is to abstract the running of an example without
|
5
|
+
# unnecessary artifacts from an RSpec example, such as: reporter, generated
|
6
|
+
# description, context and expectation.
|
7
|
+
#
|
8
|
+
# The sole purpose of this class is to generate the minimum required component
|
9
|
+
# needed to create and run an example, for our matcher to run against. The trick
|
10
|
+
# to run the example without producing unnecessary artifacts is to trigger
|
11
|
+
# the example's before and after hook manually without running any expectations.
|
3
12
|
class Example
|
4
|
-
|
13
|
+
# @return [Class] RSpec example group
|
14
|
+
attr_reader :group_target
|
15
|
+
# @return [RSpec::Core::Example] instance of RSpec example
|
16
|
+
attr_reader :target
|
5
17
|
|
6
|
-
|
7
|
-
|
8
|
-
|
18
|
+
# Initialize example using RSpec example group. The RSpec example group can
|
19
|
+
# be retrieved using example group's target, consider the following example:
|
20
|
+
#
|
21
|
+
# group = ExampleGroup.new(ArticlesController)
|
22
|
+
# example = Example.new(group.target)
|
23
|
+
#
|
24
|
+
# @param group_target [Class] RSpec example group from +ExampleGroup#target+
|
25
|
+
# @see ExampleGroup#target
|
26
|
+
def initialize(group_target)
|
27
|
+
@group_target = group_target
|
28
|
+
@target = RSpec::Core::Example.new(group_target, "", {})
|
9
29
|
|
10
30
|
set_example_group_instance
|
11
|
-
end
|
12
|
-
|
13
|
-
def run
|
14
31
|
run_before_example
|
32
|
+
run_after_example
|
15
33
|
end
|
16
34
|
|
17
35
|
private
|
18
36
|
|
19
37
|
def set_example_group_instance
|
20
|
-
|
38
|
+
target.instance_variable_set :@example_group_instance, group_target.new
|
21
39
|
end
|
22
40
|
|
23
41
|
def run_before_example
|
24
|
-
|
42
|
+
target.send :run_before_example
|
43
|
+
end
|
44
|
+
|
45
|
+
def run_after_example
|
46
|
+
target.example_group.hooks.run(:after, :example, target)
|
47
|
+
target.example_group_instance.teardown_mocks_for_rspec
|
25
48
|
end
|
26
49
|
end
|
27
50
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module RSpec::Authorization
|
2
|
+
module Adapters
|
3
|
+
# Wrapper to generate +RSpec::Core::ExampleGroup+. The example group
|
4
|
+
# includes +RSpec::Rails::ControllerExampleGroup+ to add behavior testing,
|
5
|
+
# which provides methods to test the controller, such as: +get+, +post+,
|
6
|
+
# +patch+, +put+ and +delete+.
|
7
|
+
#
|
8
|
+
# Consider the following example:
|
9
|
+
#
|
10
|
+
# group = ExampleGroup.new(ArticlesController)
|
11
|
+
# group.target # => RSpec::ExampleGroups::ArticlesController
|
12
|
+
#
|
13
|
+
# Instantiating the class for a second time produce a different result:
|
14
|
+
#
|
15
|
+
# group = ExampleGroup.new(ArticlesController)
|
16
|
+
# group.target # => RSpec::ExampleGroups::ArticlesController_2
|
17
|
+
class ExampleGroup
|
18
|
+
# @return [Class] a class namespaced from +RSPec::ExampleGroups+
|
19
|
+
attr_reader :target
|
20
|
+
|
21
|
+
# Initialize example group using controller's class.
|
22
|
+
#
|
23
|
+
# @param klass [Class] controller's class for an example group
|
24
|
+
def initialize(klass)
|
25
|
+
@target = RSpec::Core::ExampleGroup.describe(klass) do
|
26
|
+
include RSpec::Rails::ControllerExampleGroup
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Run example for our example group. The example is actualy has
|
31
|
+
# no example at all, it is simply a wrapper for +RSpec::Core::Example+,
|
32
|
+
# running an actual example would produce unnecessary artifacts, while all
|
33
|
+
# we need is a simple wrapper on controller behavior.
|
34
|
+
#
|
35
|
+
# @return [Example] example object that has been run
|
36
|
+
# @see Example
|
37
|
+
def run_example
|
38
|
+
Example.new(target)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Add instruction to be run before our example. Instructions added will be
|
42
|
+
# run inside the context of our example group, consider the following
|
43
|
+
# example:
|
44
|
+
#
|
45
|
+
# before do
|
46
|
+
# get :index
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# The above statements behave exactly the same as RSpec +before+ method, and
|
50
|
+
# this method serve as a proxy to RSpec +before+ method call. That means
|
51
|
+
# everything that we can do inside +before+ method will be available inside
|
52
|
+
# +before+ to.
|
53
|
+
#
|
54
|
+
# @return [Array<RSpec::Core::Hooks::BeforeHook>] an array of before hook filter
|
55
|
+
def before(&block)
|
56
|
+
target.before(&block)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Add instruction to be run after our example. Instructions added will be
|
60
|
+
# run inside the context of our example group, consider the following
|
61
|
+
# example:
|
62
|
+
#
|
63
|
+
# after do
|
64
|
+
# get :index
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# The above statements behave exactly the same as RSpec +after+ method, and
|
68
|
+
# this method serve as a proxy to RSpec +after+ method call. That means
|
69
|
+
# everything that we can do inside +after+ method will be available inside
|
70
|
+
# +after+ to.
|
71
|
+
#
|
72
|
+
# @return [Array<RSpec::Core::Hooks::AfterHook>] an array of after hook filter
|
73
|
+
def after(&block)
|
74
|
+
target.after(&block)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -1,16 +1,86 @@
|
|
1
1
|
module RSpec::Authorization
|
2
2
|
module Adapters
|
3
|
+
# Create a request using wrapper around RSpec example. The request is made
|
4
|
+
# possible through wrapping the call around RSpec example, this approach
|
5
|
+
# is choosen because we need to get as close as possible to how the request
|
6
|
+
# is made inside RSpec.
|
7
|
+
#
|
8
|
+
# Once the request is created, it will immediately run and we can evaluate the
|
9
|
+
# response, consider the following example.
|
10
|
+
#
|
11
|
+
# request = Request.new(ArticlesController, :index, :user)
|
12
|
+
# request.response.status # => 200
|
13
|
+
#
|
14
|
+
# Since the request is actually creating a request to the provided controller,
|
15
|
+
# it will run everything inside the controller, and no stubbing is performed.
|
16
|
+
# Therefore exception inside controller will bubble up to the request and may
|
17
|
+
# cause unexpected result. That is with one exception, there is one exception,
|
18
|
+
# ActiveRecord::RecordNotFound is rescued and bypassed, therefore it will not
|
19
|
+
# affect the request.
|
3
20
|
class Request
|
4
|
-
|
21
|
+
# @return [Class] controller class name
|
22
|
+
attr_reader :klass
|
23
|
+
# @return [Symbol] controller action name
|
24
|
+
attr_reader :action
|
25
|
+
# @return [Symbol] role name from +config/authorization_rules.rb+
|
26
|
+
attr_reader :role
|
27
|
+
# @return [ExampleGroup] example group of the request
|
28
|
+
# @see ExampleGroup
|
29
|
+
attr_reader :group
|
30
|
+
# @return [Route] route object of the action
|
31
|
+
# @see Route
|
32
|
+
attr_reader :route
|
33
|
+
# @return [ActionController::TestResponse] response object of the request
|
34
|
+
attr_reader :response
|
5
35
|
|
36
|
+
# Create request object and immediately run the request. Inside initialization
|
37
|
+
# a lot of stuff get stubbed, it is to allow request to be run with assumptions,
|
38
|
+
# following are the assumptions composed as private method run inside the
|
39
|
+
# initializer:
|
40
|
+
#
|
41
|
+
# +stub_current_user+::
|
42
|
+
# The request is expected to run as a user with provided role. There is
|
43
|
+
# no user created whatsoever, it only creates a double with role_symbols
|
44
|
+
# defined and return it inside +current_user+.
|
45
|
+
#
|
46
|
+
# +stub_authorization_load_controller_object+::
|
47
|
+
# The request is expected to ignore declarative_authorization controller's
|
48
|
+
# object loading.
|
49
|
+
#
|
50
|
+
# +stub_authorization_load_object+::
|
51
|
+
# The request is expected to ignore declarative_authorization object
|
52
|
+
# loading. This is different from the above, and is expected to be called
|
53
|
+
# if controller object isn't loaded.
|
54
|
+
#
|
55
|
+
# +stub_callbacks+::
|
56
|
+
# The request is expected to ignore all callbacks defined inside the
|
57
|
+
# controller.
|
58
|
+
#
|
59
|
+
# +stub_action+::
|
60
|
+
# The request is expected to ignore all statements run inside the action
|
61
|
+
# and configured to render nothing instead.
|
62
|
+
#
|
63
|
+
# All of the above assumptions is expected to run only inside this request
|
64
|
+
# only, and not to change the behavior of the application outside of this
|
65
|
+
# request.
|
66
|
+
#
|
67
|
+
# @param klass [Class] controller class name to request from
|
68
|
+
# @param action [Symbol] action name, currently only support RESTful action
|
69
|
+
# @param role [Symbol] role name from +config/authorization_rules.rb+
|
6
70
|
def initialize(klass, action, role)
|
7
71
|
@klass, @action, @role = klass, action, role
|
8
|
-
@group, @route =
|
72
|
+
@group, @route = ExampleGroup.new(klass), Route.new(action)
|
73
|
+
|
74
|
+
@authorization_stubbed = false
|
9
75
|
|
10
76
|
stub_current_user
|
77
|
+
stub_authorization_load_controller_object
|
78
|
+
stub_authorization_load_object
|
79
|
+
stub_callbacks
|
80
|
+
stub_action
|
11
81
|
|
12
82
|
setup_response_retrieval
|
13
|
-
|
83
|
+
group.run_example
|
14
84
|
end
|
15
85
|
|
16
86
|
private
|
@@ -32,24 +102,69 @@ module RSpec::Authorization
|
|
32
102
|
end
|
33
103
|
end
|
34
104
|
|
35
|
-
def
|
36
|
-
|
37
|
-
|
105
|
+
def stub_authorization_load_controller_object
|
106
|
+
group.before do
|
107
|
+
allow(controller).to receive(:load_controller_object)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def stub_authorization_load_object
|
112
|
+
return if @authorization_stubbed
|
113
|
+
@authorization_stubbed = true
|
38
114
|
|
39
115
|
group.before do
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
116
|
+
Authorization::ControllerPermission.instance_eval do
|
117
|
+
alias_method :load_object_original, :load_object
|
118
|
+
define_method :load_object do |*args, &block|
|
119
|
+
begin
|
120
|
+
load_object_original(*args, &block)
|
121
|
+
rescue ActiveRecord::RecordNotFound
|
122
|
+
end
|
123
|
+
end
|
44
124
|
end
|
125
|
+
end
|
45
126
|
|
46
|
-
|
127
|
+
group.after do
|
128
|
+
Authorization::ControllerPermission.instance_eval do
|
129
|
+
remove_method :load_object
|
130
|
+
|
131
|
+
alias_method :load_object, :load_object_original
|
132
|
+
remove_method :load_object_original
|
133
|
+
end
|
47
134
|
end
|
48
135
|
end
|
49
136
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
137
|
+
def stub_callbacks
|
138
|
+
group.before do
|
139
|
+
methods = controller._process_action_callbacks.map(&:filter).split(:filter_access_filter).last
|
140
|
+
controller.instance_eval do
|
141
|
+
methods.each do |method|
|
142
|
+
define_singleton_method method do |*args, &block|
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def stub_action
|
150
|
+
args = route
|
151
|
+
group.before do
|
152
|
+
controller.instance_eval do
|
153
|
+
define_singleton_method args.action do |*args, &block|
|
154
|
+
render nothing: true
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def setup_response_retrieval
|
161
|
+
args = route
|
162
|
+
setter = response_setter
|
163
|
+
|
164
|
+
group.before do
|
165
|
+
send *args
|
166
|
+
setter.call(response)
|
167
|
+
end
|
53
168
|
end
|
54
169
|
end
|
55
170
|
end
|
@@ -1,8 +1,107 @@
|
|
1
1
|
module RSpec::Authorization
|
2
2
|
module Adapters
|
3
|
+
# Generate route that defines RESTful method using provided action. It is
|
4
|
+
# used primarily in creating a new request and infered automatically to an
|
5
|
+
# array using the defined +#to_a+ method.
|
6
|
+
#
|
7
|
+
# Route generation has 3 primary part, which are:
|
8
|
+
# - +verb+
|
9
|
+
# - +action+
|
10
|
+
# - +params+
|
11
|
+
#
|
12
|
+
# The first part, +verb+ refers to RESTful method, which is described in
|
13
|
+
# +DICTIONARIES+, +action+ refers to controller action name, and +params+
|
14
|
+
# refers to parameters used in a request. This object can be automatically
|
15
|
+
# inferred as an array.
|
16
|
+
#
|
17
|
+
# Creating a route will generate a route object:
|
18
|
+
#
|
19
|
+
# route = Route.new(:index)
|
20
|
+
# route # => #<Route:...>
|
21
|
+
#
|
22
|
+
# This will infer the object as an array:
|
23
|
+
#
|
24
|
+
# route = Route.new(:show)
|
25
|
+
# send *route # => [:get, :show, { id: 1 }]
|
26
|
+
#
|
27
|
+
# @see #to_a
|
3
28
|
class Route
|
29
|
+
# @return [Symbol] returns route action name
|
4
30
|
attr_reader :action
|
5
31
|
|
32
|
+
# Initializing a route requires a RESTful action name that the route want
|
33
|
+
# to generate. The action that get passed is assigned to +action+ attributes
|
34
|
+
# and is publicly accessible.
|
35
|
+
#
|
36
|
+
# route = Route.new(:index)
|
37
|
+
# route.action # => :index
|
38
|
+
#
|
39
|
+
# Currently +Route+ only support RESTful action, passing non-RESTful action
|
40
|
+
# name is possible, but will result in unexpected result.
|
41
|
+
#
|
42
|
+
# @param action [Symbol] RESTful action name
|
43
|
+
# @see #verb
|
44
|
+
def initialize(action)
|
45
|
+
@action = action
|
46
|
+
end
|
47
|
+
|
48
|
+
# This method is used to retrieve a dummy params that's used for an action.
|
49
|
+
# Tipically an action for a resource member requires a param, while action
|
50
|
+
# for resource collection doesn't need any param.
|
51
|
+
#
|
52
|
+
# This will return a dummy params:
|
53
|
+
#
|
54
|
+
# route = Route.new(:show)
|
55
|
+
# route.params # => { id: 1 }
|
56
|
+
#
|
57
|
+
# This will return nil for a collection resource action:
|
58
|
+
#
|
59
|
+
# route = Route.new(:index)
|
60
|
+
# route.params # => nil
|
61
|
+
#
|
62
|
+
# @return [Hash, nil] a dummy hash params
|
63
|
+
def params
|
64
|
+
PARAMS[action]
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return verb used for the RESTful action. The verb uses +DICTIONARIES+ to
|
68
|
+
# retrieve a valid method for an action. This method intentionally throws
|
69
|
+
# error if a non-RESTful action is used.
|
70
|
+
#
|
71
|
+
# route = Route.new(:index)
|
72
|
+
# route.verb # => :get
|
73
|
+
#
|
74
|
+
# This will throw error:
|
75
|
+
#
|
76
|
+
# route = Route.new(:an_action)
|
77
|
+
# route.verb # => KeyError: key not found: :an_action
|
78
|
+
#
|
79
|
+
# @return [Symbol] RESTful verb to be used for an action
|
80
|
+
def verb
|
81
|
+
DICTIONARIES.fetch(action)
|
82
|
+
end
|
83
|
+
|
84
|
+
# This method is used to convert Route object into an array. This method also
|
85
|
+
# used to automatically infer +Route+ as an array on method that uses +to_a+,
|
86
|
+
# therefore we don't need to manually invoke +#to_a+ on every call that
|
87
|
+
# requires an array object.
|
88
|
+
#
|
89
|
+
# This will return an array:
|
90
|
+
#
|
91
|
+
# route = Route.new(:show)
|
92
|
+
# route.to_a # => [:get, :show, { id: 1 }]
|
93
|
+
#
|
94
|
+
# This will also return an array inferred automatically
|
95
|
+
#
|
96
|
+
# send *route # => [:get, :show, { id: 1 }]
|
97
|
+
#
|
98
|
+
# @return [Array] an array of verb, action and params
|
99
|
+
def to_a
|
100
|
+
[verb, action, params]
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
6
105
|
DICTIONARIES = {
|
7
106
|
index: :get,
|
8
107
|
show: :get,
|
@@ -19,22 +118,6 @@ module RSpec::Authorization
|
|
19
118
|
update: { id: 1 },
|
20
119
|
destroy: { id: 1 }
|
21
120
|
}
|
22
|
-
|
23
|
-
def initialize(action)
|
24
|
-
@action = action
|
25
|
-
end
|
26
|
-
|
27
|
-
def params
|
28
|
-
PARAMS[action]
|
29
|
-
end
|
30
|
-
|
31
|
-
def verb
|
32
|
-
DICTIONARIES.fetch(action)
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_a
|
36
|
-
[verb, action, params]
|
37
|
-
end
|
38
121
|
end
|
39
122
|
end
|
40
123
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require "rspec/authorization/adapters/example"
|
2
|
-
require "rspec/authorization/adapters/
|
2
|
+
require "rspec/authorization/adapters/example_group"
|
3
3
|
require "rspec/authorization/adapters/request"
|
4
4
|
require "rspec/authorization/adapters/route"
|
5
5
|
|
6
6
|
module RSpec::Authorization
|
7
|
-
module Adapters
|
7
|
+
module Adapters # :nodoc:
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -1,43 +1,158 @@
|
|
1
1
|
module RSpec::Authorization
|
2
2
|
module Matchers
|
3
|
+
# Include this module to enable the +have_permission_for+ matcher inside RSpec.
|
4
|
+
# The following module is to be included only inside controller spec, this will
|
5
|
+
# add the capability to do a matcher against decalrative_authorization rules as
|
6
|
+
# follows:
|
7
|
+
#
|
8
|
+
# it { is_expected.to have_permission_for(:user).to(:index) }
|
9
|
+
#
|
10
|
+
# For your convenience, the following configuration has been enabled inside
|
11
|
+
# RSpec configuration.
|
12
|
+
#
|
13
|
+
# RSpec.configure do |config|
|
14
|
+
# config.include RSpec::Authorization::Matchers::HavePermissionFor, type: :controller
|
15
|
+
# end
|
3
16
|
module HavePermissionFor
|
17
|
+
# Matcher to check permission of a role for a given controller in a spec. The
|
18
|
+
# following statement shows you how to use this matcher:
|
19
|
+
#
|
20
|
+
# describe ArticlesController do
|
21
|
+
# it { is_expected.to have_permission_for(:user).to(:index) }
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# Currently this matcher only support RESTful action check, to check the
|
25
|
+
# controller against +config/authorization_rules.rb+. Skipping the +#to+
|
26
|
+
# method will result in default action assigned as +:index+.
|
27
|
+
#
|
28
|
+
# Therefore, the following statement is exactly the same as above:
|
29
|
+
#
|
30
|
+
# it { is_expected.to have_permission_for(:user) }
|
31
|
+
#
|
32
|
+
# === RESTful methods
|
33
|
+
#
|
34
|
+
# For your convenience, there are 4 RESTful methods available to be chained
|
35
|
+
# from the matcher, which are:
|
36
|
+
#
|
37
|
+
# - +to_read+
|
38
|
+
# - +to_create+
|
39
|
+
# - +to_update+
|
40
|
+
# - +to_delete+
|
41
|
+
#
|
42
|
+
# Consider the following example:
|
43
|
+
#
|
44
|
+
# it { is_expected.to have_permission_for(:user).to_read }
|
45
|
+
# it { is_expected.to have_permission_for(:user).to_edit }
|
46
|
+
# it { is_expected.not_to have_permission_for(:user).to_update }
|
47
|
+
# it { is_expected.not_to have_permission_for(:user).to_delete }
|
48
|
+
#
|
49
|
+
# The above method is not related to declarative_authorization privileges,
|
50
|
+
# and serve simply as convinience method, below is a table of RESTful actions
|
51
|
+
# for each method mentioned above:
|
52
|
+
#
|
53
|
+
# Method RESTful action
|
54
|
+
# ------------------------------------
|
55
|
+
# to_read [:index, :show]
|
56
|
+
# to_edit [:edit, :update]
|
57
|
+
# to_create [:new, :create]
|
58
|
+
# to_delete [:destroy]
|
59
|
+
#
|
60
|
+
# Matcher for RESTful methods is slightly different than that of a single
|
61
|
+
# method, following is how RESTful methods request results evaluated:
|
62
|
+
#
|
63
|
+
# all_requests (of #to_read) matches? does_not_match?
|
64
|
+
# -------------------------------------------------------------------
|
65
|
+
# {index: true, show: true} true false
|
66
|
+
# {index: true, show: false} false false
|
67
|
+
# {index: false, show: false} false true
|
68
|
+
#
|
69
|
+
# @param role [Symbol] role name to matched against
|
4
70
|
def have_permission_for(role)
|
5
71
|
HavePermissionFor.new(role)
|
6
72
|
end
|
7
73
|
|
8
|
-
#
|
9
|
-
class HavePermissionFor
|
74
|
+
class HavePermissionFor # :nodoc: all
|
10
75
|
include Adapters
|
11
76
|
|
12
|
-
attr_reader :controller, :role, :
|
77
|
+
attr_reader :controller, :role, :behave, :actions, :results
|
13
78
|
|
14
79
|
def initialize(role)
|
15
|
-
@role
|
16
|
-
@action = :index
|
80
|
+
@role = role
|
17
81
|
end
|
18
82
|
|
19
83
|
def to(action)
|
20
|
-
@
|
84
|
+
@behave = action
|
85
|
+
@actions = [behave]
|
86
|
+
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_read
|
91
|
+
@behave = :read
|
92
|
+
@actions = %i(index show)
|
93
|
+
|
94
|
+
self
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_create
|
98
|
+
@behave = :create
|
99
|
+
@actions = %i(new create)
|
100
|
+
|
21
101
|
self
|
22
102
|
end
|
23
103
|
|
104
|
+
def to_update
|
105
|
+
@behave = :update
|
106
|
+
@actions = %i(edit update)
|
107
|
+
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
def to_delete
|
112
|
+
@behave = :delete
|
113
|
+
@actions = %i(destroy)
|
114
|
+
|
115
|
+
self
|
116
|
+
end
|
117
|
+
|
118
|
+
def to_manage
|
119
|
+
@behave = :manage
|
120
|
+
@actions = %i(index show new create edit update destroy)
|
121
|
+
|
122
|
+
self
|
123
|
+
end
|
124
|
+
|
125
|
+
def all_requests
|
126
|
+
actions.map do |action|
|
127
|
+
request = Request.new(controller.class, action, role)
|
128
|
+
[action, request.response.status != 403]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
24
132
|
def matches?(controller)
|
25
133
|
@controller = controller
|
134
|
+
@results = Hash[all_requests]
|
135
|
+
|
136
|
+
true unless results.value? false
|
137
|
+
end
|
138
|
+
|
139
|
+
def does_not_match?(controller)
|
140
|
+
@controller = controller
|
141
|
+
@results = Hash[all_requests]
|
26
142
|
|
27
|
-
|
28
|
-
request.response.status != 403
|
143
|
+
true unless results.value? true
|
29
144
|
end
|
30
145
|
|
31
146
|
def failure_message
|
32
|
-
"Expected #{controller.class} to have permission for #{role} to #{
|
147
|
+
"Expected #{controller.class} to have permission for #{role} to #{behave}. #{results}"
|
33
148
|
end
|
34
149
|
|
35
150
|
def failure_message_when_negated
|
36
|
-
"Did not expect #{controller.class} to have permission for #{role} to #{
|
151
|
+
"Did not expect #{controller.class} to have permission for #{role} to #{behave}. #{results}"
|
37
152
|
end
|
38
153
|
|
39
154
|
def description
|
40
|
-
"have permission for #{role}
|
155
|
+
"have permission for #{role} to #{behave}"
|
41
156
|
end
|
42
157
|
end
|
43
158
|
end
|
data/lib/rspec/authorization.rb
CHANGED
data/rspec-authorization.gemspec
CHANGED
@@ -4,7 +4,7 @@ require 'rspec/authorization/version'
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "rspec-authorization"
|
7
|
-
spec.version =
|
7
|
+
spec.version = RSpec::Authorization::VERSION
|
8
8
|
spec.authors = ["Hendra Uzia"]
|
9
9
|
spec.email = ["hendra.uzia@gmail.com"]
|
10
10
|
spec.summary = %q{RSpec matcher for declarative_authorization.}
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
20
|
spec.add_runtime_dependency "declarative_authorization"
|
21
|
-
spec.add_runtime_dependency "rspec-rails"
|
21
|
+
spec.add_runtime_dependency "rspec-rails", "~> 3.0"
|
22
22
|
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.7"
|
24
24
|
spec.add_development_dependency "rails", "~> 4.0"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe ArticlesController do
|
4
|
+
it { is_expected.to have_permission_for(:user).to(:index) }
|
5
|
+
it { is_expected.not_to have_permission_for(:user).to(:show) }
|
6
|
+
it { is_expected.not_to have_permission_for(:user).to_create }
|
7
|
+
it { is_expected.not_to have_permission_for(:user).to_update }
|
8
|
+
it { is_expected.not_to have_permission_for(:user).to_delete }
|
9
|
+
|
10
|
+
it { is_expected.to have_permission_for(:premium).to_read }
|
11
|
+
it { is_expected.not_to have_permission_for(:premium).to_create }
|
12
|
+
it { is_expected.not_to have_permission_for(:premium).to_update }
|
13
|
+
it { is_expected.not_to have_permission_for(:premium).to_delete }
|
14
|
+
|
15
|
+
it { is_expected.to have_permission_for(:writer).to_read }
|
16
|
+
it { is_expected.to have_permission_for(:writer).to_create }
|
17
|
+
it { is_expected.not_to have_permission_for(:writer).to_update }
|
18
|
+
it { is_expected.not_to have_permission_for(:writer).to_delete }
|
19
|
+
|
20
|
+
it { is_expected.to have_permission_for(:editor).to_manage }
|
21
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
include RSpec::Authorization::Adapters
|
4
|
+
|
5
|
+
describe ExampleGroup do
|
6
|
+
let(:klass) { ArticlesController }
|
7
|
+
let(:example_group) { ExampleGroup.new(klass) }
|
8
|
+
|
9
|
+
let(:before_instruction) { ->{ :before } }
|
10
|
+
let(:after_instruction) { ->{ :after } }
|
11
|
+
|
12
|
+
describe "target" do
|
13
|
+
subject { example_group.target }
|
14
|
+
its(:described_class) { is_expected.to eq klass }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#before" do
|
18
|
+
specify { expect(example_group.before(&before_instruction).last.block).to eq before_instruction }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#after" do
|
22
|
+
specify { expect(example_group.after(&after_instruction).first.block).to eq after_instruction }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#run_example" do
|
26
|
+
specify { expect(example_group.run_example).to be_a_kind_of(Example) }
|
27
|
+
end
|
28
|
+
end
|
@@ -4,23 +4,13 @@ include RSpec::Authorization::Adapters
|
|
4
4
|
|
5
5
|
describe Example do
|
6
6
|
let(:klass) { GroupTestClass }
|
7
|
-
let(:group) {
|
8
|
-
let(:example) { Example.new(group) }
|
7
|
+
let(:group) { ExampleGroup.new(klass) }
|
8
|
+
let(:example) { Example.new(group.target) }
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
its(:group) { is_expected.to eq group }
|
13
|
-
its(:example) { is_expected.to be_a_kind_of RSpec::Core::Example }
|
10
|
+
before { allow_any_instance_of(Example).to receive(:run_before_example) }
|
14
11
|
|
15
|
-
|
16
|
-
describe "#set_example_group_instance" do
|
17
|
-
before { example.send :set_example_group_instance }
|
18
|
-
specify { expect(example.example.instance_variable_get :@example_group_instance).to be_a_kind_of group }
|
19
|
-
end
|
12
|
+
subject { example }
|
20
13
|
|
21
|
-
|
22
|
-
|
23
|
-
specify { expect(example.example.send :run_before_example).to be_present }
|
24
|
-
end
|
25
|
-
end
|
14
|
+
its(:group_target) { is_expected.to eq group.target }
|
15
|
+
its(:target) { is_expected.to be_a_kind_of RSpec::Core::Example }
|
26
16
|
end
|
@@ -3,9 +3,9 @@ require 'rails_helper'
|
|
3
3
|
include RSpec::Authorization::Adapters
|
4
4
|
|
5
5
|
describe Request do
|
6
|
-
let(:klass) {
|
7
|
-
let(:action) { :
|
8
|
-
let(:role) { :
|
6
|
+
let(:klass) { ArticlesController }
|
7
|
+
let(:action) { :update }
|
8
|
+
let(:role) { :editor }
|
9
9
|
let(:request) { Request.new(klass, action, role) }
|
10
10
|
|
11
11
|
subject { request }
|
data/spec/spec_helper.rb
CHANGED
@@ -3,7 +3,8 @@ require 'rails_test_app'
|
|
3
3
|
|
4
4
|
describe RailsTestApp do
|
5
5
|
let(:test_app) { RailsTestApp.new(:version) }
|
6
|
-
let(:
|
6
|
+
let(:temp_path) { "tmp" }
|
7
|
+
let(:dummy_file) { "#{temp_path}/dummy-rails-test-app" }
|
7
8
|
|
8
9
|
describe ".new" do
|
9
10
|
subject(:test_app) { RailsTestApp.new("4.1.6", "--skip-javascript") }
|
@@ -18,6 +19,7 @@ describe RailsTestApp do
|
|
18
19
|
before { allow(test_app).to receive(:create_command).and_return("touch #{dummy_file}") }
|
19
20
|
before { allow(test_app).to receive(:template_param) }
|
20
21
|
before { allow(test_app).to receive(:option) }
|
22
|
+
before { `mkdir #{temp_path}` }
|
21
23
|
after { `rm -rf #{dummy_file}` }
|
22
24
|
|
23
25
|
context "path does not exists" do
|
@@ -5,8 +5,8 @@ rules = "config/authorization_rules.rb"
|
|
5
5
|
run "mkdir ../../../config"
|
6
6
|
run "ln -s ../spec/.rails/rails-#{Rails::VERSION::STRING}/#{rules} ../../../#{rules}"
|
7
7
|
|
8
|
-
generate "scaffold
|
9
|
-
generate "migration
|
8
|
+
generate "scaffold article --skip-assets --skip-helper"
|
9
|
+
generate "migration AddUserIdToArticles user:references"
|
10
10
|
|
11
11
|
rake "db:migrate"
|
12
12
|
run "bundle exec rake db:migrate RAILS_ENV=test"
|
@@ -14,27 +14,38 @@ run "bundle exec rake db:migrate RAILS_ENV=test"
|
|
14
14
|
first_line = /\A.*/
|
15
15
|
last_line = /^.*\Z/
|
16
16
|
|
17
|
-
inject_into_file "app/models/
|
17
|
+
inject_into_file "app/models/article.rb", %q{
|
18
18
|
belongs_to :user
|
19
19
|
}, after: first_line
|
20
20
|
|
21
21
|
inject_into_file "app/models/user.rb", %q{
|
22
|
-
has_many :
|
22
|
+
has_many :articles
|
23
23
|
}, after: first_line
|
24
24
|
|
25
25
|
inject_into_file "config/authorization_rules.rb", %q{
|
26
|
+
role :editor do
|
27
|
+
has_permission_on :articles, to: :manage
|
28
|
+
end
|
29
|
+
|
30
|
+
role :writer do
|
31
|
+
has_permission_on :articles, to: %i(read create)
|
32
|
+
end
|
33
|
+
|
34
|
+
role :premium do
|
35
|
+
has_permission_on :articles, to: :read
|
36
|
+
end
|
37
|
+
|
26
38
|
role :user do
|
27
|
-
has_permission_on :
|
39
|
+
has_permission_on :articles, to: :index
|
28
40
|
end
|
29
41
|
}, after: first_line
|
30
42
|
|
31
43
|
inject_into_file "app/controllers/application_controller.rb", %q{
|
32
44
|
def current_user
|
33
|
-
User.where(id: session[:user_id]).presence
|
34
45
|
end
|
35
46
|
}, before: last_line
|
36
47
|
|
37
|
-
inject_into_file "app/controllers/
|
48
|
+
inject_into_file "app/controllers/articles_controller.rb", %q{
|
38
49
|
filter_resource_access
|
39
50
|
}, after: first_line
|
40
51
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-authorization
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hendra Uzia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: declarative_authorization
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: rspec-rails
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
33
|
+
version: '3.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
40
|
+
version: '3.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -120,15 +120,18 @@ files:
|
|
120
120
|
- ".gitignore"
|
121
121
|
- ".rspec"
|
122
122
|
- ".ruby-version"
|
123
|
+
- ".travis.yml"
|
124
|
+
- ".yardopts"
|
123
125
|
- Gemfile
|
124
126
|
- Guardfile
|
127
|
+
- HISTORY.md
|
125
128
|
- LICENSE.txt
|
126
129
|
- README.md
|
127
130
|
- Rakefile
|
128
131
|
- lib/rspec/authorization.rb
|
129
132
|
- lib/rspec/authorization/adapters.rb
|
130
133
|
- lib/rspec/authorization/adapters/example.rb
|
131
|
-
- lib/rspec/authorization/adapters/
|
134
|
+
- lib/rspec/authorization/adapters/example_group.rb
|
132
135
|
- lib/rspec/authorization/adapters/request.rb
|
133
136
|
- lib/rspec/authorization/adapters/route.rb
|
134
137
|
- lib/rspec/authorization/matchers.rb
|
@@ -136,9 +139,9 @@ files:
|
|
136
139
|
- lib/rspec/authorization/version.rb
|
137
140
|
- rspec-authorization.gemspec
|
138
141
|
- spec/.keep
|
139
|
-
- spec/controllers/
|
142
|
+
- spec/controllers/articles_controller_spec.rb
|
143
|
+
- spec/lib/rspec/authorization/adapters/example_group_spec.rb
|
140
144
|
- spec/lib/rspec/authorization/adapters/example_spec.rb
|
141
|
-
- spec/lib/rspec/authorization/adapters/group_spec.rb
|
142
145
|
- spec/lib/rspec/authorization/adapters/request_spec.rb
|
143
146
|
- spec/lib/rspec/authorization/adapters/route_spec.rb
|
144
147
|
- spec/rails_helper.rb
|
@@ -176,12 +179,13 @@ specification_version: 4
|
|
176
179
|
summary: RSpec matcher for declarative_authorization.
|
177
180
|
test_files:
|
178
181
|
- spec/.keep
|
179
|
-
- spec/controllers/
|
182
|
+
- spec/controllers/articles_controller_spec.rb
|
183
|
+
- spec/lib/rspec/authorization/adapters/example_group_spec.rb
|
180
184
|
- spec/lib/rspec/authorization/adapters/example_spec.rb
|
181
|
-
- spec/lib/rspec/authorization/adapters/group_spec.rb
|
182
185
|
- spec/lib/rspec/authorization/adapters/request_spec.rb
|
183
186
|
- spec/lib/rspec/authorization/adapters/route_spec.rb
|
184
187
|
- spec/rails_helper.rb
|
185
188
|
- spec/spec_helper.rb
|
186
189
|
- spec/support/group_test_class.rb
|
187
190
|
- spec/tools/rails_test_app_spec.rb
|
191
|
+
has_rdoc:
|
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'rails_helper'
|
2
|
-
|
3
|
-
describe PostsController do
|
4
|
-
it { is_expected.to have_permission_for(:user).to(:index) }
|
5
|
-
it { is_expected.to have_permission_for(:user).to(:new) }
|
6
|
-
it { is_expected.to have_permission_for(:user).to(:create) }
|
7
|
-
it { is_expected.to have_permission_for(:user).to(:show) }
|
8
|
-
it { is_expected.to have_permission_for(:user).to(:edit) }
|
9
|
-
it { is_expected.to have_permission_for(:user).to(:update) }
|
10
|
-
it { is_expected.to have_permission_for(:user).to(:destroy) }
|
11
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'rails_helper'
|
2
|
-
|
3
|
-
include RSpec::Authorization::Adapters
|
4
|
-
|
5
|
-
describe Group do
|
6
|
-
let(:klass) { GroupTestClass }
|
7
|
-
let(:group) { Group.new(klass) }
|
8
|
-
|
9
|
-
describe ".new" do
|
10
|
-
subject { group }
|
11
|
-
its(:described_class) { is_expected.to eq GroupTestClass }
|
12
|
-
end
|
13
|
-
end
|