access_policy 0.0.3
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 +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +7 -0
- data/Guardfile +25 -0
- data/LICENSE.txt +22 -0
- data/README.md +118 -0
- data/Rakefile +14 -0
- data/access_policy.gemspec +44 -0
- data/lib/access_policy.rb +50 -0
- data/lib/access_policy/policy_check.rb +75 -0
- data/lib/access_policy/policy_enforcer.rb +65 -0
- data/lib/access_policy/rspec_matchers.rb +81 -0
- data/lib/access_policy/version.rb +3 -0
- data/spec/acceptance/matcher_example_spec.rb +61 -0
- data/spec/integration/lib/access_policy_spec.rb +76 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/unit/lib/access_policy/matcher_spec.rb +24 -0
- data/spec/unit/lib/access_policy/policy_check_spec.rb +133 -0
- data/spec/unit/lib/access_policy/policy_enforcer_spec.rb +135 -0
- metadata +252 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6d6fec0043cb9fd0e0e318c74c3a123d5928373e
|
4
|
+
data.tar.gz: 416b4171c59eab9dd40e2235e9059cd9a9b8c914
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aa415b1b7d75b12278d6c0edc38d79d2558c912a44d3486b2f3a719fa01bee235eeb80716a84a78e4aa00894614a9ac62cfcf3a72802cbcf27790a891be12780
|
7
|
+
data.tar.gz: 51a51cc18979bed2caf2795cdab657a3137bfb4eae275d2385b2af84c9f0a991332d175482580c49819560f976b5be03d8c04613e00b5a09854e32cb1b597727
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :rspec, all_after_pass: true ,
|
5
|
+
all_on_start: true do
|
6
|
+
|
7
|
+
watch(%r{^spec/.+_spec\.rb$})
|
8
|
+
|
9
|
+
watch('lib/yaoc.rb') { "spec" }
|
10
|
+
|
11
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/unit/lib/#{m[1]}_spec.rb" }
|
12
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/integration/lib/#{m[1]}_spec.rb" }
|
13
|
+
|
14
|
+
watch('spec/spec_helper.rb') { "spec" }
|
15
|
+
|
16
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
guard :bundler do
|
22
|
+
watch('Gemfile')
|
23
|
+
# Uncomment next line if your Gemfile contains the `gemspec' command.
|
24
|
+
watch(/^.+\.gemspec/)
|
25
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Dieter Späth
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# AccessPolicy
|
2
|
+
|
3
|
+
Object oriented authorization for ruby. It provides helper to
|
4
|
+
protect method call's via Policy-Classes.
|
5
|
+
|
6
|
+
Inspired by https://github.com/elabs/pundit, but without Rails
|
7
|
+
and with a threat local storage for the current user or role.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'access_policy'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install access_policy
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
|
27
|
+
class ToGuard
|
28
|
+
def method_to_guard
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
ToGuardPolicy = Struct.new(:current_user_or_role, :object_of_kind_to_guard) do
|
34
|
+
|
35
|
+
def method_to_guard?
|
36
|
+
current_user_or_role.is_allowed?
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
object_to_guard = ToGuard.new
|
42
|
+
|
43
|
+
policy_checker = AccessPolicy::PolicyCheck.new
|
44
|
+
|
45
|
+
policy_checker.current_user_or_role_for_policy = current_user
|
46
|
+
|
47
|
+
policy_checker.with_user_or_role(current_user) do
|
48
|
+
begin
|
49
|
+
policy_checker.authorize(object_to_guard, 'method_to_guard')
|
50
|
+
object_to_guard.method_to_guard
|
51
|
+
rescue AccessPolicy::PolicyEnforcer::NotAuthorizedError
|
52
|
+
...
|
53
|
+
rescue AccessPolicy::PolicyEnforcer::NotDefinedError
|
54
|
+
...
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
```
|
60
|
+
|
61
|
+
Or
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
|
65
|
+
class ToGuard
|
66
|
+
include AccessPolicy
|
67
|
+
|
68
|
+
policy_guarded_method 'method_to_guard' do
|
69
|
+
# do some stuff
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
ToGuardPolicy = Struct.new(:current_user_or_role, :object_of_kind_to_guard) do
|
75
|
+
|
76
|
+
def method_to_guard?
|
77
|
+
current_user_or_role.is_allowed?
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
object_to_guard = ToGuard.new
|
83
|
+
|
84
|
+
object_to_guard.with_user_or_role(current_user) do
|
85
|
+
begin
|
86
|
+
object_to_guard.method_to_guard
|
87
|
+
rescue PolicyEnforcer::NotAuthorizedError
|
88
|
+
...
|
89
|
+
rescue PolicyEnforcer::NotDefinedError
|
90
|
+
...
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
object_to_guard.with_user_or_role(current_user) do
|
95
|
+
begin
|
96
|
+
object_to_guard.method_to_guard
|
97
|
+
|
98
|
+
object_to_guard.with_user_or_role(current_user.as_root) do
|
99
|
+
object_to_guard.method_to_guard_for_root
|
100
|
+
end
|
101
|
+
|
102
|
+
rescue PolicyEnforcer::NotAuthorizedError
|
103
|
+
...
|
104
|
+
rescue PolicyEnforcer::NotDefinedError
|
105
|
+
...
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
```
|
111
|
+
|
112
|
+
## Contributing
|
113
|
+
|
114
|
+
1. Fork it ( http://github.com/slowjack2k/access_policy/fork )
|
115
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
116
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
117
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
118
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new
|
5
|
+
|
6
|
+
|
7
|
+
task :default => :spec
|
8
|
+
task :test => :spec
|
9
|
+
|
10
|
+
desc "Run RSpec with code coverage"
|
11
|
+
task :coverage do
|
12
|
+
ENV['SIMPLE_COVERAGE'] = "true"
|
13
|
+
Rake::Task["spec"].execute
|
14
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'access_policy/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "access_policy"
|
8
|
+
spec.version = AccessPolicy::VERSION
|
9
|
+
spec.authors = ["Dieter Späth"]
|
10
|
+
spec.email = ["shad0wrunner@gmx.de"]
|
11
|
+
spec.summary = %q{Object oriented authorization for ruby.}
|
12
|
+
spec.description = %q{Object oriented authorization for ruby.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency 'scoped_storage'
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
|
26
|
+
|
27
|
+
spec.add_development_dependency "rspec", "2.99.0.beta1"
|
28
|
+
# show nicely how many specs have to be run
|
29
|
+
spec.add_development_dependency "fuubar"
|
30
|
+
# extended console
|
31
|
+
spec.add_development_dependency "pry"
|
32
|
+
spec.add_development_dependency 'pry-remote'
|
33
|
+
|
34
|
+
# automatic execute tasks on file changes
|
35
|
+
spec.add_development_dependency 'guard'
|
36
|
+
spec.add_development_dependency 'guard-rspec'
|
37
|
+
spec.add_development_dependency 'guard-bundler'
|
38
|
+
spec.add_development_dependency 'rb-fsevent'
|
39
|
+
|
40
|
+
# https://github.com/pry/pry-stack_explorer
|
41
|
+
spec.add_development_dependency 'pry-stack_explorer'
|
42
|
+
# https://github.com/nixme/pry-debugger
|
43
|
+
spec.add_development_dependency 'pry-debugger'
|
44
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "access_policy/version"
|
2
|
+
require 'scoped_storage'
|
3
|
+
|
4
|
+
require 'access_policy/policy_check'
|
5
|
+
require 'access_policy/policy_enforcer'
|
6
|
+
|
7
|
+
module AccessPolicy
|
8
|
+
|
9
|
+
def self.included(base)
|
10
|
+
base.extend ClassMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
def _default_error_policy
|
14
|
+
->(*){raise}
|
15
|
+
end
|
16
|
+
|
17
|
+
def _scope_storage
|
18
|
+
ScopedStorage::ThreadLocalStorage
|
19
|
+
end
|
20
|
+
|
21
|
+
def _guard
|
22
|
+
@_guard ||= PolicyCheck.new(default_error_policy: _default_error_policy,
|
23
|
+
scope_storage: _scope_storage
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def _authorize(query)
|
28
|
+
_guard.authorize self, query.to_sym
|
29
|
+
end
|
30
|
+
|
31
|
+
def with_user_or_role(user_or_role, error_policy = _default_error_policy ,&block)
|
32
|
+
_guard.with_user_or_role(user_or_role, error_policy, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
module ClassMethods
|
36
|
+
|
37
|
+
def policy_guarded_method(action_name, &block)
|
38
|
+
unsafe_action_name = :"#{action_name}_unsafe"
|
39
|
+
|
40
|
+
define_method action_name do |*args|
|
41
|
+
_authorize "#{action_name}?"
|
42
|
+
self.send(unsafe_action_name, *args)
|
43
|
+
end
|
44
|
+
|
45
|
+
define_method unsafe_action_name, block
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module AccessPolicy
|
2
|
+
|
3
|
+
class PolicyCheck
|
4
|
+
|
5
|
+
attr_accessor :default_error_policy, :scope_storage
|
6
|
+
|
7
|
+
def initialize(default_error_policy: ->(*) { raise },
|
8
|
+
scope_storage: ScopedStorage::ThreadLocalStorage)
|
9
|
+
|
10
|
+
self.default_error_policy = default_error_policy
|
11
|
+
self.scope_storage = scope_storage
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def authorize(object_to_guard, action_to_guard, error_policy: default_error_policy)
|
16
|
+
PolicyEnforcer.new(current_user_or_role_for_policy, object_to_guard, action_to_guard).authorize(error_policy) do
|
17
|
+
self.policy_authorized=true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def policy_for(object_or_class, error_policy = default_error_policy)
|
22
|
+
PolicyEnforcer.new(current_user_or_role_for_policy, object_or_class).policy(error_policy)
|
23
|
+
end
|
24
|
+
|
25
|
+
def with_user_or_role(new_current_user_or_role_for_policy, error_policy = default_error_policy)
|
26
|
+
self.policy_authorized = false
|
27
|
+
|
28
|
+
switched_user_or_role(new_current_user_or_role_for_policy) do
|
29
|
+
begin
|
30
|
+
yield if block_given?
|
31
|
+
raise(PolicyEnforcer::NotAuthorizedError, "#{new_current_user_or_role_for_policy}") unless policy_authorized?
|
32
|
+
rescue => e
|
33
|
+
error_policy.call(e)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def current_user_or_role_for_policy=(new_user)
|
39
|
+
scope['current_user_or_role_for_policy'] = new_user
|
40
|
+
end
|
41
|
+
|
42
|
+
def current_user_or_role_for_policy
|
43
|
+
scope['current_user_or_role_for_policy']
|
44
|
+
end
|
45
|
+
|
46
|
+
def policy_authorized=(new_value)
|
47
|
+
scope['policy_authorized'] = new_value
|
48
|
+
end
|
49
|
+
|
50
|
+
def policy_authorized?
|
51
|
+
!!policy_authorized
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
def policy_authorized
|
57
|
+
scope['policy_authorized']
|
58
|
+
end
|
59
|
+
|
60
|
+
def scope
|
61
|
+
@scope ||= ScopedStorage::Scope.new('policy_infos', scope_storage)
|
62
|
+
end
|
63
|
+
|
64
|
+
def switched_user_or_role(new_current_user_or_role_for_policy)
|
65
|
+
old_current_user_or_role = self.current_user_or_role_for_policy
|
66
|
+
self.current_user_or_role_for_policy = new_current_user_or_role_for_policy
|
67
|
+
|
68
|
+
yield if block_given?
|
69
|
+
|
70
|
+
ensure
|
71
|
+
self.current_user_or_role_for_policy = old_current_user_or_role
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module AccessPolicy
|
2
|
+
class PolicyEnforcer
|
3
|
+
class NotDefinedError < StandardError;
|
4
|
+
end
|
5
|
+
class NotAuthorizedError < StandardError;
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_accessor :current_user_or_role, :object_or_class, :query, :default_error_policy
|
9
|
+
|
10
|
+
def initialize(current_user_or_role, object_or_class, query=nil, default_error_policy=->(*) { raise })
|
11
|
+
raise NotDefinedError, 'unable to find policy class for anonymous classes' if class_to_guard(object_or_class).name.nil? || class_to_guard(object_or_class).name.length < 1
|
12
|
+
|
13
|
+
self.current_user_or_role = current_user_or_role
|
14
|
+
self.object_or_class = object_or_class
|
15
|
+
self.query = query
|
16
|
+
self.default_error_policy = default_error_policy
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def authorize(error_policy=default_error_policy)
|
21
|
+
raise(PolicyEnforcer::NotAuthorizedError, "not allowed to #{query} this #{object_or_class}" ) unless _guard_action()
|
22
|
+
yield true if block_given?
|
23
|
+
true
|
24
|
+
rescue
|
25
|
+
error_policy.call(object_or_class)
|
26
|
+
end
|
27
|
+
|
28
|
+
def policy(error_policy=default_error_policy)
|
29
|
+
specific_policy_for_class.new(current_user_or_role, object_or_class)
|
30
|
+
rescue
|
31
|
+
error_policy.call(object_or_class)
|
32
|
+
end
|
33
|
+
|
34
|
+
def query=(new_query)
|
35
|
+
new_query = new_query.to_s
|
36
|
+
@query = (new_query.end_with?('?') ? new_query : "#{new_query}?").to_sym
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def class_to_guard(obj_or_class=object_or_class)
|
42
|
+
obj_or_class.is_a?(Class) ? obj_or_class : obj_or_class.class
|
43
|
+
end
|
44
|
+
|
45
|
+
def default_policy_name
|
46
|
+
"#{class_to_guard.name}Policy"
|
47
|
+
end
|
48
|
+
|
49
|
+
def _guard_action
|
50
|
+
policy(->(*) { raise }).public_send(query)
|
51
|
+
rescue NoMethodError
|
52
|
+
raise NotDefinedError, "unable to find policy method #{query} for #{policy}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def specific_policy_for_class
|
56
|
+
|
57
|
+
policy_class = class_to_guard.policy_class if class_to_guard.respond_to? :policy_class
|
58
|
+
policy_class || Object.const_get(default_policy_name, false)
|
59
|
+
rescue
|
60
|
+
raise NotDefinedError, "unable to find policy class #{default_policy_name}"
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module AccessPolicy
|
2
|
+
module RspecMatchers
|
3
|
+
extend ::RSpec::Matchers::DSL
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.metadata[:type] = :policy
|
7
|
+
end
|
8
|
+
|
9
|
+
module Common
|
10
|
+
def self.call(base)
|
11
|
+
base.instance_eval do
|
12
|
+
chain :to do |user|
|
13
|
+
@user = user
|
14
|
+
end
|
15
|
+
|
16
|
+
chain :on do |object_to_guard|
|
17
|
+
@object_to_guard = object_to_guard
|
18
|
+
end
|
19
|
+
|
20
|
+
define_method :permission_granted? do |policy_class, permission |
|
21
|
+
policy = policy_class.new(@user, @object_to_guard)
|
22
|
+
policy.public_send("#{permission}?")
|
23
|
+
end
|
24
|
+
|
25
|
+
define_method :permission_denied? do |*args|
|
26
|
+
! permission_granted?(*args)
|
27
|
+
end
|
28
|
+
|
29
|
+
define_method :object_as_text do
|
30
|
+
@object_to_guard.nil? ? '' : " on #{@object_to_guard.inspect}"
|
31
|
+
end
|
32
|
+
|
33
|
+
define_method :user_as_text do
|
34
|
+
@user.nil? ? '' : " for #{@user.inspect}"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
matcher :permit do |permission|
|
43
|
+
match do |policy_class|
|
44
|
+
permission_granted?(policy_class, permission)
|
45
|
+
end
|
46
|
+
|
47
|
+
failure_message_for_should do |policy_class|
|
48
|
+
"#{policy_class} does not permit #{permission} #{object_as_text}#{user_as_text}."
|
49
|
+
end
|
50
|
+
|
51
|
+
failure_message_for_should_not do |policy_class|
|
52
|
+
"#{policy_class} does not forbid #{permission}#{object_as_text}#{user_as_text}."
|
53
|
+
end
|
54
|
+
|
55
|
+
Common.call(self)
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
matcher :forbid do |permission|
|
60
|
+
match do |policy_class|
|
61
|
+
permission_denied?(policy_class, permission)
|
62
|
+
end
|
63
|
+
|
64
|
+
failure_message_for_should do |policy_class|
|
65
|
+
"#{policy_class} does not forbid #{permission} #{object_as_text}#{user_as_text}."
|
66
|
+
end
|
67
|
+
|
68
|
+
failure_message_for_should_not do |policy_class|
|
69
|
+
"#{policy_class} does not permit #{permission}#{object_as_text}#{user_as_text}."
|
70
|
+
end
|
71
|
+
|
72
|
+
Common.call(self)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
RSpec.configure do |config|
|
78
|
+
config.include AccessPolicy::RspecMatchers, type: :policy, example_group: ->(example_group, metadata){
|
79
|
+
metadata[:type].nil? && %r{spec/policies} =~ example_group[:file_path]
|
80
|
+
}
|
81
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'access_policy/rspec_matchers'
|
3
|
+
|
4
|
+
module MatcherExampleSpec
|
5
|
+
DummyPolicy = Struct.new(:current_user, :object_to_guard) do
|
6
|
+
def read?
|
7
|
+
true
|
8
|
+
end
|
9
|
+
|
10
|
+
def write?
|
11
|
+
current_user && current_user.allowed?
|
12
|
+
end
|
13
|
+
|
14
|
+
def destroy?
|
15
|
+
write? && object_to_guard && !object_to_guard.locked?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "PolicyMatchers", type: :policy do
|
21
|
+
subject(:policy){
|
22
|
+
MatcherExampleSpec::DummyPolicy
|
23
|
+
}
|
24
|
+
|
25
|
+
|
26
|
+
context 'for a visitor' do
|
27
|
+
let(:visitor){nil}
|
28
|
+
|
29
|
+
it 'permits read' do
|
30
|
+
expect(policy).to permit(:read).to(visitor)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'forbids write' do
|
34
|
+
expect(policy).not_to permit(:write).to(visitor)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'for a admin' do
|
39
|
+
let(:admin){double('admin', allowed?: true)}
|
40
|
+
let(:locked_object_to_guard){double('object to guard', locked?: true)}
|
41
|
+
let(:unlocked_object_to_guard){double('object to guard', locked?: false)}
|
42
|
+
|
43
|
+
it 'permits read' do
|
44
|
+
expect(policy).to permit(:read).to(admin)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'permits write' do
|
48
|
+
expect(policy).to permit(:write).to(admin)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'permits destroy for unlocked objects' do
|
52
|
+
expect(policy).to permit(:destroy).on(unlocked_object_to_guard).to(admin)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'forbids destroy for locked objects' do
|
56
|
+
expect(policy).to forbid(:destroy).on(locked_object_to_guard).to(admin)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module AccessPolicySpec
|
4
|
+
DummyPolicy = Struct.new(:current_user, :object_to_guard) do
|
5
|
+
def call?
|
6
|
+
current_user && current_user.allowed?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
class Dummy
|
12
|
+
include AccessPolicy
|
13
|
+
|
14
|
+
policy_guarded_method 'call' do
|
15
|
+
:return_value
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe AccessPolicy do
|
22
|
+
subject{
|
23
|
+
AccessPolicySpec::Dummy.new
|
24
|
+
}
|
25
|
+
|
26
|
+
let(:falsy_user){
|
27
|
+
double("user", allowed?: false)
|
28
|
+
}
|
29
|
+
|
30
|
+
let(:truethy_user){
|
31
|
+
double("user", allowed?: true)
|
32
|
+
}
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
describe '.policy_guarded_method' do
|
37
|
+
it 'creates a guarded method' do
|
38
|
+
expect(subject).to respond_to :call
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'protects created methods' do
|
42
|
+
expect {
|
43
|
+
subject.call
|
44
|
+
}.to raise_error AccessPolicy::PolicyEnforcer::NotAuthorizedError
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'grands access to guarded methods when the user has the right' do
|
48
|
+
expect {
|
49
|
+
subject.with_user_or_role(truethy_user) do
|
50
|
+
subject.call
|
51
|
+
end
|
52
|
+
}.not_to raise_error
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'creates a not guarded method' do
|
56
|
+
expect(subject).to respond_to :call_unsafe
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'does not protect unsafe methods' do
|
60
|
+
expect {
|
61
|
+
subject.call_unsafe
|
62
|
+
}.not_to raise_error
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '.with_user_or_role' do
|
67
|
+
it 'delegates to the policy check object' do
|
68
|
+
error_policy = ->(exception){}
|
69
|
+
current_user = double('user')
|
70
|
+
expect(subject._guard).to receive(:with_user_or_role).with(current_user, error_policy)
|
71
|
+
|
72
|
+
subject.with_user_or_role(current_user, error_policy)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
Bundler.require(:development)
|
3
|
+
|
4
|
+
require 'coveralls'
|
5
|
+
Coveralls.wear! unless ENV["SIMPLE_COVERAGE"]
|
6
|
+
|
7
|
+
begin
|
8
|
+
if ENV["SIMPLE_COVERAGE"]
|
9
|
+
require 'simplecov'
|
10
|
+
SimpleCov.start do
|
11
|
+
add_group "Lib", "lib"
|
12
|
+
|
13
|
+
add_filter "/spec/"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
rescue LoadError
|
17
|
+
warn "=" * 80
|
18
|
+
warn 'simplecov not installed. No coverage report'
|
19
|
+
warn "=" * 80
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'access_policy'
|
23
|
+
|
24
|
+
Dir[File.join(File.expand_path(__dir__ ), "support/**/*.rb")].each { |f| require f }
|
25
|
+
|
26
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
27
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
28
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
29
|
+
# loaded once.
|
30
|
+
#
|
31
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
32
|
+
RSpec.configure do |config|
|
33
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
34
|
+
config.run_all_when_everything_filtered = true
|
35
|
+
config.filter_run :focus
|
36
|
+
|
37
|
+
# Run specs in random order to surface order dependencies. If you find an
|
38
|
+
# order dependency and want to debug it, you can fix the order by providing
|
39
|
+
# the seed, which is printed after each run.
|
40
|
+
# --seed 1234
|
41
|
+
config.order = 'random'
|
42
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'access_policy/rspec_matchers'
|
3
|
+
|
4
|
+
describe 'PolicyMatchers' do
|
5
|
+
context 'none policy spec' do
|
6
|
+
it 'has no access to permit' do
|
7
|
+
expect { permit }.to raise_error(NameError)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'has no access to forbid' do
|
11
|
+
expect { forbid }.to raise_error(NameError)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'policy spec', type: :policy do
|
16
|
+
it 'grands access to permit' do
|
17
|
+
expect { permit }.not_to raise_error
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'grands access to forbid' do
|
21
|
+
expect { forbid }.not_to raise_error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PolicyCheckSpec
|
4
|
+
class Dummy
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
DummyPolicy = Struct.new(:current_user, :object_to_guard) do
|
9
|
+
def call?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module AccessPolicy
|
16
|
+
describe PolicyCheck do
|
17
|
+
subject {
|
18
|
+
AccessPolicy::PolicyCheck.new.tap { |p|
|
19
|
+
p.current_user_or_role_for_policy=nil
|
20
|
+
p.policy_authorized = true
|
21
|
+
}
|
22
|
+
|
23
|
+
}
|
24
|
+
|
25
|
+
let(:current_user) {
|
26
|
+
"It's me"
|
27
|
+
}
|
28
|
+
|
29
|
+
|
30
|
+
describe '.policy_for' do
|
31
|
+
|
32
|
+
it 'returns a policy object for a class' do
|
33
|
+
expect(subject.policy_for(PolicyCheckSpec::Dummy)).to be_kind_of PolicyCheckSpec::DummyPolicy
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns a policy object for a object' do
|
37
|
+
expect(subject.policy_for(PolicyCheckSpec::Dummy.new)).to be_kind_of PolicyCheckSpec::DummyPolicy
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'sets the current user' do
|
41
|
+
subject.current_user_or_role_for_policy = current_user
|
42
|
+
expect(subject.policy_for(PolicyCheckSpec::Dummy.new).current_user).to be current_user
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'uses my error handler' do
|
46
|
+
object_to_guard = Object.new
|
47
|
+
error_handler=double('error handler')
|
48
|
+
expect(error_handler).to receive(:call).with(object_to_guard)
|
49
|
+
|
50
|
+
subject.policy_for(object_to_guard, error_handler)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '.with_user_or_role' do
|
55
|
+
it 'sets the current user' do
|
56
|
+
subject.with_user_or_role(current_user) do
|
57
|
+
subject.policy_authorized = true
|
58
|
+
expect(subject.current_user_or_role_for_policy).to eq current_user
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'sets the current user back after execution' do
|
63
|
+
subject.current_user_or_role_for_policy = 'other user'
|
64
|
+
|
65
|
+
subject.with_user_or_role(current_user) do
|
66
|
+
subject.policy_authorized = true
|
67
|
+
end
|
68
|
+
|
69
|
+
expect(subject.current_user_or_role_for_policy).to eq 'other user'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'raises PolicyEnforcer::NotAuthorizedError when authorize is not called' do
|
73
|
+
expect { subject.with_user_or_role(current_user) }.to raise_error PolicyEnforcer::NotAuthorizedError
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'does not raise PolicyEnforcer::NotAuthorizedError when authorize is called' do
|
77
|
+
expect {
|
78
|
+
subject.with_user_or_role(current_user) do
|
79
|
+
subject.authorize(PolicyCheckSpec::Dummy.new, "call")
|
80
|
+
end
|
81
|
+
}.not_to raise_error
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'uses an custom an error handler' do
|
85
|
+
error_handler=double('error handler')
|
86
|
+
expect(error_handler).to receive(:call).with(kind_of(StandardError))
|
87
|
+
|
88
|
+
subject.with_user_or_role(current_user, error_handler)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'supports nested context switches' do
|
92
|
+
user1 = 'user 1'
|
93
|
+
user2 = 'user 2'
|
94
|
+
user3 = 'user 3'
|
95
|
+
|
96
|
+
subject.current_user_or_role_for_policy = user1
|
97
|
+
|
98
|
+
subject.with_user_or_role(user2, ->(*){}) do
|
99
|
+
expect(subject.current_user_or_role_for_policy).to eq user2
|
100
|
+
|
101
|
+
subject.with_user_or_role(user3) do
|
102
|
+
expect(subject.current_user_or_role_for_policy).to eq user3
|
103
|
+
end
|
104
|
+
|
105
|
+
expect(subject.current_user_or_role_for_policy).to eq user2
|
106
|
+
end
|
107
|
+
|
108
|
+
expect(subject.current_user_or_role_for_policy).to eq user1
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
describe '.authorize' do
|
115
|
+
it 'returns true when the user is authorized' do
|
116
|
+
expect(subject.authorize(PolicyCheckSpec::Dummy.new, "call")).to be == true
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'raises an exception when no method is defined' do
|
120
|
+
expect { subject.authorize(PolicyCheckSpec::Dummy.new, "call2") }.to raise_error
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'uses a given error handler' do
|
124
|
+
object_to_guard = PolicyCheckSpec::Dummy.new
|
125
|
+
error_handler=double('error handler')
|
126
|
+
expect(error_handler).to receive(:call).with(object_to_guard)
|
127
|
+
|
128
|
+
subject.authorize(object_to_guard, "call2", error_policy: error_handler)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PolicyEnforcerSpec
|
4
|
+
class Dummy
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
DummyPolicy = Struct.new(:current_user, :object_to_guard) do
|
9
|
+
def call?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def not_allowed_call?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module A
|
19
|
+
class Dummy
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
DummyPolicy = Struct.new(:d_current_user, :d_object_to_guard)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module AccessPolicy
|
28
|
+
describe PolicyEnforcer do
|
29
|
+
subject {
|
30
|
+
AccessPolicy::PolicyEnforcer.new(current_user, object_to_guard, action, error_policy)
|
31
|
+
}
|
32
|
+
|
33
|
+
let(:current_user) {
|
34
|
+
double('user')
|
35
|
+
}
|
36
|
+
|
37
|
+
let(:object_to_guard) {
|
38
|
+
PolicyEnforcerSpec::Dummy.new
|
39
|
+
}
|
40
|
+
|
41
|
+
let(:action) {
|
42
|
+
"call"
|
43
|
+
}
|
44
|
+
|
45
|
+
let(:error_policy) {
|
46
|
+
->(*) { raise }
|
47
|
+
}
|
48
|
+
|
49
|
+
describe '#new' do
|
50
|
+
it 'raises an error when class to guard has no name' do
|
51
|
+
expect{AccessPolicy::PolicyEnforcer.new(current_user, Class.new.new, action, error_policy)}.to raise_error
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
describe '.policy' do
|
57
|
+
|
58
|
+
it 'returns a policy object for a class' do
|
59
|
+
subject.object_or_class = PolicyEnforcerSpec::Dummy
|
60
|
+
expect(subject.policy).to be_kind_of PolicyEnforcerSpec::DummyPolicy
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'returns a policy object for a object' do
|
64
|
+
expect(subject.policy).to be_kind_of PolicyEnforcerSpec::DummyPolicy
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'sets the current user' do
|
68
|
+
expect(subject.policy.current_user).to be current_user
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'uses my error handler' do
|
72
|
+
object_to_guard = Object.new
|
73
|
+
error_handler=double('error handler')
|
74
|
+
expect(error_handler).to receive(:call).with(object_to_guard)
|
75
|
+
|
76
|
+
subject.object_or_class = object_to_guard
|
77
|
+
|
78
|
+
subject.policy(error_handler)
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
it 'returns a policy object for a class within a module' do
|
83
|
+
subject.object_or_class = PolicyEnforcerSpec::A::Dummy.new
|
84
|
+
expect(subject.policy).to be_kind_of PolicyEnforcerSpec::A::DummyPolicy
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'raises Policy::NotDefinedError when no policy class found' do
|
88
|
+
B = Object
|
89
|
+
subject.object_or_class = B
|
90
|
+
expect { subject.policy }.to raise_error PolicyEnforcer::NotDefinedError
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'raises Policy::NotDefinedError when class.name is empty' do
|
94
|
+
subject.object_or_class = Class.new
|
95
|
+
expect { subject.policy }.to raise_error PolicyEnforcer::NotDefinedError
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '.authorize' do
|
100
|
+
it 'returns true when the user is authorized' do
|
101
|
+
expect(subject.authorize).to be == true
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'raises an exception when the user is not authorized' do
|
105
|
+
subject.query = "not_allowed_call"
|
106
|
+
expect{subject.authorize}.to raise_error
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'raises an exception when no method is defined' do
|
110
|
+
subject.query = "call2"
|
111
|
+
expect { subject.authorize }.to raise_error PolicyEnforcer::NotDefinedError
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'uses a given error handler' do
|
115
|
+
object_to_guard = Object.new
|
116
|
+
error_handler=double('error handler')
|
117
|
+
expect(error_handler).to receive(:call).with(object_to_guard)
|
118
|
+
|
119
|
+
subject.object_or_class = object_to_guard
|
120
|
+
|
121
|
+
subject.authorize(error_handler)
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'yields when authorize was successful' do
|
125
|
+
expect { |block| subject.authorize(&block) }.to yield_with_args(true)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'does not yield when authorize was not successful' do
|
129
|
+
subject.query = "call2"
|
130
|
+
expect { |block| subject.authorize(->(*) {}, &block) }.not_to yield_with_args
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
metadata
ADDED
@@ -0,0 +1,252 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: access_policy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dieter Späth
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: scoped_storage
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.99.0.beta1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.99.0.beta1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: fuubar
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry-remote
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: guard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: guard-rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: guard-bundler
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rb-fsevent
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: pry-stack_explorer
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: pry-debugger
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
description: Object oriented authorization for ruby.
|
196
|
+
email:
|
197
|
+
- shad0wrunner@gmx.de
|
198
|
+
executables: []
|
199
|
+
extensions: []
|
200
|
+
extra_rdoc_files: []
|
201
|
+
files:
|
202
|
+
- ".gitignore"
|
203
|
+
- ".rspec"
|
204
|
+
- ".travis.yml"
|
205
|
+
- Gemfile
|
206
|
+
- Guardfile
|
207
|
+
- LICENSE.txt
|
208
|
+
- README.md
|
209
|
+
- Rakefile
|
210
|
+
- access_policy.gemspec
|
211
|
+
- lib/access_policy.rb
|
212
|
+
- lib/access_policy/policy_check.rb
|
213
|
+
- lib/access_policy/policy_enforcer.rb
|
214
|
+
- lib/access_policy/rspec_matchers.rb
|
215
|
+
- lib/access_policy/version.rb
|
216
|
+
- spec/acceptance/matcher_example_spec.rb
|
217
|
+
- spec/integration/lib/access_policy_spec.rb
|
218
|
+
- spec/spec_helper.rb
|
219
|
+
- spec/unit/lib/access_policy/matcher_spec.rb
|
220
|
+
- spec/unit/lib/access_policy/policy_check_spec.rb
|
221
|
+
- spec/unit/lib/access_policy/policy_enforcer_spec.rb
|
222
|
+
homepage: ''
|
223
|
+
licenses:
|
224
|
+
- MIT
|
225
|
+
metadata: {}
|
226
|
+
post_install_message:
|
227
|
+
rdoc_options: []
|
228
|
+
require_paths:
|
229
|
+
- lib
|
230
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
231
|
+
requirements:
|
232
|
+
- - ">="
|
233
|
+
- !ruby/object:Gem::Version
|
234
|
+
version: '0'
|
235
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
236
|
+
requirements:
|
237
|
+
- - ">="
|
238
|
+
- !ruby/object:Gem::Version
|
239
|
+
version: '0'
|
240
|
+
requirements: []
|
241
|
+
rubyforge_project:
|
242
|
+
rubygems_version: 2.2.1
|
243
|
+
signing_key:
|
244
|
+
specification_version: 4
|
245
|
+
summary: Object oriented authorization for ruby.
|
246
|
+
test_files:
|
247
|
+
- spec/acceptance/matcher_example_spec.rb
|
248
|
+
- spec/integration/lib/access_policy_spec.rb
|
249
|
+
- spec/spec_helper.rb
|
250
|
+
- spec/unit/lib/access_policy/matcher_spec.rb
|
251
|
+
- spec/unit/lib/access_policy/policy_check_spec.rb
|
252
|
+
- spec/unit/lib/access_policy/policy_enforcer_spec.rb
|