ability_list 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +1 -0
- data/README.md +200 -0
- data/RECIPES.md +101 -0
- data/Rakefile +6 -0
- data/ability_list.gemspec +15 -0
- data/lib/ability_list.rb +90 -0
- data/lib/ability_list/version.rb +3 -0
- data/test/basic_test.rb +73 -0
- data/test/column_test.rb +43 -0
- data/test/helper.rb +9 -0
- data/test/helpers_test.rb +34 -0
- data/test/nil_test.rb +36 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 02257b2981224d6a1e1e43d60bb9721eba16420a
|
4
|
+
data.tar.gz: 7b586e6a4ba0bf248bfef3084310353a2ac89015
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1cea5050c2133f0bc47a4d266fb4a1bbbad62e2fff7c9a6533e4d873d4174515afb43437af66a674eecdf6e7a356ea97cc01d437e0acef0bb7d0994b44ba83f1
|
7
|
+
data.tar.gz: 14241716362b1380591ae3dbc59d847be38b9e8cb87d64b89892a35f4132967bf76ba1dee4f68673be0687f61aca57728025a6a6215d8837dbdc65d1c8182d40
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Gemfile.lock
|
data/Gemfile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
gemspec
|
data/README.md
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
AbilityList
|
2
|
+
===========
|
3
|
+
|
4
|
+
Simple permissions system as plain old Ruby objects. No fancy integration with
|
5
|
+
ORMs or frameworks.
|
6
|
+
|
7
|
+
All of this is just a single Ruby file with less than 50 lines of significant
|
8
|
+
code. [Read it now][ability_list.rb].
|
9
|
+
|
10
|
+
## Defining abilities
|
11
|
+
|
12
|
+
Define the list of abilities a user has by subclassing `AbilityList`.
|
13
|
+
|
14
|
+
Each ability is comprised of a **verb** (required) and an **object** (optional).
|
15
|
+
A *verb* is any symbol, while the *object* can be a symbol or a class.
|
16
|
+
|
17
|
+
``` ruby
|
18
|
+
class Abilities < AbilityList
|
19
|
+
def initialize(user)
|
20
|
+
can :view, Video
|
21
|
+
|
22
|
+
if user.admin?
|
23
|
+
can :delete, Video
|
24
|
+
can :upload, Video
|
25
|
+
end
|
26
|
+
|
27
|
+
can :login
|
28
|
+
|
29
|
+
can :view, :admin
|
30
|
+
end
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
Then hook it to user by defining an `abilities` method.
|
35
|
+
|
36
|
+
``` ruby
|
37
|
+
class User < OpenStruct
|
38
|
+
include AbilityList::Helpers
|
39
|
+
|
40
|
+
def abilities
|
41
|
+
@abilities ||= Abilities.new(self)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
## Checking for abilities
|
47
|
+
|
48
|
+
Now you may use `can?`:
|
49
|
+
|
50
|
+
``` ruby
|
51
|
+
user = User.new
|
52
|
+
user.can?(:view, Video)
|
53
|
+
user.can?(:view, Video.find(20))
|
54
|
+
|
55
|
+
user.can?(:login)
|
56
|
+
user.can?(:view, :admin)
|
57
|
+
```
|
58
|
+
|
59
|
+
The inverse `cannot?` is also available.
|
60
|
+
|
61
|
+
## Raising errors
|
62
|
+
|
63
|
+
Or you can use `authorize!`, which is exactly like `can?` except it raises
|
64
|
+
an `AbilityList::Error` exception. Perfect for controllers.
|
65
|
+
|
66
|
+
``` ruby
|
67
|
+
user.authorize! :view, Video.find(20)
|
68
|
+
```
|
69
|
+
|
70
|
+
## Custom criteria
|
71
|
+
|
72
|
+
You can pass a block to `can` for custom criteria:
|
73
|
+
|
74
|
+
``` ruby
|
75
|
+
can :view, Video do |video|
|
76
|
+
!video.restricted? or user.age > 18
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
You can even use Ruby's `&:sym` syntax:
|
81
|
+
|
82
|
+
``` ruby
|
83
|
+
cannot :edit, Article, &:published?
|
84
|
+
|
85
|
+
# Equivalent to cannot(:edit, Article) { |article| article.published? }
|
86
|
+
```
|
87
|
+
|
88
|
+
## Object types
|
89
|
+
|
90
|
+
The method `can` always accepts at least 2 arguments: a *verb* and an *object*.
|
91
|
+
|
92
|
+
You can define your permissions by passing a class as the object:
|
93
|
+
|
94
|
+
``` ruby
|
95
|
+
can :view, Video
|
96
|
+
```
|
97
|
+
|
98
|
+
which makes it possible to check for instances or classes:
|
99
|
+
|
100
|
+
``` ruby
|
101
|
+
user.can?(:view, Video) #-> passing a class
|
102
|
+
user.can?(:view, Video.find(1008)) #-> passing an instance
|
103
|
+
```
|
104
|
+
|
105
|
+
But this doesn't have to be classes. Just pass anything else, like a symbol:
|
106
|
+
|
107
|
+
``` ruby
|
108
|
+
can :login, :mobile_site
|
109
|
+
|
110
|
+
# user.can?(:login, :mobile_site)
|
111
|
+
```
|
112
|
+
|
113
|
+
## Overriding criteria
|
114
|
+
|
115
|
+
Criteria are evaluated on a top-down basis, and the ones at the bottom will
|
116
|
+
override the ones on top.
|
117
|
+
|
118
|
+
The method `cannot` is provided to make exceptions to rules.
|
119
|
+
|
120
|
+
For example:
|
121
|
+
|
122
|
+
``` ruby
|
123
|
+
# Everyone can edit comments.
|
124
|
+
can :edit, Comment
|
125
|
+
|
126
|
+
# ...but unconfirmed users can't edit their comments.
|
127
|
+
if user.unconfirmed?
|
128
|
+
cannot :edit, Comment
|
129
|
+
end
|
130
|
+
|
131
|
+
# ...but if the comments are really new, they can be edited, even if the user
|
132
|
+
# hasn't confirmed.
|
133
|
+
can :edit, Comment { |c| c.created_at < 3.minutes.ago }
|
134
|
+
```
|
135
|
+
|
136
|
+
## The `:manage` keyword
|
137
|
+
|
138
|
+
You can use `:manage` as the verb to allow any verb.
|
139
|
+
|
140
|
+
``` ruby
|
141
|
+
can :manage, Group
|
142
|
+
```
|
143
|
+
|
144
|
+
This allows the user to do anything to `Group` its instances.
|
145
|
+
|
146
|
+
``` ruby
|
147
|
+
user.can?(:delete, Group) #=> true
|
148
|
+
user.can?(:create, Group) #=> true
|
149
|
+
user.can?(:eviscerate, Group) #=> true
|
150
|
+
```
|
151
|
+
|
152
|
+
## The `:all` keyword
|
153
|
+
|
154
|
+
You can use `:all` as the object for any permission. This allows a verb to work
|
155
|
+
on anything.
|
156
|
+
|
157
|
+
Don't know why you'll want this, but cancan has it, so:
|
158
|
+
|
159
|
+
``` ruby
|
160
|
+
can :delete, :all
|
161
|
+
```
|
162
|
+
|
163
|
+
So you can:
|
164
|
+
|
165
|
+
``` ruby
|
166
|
+
user.can?(:delete, Video) #=> true
|
167
|
+
user.can?(:delete, Article) #=> true
|
168
|
+
user.can?(:delete, Recipe) #=> true
|
169
|
+
```
|
170
|
+
|
171
|
+
More examples
|
172
|
+
-------------
|
173
|
+
|
174
|
+
See [RECIPES.md] for some practical examples.
|
175
|
+
|
176
|
+
Limitations
|
177
|
+
-----------
|
178
|
+
|
179
|
+
AbilityList aims to be extremely lean, and to be as framework- and ORM-agnostic
|
180
|
+
as possible. As such, it doesn't:
|
181
|
+
|
182
|
+
* No explicit integration with Rails controllers.
|
183
|
+
|
184
|
+
* No explicit integration with ActiveRecord (or any other ORM).
|
185
|
+
|
186
|
+
* No explicit provisions for roles.
|
187
|
+
|
188
|
+
See [RECIPES.md] on how to do these things.
|
189
|
+
|
190
|
+
Acknowledgements
|
191
|
+
----------------
|
192
|
+
|
193
|
+
Heavily inspired by [cancan]. AbilityList is generally a stripped-down version
|
194
|
+
of cancan with a lot less features (see Limitations) above.
|
195
|
+
|
196
|
+
(c) 2013 MIT License.
|
197
|
+
|
198
|
+
[cancan]: https://github.com/ryanb/cancan
|
199
|
+
[RECIPES.md]: https://github.com/rstacruz/ability_list/blob/master/RECIPES.md
|
200
|
+
[ability_list.rb]:https://github.com/rstacruz/ability_list/blob/master/lib/ability_list.rb
|
data/RECIPES.md
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
How to implement roles
|
2
|
+
----------------------
|
3
|
+
|
4
|
+
AbilityList has no explicit support for roles because they're pretty easy to do
|
5
|
+
in the plain ol' Ruby way.
|
6
|
+
|
7
|
+
``` ruby
|
8
|
+
class Abilities < AbilityList
|
9
|
+
def initialize(user)
|
10
|
+
# Assume this returns an array of strings like ['admin', 'editor'].
|
11
|
+
roles = user.roles
|
12
|
+
|
13
|
+
# Now simply call the respective methods of each role.
|
14
|
+
roles.each { |role| send role }
|
15
|
+
end
|
16
|
+
|
17
|
+
def admin
|
18
|
+
can :manage, User
|
19
|
+
can :manage, Group
|
20
|
+
end
|
21
|
+
|
22
|
+
def editor
|
23
|
+
can :edit, Article
|
24
|
+
end
|
25
|
+
|
26
|
+
def publisher
|
27
|
+
can :publish, Article
|
28
|
+
end
|
29
|
+
|
30
|
+
def writer
|
31
|
+
can :create, Article
|
32
|
+
end
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
How to integrate with Rails controllers
|
37
|
+
---------------------------------------
|
38
|
+
|
39
|
+
This Rails example raises an error when the logged in user is not allowed of a
|
40
|
+
certain permission.
|
41
|
+
|
42
|
+
``` ruby
|
43
|
+
class ArticleController
|
44
|
+
before_filter :authorize_viewing
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def authorize_viewing
|
49
|
+
current_user.authorize! :view, Article
|
50
|
+
end
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
How to implement user levels
|
55
|
+
----------------------------
|
56
|
+
|
57
|
+
If your `User` model has a numeric field `level`, where more permissions are
|
58
|
+
available to users with higher levels, you can implement it like so:
|
59
|
+
|
60
|
+
``` ruby
|
61
|
+
class Abilities < AbilityList
|
62
|
+
def initialize(user)
|
63
|
+
if user.level > 50
|
64
|
+
can :launch, Rocket
|
65
|
+
can :command, Army
|
66
|
+
end
|
67
|
+
|
68
|
+
if user.level > 30
|
69
|
+
can :view_status, Rocket
|
70
|
+
end
|
71
|
+
|
72
|
+
if user.level > 1
|
73
|
+
can :login, :site
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
Defining Rails helpers
|
80
|
+
----------------------
|
81
|
+
|
82
|
+
The `Helpers` module used in Users can be used as Rails helpers too.
|
83
|
+
|
84
|
+
``` ruby
|
85
|
+
module PermissionsHelper
|
86
|
+
# Provides `can?` and `cannot?`... as long as you have `#abilities` defined.
|
87
|
+
include AbilityList::Helpers
|
88
|
+
|
89
|
+
def abilities
|
90
|
+
current_user.try :abilities
|
91
|
+
end
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
So that you may:
|
96
|
+
|
97
|
+
``` erb
|
98
|
+
<% if can?(:edit, @post) %>
|
99
|
+
<a href="#edit">Edit</a>
|
100
|
+
<% end %>
|
101
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require './lib/ability_list/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "ability_list"
|
5
|
+
s.version = AbilityList::VERSION
|
6
|
+
s.summary = %[Simple user permissions management.]
|
7
|
+
s.description = %[A very simple way to manage permissions. Works with any ORM.]
|
8
|
+
s.authors = ["Rico Sta. Cruz", 'CJ Lazell']
|
9
|
+
s.email = ["hi@ricostacruz.com"]
|
10
|
+
s.homepage = "http://github.com/cj/ability_list"
|
11
|
+
s.files = `git ls-files`.strip.split("\n")
|
12
|
+
|
13
|
+
s.add_development_dependency "minitest"
|
14
|
+
s.add_development_dependency "rake"
|
15
|
+
end
|
data/lib/ability_list.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
class AbilityList
|
2
|
+
Error = Class.new(StandardError)
|
3
|
+
|
4
|
+
# Returns a list of rules. These are populated by `can` and `cannot`.
|
5
|
+
# (Rules are tuples)
|
6
|
+
def rules
|
7
|
+
@rules ||= []
|
8
|
+
end
|
9
|
+
|
10
|
+
# ---
|
11
|
+
|
12
|
+
# Declares that the owner can perform `verb` on `class`.
|
13
|
+
def can(verb, klass=nil, columns=[], &block)
|
14
|
+
columns = [columns] unless columns.is_a? Array
|
15
|
+
rules << [true, verb, get_class(klass), columns, block]
|
16
|
+
end
|
17
|
+
|
18
|
+
# Inverse of `can`.
|
19
|
+
def cannot(verb, klass=nil, columns=[], &block)
|
20
|
+
columns = [columns] unless columns.is_a? Array
|
21
|
+
rules << [false, verb, get_class(klass), columns, block]
|
22
|
+
end
|
23
|
+
|
24
|
+
# ---
|
25
|
+
|
26
|
+
# Checks if the owner can perform `verb` on the given `object` (or class).
|
27
|
+
def can?(verb, object=nil, columns=[])
|
28
|
+
columns = [columns] unless columns.is_a? Array
|
29
|
+
rules = rules_for(verb, get_class(object))
|
30
|
+
rules.inject(false) do |bool, (sign, _, _, cols, proc)|
|
31
|
+
sign ?
|
32
|
+
((bool || !proc || proc.call(object)) && ((columns & cols) == columns)) : # can
|
33
|
+
(bool && proc && !proc.call(object) && (columns.empty? || (columns & cols) != columns)) # cannot
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Inverse of `can?`.
|
38
|
+
def cannot?(verb, object=nil, columns)
|
39
|
+
! can?(verb, object, columns)
|
40
|
+
end
|
41
|
+
|
42
|
+
# ---
|
43
|
+
|
44
|
+
# Ensures that the owner can perform `verb` on `object/class` -- raises an
|
45
|
+
# error otherwise.
|
46
|
+
def authorize!(verb, object=nil)
|
47
|
+
can?(verb, object) or raise Error.new("Access denied (#{verb})")
|
48
|
+
end
|
49
|
+
|
50
|
+
# Inverse of `authorize!`.
|
51
|
+
def unauthorize!(verb, object=nil)
|
52
|
+
cannot?(verb, object) or raise Error.new("Access denied (#{verb})")
|
53
|
+
end
|
54
|
+
|
55
|
+
# ---
|
56
|
+
|
57
|
+
# Returns a subset of `rules` that match the given `verb` and `class`.
|
58
|
+
def rules_for(verb, klass)
|
59
|
+
rules.select do |(sign, _verb, _klass, cols, block)|
|
60
|
+
(_verb == :manage || _verb == verb) &&
|
61
|
+
(_klass == :all || _klass == klass)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def get_class(object)
|
68
|
+
[NilClass, Symbol, Class].include?(object.class) ? object : object.class
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Provides `#can?` and `#cannot?` and other helpers.
|
73
|
+
# Assumes that you have an `#ability` method defined.
|
74
|
+
module AbilityList::Helpers
|
75
|
+
def can?(*a)
|
76
|
+
abilities && abilities.can?(*a)
|
77
|
+
end
|
78
|
+
|
79
|
+
def cannot?(*a)
|
80
|
+
!abilities || abilities.cannot?(*a)
|
81
|
+
end
|
82
|
+
|
83
|
+
def authorize!(*a)
|
84
|
+
raise AbilityList::Error.new("No 'ability' defined") unless abilities
|
85
|
+
abilities.authorize!(*a)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
require 'ability_list/version'
|
90
|
+
|
data/test/basic_test.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path('../helper.rb', __FILE__)
|
2
|
+
|
3
|
+
module BasicTest
|
4
|
+
Video = Class.new(OpenStruct)
|
5
|
+
|
6
|
+
# ---
|
7
|
+
|
8
|
+
class User < OpenStruct
|
9
|
+
include AbilityList::Helpers
|
10
|
+
|
11
|
+
def abilities
|
12
|
+
@abilities ||= Abilities.new(self)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# ---
|
17
|
+
|
18
|
+
class Abilities < AbilityList
|
19
|
+
def initialize(user)
|
20
|
+
# Every can view videos.
|
21
|
+
can :view, Video
|
22
|
+
|
23
|
+
# ...except restricted ones.
|
24
|
+
cannot :view, Video, &:restricted
|
25
|
+
|
26
|
+
# ...but for those that are restricted, it's okay if the user is old enough.
|
27
|
+
can :view, Video do |vid|
|
28
|
+
vid.restricted && user.age > 18
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# ---
|
34
|
+
|
35
|
+
describe "Basic tests" do
|
36
|
+
it "#can? 1" do
|
37
|
+
user = User.new :age => 22
|
38
|
+
video = Video.new :restricted => false
|
39
|
+
|
40
|
+
user.can?(:view, video).must_equal true
|
41
|
+
end
|
42
|
+
|
43
|
+
it "#can? 2" do
|
44
|
+
user = User.new :age => 10
|
45
|
+
video = Video.new :restricted => true
|
46
|
+
|
47
|
+
user.can?(:view, video).must_equal false
|
48
|
+
end
|
49
|
+
|
50
|
+
it "#can? 3" do
|
51
|
+
user = User.new :age => 42
|
52
|
+
video = Video.new :restricted => true
|
53
|
+
|
54
|
+
user.can?(:view, video).must_equal true
|
55
|
+
end
|
56
|
+
|
57
|
+
it "#cannot?" do
|
58
|
+
user = User.new :age => 10
|
59
|
+
video = Video.new :restricted => true
|
60
|
+
|
61
|
+
user.cannot?(:view, video).must_equal true
|
62
|
+
end
|
63
|
+
|
64
|
+
it "#authorize!" do
|
65
|
+
user = User.new :age => 10
|
66
|
+
video = Video.new :restricted => true
|
67
|
+
|
68
|
+
assert_raises AbilityList::Error do
|
69
|
+
user.authorize! :view, video
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/test/column_test.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.expand_path('../helper.rb', __FILE__)
|
2
|
+
|
3
|
+
module ColumnTest
|
4
|
+
Video = Class.new(OpenStruct)
|
5
|
+
Player = Class.new(OpenStruct)
|
6
|
+
|
7
|
+
# ---
|
8
|
+
|
9
|
+
class User < OpenStruct
|
10
|
+
include AbilityList::Helpers
|
11
|
+
|
12
|
+
def abilities
|
13
|
+
@abilities ||= Abilities.new(self)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# ---
|
18
|
+
|
19
|
+
class Abilities < AbilityList
|
20
|
+
def initialize(user)
|
21
|
+
# Every can view videos.
|
22
|
+
can :view, Video, [:title, :description]
|
23
|
+
can :view, Player, :name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# ---
|
28
|
+
|
29
|
+
describe 'Column tests' do
|
30
|
+
it '#can? 1' do
|
31
|
+
user = User.new
|
32
|
+
video = Video.new title: 'moo', description: 'cow', about: 'grass'
|
33
|
+
player = Player.new name: 'Bob', age: 100
|
34
|
+
|
35
|
+
user.can?(:view, video, :title).must_equal true
|
36
|
+
user.can?(:view, video, [:title, :description]).must_equal true
|
37
|
+
user.can?(:view, video, :about).must_equal false
|
38
|
+
user.can?(:view, player, :name).must_equal true
|
39
|
+
user.cannot?(:view, player, :age).must_equal true
|
40
|
+
user.cannot?(:view, player, :name).must_equal false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.expand_path('../helper.rb', __FILE__)
|
2
|
+
|
3
|
+
module HelpersTest
|
4
|
+
Video = Class.new(OpenStruct)
|
5
|
+
|
6
|
+
# ---
|
7
|
+
|
8
|
+
class User < OpenStruct
|
9
|
+
include AbilityList::Helpers
|
10
|
+
|
11
|
+
def abilities
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# ---
|
16
|
+
|
17
|
+
describe "Helper tests" do
|
18
|
+
let(:user) { User.new }
|
19
|
+
|
20
|
+
it '#can? fail' do
|
21
|
+
(!! user.can?(:cook, :spam)).must_equal false
|
22
|
+
end
|
23
|
+
|
24
|
+
it '#cannot? fail' do
|
25
|
+
(!! user.cannot?(:cook, :spam)).must_equal true
|
26
|
+
end
|
27
|
+
|
28
|
+
it '#authorize! fail' do
|
29
|
+
assert_raises AbilityList::Error do
|
30
|
+
user.authorize! :cook, :spam
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/test/nil_test.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path('../helper.rb', __FILE__)
|
2
|
+
|
3
|
+
module NilTest
|
4
|
+
class User < OpenStruct
|
5
|
+
include AbilityList::Helpers
|
6
|
+
|
7
|
+
def abilities
|
8
|
+
@abilities ||= Abilities.new(self)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# ---
|
13
|
+
|
14
|
+
class Abilities < AbilityList
|
15
|
+
def initialize(user)
|
16
|
+
can :make, :fire
|
17
|
+
can :make
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# ---
|
22
|
+
|
23
|
+
describe "Nil tests" do
|
24
|
+
let(:user) { User.new }
|
25
|
+
|
26
|
+
it "#can? 1" do
|
27
|
+
user.can?(:make, :fire).must_equal true
|
28
|
+
end
|
29
|
+
it "#can? 2" do
|
30
|
+
user.can?(:make).must_equal true
|
31
|
+
end
|
32
|
+
it "#can? 3" do
|
33
|
+
user.can?(:make, :lasagna).must_equal false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ability_list
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rico Sta. Cruz
|
8
|
+
- CJ Lazell
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-02-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: minitest
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
description: A very simple way to manage permissions. Works with any ORM.
|
43
|
+
email:
|
44
|
+
- hi@ricostacruz.com
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- ".gitignore"
|
50
|
+
- Gemfile
|
51
|
+
- README.md
|
52
|
+
- RECIPES.md
|
53
|
+
- Rakefile
|
54
|
+
- ability_list.gemspec
|
55
|
+
- lib/ability_list.rb
|
56
|
+
- lib/ability_list/version.rb
|
57
|
+
- test/basic_test.rb
|
58
|
+
- test/column_test.rb
|
59
|
+
- test/helper.rb
|
60
|
+
- test/helpers_test.rb
|
61
|
+
- test/nil_test.rb
|
62
|
+
homepage: http://github.com/cj/ability_list
|
63
|
+
licenses: []
|
64
|
+
metadata: {}
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 2.2.2
|
82
|
+
signing_key:
|
83
|
+
specification_version: 4
|
84
|
+
summary: Simple user permissions management.
|
85
|
+
test_files: []
|
86
|
+
has_rdoc:
|