aclatraz 0.1.0 → 0.1.1
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/CHANGELOG.rdoc +6 -0
- data/README.rdoc +51 -45
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/aclatraz.gemspec +6 -2
- data/lib/aclatraz/helpers.rb +6 -16
- data/lib/aclatraz/store.rb +1 -0
- data/lib/aclatraz/store/redis.rb +46 -15
- data/lib/aclatraz/store/riak.rb +83 -0
- data/spec/aclatraz/helpers_spec.rb +0 -10
- data/spec/aclatraz/stores_spec.rb +15 -5
- metadata +22 -6
data/CHANGELOG.rdoc
CHANGED
data/README.rdoc
CHANGED
@@ -26,7 +26,7 @@ Suspects are objects which we can assign specific permissions. There is only
|
|
26
26
|
one condition which object have to meet to be suspect - it must have the #id
|
27
27
|
method which returns an unique identifier after which we will be able to
|
28
28
|
reference this object. To enable suspect behaviour you have to include the
|
29
|
-
|
29
|
+
<tt>Aclatraz::Suspect</tt> module to specified class, eg:
|
30
30
|
|
31
31
|
class Account < ActiveRecord::Base
|
32
32
|
include Aclatraz::Suspect
|
@@ -38,24 +38,22 @@ Now your suspect have few methods which will helps you manage it permissions.
|
|
38
38
|
|
39
39
|
ACLatraz distinguishes between three types of roles:
|
40
40
|
|
41
|
-
*global
|
42
|
-
|
43
|
-
|
44
|
-
*class-related
|
45
|
-
|
46
|
-
|
47
|
-
*
|
48
|
-
roles that affects management of an object. For example *author* of
|
49
|
-
_specified page_, *owner* of _specified product_, etc.
|
41
|
+
* <b>global:</b> simple roles, which are most commonly assigned to many users.
|
42
|
+
We can say that they are kind of groups. Global roles are eg. _guest_, _admin_,
|
43
|
+
_customer_.
|
44
|
+
* <b>class-related:</b> roles that affects management of a particular class.
|
45
|
+
Example of this kind of role can be *manager* of +Pages+, *admin* of +Products+, etc.
|
46
|
+
* <b>object-related:</b> roles that affects management of an object. For example
|
47
|
+
*author* of <em>specified page</em>, *owner* of <em>specified product</em>, etc.
|
50
48
|
|
51
|
-
Now there is two ways for managing roles. You can use
|
52
|
-
look like
|
49
|
+
Now there is two ways for managing roles. You can use <tt>#roles</tt> or semanticaly
|
50
|
+
look like <tt>#is</tt> and <tt>#is_not</tt> proxies.
|
53
51
|
|
54
52
|
==== Assigning
|
55
53
|
|
56
|
-
To add given role you can use
|
57
|
-
semantic shortcuts. Semantic shortcut have to ends with
|
58
|
-
optional suffixes: <em>_on</em>, <em>_of</em>, <em>_at</em>, <em>_for</em>,
|
54
|
+
To add given role you can use <tt>#assign</tt> method from <tt>#roles</tt> proxy
|
55
|
+
or use semantic shortcuts. Semantic shortcut have to ends with <b>"!"</b>, and
|
56
|
+
can have optional suffixes: <em>_on</em>, <em>_of</em>, <em>_at</em>, <em>_for</em>,
|
59
57
|
<em>_in</em>, <em>_by</em>. Take a look at the following examples to get
|
60
58
|
everything to be clear:
|
61
59
|
|
@@ -67,51 +65,58 @@ everything to be clear:
|
|
67
65
|
@account.roles.assign(:responsible, Foo) # or...
|
68
66
|
@account.is.responsible_for!(Foo)
|
69
67
|
|
70
|
-
...will assign to the account _responsible_ role related with Foo class.
|
68
|
+
...will assign to the account _responsible_ role related with +Foo+ class.
|
71
69
|
|
72
70
|
@account.roles.assign(:author, Page.find(15)) # or...
|
73
71
|
@account.is.author_of!(Page.find(15))
|
74
72
|
|
75
|
-
...will assign to the account _author_ role related with given
|
73
|
+
...will assign to the account _author_ role related with given +Page+ object.
|
76
74
|
|
77
75
|
==== Checking
|
78
76
|
|
79
|
-
Using #roles proxy you can call
|
77
|
+
Using #roles proxy you can call <tt>#has?</t> method on it, eg:
|
80
78
|
|
81
79
|
@account.roles.has?(:admin) # => true
|
82
80
|
@account.roles.has?(:responsible, Foo) # => true
|
83
81
|
@account.roles.has?(:author, Page.find(15) # => true
|
84
82
|
|
85
|
-
With semantic shortcuts your method name have to ends with
|
83
|
+
With semantic shortcuts your method name have to ends with <b>"?"</b> and can contain
|
86
84
|
any of suffixes listed above, eg:
|
87
85
|
|
88
|
-
@account.is.admin?
|
89
|
-
@account.is.responsible_for?(Foo)
|
90
|
-
@account.is.author_of(Page.find(15)) # => true
|
86
|
+
@account.is.admin? # => true
|
87
|
+
@account.is.responsible_for?(Foo) # => true
|
88
|
+
@account.is.author_of?(Page.find(15)) # => true
|
91
89
|
|
92
90
|
Few more examples with semantic negation:
|
93
91
|
|
94
|
-
@account.is_not.admin?
|
95
|
-
@account.is_not.responsible_for(Foo) # => false
|
92
|
+
@account.is_not.admin? # => false
|
93
|
+
@account.is_not.responsible_for?(Foo) # => false
|
94
|
+
|
95
|
+
You can also check permissions using nice block-style syntax. The code inside
|
96
|
+
the block will be executed only when object has given role. An quick example:
|
97
|
+
|
98
|
+
@account.is.admin? do
|
99
|
+
# only admins can se this...
|
100
|
+
end
|
96
101
|
|
97
102
|
==== Deleting
|
98
103
|
|
99
|
-
To unassign given role from object use
|
104
|
+
To unassign given role from object use <tt>#delete</tt> method from <tt>#roles</tt>, eg:
|
100
105
|
|
101
106
|
@account.roles.delete(:admin)
|
102
107
|
@account.roles.delete(:responsible, Foo)
|
103
108
|
|
104
|
-
Another way is to use semantic negation, where method name have to ends with
|
109
|
+
Another way is to use semantic negation, where method name have to ends with <b>"!"</b>
|
105
110
|
and can contain one of allowed suffixes, eg:
|
106
111
|
|
107
112
|
@account.is_not.admin!
|
108
|
-
@account.is_not.author_of(Page.find(15))
|
113
|
+
@account.is_not.author_of!(Page.find(15))
|
109
114
|
|
110
115
|
== Guards
|
111
116
|
|
112
117
|
To enable access control in your for your objects you have to include to it the
|
113
|
-
|
114
|
-
permissions of an suspected object. Take a look for this basic example:
|
118
|
+
<tt>Aclatraz::Guard</tt> module. This module provides methods for defining and
|
119
|
+
checking permissions of an suspected object. Take a look for this basic example:
|
115
120
|
|
116
121
|
class Foo
|
117
122
|
include Aclatraz::Guard
|
@@ -122,23 +127,23 @@ permissions of an suspected object. Take a look for this basic example:
|
|
122
127
|
end
|
123
128
|
end
|
124
129
|
|
125
|
-
The
|
126
|
-
symbol given, like in example above, then will treat
|
127
|
-
result as suspected object. When you will use string, eg:
|
130
|
+
The <tt>#suspects</tt> block is passing one argument - suspected object. When
|
131
|
+
there is symbol given, like in example above, then will treat <tt>#account</tt>
|
132
|
+
instance method result as suspected object. When you will use string, eg:
|
128
133
|
|
129
134
|
suspects "account" do # or suspects "@account" do ...
|
130
135
|
|
131
|
-
... it will treat
|
132
|
-
suspected object directly, eg:
|
136
|
+
... it will treat <tt>@account</tt> instance variable as suspect. You can also
|
137
|
+
specify suspected object directly, eg:
|
133
138
|
|
134
139
|
account = Account.find(1)
|
135
140
|
suspects account do # ...
|
136
141
|
|
137
|
-
===
|
142
|
+
=== Setting up permissions
|
138
143
|
|
139
144
|
As you probably noticed, there is two methods responsible for access control,
|
140
|
-
namely
|
141
|
-
or permission statement, eg:
|
145
|
+
namely <tt>#allow</tt> and <tt>#deny</tt>. As its argument you can pass simple
|
146
|
+
name of role or permission statement, eg:
|
142
147
|
|
143
148
|
allow :admin
|
144
149
|
deny :guest
|
@@ -146,8 +151,8 @@ or permission statement, eg:
|
|
146
151
|
allow :author_of => "@page"
|
147
152
|
|
148
153
|
Like you see, you can easy specify access for each kind of role. The object-related
|
149
|
-
permissions behaviour is similar to
|
150
|
-
is string then applies permissions for an instance variable, when symbol then
|
154
|
+
permissions behaviour is similar to <tt>#suspects</tt> method. When given related
|
155
|
+
object is string then applies permissions for an instance variable, when symbol then
|
151
156
|
applies it for instance method, otherwise directly for given object.
|
152
157
|
|
153
158
|
=== Actions
|
@@ -172,9 +177,10 @@ Obviously all actions inherits all permissions from main block.
|
|
172
177
|
|
173
178
|
=== Authorizing
|
174
179
|
|
175
|
-
The
|
176
|
-
When suspected object don't have any of allowed permissions or have
|
177
|
-
then it will raise the
|
180
|
+
The <tt>Aclatraz::Guards</tt> module provides <tt>#guard!</tt> method for checking
|
181
|
+
permissions. When suspected object don't have any of allowed permissions or have
|
182
|
+
any of defnied then it will raise the <tt>Aclatraz::AccessDenied</tt> error.
|
183
|
+
Here's an comprehensive example:
|
178
184
|
|
179
185
|
class Foo
|
180
186
|
suspects "@account" do
|
@@ -215,7 +221,7 @@ then it will raise the +Aclatraz::AccessDenied+ error. Here's an comprehensive e
|
|
215
221
|
end
|
216
222
|
|
217
223
|
There is also a very nice feature. You can define additional permissions directly
|
218
|
-
in
|
224
|
+
in <tt>#guard!</tt> block, eg:
|
219
225
|
|
220
226
|
def foo
|
221
227
|
guard! do
|
@@ -253,8 +259,8 @@ in each child class you can freely modify permissions. Here's an example:
|
|
253
259
|
|
254
260
|
=== Aliases
|
255
261
|
|
256
|
-
If you prefer you can use aliases:
|
257
|
-
|
262
|
+
If you prefer you can use aliases: <tt>#access_control</tt> instead of
|
263
|
+
<tt>#suspects</tt> and <tt>#authorize!</tt> instead of <tt>#guard!</tt>.
|
258
264
|
|
259
265
|
== Note on Patches/Pull Requests
|
260
266
|
|
data/Rakefile
CHANGED
@@ -16,6 +16,7 @@ begin
|
|
16
16
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
17
17
|
gem.add_development_dependency "mocha", ">= 0.9"
|
18
18
|
gem.add_development_dependency "redis", "~> 2.0"
|
19
|
+
gem.add_development_dependency "riak-client", "~> 0.8"
|
19
20
|
gem.add_dependency "dictionary", "~> 1.0"
|
20
21
|
end
|
21
22
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
data/aclatraz.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{aclatraz}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Kriss 'nu7hatch' Kowalik"]
|
12
|
-
s.date = %q{2010-09-
|
12
|
+
s.date = %q{2010-09-17}
|
13
13
|
s.description = %q{ Extremaly fast and flexible access control mechanism inspired by *nix ACLs,
|
14
14
|
powered by fast key value stores like Redis or TokyoCabinet.
|
15
15
|
}
|
@@ -35,6 +35,7 @@ Gem::Specification.new do |s|
|
|
35
35
|
"lib/aclatraz/helpers.rb",
|
36
36
|
"lib/aclatraz/store.rb",
|
37
37
|
"lib/aclatraz/store/redis.rb",
|
38
|
+
"lib/aclatraz/store/riak.rb",
|
38
39
|
"lib/aclatraz/suspect.rb",
|
39
40
|
"spec/aclatraz/acl_spec.rb",
|
40
41
|
"spec/aclatraz/guard_spec.rb",
|
@@ -71,17 +72,20 @@ Gem::Specification.new do |s|
|
|
71
72
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
72
73
|
s.add_development_dependency(%q<mocha>, [">= 0.9"])
|
73
74
|
s.add_development_dependency(%q<redis>, ["~> 2.0"])
|
75
|
+
s.add_development_dependency(%q<riak-client>, ["~> 0.8"])
|
74
76
|
s.add_runtime_dependency(%q<dictionary>, ["~> 1.0"])
|
75
77
|
else
|
76
78
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
77
79
|
s.add_dependency(%q<mocha>, [">= 0.9"])
|
78
80
|
s.add_dependency(%q<redis>, ["~> 2.0"])
|
81
|
+
s.add_dependency(%q<riak-client>, ["~> 0.8"])
|
79
82
|
s.add_dependency(%q<dictionary>, ["~> 1.0"])
|
80
83
|
end
|
81
84
|
else
|
82
85
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
83
86
|
s.add_dependency(%q<mocha>, [">= 0.9"])
|
84
87
|
s.add_dependency(%q<redis>, ["~> 2.0"])
|
88
|
+
s.add_dependency(%q<riak-client>, ["~> 0.8"])
|
85
89
|
s.add_dependency(%q<dictionary>, ["~> 1.0"])
|
86
90
|
end
|
87
91
|
end
|
data/lib/aclatraz/helpers.rb
CHANGED
@@ -1,26 +1,16 @@
|
|
1
1
|
module Aclatraz
|
2
2
|
module Helpers
|
3
|
-
# Pack given permission data.
|
4
|
-
#
|
5
|
-
# pack(10) # => "10"
|
6
|
-
# pack(10, "FooClass") # => "10/FooClass"
|
7
|
-
# pack(10, FooClass.new) # => "10/FooClass/{foo_object_ID}"
|
8
|
-
def pack(owner, object=nil)
|
9
|
-
case object
|
10
|
-
when nil
|
11
|
-
"#{owner}"
|
12
|
-
when Class
|
13
|
-
"#{owner}/#{object.name}"
|
14
|
-
else
|
15
|
-
"#{owner}/#{object.class.name}/#{object.id}"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
3
|
# Given underscored word, returns camelized version of it.
|
20
4
|
#
|
21
5
|
# camelize(foo_bar_bla) # => "FooBarBla"
|
22
6
|
def camelize(str)
|
23
7
|
str.split('_').map {|w| w.capitalize}.join
|
24
8
|
end
|
9
|
+
|
10
|
+
# If given object is kind of string or integer then returns it, otherwise
|
11
|
+
# it tries to return its ID.
|
12
|
+
def member_id(member)
|
13
|
+
member.is_a?(String) || member.is_a?(Integer) ? member.to_s : member.id.to_s
|
14
|
+
end
|
25
15
|
end # Helpers
|
26
16
|
end # Aclatraz
|
data/lib/aclatraz/store.rb
CHANGED
data/lib/aclatraz/store/redis.rb
CHANGED
@@ -6,47 +6,78 @@ end
|
|
6
6
|
|
7
7
|
module Aclatraz
|
8
8
|
module Store
|
9
|
+
# List of global roles are stored in ROLES set. Each member has its
|
10
|
+
# own key, which contains list of assigned roles. Roles are stored in
|
11
|
+
# following format:
|
12
|
+
#
|
13
|
+
# member.{:member_id}.roles:
|
14
|
+
# "role_name"
|
15
|
+
# "role_name/ClassName"
|
16
|
+
# "role_name/ObjectClass/object_id"
|
9
17
|
class Redis
|
10
18
|
include Aclatraz::Helpers
|
11
19
|
|
12
|
-
|
13
|
-
|
20
|
+
ROLES = "roles"
|
21
|
+
MEMBER_ROLES = "member.%s.roles"
|
14
22
|
|
15
23
|
def initialize(*args) # :nodoc:
|
16
24
|
@backend = ::Redis.new(*args)
|
17
25
|
end
|
18
26
|
|
19
|
-
def set(role,
|
27
|
+
def set(role, member, object=nil)
|
20
28
|
@backend.multi do
|
21
|
-
unless object
|
22
|
-
|
23
|
-
@backend.hset(MEMBER_ROLES_KEY % owner.id.to_s, role, 1)
|
24
|
-
end
|
25
|
-
@backend.sadd(role.to_s, pack(owner.id, object))
|
29
|
+
@backend.sadd(ROLES, role.to_s) unless object
|
30
|
+
@backend.sadd(MEMBER_ROLES % member_id(member), pack(role.to_s, object))
|
26
31
|
end
|
27
32
|
end
|
28
33
|
|
29
34
|
def roles(member=nil)
|
30
35
|
if member
|
31
|
-
@backend.
|
36
|
+
@backend.smembers(MEMBER_ROLES % member_id(member)).map {|role|
|
37
|
+
role = unpack(role)
|
38
|
+
role[0] if role.size == 1
|
39
|
+
}.compact.uniq
|
32
40
|
else
|
33
|
-
@backend.
|
41
|
+
@backend.smembers(ROLES)
|
34
42
|
end
|
35
43
|
end
|
36
44
|
|
37
|
-
def check(role,
|
38
|
-
@backend.sismember(
|
39
|
-
object && !object.is_a?(Class) ? check(role,
|
45
|
+
def check(role, member, object=nil)
|
46
|
+
@backend.sismember(MEMBER_ROLES % member_id(member), pack(role.to_s, object)) or begin
|
47
|
+
object && !object.is_a?(Class) ? check(role, member, object.class) : false
|
40
48
|
end
|
41
49
|
end
|
42
50
|
|
43
|
-
def delete(role,
|
44
|
-
@backend.srem(
|
51
|
+
def delete(role, member, object=nil)
|
52
|
+
@backend.srem(MEMBER_ROLES % member_id(member), pack(role.to_s, object))
|
45
53
|
end
|
46
54
|
|
47
55
|
def clear
|
48
56
|
@backend.flushdb
|
49
57
|
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# Pack given permission data.
|
62
|
+
#
|
63
|
+
# pack(foo) # => "foo"
|
64
|
+
# pack(foo, "FooClass") # => "foo/FooClass"
|
65
|
+
# pack(foo, FooClass.new) # => "foo/FooClass/{foo_object_ID}"
|
66
|
+
def pack(role, object=nil)
|
67
|
+
case object
|
68
|
+
when nil
|
69
|
+
"#{role}"
|
70
|
+
when Class
|
71
|
+
"#{role}/#{object.name}"
|
72
|
+
else
|
73
|
+
"#{role}/#{object.class.name}/#{object.id}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Unpack given permission data.
|
78
|
+
def unpack(data)
|
79
|
+
data.to_s.split("/")
|
80
|
+
end
|
50
81
|
end # Redis
|
51
82
|
end # Store
|
52
83
|
end # Aclatraz
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "riak"
|
5
|
+
rescue LoadError
|
6
|
+
raise "You must install the redis-client gem to use the Riak store"
|
7
|
+
end
|
8
|
+
|
9
|
+
module Aclatraz
|
10
|
+
module Store
|
11
|
+
# The most optimal way to store roles in riak database is pack everything
|
12
|
+
# in a single key name, eg:
|
13
|
+
#
|
14
|
+
# :suspect_id/:role_name
|
15
|
+
# :suspect_id/:role_name/:ClassName
|
16
|
+
# :suspect_id/:role_name/:ObjectClass/object_id
|
17
|
+
class Riak
|
18
|
+
include Aclatraz::Helpers
|
19
|
+
|
20
|
+
def initialize(bucket_name, *args) # :nodoc:
|
21
|
+
@backend = ::Riak::Client.new(*args).bucket(bucket_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def set(role, member, object=nil)
|
25
|
+
obj = @backend.new(pack(role.to_s, member_id(member), object))
|
26
|
+
obj.content_type = "text/plain"
|
27
|
+
obj.data = "1"
|
28
|
+
obj.store
|
29
|
+
end
|
30
|
+
|
31
|
+
def roles(member=nil)
|
32
|
+
roles = []
|
33
|
+
# Also this can be a little bit slow...
|
34
|
+
@backend.keys.each do |key|
|
35
|
+
@backend.exists?(key) ? perm = unpack(key) : next
|
36
|
+
if perm.size == 2 && (!member || (member && perm[0].to_s == member_id(member)))
|
37
|
+
roles.push(perm[1])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
roles.compact.uniq
|
41
|
+
end
|
42
|
+
|
43
|
+
def check(role, member, object=nil)
|
44
|
+
@backend.exists?(pack(role.to_s, member_id(member), object)) or begin
|
45
|
+
object && !object.is_a?(Class) ? check(role, member, object.class) : false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete(role, member, object=nil)
|
50
|
+
@backend.delete(pack(role.to_s, member_id(member), object))
|
51
|
+
end
|
52
|
+
|
53
|
+
def clear
|
54
|
+
# not optimal... yea but there is no other way to clear all keys
|
55
|
+
# in the riak bucket -_-"
|
56
|
+
@backend.keys.each {|key| @backend.delete(key) }
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# Pack given permission data.
|
62
|
+
#
|
63
|
+
# pack("foo", 10) # => "10/foo"
|
64
|
+
# pack("foo", 10, "FooClass") # => "10/foo/FooClass"
|
65
|
+
# pack("foo", 10, FooClass.new) # => "10/foo/FooClass/{foo_object_ID}"
|
66
|
+
def pack(role, member, object=nil)
|
67
|
+
case object
|
68
|
+
when nil
|
69
|
+
"#{member}/#{role}"
|
70
|
+
when Class
|
71
|
+
"#{member}/#{role}/#{object.name}"
|
72
|
+
else
|
73
|
+
"#{member}/#{role}/#{object.class.name}/#{object.id}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Unpack given permission data.
|
78
|
+
def unpack(data)
|
79
|
+
data.to_s.split("/")
|
80
|
+
end
|
81
|
+
end # Riak
|
82
|
+
end # Store
|
83
|
+
end # Aclatraz
|
@@ -7,14 +7,4 @@ describe "Aclatraz helpers" do
|
|
7
7
|
camelize("foo_bar_bla").should == "FooBarBla"
|
8
8
|
camelize("foo").should == "Foo"
|
9
9
|
end
|
10
|
-
|
11
|
-
it "#pack should return packed permission" do
|
12
|
-
pack(10).should == "10"
|
13
|
-
|
14
|
-
class StubTarget; def id; 10; end; end
|
15
|
-
pack(10, StubTarget).should == "10/StubTarget"
|
16
|
-
|
17
|
-
target = StubTarget.new
|
18
|
-
pack(20, target).should == "20/StubTarget/10"
|
19
|
-
end
|
20
10
|
end
|
@@ -2,6 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
STORE_SPECS = proc do
|
4
4
|
it "should properly assign given roles to owner and check permissions" do
|
5
|
+
subject.clear
|
5
6
|
subject.set("foo", owner)
|
6
7
|
subject.check("foo", owner).should be_true
|
7
8
|
|
@@ -17,13 +18,14 @@ STORE_SPECS = proc do
|
|
17
18
|
end
|
18
19
|
|
19
20
|
it "should properly delete given permission" do
|
21
|
+
subject.clear
|
20
22
|
subject.set("foo", owner)
|
21
23
|
subject.set("bar", owner, StubTarget)
|
22
24
|
subject.set("bla", owner, target)
|
23
25
|
|
24
|
-
subject.delete("
|
26
|
+
subject.delete("foo", owner)
|
25
27
|
subject.delete("bar", owner, StubTarget)
|
26
|
-
subject.delete("
|
28
|
+
subject.delete("bla", owner, target)
|
27
29
|
|
28
30
|
subject.check("bar", owner).should be_false
|
29
31
|
subject.check("bar", owner, StubTarget).should be_false
|
@@ -35,6 +37,7 @@ STORE_SPECS = proc do
|
|
35
37
|
subject.set("bar", owner)
|
36
38
|
subject.set("bla", owner)
|
37
39
|
|
40
|
+
subject.roles.should_not be_empty
|
38
41
|
(subject.roles - ["foo", "bar", "bla"]).should be_empty
|
39
42
|
end
|
40
43
|
|
@@ -43,8 +46,8 @@ STORE_SPECS = proc do
|
|
43
46
|
subject.set("bar", owner)
|
44
47
|
subject.set("bla", owner)
|
45
48
|
|
46
|
-
|
47
|
-
subject.roles(
|
49
|
+
subject.roles(owner).should_not be_empty
|
50
|
+
(subject.roles(owner) - ["foo", "bar", "bla"]).should be_empty
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
@@ -56,7 +59,14 @@ describe "Aclatraz" do
|
|
56
59
|
before(:all) { @redis = Thread.new { `redis-server` } }
|
57
60
|
after(:all) { @redis.exit! }
|
58
61
|
subject { Aclatraz.init(:redis, "redis://localhost:6379/0") }
|
59
|
-
|
62
|
+
|
63
|
+
class_eval &STORE_SPECS
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "Riak store" do
|
67
|
+
before(:all) { @riak = Thread.new { `riak start` } }
|
68
|
+
after(:all) { @riak.exit! }
|
69
|
+
subject { Aclatraz.init(:riak, "roles") }
|
60
70
|
|
61
71
|
class_eval &STORE_SPECS
|
62
72
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aclatraz
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kriss 'nu7hatch' Kowalik
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-09-
|
18
|
+
date: 2010-09-17 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -65,9 +65,24 @@ dependencies:
|
|
65
65
|
type: :development
|
66
66
|
version_requirements: *id003
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
|
-
name:
|
68
|
+
name: riak-client
|
69
69
|
prerelease: false
|
70
70
|
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 27
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
- 8
|
79
|
+
version: "0.8"
|
80
|
+
type: :development
|
81
|
+
version_requirements: *id004
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: dictionary
|
84
|
+
prerelease: false
|
85
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
71
86
|
none: false
|
72
87
|
requirements:
|
73
88
|
- - ~>
|
@@ -78,7 +93,7 @@ dependencies:
|
|
78
93
|
- 0
|
79
94
|
version: "1.0"
|
80
95
|
type: :runtime
|
81
|
-
version_requirements: *
|
96
|
+
version_requirements: *id005
|
82
97
|
description: " Extremaly fast and flexible access control mechanism inspired by *nix ACLs, \n powered by fast key value stores like Redis or TokyoCabinet.\n"
|
83
98
|
email: kriss.kowalik@gmail.com
|
84
99
|
executables: []
|
@@ -105,6 +120,7 @@ files:
|
|
105
120
|
- lib/aclatraz/helpers.rb
|
106
121
|
- lib/aclatraz/store.rb
|
107
122
|
- lib/aclatraz/store/redis.rb
|
123
|
+
- lib/aclatraz/store/riak.rb
|
108
124
|
- lib/aclatraz/suspect.rb
|
109
125
|
- spec/aclatraz/acl_spec.rb
|
110
126
|
- spec/aclatraz/guard_spec.rb
|