aclatraz 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|