rushiro 1.0.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.
- data/Gemfile +2 -0
- data/Rakefile +161 -0
- data/lib/rushiro.rb +4 -0
- data/lib/rushiro/access_control_hash.rb +50 -0
- data/lib/rushiro/access_levels.rb +45 -0
- data/lib/rushiro/allow_based_control.rb +8 -0
- data/lib/rushiro/deny_based_control.rb +9 -0
- data/lib/rushiro/permission.rb +41 -0
- data/lib/rushiro/permissions.rb +30 -0
- data/lib/rushiro/version.rb +3 -0
- data/readme.md +108 -0
- data/rushiro.gemspec +37 -0
- data/spec/access_control_spec.rb +63 -0
- data/spec/spec_helper.rb +11 -0
- metadata +94 -0
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
#############################################################################
|
5
|
+
#
|
6
|
+
# Helper functions
|
7
|
+
#
|
8
|
+
#############################################################################
|
9
|
+
|
10
|
+
def name
|
11
|
+
@name ||= Dir['*.gemspec'].first.split('.').first
|
12
|
+
end
|
13
|
+
|
14
|
+
def version
|
15
|
+
line = File.read("lib/#{name}/version.rb")[/^\s*VERSION\s*=\s*.*/]
|
16
|
+
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
17
|
+
end
|
18
|
+
|
19
|
+
def date
|
20
|
+
Date.today.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def rubyforge_project
|
24
|
+
name
|
25
|
+
end
|
26
|
+
|
27
|
+
def gemspec_file
|
28
|
+
"#{name}.gemspec"
|
29
|
+
end
|
30
|
+
|
31
|
+
def gem_file
|
32
|
+
"#{name}-#{version}.gem"
|
33
|
+
end
|
34
|
+
|
35
|
+
def replace_header(head, header_name, provider = nil)
|
36
|
+
if provider
|
37
|
+
value = send(provider)
|
38
|
+
else
|
39
|
+
value = "'#{send(header_name)}'"
|
40
|
+
end
|
41
|
+
|
42
|
+
provider ||= header_name
|
43
|
+
head.sub!(/(\.#{header_name}\s*= ).*/) { "#{$1}#{value}"}
|
44
|
+
end
|
45
|
+
|
46
|
+
def platform
|
47
|
+
jruby? ? '-java' : ''
|
48
|
+
end
|
49
|
+
|
50
|
+
def platform_dependant_gem_file
|
51
|
+
"#{name}-#{version}#{platform}.gem"
|
52
|
+
end
|
53
|
+
|
54
|
+
def platform_dependent_version
|
55
|
+
"'#{version}#{platform}'"
|
56
|
+
end
|
57
|
+
|
58
|
+
def jruby?
|
59
|
+
RUBY_PLATFORM.to_s == 'java'
|
60
|
+
end
|
61
|
+
|
62
|
+
def trim_array_ends array
|
63
|
+
array.shift
|
64
|
+
array.pop
|
65
|
+
array
|
66
|
+
end
|
67
|
+
|
68
|
+
#############################################################################
|
69
|
+
#
|
70
|
+
# Custom tasks
|
71
|
+
#
|
72
|
+
#############################################################################
|
73
|
+
|
74
|
+
default_rspec_opts = %w[--colour --format Fuubar]
|
75
|
+
|
76
|
+
desc "Run all examples"
|
77
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
78
|
+
t.rspec_opts = default_rspec_opts
|
79
|
+
end
|
80
|
+
|
81
|
+
#############################################################################
|
82
|
+
#
|
83
|
+
# Packaging tasks
|
84
|
+
#
|
85
|
+
#############################################################################
|
86
|
+
|
87
|
+
def built_gem
|
88
|
+
@built_gem ||= Dir["#{name}*.gem"].first
|
89
|
+
end
|
90
|
+
|
91
|
+
desc "Create tag v#{platform_dependent_version} and build and push #{platform_dependant_gem_file} to Rubygems"
|
92
|
+
task :release => :build do
|
93
|
+
unless `git branch` =~ /^\* master$/
|
94
|
+
puts "You must be on the master branch to release!"
|
95
|
+
exit!
|
96
|
+
end
|
97
|
+
|
98
|
+
sh "git commit --allow-empty -a -m 'Release #{platform_dependent_version}'"
|
99
|
+
sh "git tag v#{platform_dependent_version}"
|
100
|
+
sh "git push origin master"
|
101
|
+
sh "git push origin v#{platform_dependent_version}"
|
102
|
+
|
103
|
+
command = "gem push pkg/#{platform_dependant_gem_file}"
|
104
|
+
|
105
|
+
if jruby?
|
106
|
+
puts "--------------------------------------------------------------------------------------"
|
107
|
+
puts "can't push to rubygems using jruby at the moment, so switch to mri and run: #{command}"
|
108
|
+
puts "--------------------------------------------------------------------------------------"
|
109
|
+
else
|
110
|
+
sh command
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
desc "Build #{platform_dependant_gem_file} into the pkg directory"
|
115
|
+
task :build => :gemspec do
|
116
|
+
sh "mkdir -p pkg"
|
117
|
+
sh "gem build #{gemspec_file}"
|
118
|
+
sh "mv #{built_gem} pkg"
|
119
|
+
end
|
120
|
+
|
121
|
+
desc "Generate #{gemspec_file}"
|
122
|
+
task :gemspec => :validate do
|
123
|
+
# read spec file and split out manifest section
|
124
|
+
spec = File.read(gemspec_file)
|
125
|
+
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
126
|
+
|
127
|
+
# replace name version and date
|
128
|
+
replace_header(head, :name)
|
129
|
+
replace_header(head, :version)
|
130
|
+
replace_header(head, :date)
|
131
|
+
#comment this out if your rubyforge_project has a different name
|
132
|
+
#replace_header(head, :rubyforge_project)
|
133
|
+
|
134
|
+
# determine file list from git ls-files
|
135
|
+
files = `git ls-files`.
|
136
|
+
split("\n").
|
137
|
+
sort.
|
138
|
+
reject { |file| file =~ /^\./ }.
|
139
|
+
reject { |file| file =~ /^(rdoc|pkg)/ }.
|
140
|
+
map { |file| " #{file}" }.
|
141
|
+
join("\n")
|
142
|
+
|
143
|
+
# piece file back together and write
|
144
|
+
manifest = " s.files = %w[\n#{files}\n ]\n"
|
145
|
+
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
|
146
|
+
File.open(gemspec_file, 'w') { |io| io.write(spec) }
|
147
|
+
puts "Updated #{gemspec_file}"
|
148
|
+
end
|
149
|
+
|
150
|
+
desc "Validate #{gemspec_file}"
|
151
|
+
task :validate do
|
152
|
+
libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
|
153
|
+
unless libfiles.empty?
|
154
|
+
puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
|
155
|
+
exit!
|
156
|
+
end
|
157
|
+
unless Dir['VERSION*'].empty?
|
158
|
+
puts "A `VERSION` file at root level violates Gem best practices."
|
159
|
+
exit!
|
160
|
+
end
|
161
|
+
end
|
data/lib/rushiro.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module Rushiro
|
2
|
+
GSEP = '|'
|
3
|
+
FSEP = ','
|
4
|
+
class AccessControlHash
|
5
|
+
attr_reader :allows, :denies, :original, :dirty
|
6
|
+
def initialize(hash)
|
7
|
+
@allows = AccessLevels.new(hash[:allows] || {})
|
8
|
+
@denies = AccessLevels.new(hash[:denies] || {})
|
9
|
+
@dirty = false
|
10
|
+
@original = hash
|
11
|
+
end
|
12
|
+
|
13
|
+
def permitted?(perm)
|
14
|
+
# virtual
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_permission(perm) #as string "allow|individual|domain(|action(|instance))"
|
18
|
+
grant, rest = perm.split(GSEP, 2)
|
19
|
+
case grant
|
20
|
+
when 'allows'
|
21
|
+
@allows.add_permission(rest) and @dirty = true
|
22
|
+
when 'denies'
|
23
|
+
@denies.add_permission(rest) and @dirty = true
|
24
|
+
else
|
25
|
+
raise ArgumentError.new("Could not add permission for type: #{grant} of #{perm}")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def remove_permission(perm) #as string "allow|individual|domain(|action(|instance))"
|
30
|
+
grant, rest = perm.split(GSEP, 2)
|
31
|
+
case grant
|
32
|
+
when 'allows'
|
33
|
+
@allows.remove_permission(rest) and @dirty = true
|
34
|
+
when 'denies'
|
35
|
+
@denies.remove_permission(rest) and @dirty = true
|
36
|
+
else
|
37
|
+
raise ArgumentError.new("Could not remove permission for type: #{grant} of #{perm}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def serialize
|
42
|
+
unless @dirty
|
43
|
+
@original
|
44
|
+
else
|
45
|
+
Hash[:allows, @allows.serialize, :denies, @denies.serialize]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Rushiro
|
2
|
+
class AccessLevels
|
3
|
+
attr_reader :individual, :organization, :musicglue
|
4
|
+
def initialize(hash)
|
5
|
+
@individual = Permissions.new(hash[:individual] || [])
|
6
|
+
@organization = Permissions.new(hash[:organization] || [])
|
7
|
+
@system = Permissions.new(hash[:system] || [])
|
8
|
+
end
|
9
|
+
|
10
|
+
def permitted?(perm)
|
11
|
+
@system.permitted?(perm) || @organization.permitted?(perm) || @individual.permitted?(perm)
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_permission(perm)
|
15
|
+
level, rest = perm.split(GSEP, 2)
|
16
|
+
case level
|
17
|
+
when 'individual'
|
18
|
+
@individual.add_permission(rest)
|
19
|
+
when 'organization'
|
20
|
+
@organization.add_permission(rest)
|
21
|
+
when 'system'
|
22
|
+
@system.add_permission(rest)
|
23
|
+
else
|
24
|
+
raise ArgumentError.new("Could not add permission for level: #{level} of #{level}#{SEP}#{perm}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def remove_permission(perm)
|
29
|
+
level, rest = perm.split(GSEP, 2)
|
30
|
+
case level
|
31
|
+
when 'individual'
|
32
|
+
@individual.remove_permission(rest)
|
33
|
+
when 'organization'
|
34
|
+
@organization.remove_permission(rest)
|
35
|
+
when 'system'
|
36
|
+
@system.remove_permission(rest)
|
37
|
+
else
|
38
|
+
raise ArgumentError.new("Could not remove permission for level: #{level} of #{level}#{SEP}#{rest}")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
def serialize
|
42
|
+
Hash[:individual, @individual.serialize, :organization, @organization.serialize, :system, @system.serialize]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Rushiro
|
2
|
+
class Permission
|
3
|
+
attr_reader :parts, :original, :size
|
4
|
+
|
5
|
+
WildCard = :*
|
6
|
+
|
7
|
+
def initialize(permission)
|
8
|
+
raise ArgumentError.new("Invalid permission, empty string") if permission.empty?
|
9
|
+
@original = permission
|
10
|
+
@parts = permission.split(GSEP).map {|part| part.split(FSEP).map(&:to_sym)}
|
11
|
+
@size = @parts.size
|
12
|
+
end
|
13
|
+
|
14
|
+
def implied?(perm)
|
15
|
+
if perm.include?(FSEP)
|
16
|
+
msg = "Field separator: #{FSEP} used in input. Be specific, one of domain, action or instance per section."
|
17
|
+
raise ArgumentError.new(msg)
|
18
|
+
end
|
19
|
+
array = perm.split(GSEP).map(&:to_sym)
|
20
|
+
array.each_with_index do |part_sym, idx|
|
21
|
+
# If the permission has less parts than the permission being tested, everything after the number
|
22
|
+
# of parts contained in this permission is automatically implied, so return true
|
23
|
+
break if @size.pred < idx
|
24
|
+
return false if (@parts[idx] & [WildCard, part_sym]).empty?
|
25
|
+
end
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def ==(other)
|
30
|
+
return false unless @size == other.size
|
31
|
+
@parts.each_with_index do |part, idx|
|
32
|
+
return false unless (part - other.parts[idx]).empty?
|
33
|
+
end
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def serialize
|
38
|
+
@parts.map { |part| part.map(&:to_s).join(FSEP) }.join(GSEP)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Rushiro
|
2
|
+
class Permissions
|
3
|
+
attr_reader :permissions
|
4
|
+
def initialize(entries)
|
5
|
+
@permissions = entries.map do |permission|
|
6
|
+
Permission.new(permission)
|
7
|
+
end || []
|
8
|
+
end
|
9
|
+
|
10
|
+
def permitted?(perm)
|
11
|
+
return nil if @permissions.empty?
|
12
|
+
@permissions.any? { |permission| permission.implied?(perm) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_permission(perm)
|
16
|
+
to_add = Permission.new(perm)
|
17
|
+
return false if @permissions.any?{|_p| _p == to_add}
|
18
|
+
@permissions << to_add
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def remove_permission(perm)
|
23
|
+
!!@permissions.delete(Permission.new(perm))
|
24
|
+
end
|
25
|
+
|
26
|
+
def serialize
|
27
|
+
@permissions.map(&:serialize)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/readme.md
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
# Description
|
2
|
+
|
3
|
+
## Summary
|
4
|
+
|
5
|
+
Rushiro takes a source hash (of permissions definitions) and gives you an object that
|
6
|
+
you use to test for permitted access.
|
7
|
+
|
8
|
+
## Strategies
|
9
|
+
|
10
|
+
- Deny all allow some, use the AllowBasedControl class
|
11
|
+
- Allow all deny some, use the DenyBasedControl class
|
12
|
+
|
13
|
+
## Permissions
|
14
|
+
|
15
|
+
Manages explicit permissions. It lets you define 'allows' or 'denies' permissions.
|
16
|
+
You can define level based permissions i.e. individual, organization or
|
17
|
+
system. Organization or system levels are meant for short term overrides.
|
18
|
+
Set long term permissions at the individual level.
|
19
|
+
|
20
|
+
For more information on this check out [Apache Shiro permissions][shiro_p].
|
21
|
+
|
22
|
+
The permission part has three pipe separated sections, domain, action and instance:
|
23
|
+
|
24
|
+
- Domain - aka resources, e.g. webpages, db entities, domain models or services
|
25
|
+
- Action - these entries are from the set of actions available for the domain
|
26
|
+
- Instance - these entries are 'labels' you have given to instances of the domain,
|
27
|
+
e.g. a particular webpage, a uuid or unique id of a db record
|
28
|
+
Note: Multiple comma separated entries are allowed, as is the * wildcard
|
29
|
+
|
30
|
+
|
31
|
+
example: this hash is processed into a hierarchy of objects
|
32
|
+
``` ruby
|
33
|
+
perm = {
|
34
|
+
allows: {
|
35
|
+
individual: [
|
36
|
+
"feature|create,read,update|feat-x",
|
37
|
+
"page|*|posts",
|
38
|
+
"company|read"
|
39
|
+
"company|update|5b90a720-e6b0-012e-dc18-782bcb979e60"
|
40
|
+
],
|
41
|
+
organization: [],
|
42
|
+
system: []
|
43
|
+
},
|
44
|
+
denies: {}
|
45
|
+
}
|
46
|
+
|
47
|
+
access_control = AllowBasedControl.new(perm)
|
48
|
+
access_control.permitted?("company|read|5b90a720-e6b0-012e-dc18-782bcb979e60") ==> true
|
49
|
+
access_control.permitted?("feature|delete|feat-x") ==> false
|
50
|
+
```
|
51
|
+
|
52
|
+
Read the specs for more usage examples.
|
53
|
+
|
54
|
+
## Source Hash
|
55
|
+
|
56
|
+
Typically the source hash will be stored in a document database directly as a hash field
|
57
|
+
in the User record (see [Subject][shiro_s]). In most cases this would be the current_users db document.
|
58
|
+
|
59
|
+
## Authorization
|
60
|
+
|
61
|
+
The permitted?(permission) method is called to check authorization. The string you pass
|
62
|
+
in is obtained from metadata in your application. It should be specific, exact domain,
|
63
|
+
action and instance.
|
64
|
+
|
65
|
+
# Future
|
66
|
+
|
67
|
+
## Roles
|
68
|
+
|
69
|
+
A chaining mechanism is needed. References to other Rushiro control objects are assigned
|
70
|
+
to the current_user's Rushiro control and permission is tested through the chain.
|
71
|
+
|
72
|
+
## Mixed Mode
|
73
|
+
|
74
|
+
The jury is still out on whether it is practical to have a mixture of allows and denies.
|
75
|
+
|
76
|
+
# Development
|
77
|
+
|
78
|
+
* Source hosted at [GitHub][repo]
|
79
|
+
* Report issues/Questions/Feature requests on [GitHub Issues][issues]
|
80
|
+
|
81
|
+
Pull requests are very welcome! Make sure your patches are well tested.
|
82
|
+
Ideally create a topic branch for every separate change you make.
|
83
|
+
|
84
|
+
# License and Authors
|
85
|
+
|
86
|
+
Author:: Guy Boertje (<guyboertje@gmail.com>)
|
87
|
+
Author:: Lee Henson (<leemhenson@gmail.com>)
|
88
|
+
|
89
|
+
Contributors:: https://github.com/guyboertje/rushiro/contributors
|
90
|
+
|
91
|
+
Copyright (c) 2011, Guy Boertje
|
92
|
+
|
93
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
94
|
+
you may not use this file except in compliance with the License.
|
95
|
+
You may obtain a copy of the License at
|
96
|
+
|
97
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
98
|
+
|
99
|
+
Unless required by applicable law or agreed to in writing, software
|
100
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
101
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
102
|
+
See the License for the specific language governing permissions and
|
103
|
+
limitations under the License.
|
104
|
+
|
105
|
+
[repo]: https://github.com/guyboertje/rushiro
|
106
|
+
[issues]: https://github.com/guyboertje/rushiro/issues
|
107
|
+
[shiro_p]: http://shiro.apache.org/permissions.html
|
108
|
+
[shiro_s]: http://shiro.apache.org/subject.html
|
data/rushiro.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'rushiro'
|
3
|
+
s.version = '1.0.0'
|
4
|
+
s.date = '2011-11-03'
|
5
|
+
s.platform = Gem::Platform::RUBY
|
6
|
+
s.authors = ['Lee Henson', 'Guy Boertje']
|
7
|
+
s.email = ['lee.m.henson@gmail.com', 'guyboertje@gmail.com']
|
8
|
+
s.homepage = "http://github.com/guyboertje/rushiro"
|
9
|
+
s.summary = %q{Explicit permissions inspired by Apache Shiro}
|
10
|
+
s.description = %q{}
|
11
|
+
|
12
|
+
# = MANIFEST =
|
13
|
+
s.files = %w[
|
14
|
+
Gemfile
|
15
|
+
Rakefile
|
16
|
+
lib/rushiro.rb
|
17
|
+
lib/rushiro/access_control_hash.rb
|
18
|
+
lib/rushiro/access_levels.rb
|
19
|
+
lib/rushiro/allow_based_control.rb
|
20
|
+
lib/rushiro/deny_based_control.rb
|
21
|
+
lib/rushiro/permission.rb
|
22
|
+
lib/rushiro/permissions.rb
|
23
|
+
lib/rushiro/version.rb
|
24
|
+
readme.md
|
25
|
+
rushiro.gemspec
|
26
|
+
spec/access_control_spec.rb
|
27
|
+
spec/spec_helper.rb
|
28
|
+
]
|
29
|
+
# = MANIFEST =
|
30
|
+
|
31
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
32
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
33
|
+
|
34
|
+
s.add_development_dependency 'awesome_print', '~> 0.4.0'
|
35
|
+
s.add_development_dependency 'fuubar', '~> 0.0.0'
|
36
|
+
s.add_development_dependency 'rspec', '~> 2.6.0'
|
37
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Rushiro
|
4
|
+
describe "Allow all deny some Access Control" do
|
5
|
+
let(:access_control) { DenyBasedControl.new(acl)}
|
6
|
+
describe "with no set permissions" do
|
7
|
+
let(:acl) { Hash.new }
|
8
|
+
it "should deny all" do
|
9
|
+
access_control.permitted?("page|view|posts").should be_true
|
10
|
+
access_control.serialize.should == {}
|
11
|
+
access_control.dirty.should be_false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "when adding a denies permission" do
|
16
|
+
let(:acl) { Hash.new }
|
17
|
+
it "should add the permission" do
|
18
|
+
access_control.add_permission("denies|individual|company|edit|acme-123")
|
19
|
+
access_control.dirty.should be_true
|
20
|
+
access_control.serialize.should_not == {}
|
21
|
+
access_control.permitted?("page|view|posts").should be_true
|
22
|
+
access_control.permitted?("company|view|acme-125").should be_true
|
23
|
+
access_control.permitted?("company|edit|acme-123").should be_false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "when removing a denies permission" do
|
28
|
+
let(:acl) { Hash.new }
|
29
|
+
it "should remove the permission" do
|
30
|
+
access_control.add_permission("denies|individual|company|edit|acme-123")
|
31
|
+
access_control.add_permission("denies|organization|page|edit")
|
32
|
+
access_control.permitted?("page|view|settings").should be_true
|
33
|
+
access_control.permitted?("page|edit|settings").should be_false
|
34
|
+
access_control.permitted?("company|edit|acme-123").should be_false
|
35
|
+
access_control.remove_permission("denies|organization|page|edit")
|
36
|
+
access_control.permitted?("page|view|settings").should be_true
|
37
|
+
access_control.permitted?("page|edit|settings").should be_true
|
38
|
+
access_control.permitted?("company|edit|acme-123").should be_false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "Deny all allow some Access Control" do
|
44
|
+
let(:access_control) { AllowBasedControl.new(acl)}
|
45
|
+
describe "with no set permissions" do
|
46
|
+
let(:acl) { Hash.new }
|
47
|
+
it "should deny all" do
|
48
|
+
access_control.permitted?("page|view|posts").should be_false
|
49
|
+
access_control.serialize.should == {}
|
50
|
+
access_control.dirty.should be_false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "when adding an allows permission" do
|
55
|
+
let(:acl) { Hash.new }
|
56
|
+
it "should add the permission" do
|
57
|
+
access_control.add_permission("allows|individual|page")
|
58
|
+
access_control.permitted?("page|view|posts").should be_true
|
59
|
+
access_control.permitted?("company|edit|acme-123").should be_false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rushiro
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Lee Henson
|
9
|
+
- Guy Boertje
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2011-11-03 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: awesome_print
|
17
|
+
requirement: &9402520 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.4.0
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *9402520
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: fuubar
|
28
|
+
requirement: &9401920 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.0.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *9401920
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rspec
|
39
|
+
requirement: &9401440 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 2.6.0
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *9401440
|
48
|
+
description: ''
|
49
|
+
email:
|
50
|
+
- lee.m.henson@gmail.com
|
51
|
+
- guyboertje@gmail.com
|
52
|
+
executables: []
|
53
|
+
extensions: []
|
54
|
+
extra_rdoc_files: []
|
55
|
+
files:
|
56
|
+
- Gemfile
|
57
|
+
- Rakefile
|
58
|
+
- lib/rushiro.rb
|
59
|
+
- lib/rushiro/access_control_hash.rb
|
60
|
+
- lib/rushiro/access_levels.rb
|
61
|
+
- lib/rushiro/allow_based_control.rb
|
62
|
+
- lib/rushiro/deny_based_control.rb
|
63
|
+
- lib/rushiro/permission.rb
|
64
|
+
- lib/rushiro/permissions.rb
|
65
|
+
- lib/rushiro/version.rb
|
66
|
+
- readme.md
|
67
|
+
- rushiro.gemspec
|
68
|
+
- spec/access_control_spec.rb
|
69
|
+
- spec/spec_helper.rb
|
70
|
+
homepage: http://github.com/guyboertje/rushiro
|
71
|
+
licenses: []
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 1.8.10
|
91
|
+
signing_key:
|
92
|
+
specification_version: 3
|
93
|
+
summary: Explicit permissions inspired by Apache Shiro
|
94
|
+
test_files: []
|