acts_as_permission 1.2.0 → 2.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/.gitignore +4 -0
- data/.rvmrc +1 -0
- data/Gemfile +11 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +273 -26
- data/Rakefile +10 -10
- data/VERSION.yml +2 -2
- data/acts_as_permission.gemspec +13 -27
- data/app/views/acts_as_permission/_permission_fields.html.erb +35 -0
- data/config/locales/en.yml +8 -0
- data/config/locales/fr.yml +8 -0
- data/config/locales/ja.yml +8 -0
- data/lib/acts_as_permission.rb +117 -32
- data/lib/generators/permissions/USAGE +8 -0
- data/lib/generators/permissions/permissions_generator.rb +17 -0
- data/lib/generators/permissions/templates/create_permissions.rb +15 -0
- data/lib/generators/permissions/templates/permission.rb +27 -0
- data/lib/generators/permissions/templates/permissions_helper.rb +7 -0
- data/test/permission_test.rb +331 -0
- data/test/test_helper.rb +4 -0
- metadata +57 -79
- data/Manifest +0 -10
- data/generators/acts_as_permission/USAGE +0 -20
- data/generators/acts_as_permission/acts_as_permission_generator.rb +0 -40
- data/lib/permissions_helper.rb +0 -17
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm ruby-1.9.2@acts_as_permission
|
data/Gemfile
ADDED
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -1,49 +1,296 @@
|
|
1
1
|
= Acts as permission
|
2
2
|
|
3
|
-
|
3
|
+
Acts as permission is a plugin for Ruby on Rails that allows to assign a list of
|
4
|
+
permissions on an object, according to the ACL concept, where each permission
|
5
|
+
can be extended to a subject.
|
4
6
|
|
5
|
-
|
7
|
+
More specifically, it can make possible to allow or to deny any action of the
|
8
|
+
controller of a protected resource. These actions are called permittables.
|
6
9
|
|
7
|
-
|
10
|
+
A permittable action can be directly attached to a resource. Examples of such
|
11
|
+
actions:
|
8
12
|
|
9
|
-
|
13
|
+
* <tt>show</tt>,
|
14
|
+
* <tt>edit</tt>,
|
15
|
+
* <tt>update</tt>,
|
16
|
+
* <tt>destroy</tt>.
|
10
17
|
|
11
|
-
|
18
|
+
Or it can be indirectly, through a parent resource. Examples:
|
12
19
|
|
13
|
-
|
20
|
+
* <tt>index</tt>,
|
21
|
+
* <tt>new</tt>,
|
22
|
+
* <tt>create</tt>.
|
14
23
|
|
15
|
-
|
24
|
+
Here is an example of query to a direct article's action:
|
16
25
|
|
17
|
-
|
26
|
+
@article = Article.find(params[:id])
|
27
|
+
@article.permission?("articles#destroy") # => false
|
18
28
|
|
19
|
-
|
20
|
-
|
29
|
+
Same query, extended to a user:
|
30
|
+
|
31
|
+
@article.permission?("articles#destroy", @bob) # => nil
|
32
|
+
@article.permission?("articles#destroy", @admin) # => true
|
33
|
+
|
34
|
+
A query example on an indirect articles' action, through a category:
|
35
|
+
|
36
|
+
@category = Category.find(params[:category_id])
|
37
|
+
@category.permission?("articles#index") # => true
|
38
|
+
|
39
|
+
Other examples, on unpermittable actions:
|
40
|
+
|
41
|
+
@category.permission?("articles#read") # => nil
|
42
|
+
@category.permission?("silk_routes#index") # => nil
|
43
|
+
|
44
|
+
The value of a permission depends on its context, which includes a route and an
|
45
|
+
optional extension to a permitted resource.
|
46
|
+
|
47
|
+
The <tt>permission?(route, ext = nil)</tt> query may return, depending on the
|
48
|
+
context:
|
49
|
+
|
50
|
+
* <tt>true</tt>, if the permission is allowed;
|
51
|
+
* <tt>false</tt>, if the permission is denied;
|
52
|
+
* <tt>nil</tt>, if the permission is indefinable (resulting of the unknowned
|
53
|
+
context).
|
54
|
+
|
55
|
+
== Philosophy
|
56
|
+
|
57
|
+
General library that does only one thing, without any feature.
|
58
|
+
|
59
|
+
== Installation
|
60
|
+
|
61
|
+
Include the gem in your <tt>Gemfile</tt>:
|
62
|
+
|
63
|
+
gem 'acts_as_permission'
|
21
64
|
|
22
|
-
|
65
|
+
And run the +bundle+ command. Or as a plugin:
|
23
66
|
|
24
|
-
|
25
|
-
|
67
|
+
rails plugin install git://github.com/cyril/acts_as_permission.git
|
68
|
+
|
69
|
+
Then, generate files and apply the migration:
|
70
|
+
|
71
|
+
rails generate permissions
|
26
72
|
rake db:migrate
|
27
73
|
|
28
|
-
|
29
|
-
|
74
|
+
== Getting started
|
75
|
+
|
76
|
+
=== Configuring models
|
77
|
+
|
78
|
+
Permittable models have to be declared with <tt>acts_as_permission</tt>. And
|
79
|
+
they have to be so with a default permission mask. For example:
|
80
|
+
|
81
|
+
# app/models/article.rb
|
82
|
+
class Article < ActiveRecord::Base
|
83
|
+
acts_as_permission({
|
84
|
+
'articles#show' => [true, {}],
|
85
|
+
'articles#edit' => [false, {
|
86
|
+
:permitted_id => 1,
|
87
|
+
:permitted_type => "User",
|
88
|
+
:value => true }],
|
89
|
+
'articles#update' => [false, {
|
90
|
+
:permitted_id => 1,
|
91
|
+
:permitted_type => "User",
|
92
|
+
:value => true }],
|
93
|
+
'articles#destroy' => [false, {
|
94
|
+
:permitted_id => 1,
|
95
|
+
:permitted_type => "User",
|
96
|
+
:value => true }],
|
97
|
+
'comments#index' => true,
|
98
|
+
'comments#new' => [true, [{
|
99
|
+
:permitted_id => 3,
|
100
|
+
:permitted_type => "User",
|
101
|
+
:value => false }]],
|
102
|
+
'comments#create' => [true, [{
|
103
|
+
:permitted_id => 3,
|
104
|
+
:permitted_type => "User",
|
105
|
+
:value => false }]]})
|
106
|
+
|
30
107
|
belongs_to :user
|
31
|
-
has_many :
|
108
|
+
has_many :comments, :dependent => :destroy
|
32
109
|
end
|
33
110
|
|
34
|
-
|
35
|
-
|
36
|
-
|
111
|
+
# app/models/comment.rb
|
112
|
+
class Comment < ActiveRecord::Base
|
113
|
+
acts_as_permission([
|
114
|
+
["comments#show", true],
|
115
|
+
["comments#edit", [false, [
|
116
|
+
{:permitted_id => 1, :permitted_type => "User", :value => true},
|
117
|
+
{:permitted_id => 2, :permitted_type => "User", :value => true} ]]],
|
118
|
+
["comments#update", [false, [
|
119
|
+
{:permitted_id => 1, :permitted_type => "User", :value => true},
|
120
|
+
{:permitted_id => 2, :permitted_type => "User", :value => true} ]]],
|
121
|
+
["comments#destroy", [false, {
|
122
|
+
:permitted_id => 1,
|
123
|
+
:permitted_type => "User",
|
124
|
+
:value => true }]]])
|
125
|
+
|
126
|
+
belongs_to :article
|
37
127
|
belongs_to :user
|
38
128
|
end
|
39
129
|
|
40
|
-
|
41
|
-
|
130
|
+
Optionally, some models (such as <tt>User</tt>, <tt>Group</tt>, <tt>Role</tt>)
|
131
|
+
can also be declared as permitted with <tt>is_able_to_be_permitted</tt>.
|
132
|
+
Example:
|
133
|
+
|
134
|
+
# app/models/user.rb
|
135
|
+
class User < ActiveRecord::Base
|
136
|
+
is_able_to_be_permitted
|
137
|
+
|
138
|
+
with_options :dependent => :destroy do |opts|
|
139
|
+
opts.has_many :articles
|
140
|
+
opts.has_many :comments
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
=== Configuring controllers
|
145
|
+
|
146
|
+
Example of a fully protected comments controller:
|
147
|
+
|
148
|
+
class CommentsController < ApplicationController
|
149
|
+
before_filter :check_permissions
|
150
|
+
|
151
|
+
# GET /comments
|
152
|
+
# GET /comments.xml
|
153
|
+
def index
|
154
|
+
@comments = current_resource.comments
|
155
|
+
|
156
|
+
respond_to do |format|
|
157
|
+
format.html # index.html.erb
|
158
|
+
format.xml { render :xml => @comments }
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# GET /comments/1
|
163
|
+
# GET /comments/1.xml
|
164
|
+
def show
|
165
|
+
@comment = current_resource
|
166
|
+
|
167
|
+
respond_to do |format|
|
168
|
+
format.html # show.html.erb
|
169
|
+
format.xml { render :xml => @comment }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# GET /comments/new
|
174
|
+
# GET /comments/new.xml
|
175
|
+
def new
|
176
|
+
@comment = current_resource.comments.build
|
177
|
+
|
178
|
+
respond_to do |format|
|
179
|
+
format.html # new.html.erb
|
180
|
+
format.xml { render :xml => @comment }
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# GET /comments/1/edit
|
185
|
+
def edit
|
186
|
+
@comment = current_resource
|
187
|
+
end
|
188
|
+
|
189
|
+
# POST /comments
|
190
|
+
# POST /comments.xml
|
191
|
+
def create
|
192
|
+
@comment = current_resource.comments.build(params[:comment])
|
193
|
+
|
194
|
+
respond_to do |format|
|
195
|
+
if @comment.save
|
196
|
+
format.html { redirect_to(@comment,
|
197
|
+
:notice => 'Comment was successfully created.') }
|
198
|
+
format.xml { render :xml => @comment, :status => :created,
|
199
|
+
:location => @comment }
|
200
|
+
else
|
201
|
+
format.html { render :action => "new" }
|
202
|
+
format.xml { render :xml => @comment.errors,
|
203
|
+
:status => :unprocessable_entity }
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# PUT /comments/1
|
209
|
+
# PUT /comments/1.xml
|
210
|
+
def update
|
211
|
+
@comment = current_resource
|
212
|
+
|
213
|
+
respond_to do |format|
|
214
|
+
if @comment.update_attributes(params[:comment])
|
215
|
+
format.html { redirect_to(@comment,
|
216
|
+
:notice => 'Comment was successfully updated.') }
|
217
|
+
format.xml { head :ok }
|
218
|
+
else
|
219
|
+
format.html { render :action => "edit" }
|
220
|
+
format.xml { render :xml => @comment.errors,
|
221
|
+
:status => :unprocessable_entity }
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# DELETE /comments/1
|
227
|
+
# DELETE /comments/1.xml
|
228
|
+
def destroy
|
229
|
+
@comment = current_resource
|
230
|
+
@comment.destroy
|
231
|
+
|
232
|
+
respond_to do |format|
|
233
|
+
format.html { redirect_to(comments_url) }
|
234
|
+
format.xml { head :ok }
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
protected
|
239
|
+
|
240
|
+
def check_permissions
|
241
|
+
route = [ params[:controller],
|
242
|
+
params[:action] ].join('#')
|
243
|
+
|
244
|
+
unless (current_user &&
|
245
|
+
current_resource.permission?(route, current_user)) ||
|
246
|
+
current_resource.permission?(route)
|
247
|
+
respond_to do |format|
|
248
|
+
format.html { redirect_to(:back, :warning => '403 Forbidden',
|
249
|
+
:status => :forbidden) }
|
250
|
+
format.xml { render :xml => '403 Forbidden', :status => :forbidden }
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def current_resource
|
256
|
+
@current_resource ||= if params[:id]
|
257
|
+
Comment.find(params[:id])
|
258
|
+
else
|
259
|
+
Article.find(params[:article_id], :readonly => true)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
=== Configuring views
|
265
|
+
|
266
|
+
We can now perform some checks on related views from a comment instance, thanks
|
267
|
+
to the protected actions of its controller, in order to only display allowed
|
268
|
+
links:
|
269
|
+
|
270
|
+
<% if current_user && @comment.permission?("comments#edit", current_user) ||
|
271
|
+
@comment.permission?("comments#edit") %>
|
272
|
+
<%= link_to "Edit comment",
|
273
|
+
edit_article_comment_path(@comment.article, @comment) %>
|
274
|
+
<% end %>
|
275
|
+
|
276
|
+
And also some indirect checks from the current article instance, like this one:
|
277
|
+
|
278
|
+
<% if current_user && @article.permission?("comments#index", current_user) ||
|
279
|
+
@article.permission?("comments#index") %>
|
280
|
+
<%= link_to "Comments", article_comments_path(@article) %>
|
281
|
+
<% end %>
|
282
|
+
|
283
|
+
Or this other one:
|
284
|
+
|
285
|
+
<% if current_user && @article.permission?("comments#new", current_user) ||
|
286
|
+
@article.permission?("comments#new") %>
|
287
|
+
<%= link_to "New comment", new_article_comment_path(@article) %>
|
288
|
+
<% end %>
|
289
|
+
|
290
|
+
==== Form helper
|
42
291
|
|
43
|
-
|
44
|
-
@article.has_permission?('destroy')
|
292
|
+
Object's permissions management is as simple as:
|
45
293
|
|
46
|
-
|
47
|
-
<%= permission_fields :article %>
|
294
|
+
<%= permission_fields f %>
|
48
295
|
|
49
|
-
Copyright (c) 2009 Cyril Wack, released under the MIT license
|
296
|
+
Copyright (c) 2009-2011 Cyril Wack, released under the MIT license
|
data/Rakefile
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
require 'echoe'
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
p.development_dependencies = []
|
4
|
+
require 'rake/testtask'
|
5
|
+
|
6
|
+
Rake::TestTask.new do |t|
|
7
|
+
t.libs << 'lib'
|
8
|
+
t.libs << 'test'
|
9
|
+
t.test_files = FileList["test/**/*_{helper,test}.rb"]
|
12
10
|
end
|
11
|
+
|
12
|
+
task :default => :test
|
data/VERSION.yml
CHANGED
data/acts_as_permission.gemspec
CHANGED
@@ -1,32 +1,18 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
1
|
Gem::Specification.new do |s|
|
4
|
-
s.name
|
5
|
-
s.version
|
6
|
-
|
7
|
-
s.
|
8
|
-
s.
|
9
|
-
s.
|
10
|
-
s.
|
2
|
+
s.name = "acts_as_permission"
|
3
|
+
s.version = Psych.load_file("VERSION.yml").values.join('.')
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.authors = ["Cyril Wack"]
|
6
|
+
s.email = ["cyril@gosu.fr"]
|
7
|
+
s.homepage = "http://github.com/cyril/acts_as_permission"
|
8
|
+
s.summary = %q{Simple permission solution for Rails.}
|
11
9
|
s.description = %q{Simple Rails plugin to assign a list of permissions on a resource.}
|
12
|
-
s.email = %q{cyril.wack@gmail.com}
|
13
|
-
s.extra_rdoc_files = ["README.rdoc", "lib/acts_as_permission.rb", "lib/permissions_helper.rb"]
|
14
|
-
s.files = ["MIT-LICENSE", "README.rdoc", "Rakefile", "VERSION.yml", "generators/acts_as_permission/USAGE", "generators/acts_as_permission/acts_as_permission_generator.rb", "init.rb", "lib/acts_as_permission.rb", "lib/permissions_helper.rb", "Manifest", "acts_as_permission.gemspec"]
|
15
|
-
s.homepage = %q{http://github.com/cyril/acts_as_permission}
|
16
|
-
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Acts_as_permission", "--main", "README.rdoc"]
|
17
|
-
s.require_paths = ["lib"]
|
18
|
-
s.rubyforge_project = %q{acts_as_permission}
|
19
|
-
s.rubygems_version = %q{1.3.6}
|
20
|
-
s.signing_key = %q{/Users/cyril/gem-private_key.pem}
|
21
|
-
s.summary = %q{Simple Rails plugin to assign a list of permissions on a resource.}
|
22
10
|
|
23
|
-
|
24
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
-
s.specification_version = 3
|
11
|
+
s.rubyforge_project = "acts_as_permission"
|
26
12
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
13
|
+
s.add_runtime_dependency "railties", ">= 3.0.0"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.require_paths = ["lib"]
|
32
18
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<%= content_tag :fieldset, :id => "#{f.object}_permissions" do %>
|
2
|
+
<%= content_tag :legend, t('.legend') %>
|
3
|
+
|
4
|
+
<%= f.fields_for :permissions do |permission_fields| %>
|
5
|
+
<p>
|
6
|
+
<strong>
|
7
|
+
<%= permission_fields.object.route %>
|
8
|
+
|
9
|
+
<% if permission_fields.object.permitted.present? %>
|
10
|
+
; <%= [ permission_fields.object.permitted.type,
|
11
|
+
permission_fields.object.permitted.id ].join('-') %>
|
12
|
+
<% end %>
|
13
|
+
</strong>
|
14
|
+
</p>
|
15
|
+
|
16
|
+
<p>
|
17
|
+
<label>
|
18
|
+
<%= permission_fields.radio_button(:value, true) %>
|
19
|
+
<%= t('.verb.allow') %>
|
20
|
+
</label>
|
21
|
+
|
22
|
+
<label>
|
23
|
+
<%= permission_fields.radio_button(:value, false) %>
|
24
|
+
<%= t('.verb.deny') %>
|
25
|
+
</label>
|
26
|
+
|
27
|
+
<br />
|
28
|
+
|
29
|
+
<label>
|
30
|
+
<%= t('.destroy') %>:
|
31
|
+
<%= permission_fields.check_box :_destroy %>
|
32
|
+
</label>
|
33
|
+
</p>
|
34
|
+
<% end %>
|
35
|
+
<% end %>
|
data/lib/acts_as_permission.rb
CHANGED
@@ -1,51 +1,136 @@
|
|
1
|
-
require 'active_record/base'
|
2
|
-
|
3
1
|
module ActsAsPermission
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
module Permittable
|
3
|
+
def permission(route, ext = nil)
|
4
|
+
ext = {
|
5
|
+
:permitted_type => (ext.blank? ? nil : ext.class.name),
|
6
|
+
:permitted_id => (ext.blank? ? nil : ext.id) } unless ext.is_a? Hash
|
7
|
+
|
8
|
+
context = {:route => route}.merge(ext)
|
7
9
|
|
8
|
-
|
9
|
-
attr_accessor :parental_resource_permission
|
10
|
+
create_default_permission!(route, ext) unless permissions.exists?(context)
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
permissions.first(:conditions => context)
|
13
|
+
end
|
14
|
+
|
15
|
+
def permission?(route, ext = nil)
|
16
|
+
permission = permission(route, ext)
|
17
|
+
permission.value? if permission.present?
|
18
|
+
end
|
14
19
|
|
15
|
-
|
20
|
+
def create_permission!(route, value, ext = nil)
|
21
|
+
return unless self.class.permittable?(route)
|
16
22
|
|
17
|
-
|
18
|
-
|
23
|
+
ext = {
|
24
|
+
:permitted_type => (ext.blank? ? nil : ext.class.name),
|
25
|
+
:permitted_id => (ext.blank? ? nil : ext.id) } unless ext.is_a? Hash
|
19
26
|
|
20
|
-
|
21
|
-
|
27
|
+
context = {:route => route}.merge(ext)
|
28
|
+
parameters = context.merge(:value => value)
|
29
|
+
|
30
|
+
permissions.create(parameters) unless permissions.exists?(context)
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_default_permissions!
|
34
|
+
permissions = self.class.permissions.map do |route, masks|
|
35
|
+
masks.map do |mask|
|
36
|
+
ext = mask.dup
|
37
|
+
value = ext.delete(:value)
|
38
|
+
|
39
|
+
create_permission!(route, value, ext)
|
22
40
|
end
|
23
|
-
|
41
|
+
end
|
42
|
+
|
43
|
+
permissions.flatten!
|
44
|
+
permissions.compact
|
45
|
+
end
|
46
|
+
|
47
|
+
def mass_assignment_authorizer
|
48
|
+
super + [:permissions_attributes]
|
24
49
|
end
|
25
|
-
end
|
26
50
|
|
27
|
-
module InstanceMethods
|
28
51
|
def has_permission?(action)
|
29
|
-
|
30
|
-
|
52
|
+
ActiveSupport::Deprecation.warn 'has_permission?(action) is deprecated ' +
|
53
|
+
'and may be removed from future releases, use permission?(route, ext ' +
|
54
|
+
'= nil) instead.'
|
55
|
+
|
56
|
+
permission? [self.class.name.tableize, action].join('#')
|
57
|
+
end
|
58
|
+
|
59
|
+
protected
|
60
|
+
|
61
|
+
def create_default_permission!(route, ext = nil)
|
62
|
+
return unless self.class.permittable?(route)
|
63
|
+
|
64
|
+
ext = {
|
65
|
+
:permitted_type => (ext.blank? ? nil : ext.class.name),
|
66
|
+
:permitted_id => (ext.blank? ? nil : ext.id) } unless ext.is_a? Hash
|
67
|
+
|
68
|
+
masks = self.class.permissions[route.to_sym].select do |mask|
|
69
|
+
mask[:permitted_id] == ext[:permitted_id] &&
|
70
|
+
mask[:permitted_type] == ext[:permitted_type]
|
31
71
|
end
|
32
72
|
|
33
|
-
if
|
34
|
-
|
35
|
-
|
36
|
-
false
|
73
|
+
if (mask = masks.first).present?
|
74
|
+
parameters = mask.merge({:route => route.to_s})
|
75
|
+
permissions.create(parameters)
|
37
76
|
end
|
38
77
|
end
|
78
|
+
end
|
39
79
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
self.update_permission = self.edit_permission if self.respond_to?('edit_permission') && self.respond_to?('update_permission')
|
44
|
-
self.create_permission = self.new_permission if self.respond_to?('new_permission') && self.respond_to?('create_permission')
|
45
|
-
true
|
80
|
+
module Permitted
|
81
|
+
def permitted?(object, route)
|
82
|
+
object.permission?(route, self)
|
46
83
|
end
|
47
84
|
end
|
48
85
|
end
|
49
86
|
|
50
|
-
ActiveRecord::Base
|
51
|
-
|
87
|
+
class ActiveRecord::Base
|
88
|
+
def self.is_able_to_be_permitted
|
89
|
+
has_many :permissions, :as => :permitted, :dependent => :destroy
|
90
|
+
validates_associated :permissions
|
91
|
+
|
92
|
+
include ActsAsPermission::Permitted
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.acts_as_permission(acl)
|
96
|
+
@acl = acl.to_a.inject({}) do |list, permission|
|
97
|
+
route, masks = permission.to_a[0], permission.to_a[1]
|
98
|
+
masks = [masks] unless masks.is_a?(Array)
|
99
|
+
|
100
|
+
permission = {:value => masks.first}
|
101
|
+
permission.freeze
|
102
|
+
|
103
|
+
extensions = masks[1] || []
|
104
|
+
extensions = [extensions] unless extensions.is_a?(Array)
|
105
|
+
extensions.map! do |ext|
|
106
|
+
ext ||= {}
|
107
|
+
ext.freeze
|
108
|
+
end
|
109
|
+
|
110
|
+
permissions = extensions.unshift(permission)
|
111
|
+
permissions.compact!
|
112
|
+
permissions.uniq!
|
113
|
+
permissions.freeze
|
114
|
+
|
115
|
+
list.update({route.to_sym => permissions})
|
116
|
+
end
|
117
|
+
|
118
|
+
@acl.freeze
|
119
|
+
|
120
|
+
has_many :permissions, :as => :permittable, :dependent => :destroy
|
121
|
+
accepts_nested_attributes_for :permissions, :allow_destroy => true
|
122
|
+
validates_associated :permissions
|
123
|
+
|
124
|
+
class << self
|
125
|
+
def permittable?(route)
|
126
|
+
@acl.has_key?(route.to_sym)
|
127
|
+
end
|
128
|
+
|
129
|
+
def permissions
|
130
|
+
@acl
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
include ActsAsPermission::Permittable
|
135
|
+
end
|
136
|
+
end
|