credentials 2.0.0 → 2.1.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/.gitignore +1 -0
- data/{History.txt → HISTORY} +12 -0
- data/README.rdoc +2 -9
- data/VERSION +1 -1
- data/credentials.gemspec +4 -3
- data/lib/credentials/object_extensions.rb +54 -2
- data/lib/credentials/rule.rb +45 -1
- data/lib/credentials/rulebook.rb +125 -0
- data/spec/credentials_spec.rb +31 -0
- data/spec/domain.rb +4 -2
- data/spec/rule_spec.rb +8 -0
- data/spec/rulebook_spec.rb +4 -2
- data/spec/spec_helper.rb +1 -0
- data/tasks/rdoc.rake +17 -0
- metadata +4 -3
data/.gitignore
CHANGED
data/{History.txt → HISTORY}
RENAMED
@@ -1,3 +1,15 @@
|
|
1
|
+
=== 2.1.0 / 2009-11-12
|
2
|
+
|
3
|
+
* Added support for :self
|
4
|
+
* Added array arguments to +can+ and +cannot+
|
5
|
+
* Put in masses of RDoc
|
6
|
+
* Added magic method support back in
|
7
|
+
|
8
|
+
=== 2.0.0 / 2009-11-11
|
9
|
+
|
10
|
+
* Rewritten from first principles! Faster, smarter, leaner and with more
|
11
|
+
features than you can shake a very light stick at.
|
12
|
+
|
1
13
|
=== 1.0.1 / 2009-04-23
|
2
14
|
|
3
15
|
* Now sort of framework-agnostic. I say "sort of", because what I've actually
|
data/README.rdoc
CHANGED
@@ -8,7 +8,7 @@ A generic actor/resource permission framework.
|
|
8
8
|
|
9
9
|
== Installation
|
10
10
|
|
11
|
-
* <tt>sudo gem install
|
11
|
+
* <tt>sudo gem install credentials</tt>
|
12
12
|
|
13
13
|
== Examples
|
14
14
|
|
@@ -29,9 +29,6 @@ A generic actor/resource permission framework.
|
|
29
29
|
b.can_edit?(b) #=> true
|
30
30
|
b.can_edit?(a) #=> true
|
31
31
|
|
32
|
-
Check out the example application (in +spec/test_app+) for more (completely
|
33
|
-
frivolous) examples.
|
34
|
-
|
35
32
|
== Philosophy
|
36
33
|
|
37
34
|
Credentials is NOT a role-based permission system. Permissions are based
|
@@ -85,12 +82,8 @@ and turned into a nice pretty error page.
|
|
85
82
|
|
86
83
|
== To do
|
87
84
|
|
88
|
-
*
|
89
|
-
of testing the functionality of the library, but I'd like to rewrite
|
90
|
-
it into a proper test suite.
|
91
|
-
* Proper documentation of the API. It's been a while since I touched this.
|
85
|
+
* Proper documentation of the API.
|
92
86
|
* Better support for groups would make integration with RBA systems easier.
|
93
|
-
* Deny permissions (+cannot+).
|
94
87
|
|
95
88
|
== License
|
96
89
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.1.0
|
data/credentials.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{credentials}
|
8
|
-
s.version = "2.
|
8
|
+
s.version = "2.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Matt Powell"]
|
12
|
-
s.date = %q{2009-11-
|
12
|
+
s.date = %q{2009-11-12}
|
13
13
|
s.description = %q{A generic actor/resource permission framework based on rules, not objects.}
|
14
14
|
s.email = %q{fauxparse@gmail.com.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".gitignore",
|
21
|
-
"
|
21
|
+
"HISTORY",
|
22
22
|
"LICENSE",
|
23
23
|
"README.rdoc",
|
24
24
|
"Rakefile",
|
@@ -39,6 +39,7 @@ Gem::Specification.new do |s|
|
|
39
39
|
"spec/rulebook_spec.rb",
|
40
40
|
"spec/spec_helper.rb",
|
41
41
|
"tasks/gems.rake",
|
42
|
+
"tasks/rdoc.rake",
|
42
43
|
"tasks/spec.rake",
|
43
44
|
"tasks/stats.rake",
|
44
45
|
"uninstall.rb"
|
@@ -1,6 +1,35 @@
|
|
1
1
|
module Credentials
|
2
|
-
module ObjectExtensions #:nodoc
|
2
|
+
module ObjectExtensions #:nodoc:
|
3
3
|
module ClassMethods
|
4
|
+
# The main method for specifying and retrieving the permissions of
|
5
|
+
# a member of this class.
|
6
|
+
#
|
7
|
+
# When called with a block, this method yields a Credentials::Rulebook
|
8
|
+
# object, allowing you to specify the class's credentials
|
9
|
+
# in a declarative fashion. For example:
|
10
|
+
#
|
11
|
+
# class User
|
12
|
+
# credentials do |user|
|
13
|
+
# user.can :edit, User, :if => :administrator?
|
14
|
+
# user.can :edit, :self
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# You can also specify options in this way:
|
19
|
+
#
|
20
|
+
# class User
|
21
|
+
# credentials(:default => :allow) do |user|
|
22
|
+
# user.cannot :eat, "ice cream", :if => :lactose_intolerant?
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# The following options are supported:
|
27
|
+
#
|
28
|
+
# [+:default+] Whether to +:allow+ or +:deny+ permissions that aren't
|
29
|
+
# specified explicitly. The default default (!) is +:deny+.
|
30
|
+
#
|
31
|
+
# When called without a block, +credentials+ just returns the class's
|
32
|
+
# Credentials::Rulebook, creating it if necessary.
|
4
33
|
def credentials(options = nil)
|
5
34
|
@credentials ||= Credentials::Rulebook.new(self)
|
6
35
|
if block_given?
|
@@ -12,22 +41,45 @@ module Credentials
|
|
12
41
|
@credentials
|
13
42
|
end
|
14
43
|
|
15
|
-
def inherited_with_credentials(child_class) #:nodoc
|
44
|
+
def inherited_with_credentials(child_class) #:nodoc:
|
16
45
|
inherited_without_credentials(child_class) if child_class.respond_to? :inherited_without_credentials
|
17
46
|
child_class.instance_variable_set("@credentials", Rulebook.for(child_class))
|
18
47
|
end
|
19
48
|
end
|
20
49
|
|
21
50
|
module InstanceMethods
|
51
|
+
# Returns true if the receiver has access to the specified resource or action.
|
22
52
|
def can?(*args)
|
23
53
|
self.class.credentials.allow? self, *args
|
24
54
|
end
|
25
55
|
alias_method :able_to?, :can?
|
56
|
+
|
57
|
+
# Allows you to use magic methods to test permissions.
|
58
|
+
# For example:
|
59
|
+
#
|
60
|
+
# class User
|
61
|
+
# credentials do |user|
|
62
|
+
# user.can :edit, :self
|
63
|
+
# end
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# user = User.new
|
67
|
+
# user.can_edit? user #=> true
|
68
|
+
def method_missing_with_credentials(sym, *args)
|
69
|
+
if sym.to_s =~ /\Acan_(.*)\?\z/
|
70
|
+
can? $1.to_sym, *args
|
71
|
+
else
|
72
|
+
method_missing_without_credentials sym, *args
|
73
|
+
end
|
74
|
+
end
|
26
75
|
end
|
27
76
|
|
28
77
|
def self.included(receiver) #:nodoc
|
29
78
|
receiver.extend ClassMethods
|
30
79
|
receiver.send :include, InstanceMethods
|
80
|
+
|
81
|
+
receiver.send :alias_method, :method_missing_without_credentials, :method_missing
|
82
|
+
receiver.send :alias_method, :method_missing, :method_missing_with_credentials
|
31
83
|
|
32
84
|
class << receiver
|
33
85
|
alias_method :inherited_without_credentials, :inherited if respond_to? :inherited
|
data/lib/credentials/rule.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
module Credentials
|
2
|
+
# Specifies an individual 'line' in a Rulebook.
|
3
|
+
# Trivially subclassed as Credentials::Rule::AllowRule
|
4
|
+
# and Credentials::Rule::DenyRule, but this is just
|
5
|
+
# to allow you to create your own, more complex rule types.
|
2
6
|
class Rule
|
3
7
|
attr_accessor :parameters
|
4
8
|
attr_accessor :options
|
@@ -8,15 +12,49 @@ module Credentials
|
|
8
12
|
self.parameters = args
|
9
13
|
end
|
10
14
|
|
15
|
+
# Returns the number of arguments expected in a test to this
|
16
|
+
# rule. This is really basic, but allows a quick first-pass
|
17
|
+
# filtering of the rules.
|
11
18
|
def arity
|
12
19
|
parameters.length
|
13
20
|
end
|
14
21
|
|
22
|
+
# Returns +true+ if the given arguments match this rule.
|
23
|
+
# Rules mostly use the same matching criteria as Ruby's
|
24
|
+
# +case+ statement: that is, the <tt>===</tt> operator.
|
25
|
+
# Remember:
|
26
|
+
# User === User.new # a class matches an instance
|
27
|
+
# /\w+/ === "abc" # a RegExp matches a valid string
|
28
|
+
# (1..5) === 3 # a Range matches a number
|
29
|
+
# :foo === :foo # anything matches itself
|
30
|
+
#
|
31
|
+
# There are two exceptions to this behaviour. Firstly,
|
32
|
+
# if the rule specifies an array, then the argument will
|
33
|
+
# match any element of that array:
|
34
|
+
# class User
|
35
|
+
# credentials do |user|
|
36
|
+
# user.can :fight, [ :shatner, :gandhi ]
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# user.can? :fight, :gandhi # => true
|
41
|
+
#
|
42
|
+
# Secondly, specifying <tt>:self</tt> in a rule is a nice
|
43
|
+
# shorthand for specifying an object's permissions on itself:
|
44
|
+
# class User
|
45
|
+
# credentials do |user|
|
46
|
+
# user.can :fight, :self # SPOILER ALERT
|
47
|
+
# end
|
48
|
+
# end
|
15
49
|
def match?(*args)
|
16
50
|
return false unless arity == args.length
|
17
51
|
|
18
52
|
parameters.zip(args).each do |expected, actual|
|
19
|
-
|
53
|
+
case expected
|
54
|
+
when :self then return false unless actual == args.first
|
55
|
+
when Array then return false unless expected.any? { |item| (item === actual) || (item == :self && actual == args.first) }
|
56
|
+
else return false unless expected === actual
|
57
|
+
end
|
20
58
|
end
|
21
59
|
result = true
|
22
60
|
result = result && evaluate_condition(options[:if], :|, *args) unless options[:if].nil?
|
@@ -24,6 +62,12 @@ module Credentials
|
|
24
62
|
result
|
25
63
|
end
|
26
64
|
|
65
|
+
# Evaluates an +if+ or +unless+ condition.
|
66
|
+
# [+conditions+] One or more conditions to evaluate.
|
67
|
+
# Can be symbols or procs.
|
68
|
+
# [+op+] Operator used to combine the results
|
69
|
+
# (+|+ for +if+, +&+ for +unless+).
|
70
|
+
# [+args+] List of arguments to test with/against
|
27
71
|
def evaluate_condition(conditions, op, *args)
|
28
72
|
receiver = args.shift
|
29
73
|
args.reject! { |arg| arg.is_a? Symbol }
|
data/lib/credentials/rulebook.rb
CHANGED
@@ -3,6 +3,10 @@ require "credentials/allow_rule"
|
|
3
3
|
require "credentials/deny_rule"
|
4
4
|
|
5
5
|
module Credentials
|
6
|
+
# Represents a collection of rules for granting and denying
|
7
|
+
# permissions to instances of a class.
|
8
|
+
# This is the return type of a call to a class's
|
9
|
+
# +credentials+ method.
|
6
10
|
class Rulebook
|
7
11
|
attr_accessor :klass
|
8
12
|
attr_accessor :options
|
@@ -18,6 +22,9 @@ module Credentials
|
|
18
22
|
@options = {}
|
19
23
|
end
|
20
24
|
|
25
|
+
# Creates a Rulebook for the given class.
|
26
|
+
# Should not be called directly: instead,
|
27
|
+
# use +class.credentials+ (q.v.).
|
21
28
|
def self.for(klass)
|
22
29
|
rulebook = new(klass)
|
23
30
|
if superclass && superclass.respond_to?(:credentials)
|
@@ -26,22 +33,138 @@ module Credentials
|
|
26
33
|
rulebook
|
27
34
|
end
|
28
35
|
|
36
|
+
# Returns +true+ if there are no rules defined in this Rulebook.
|
29
37
|
def empty?
|
30
38
|
rules.empty?
|
31
39
|
end
|
32
40
|
|
41
|
+
# Declaratively specify a permission.
|
42
|
+
# This is usually done in the context of a +credentials+ block
|
43
|
+
# (see Credentials::ObjectExtensions::ClassMethods#credentials).
|
44
|
+
# The examples below assume that context.
|
45
|
+
#
|
46
|
+
# == Simple (intransitive) permissions
|
47
|
+
# class User
|
48
|
+
# credentials do |user|
|
49
|
+
# user.can :log_in
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
# Permission is expressed as a symbol; usually an intransitive verb.
|
53
|
+
# Permission can be tested with:
|
54
|
+
# user.can? :log_in
|
55
|
+
# or
|
56
|
+
# user.can_log_in?
|
57
|
+
#
|
58
|
+
# == Resource (transitive) permissions
|
59
|
+
# class User
|
60
|
+
# credentials do |user|
|
61
|
+
# user.can :edit, Post
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
# As above, but a resource type is specified.
|
65
|
+
# Permission can be tested with:
|
66
|
+
# user.can? :edit, Post.first
|
67
|
+
# or
|
68
|
+
# user.can_edit? Post.first
|
69
|
+
#
|
70
|
+
# == +if+ and +unless+
|
71
|
+
# You can specify complex conditions with the +if+ and +unless+ options.
|
72
|
+
# These options can be either a symbol (which is assumed to be a method
|
73
|
+
# of the instance under test), or a proc, which is passed any non-symbol
|
74
|
+
# arguments from the +can?+ method.
|
75
|
+
# class User
|
76
|
+
# credentials do |user|
|
77
|
+
# user.can :create, Post, :if => :administrator?
|
78
|
+
# user.can :edit, Post, :if => lambda { |user, post| user == post.author }
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# user.can? :create, Post # checks user.administrator?
|
83
|
+
# user.can? :edit, post # checks user == post.author
|
84
|
+
#
|
85
|
+
# Both +if+ and +unless+ options can be specified for the same rule:
|
86
|
+
# class User
|
87
|
+
# credentials do |user|
|
88
|
+
# user.can :eat, "chunky bacon", :if => :hungry?, :unless => :vegetarian?
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
# So, only hungry users who are not vegetarian can eat chunky bacon.
|
92
|
+
#
|
93
|
+
# You can also specify multiple options for +if+ and +unless+.
|
94
|
+
# If there are multiple options for +if+, any one match will do:
|
95
|
+
# class User
|
96
|
+
# credentials do |user|
|
97
|
+
# user.can :go_backstage, :if => [ :crew?, :good_looking? ]
|
98
|
+
# end
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# However, multiple options for +unless+ must _all_ match:
|
102
|
+
# class User
|
103
|
+
# credentials(:default => :allow) do |user|
|
104
|
+
# user.cannot :record, Album, :unless => [ :talented?, :dedicated? ]
|
105
|
+
# end
|
106
|
+
# end
|
107
|
+
# You cannot record an album unless you are both talented and dedicated.
|
108
|
+
# Note that we have specified the default permission as +allow+ in this example:
|
109
|
+
# otherwise, the rule would never match.
|
110
|
+
#
|
111
|
+
# If your rules are any more complicated than that, you might want to
|
112
|
+
# consider using the lambda form of arguments to +if+ and/or +unless+.
|
113
|
+
#
|
114
|
+
# == Reflexive permissions (+:self+)
|
115
|
+
# The following two permissions are identical:
|
116
|
+
# class User
|
117
|
+
# credentials do |user|
|
118
|
+
# user.can :edit, User, :if => lambda { |user, another| user == another }
|
119
|
+
# user.can :edit, :self
|
120
|
+
# end
|
121
|
+
# end
|
33
122
|
def can(*args)
|
34
123
|
self.rules << AllowRule.new(klass, *args)
|
35
124
|
end
|
36
125
|
|
126
|
+
# Declaratively remove a permission.
|
127
|
+
# This is handy to explicitly remove a permission in a child class that
|
128
|
+
# you have granted in a parent class.
|
129
|
+
# It is also useful if your default is set to +allow+ and you want to
|
130
|
+
# tighten up some permissions:
|
131
|
+
# class User
|
132
|
+
# credentials(:default => :allow) do |user|
|
133
|
+
# user.cannot :delete, :self
|
134
|
+
# end
|
135
|
+
# end
|
136
|
+
# See Credentials::Rulebook#can for more on specifying permissions:
|
137
|
+
# just remember that everything is backwards!
|
37
138
|
def cannot(*args)
|
38
139
|
self.rules << DenyRule.new(klass, *args)
|
39
140
|
end
|
40
141
|
|
142
|
+
# Determines whether to +:allow+ or +:deny+ by default.
|
41
143
|
def default
|
42
144
|
options[:default] && options[:default].to_sym
|
43
145
|
end
|
44
146
|
|
147
|
+
# Decides whether to allow the requested permission.
|
148
|
+
#
|
149
|
+
# == Match algorithm
|
150
|
+
# 1. Set +ALLOWED+ to true if permission is specifically allowed
|
151
|
+
# by any allow_rules; otherwise, false.
|
152
|
+
# 2. Set +DENIED+ to true if permission is specifically denied
|
153
|
+
# by any deny_rules; otherwise, false.
|
154
|
+
# 3. The final result depends on the value of +default+:
|
155
|
+
# a. if +:allow+: <tt>ALLOWED OR !DENIED</tt>
|
156
|
+
# b. if +:deny+: <tt>ALLOWED AND !DENIED</tt>
|
157
|
+
#
|
158
|
+
# Expressed as a table:
|
159
|
+
# <table>
|
160
|
+
# <thead><tr><th>Matching rules</th><th>Default allow</th><th>Default deny</th></tr></thead>
|
161
|
+
# <tbody>
|
162
|
+
# <tr><td>None of the +allow+ or +deny+ rules matched.</td><td>allow</td><td>deny</td></tr>
|
163
|
+
# <tr><td>Some of the +allow+ rules matched, none of the +deny+ rules matched.</td><td>allow</td><td>allow</td></tr>
|
164
|
+
# <tr><td>None of the +allow+ rules matched, some of the +deny+ rules matched.</td><td>deny</td><td>deny</td></tr>
|
165
|
+
# <tr><td>Some of the +allow+ rules matched, some of the +deny+ rules matched.</td><td>allow</td><td>deny</td></tr>
|
166
|
+
# </tbody>
|
167
|
+
# </table>
|
45
168
|
def allow?(*args)
|
46
169
|
allowed = allow_rules.inject(false) { |memo, rule| memo || rule.allow?(*args) }
|
47
170
|
denied = deny_rules.inject(false) { |memo, rule| memo || rule.deny?(*args) }
|
@@ -53,10 +176,12 @@ module Credentials
|
|
53
176
|
end
|
54
177
|
end
|
55
178
|
|
179
|
+
# Subset of rules that grant permission by exposing an +allow?+ method.
|
56
180
|
def allow_rules
|
57
181
|
rules.select { |rule| rule.respond_to? :allow? }
|
58
182
|
end
|
59
183
|
|
184
|
+
# Subset of rules that deny permission by exposing an +deny?+ method.
|
60
185
|
def deny_rules
|
61
186
|
rules.select { |rule| rule.respond_to? :deny? }
|
62
187
|
end
|
data/spec/credentials_spec.rb
CHANGED
@@ -14,6 +14,26 @@ describe Animal do
|
|
14
14
|
it "shouldn't be able to do anything without explicit permission" do
|
15
15
|
@cow.should_not be_able_to :jump, "Moon"
|
16
16
|
end
|
17
|
+
|
18
|
+
it "should be able to clean itself" do
|
19
|
+
@sheep.should be_able_to :clean, @sheep
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should not be able to clean another animal" do
|
23
|
+
@sheep.should_not be_able_to :clean, @cow
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should have magic methods for permissions" do
|
27
|
+
lambda {
|
28
|
+
@sheep.can_eat?(@cow).should == false
|
29
|
+
}.should_not raise_error
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should still do normal method_missing stuff" do
|
33
|
+
lambda {
|
34
|
+
@sheep.foo
|
35
|
+
}.should raise_error
|
36
|
+
end
|
17
37
|
end
|
18
38
|
|
19
39
|
describe Carnivore do
|
@@ -75,6 +95,17 @@ describe Carnivore do
|
|
75
95
|
end
|
76
96
|
end
|
77
97
|
|
98
|
+
describe Bird do
|
99
|
+
before :each do
|
100
|
+
@toucan = Bird.new("Toucan")
|
101
|
+
@crocodile = Carnivore.new("Crocodile")
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should be able to clean another animal" do
|
105
|
+
@toucan.should be_able_to :clean, @crocodile
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
78
109
|
describe Man do
|
79
110
|
before :each do
|
80
111
|
@man = Man.new
|
data/spec/domain.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class Animal < Struct.new(:species, :hungry, :fast)
|
2
2
|
credentials do |animal|
|
3
|
+
animal.can :clean, :self
|
3
4
|
end
|
4
5
|
|
5
6
|
def edible?
|
@@ -22,7 +23,9 @@ class Prey < Animal
|
|
22
23
|
end
|
23
24
|
|
24
25
|
class Bird < Prey
|
25
|
-
|
26
|
+
credentials do |bird|
|
27
|
+
bird.can :clean, Animal # they are good like that
|
28
|
+
end
|
26
29
|
end
|
27
30
|
|
28
31
|
class Carnivore < Animal
|
@@ -35,7 +38,6 @@ end
|
|
35
38
|
|
36
39
|
class Man < Animal
|
37
40
|
credentials :default => :allow do |man|
|
38
|
-
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
data/spec/rule_spec.rb
CHANGED
@@ -23,6 +23,14 @@ describe Credentials::AllowRule do
|
|
23
23
|
rule.match?(lion, :jump)
|
24
24
|
}.should raise_error(ArgumentError)
|
25
25
|
end
|
26
|
+
|
27
|
+
it "should match with an array" do
|
28
|
+
rule = Credentials::AllowRule.new Animal, :bite, [ :self, Prey ]
|
29
|
+
lion = Carnivore.new("lion")
|
30
|
+
antelope = Prey.new("antelope")
|
31
|
+
rule.should be_match(lion, :bite, antelope)
|
32
|
+
rule.should be_match(lion, :bite, lion)
|
33
|
+
end
|
26
34
|
end
|
27
35
|
|
28
36
|
describe Credentials::DenyRule do
|
data/spec/rulebook_spec.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
3
|
describe Credentials::Rulebook do
|
4
|
+
it "should be empty when created" do
|
5
|
+
Credentials::Rulebook.new(Animal).should be_empty
|
6
|
+
end
|
7
|
+
|
4
8
|
it "should duplicate on inheritance" do
|
5
9
|
Animal.credentials.should_not == Carnivore.credentials
|
6
10
|
Animal.credentials.rules.should_not == Carnivore.credentials.rules
|
7
|
-
Animal.credentials.should be_empty
|
8
|
-
Carnivore.credentials.should_not be_empty
|
9
11
|
end
|
10
12
|
end
|
data/spec/spec_helper.rb
CHANGED
data/tasks/rdoc.rake
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
begin
|
2
|
+
require 'hanna/rdoctask'
|
3
|
+
rescue
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
end
|
6
|
+
|
7
|
+
desc 'Generate RDoc documentation.'
|
8
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
9
|
+
rdoc.rdoc_files.include('README.rdoc', 'LICENSE', 'HISTORY').
|
10
|
+
include('lib/**/*.rb')
|
11
|
+
|
12
|
+
rdoc.main = "README.rdoc" # page to start on
|
13
|
+
rdoc.title = "credentials documentation"
|
14
|
+
|
15
|
+
rdoc.rdoc_dir = 'doc' # rdoc output folder
|
16
|
+
rdoc.options << '--webcvs=http://github.com/fauxparse/credentials/'
|
17
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: credentials
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Powell
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-12 00:00:00 +13:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -24,7 +24,7 @@ extra_rdoc_files:
|
|
24
24
|
- README.rdoc
|
25
25
|
files:
|
26
26
|
- .gitignore
|
27
|
-
-
|
27
|
+
- HISTORY
|
28
28
|
- LICENSE
|
29
29
|
- README.rdoc
|
30
30
|
- Rakefile
|
@@ -45,6 +45,7 @@ files:
|
|
45
45
|
- spec/rulebook_spec.rb
|
46
46
|
- spec/spec_helper.rb
|
47
47
|
- tasks/gems.rake
|
48
|
+
- tasks/rdoc.rake
|
48
49
|
- tasks/spec.rake
|
49
50
|
- tasks/stats.rake
|
50
51
|
- uninstall.rb
|