activeaclplus 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/README.rdoc +125 -49
- data/Rakefile +13 -14
- data/{generators/active_acl/templates → app}/controllers/privileges_controller.rb +1 -1
- data/{lib → app/models}/active_acl/acl.rb +5 -5
- data/{lib → app/models}/active_acl/acl_section.rb +3 -3
- data/{lib → app/models}/active_acl/controller_action.rb +1 -1
- data/{lib → app/models}/active_acl/controller_group.rb +1 -1
- data/{lib → app/models}/active_acl/privilege.rb +0 -0
- data/{lib → app/models}/active_acl/requester_group_link.rb +0 -0
- data/{lib → app/models}/active_acl/requester_link.rb +0 -0
- data/{lib → app/models}/active_acl/target_group_link.rb +0 -0
- data/{lib → app/models}/active_acl/target_link.rb +0 -0
- data/{generators/active_acl/templates/views → app/view}/privileges/_privilege_form.rhtml +0 -0
- data/{generators/active_acl/templates/views → app/view}/privileges/edit.rhtml +0 -0
- data/{generators/active_acl/templates/views → app/view}/privileges/list.rhtml +0 -0
- data/db/migrate/001_base_table_setup.rb +7 -4
- data/init.rb +7 -1
- data/lib/active_acl/acts_as_access_group.rb +17 -22
- data/lib/active_acl/acts_as_access_object.rb +41 -208
- data/lib/active_acl/base.rb +17 -0
- data/lib/active_acl/cache/memcache_adapter.rb +12 -10
- data/lib/active_acl/cache/no_cache_adapter.rb +5 -5
- data/lib/active_acl/db/active_record_adapter.rb +3 -3
- data/lib/active_acl/db/mysql_adapter.rb +2 -2
- data/lib/active_acl/grant.rb +38 -0
- data/lib/active_acl/handler/nested_set.rb +33 -0
- data/lib/active_acl/handler/object_handler.rb +250 -0
- data/lib/active_acl/load_controller_actions.rb +1 -3
- data/lib/active_acl/privilege_const_set.rb +2 -2
- data/lib/active_acl.rb +11 -5
- metadata +35 -27
- data/generators/active_acl/active_acl_generator.rb +0 -29
data/CHANGELOG
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
ActiveAcl rails authorization system
|
2
2
|
|
3
|
+
Version 0.4.0 - 2008/03/08
|
4
|
+
- complete rewrite of the SQL generation
|
5
|
+
- abstraction of the grouping
|
6
|
+
- added #grant_privilege
|
7
|
+
- dropped test, moving to rspec
|
8
|
+
- allows ungrouped requesters/targets
|
9
|
+
- propper namespace handling of options (THANKS http://github.com/garytaylor)
|
10
|
+
|
11
|
+
Version 0.3.1 - 2008/12/11
|
12
|
+
- forgot active_acl.rb in gem
|
13
|
+
- fixed generator
|
14
|
+
|
3
15
|
Version 0.3.0 - 2008/12/07
|
4
16
|
- Renamed Project to ActiveACLPlus
|
5
17
|
- code cleanup
|
data/README.rdoc
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
The ActiveAclPlus plugin implements a flexible, fast and easy to use generic access control system.
|
3
3
|
|
4
4
|
==License
|
5
|
-
ActiveAclPlus is released under the LGPL[http://www.opensource.org/licenses/lgpl-license.php]
|
5
|
+
ActiveAclPlus is released under the LGPL[http://www.opensource.org/licenses/lgpl-license.php]
|
6
|
+
(Gnu Lesser General Public License) - see the included LICENSE file, too.
|
6
7
|
|
7
8
|
==Features
|
8
9
|
* ease of use - uses polymorphic collections for associations.
|
@@ -10,11 +11,10 @@ ActiveAclPlus is released under the LGPL[http://www.opensource.org/licenses/lgpl
|
|
10
11
|
* scalable - there are no real benchmarks yet. But the system design is based on http://phpgacl.sourceforge.net, adding object orientation, polymorphism and two levels of caching. PhpGacl claims "A real-world working version with many added layers of complexity supports over 60,000 Accounts, 200 Groups and 300 ACO's." Tests on my dev notebook show 10 - 30 times performance improvements compared to active_rbac.
|
11
12
|
* caching - uses instance caching and optionally stores permission results in memcached using timeouts.
|
12
13
|
* flexible - grants simple (2D, like <code>current_user.has_permission?(User::LOGIN)</code>) and object level (3D, like <code>admin.has_permission?(Forum::ADMIN, :on => team_forum)</code>) permissions. Can assign and request permissions to and from every ActiveRecord model. No "hardcoded" permissions - all permissions can be assigned at runtime.
|
13
|
-
* grouping - permissions
|
14
|
+
* grouping - permissions can be inherited at target and requester side through groups. Every model implementing an SQL nested set tree may be used as a group.
|
14
15
|
* ControllerAction model loader: It maps controller actions to the DB so they can be used in permission assignment. The access object is available via calling <code>current_action</code> on the controller.
|
15
16
|
* exchangeable DB interface: ActiveRecord and direct MySQL adapter available
|
16
17
|
* supports namespaced models and single table inheritance (STI)
|
17
|
-
* 100 % C0 code coverage on unit tests
|
18
18
|
|
19
19
|
==Limitations
|
20
20
|
* At present only one grouping type per model is supported. This could be changed on request but I don't see a use case for it yet.
|
@@ -25,41 +25,76 @@ ActiveAclPlus is released under the LGPL[http://www.opensource.org/licenses/lgpl
|
|
25
25
|
ActiveAclPlus uses the has_many_polymorphs[http://www.agilewebdevelopment.com/plugins/restful_authentication] plugin. Make shure you've got a recent version, old versions have bugs affecting active_acl_plus.
|
26
26
|
!!Be sure you have the paches for 2.1, see: http://rubyforge.org/forum/forum.php?thread_id=26041&forum_id=16450
|
27
27
|
|
28
|
-
./script/plugin install git://github.com/popel/active_acl_plus.git
|
28
|
+
./script/plugin install git://github.com/popel/active_acl_plus.git
|
29
29
|
|
30
|
-
|
30
|
+
or
|
31
31
|
|
32
|
+
sudo gem install activeaclplus
|
33
|
+
|
34
|
+
or from a github repository.
|
35
|
+
|
36
|
+
If you want to use grouped access objects you should install some kind of nested_set plugin
|
37
|
+
(awesome_nested_set,better_nested_set,...).
|
32
38
|
==Short summary
|
33
|
-
The ActiveAclPlus system consists of access objects,
|
39
|
+
The ActiveAclPlus system consists of access objects, which can be organized by access groups,
|
40
|
+
that request privileges on each other. Allowing or denying access to a privilege is controlled by
|
41
|
+
ACL (access control list entry) objects. Access objects and access groups can be instances of arbitrary
|
42
|
+
ActiveRecord model classes enhanced by acts_as_access_object and acts_as_access_group. They are associated
|
43
|
+
to ACL entries via polymorphic associations.
|
34
44
|
|
35
45
|
===Access objects
|
36
|
-
These are basically requesters and targets in the permission system, as for example a User or a Forum model object.
|
46
|
+
These are basically requesters and targets in the permission system, as for example a User or a Forum model object.
|
47
|
+
In this case a user could act as a requester ("do I have privilege Y?") or target ("does access object X have
|
48
|
+
privilege Y on me?"). A Forum would most certainly be only used as a target, but all access objects can theoretically
|
49
|
+
be used as both requesters and targets. Access objects use the acts_as_access_object macro inside their definition.
|
50
|
+
This registers the model with the ACL system and enhances it with methods like has_privilege?.
|
37
51
|
|
38
|
-
|
52
|
+
See: ActiveAcl::Acts::AccessObject::ClassMethods, ActiveAcl::Acts::AccessObject::InstanceMethods,
|
53
|
+
ActiveAcl::Acts::AccessObject::SingletonMethods, ActiveAcl::Acts::Grant
|
39
54
|
|
40
55
|
|
41
|
-
|
42
|
-
|
56
|
+
Every access object class can specify an association that is used as the "grouping type" to it. So User may declare
|
57
|
+
has_and_belongs_to_many :user_groups and use acts_as_access_object :grouped_by => :user_groups. You can use
|
58
|
+
a has_and_belongs_to_many or a belongs_to association for this. Common mapping attributes
|
59
|
+
(:join_table, :foreign_key etc.) are supported.
|
43
60
|
|
44
|
-
|
61
|
+
===Access groups
|
62
|
+
The access group model needs to implement a tree with nested set semantics having a "left" and "right"
|
63
|
+
column, e.g. by using the built-in acts_as_nested_set or the much more recommended acts_as_betted_nested_set
|
64
|
+
plugin. Groups are declared with acts_as_access_group.
|
45
65
|
|
66
|
+
Groups may be used to specify inheritance hierarchies for permissions. So you could have a 'registered users'
|
67
|
+
group as a subgroup of the 'users' group and assign the privilege to log in to this group via an ACL entry.
|
68
|
+
Every user belonging to this group will now be granted the privilege to log in. Then you could add a subgroup
|
69
|
+
to registerd users, 'banned users', and deny the log in privilege for this group. Every user added to this
|
70
|
+
group would now be unable to log in, regardless of beeing in 'registered users' or not, as 'banned users' would
|
71
|
+
override the permission settings of 'registered users'.
|
46
72
|
|
47
73
|
===Privileges
|
48
|
-
A privilege object is an object for the thing we wish to define a permission for. So User::LOGIN could be a
|
49
|
-
|
50
|
-
A privilege object itself is little more than it’s name and id and is usually bound to a constant inside the application, as it is not expected to change at runtime. Privileges are usually created by the developer in the source code and not in the admin frontend, as creating new privilege objects that have no meaning (by code that checks for them) would be pointless.
|
74
|
+
A privilege object is an object for the thing we wish to define a permission for. So User::LOGIN could be a
|
75
|
+
privilege object for checking a users permission to log in, while Forum::ADMIN might define administration rights on a forum.
|
51
76
|
|
77
|
+
A privilege object itself is little more than it’s name and id and is usually bound to a constant inside the
|
78
|
+
application, as it is not expected to change at runtime. Privileges are usually created by the developer in
|
79
|
+
the source code and not in the admin frontend, as creating new privilege objects that have no meaning (by code
|
80
|
+
that checks for them) would be pointless.
|
52
81
|
|
53
82
|
===Access Control List (ACL) entries
|
54
|
-
ACL entries are the glue between all these objects, defining which requesters and requester groups have access
|
55
|
-
|
83
|
+
ACL entries are the glue between all these objects, defining which requesters and requester groups have access
|
84
|
+
to which privileges, optionally defining target objects and target groups as well. ACL entries are organized by
|
85
|
+
ACL sections, for better overview in the admin screens.
|
56
86
|
|
57
87
|
==Usage
|
58
88
|
===In short
|
59
|
-
"No access defined" for a privilege evaluates to "deny". This may be overriden by an explicit "allow" or "deny".
|
89
|
+
"No access defined" for a privilege evaluates to "deny". This may be overriden by an explicit "allow" or "deny".
|
90
|
+
Privileges are inherited in requestor and target groups, this means you can override them in subgroups again.
|
91
|
+
Privileges directly assigned to an object always supercede those assigned to groups.
|
60
92
|
|
61
93
|
===Simple (2D) permissions
|
62
|
-
We want all registered users to be able to log in. We create the User model, the UserGroup model and the
|
94
|
+
We want all registered users to be able to log in. We create the User model, the UserGroup model and the
|
95
|
+
User::LOGIN privilege object as described above. Then we create a new ACL entry, set 'allow' to true, add
|
96
|
+
the "registered users" group as requester group, User::LOGIN as privilege and we are done. Every user assigned
|
97
|
+
to "registered users" or a subgroup of it will now be granted access by calling <code>my_user.has_privilege?(User::LOGIN)</code>.
|
63
98
|
|
64
99
|
====Simple permissions example
|
65
100
|
|
@@ -78,22 +113,29 @@ We want all registered users to be able to log in. We create the User model, the
|
|
78
113
|
# assume 'registered_users' exists and users 'john' and 'dr_evil' are members of it but 'anonymous' is not.
|
79
114
|
registered_users = UserGroup.find_by_name('registered_users')
|
80
115
|
|
116
|
+
the hard way:
|
81
117
|
acl = ActiveAcl::Acl.create :section => ActiveAcl::AclSection.create(:description => 'users')
|
82
118
|
|
83
119
|
acl.allow = true # true is default
|
84
120
|
acl.privileges << User::LOGIN
|
85
|
-
acl.
|
121
|
+
acl.iname="login"
|
86
122
|
acl.save
|
87
123
|
|
88
124
|
acl.requester_groups << registered_users
|
89
125
|
|
126
|
+
or much easier:
|
127
|
+
|
128
|
+
registered_users.grant_privilege!(User::LOGIN,:section_name => 'users',:acl_name => 'login')
|
129
|
+
|
90
130
|
john.has_privilege?(User::LOGIN) #=> true
|
91
131
|
dr_evil.has_privilege?(User::LOGIN) #=> true
|
92
132
|
|
93
133
|
anonymous.has_privilege?(User::LOGIN) #=> false
|
94
134
|
|
95
135
|
===Overriding permissions
|
96
|
-
We want to ban specific users from our site. We create another ACL entry, assign the User::LOGIN privilege
|
136
|
+
We want to ban specific users from our site. We create another ACL entry, assign the User::LOGIN privilege
|
137
|
+
object, set 'allow' to false and then assign these users as requesters to the ACL entry. The direct
|
138
|
+
permission assignment on the objects overrides the 'allow login' ACL entry from above.
|
97
139
|
|
98
140
|
====Overriding permissions example
|
99
141
|
|
@@ -109,11 +151,17 @@ We want to ban specific users from our site. We create another ACL entry, assign
|
|
109
151
|
dr_evil.has_privilege?(User::LOGIN) #=> false
|
110
152
|
|
111
153
|
===Object level (3D) permissions
|
112
|
-
We want to assign forum permissions. We have several privileges (Forum::ADMIN, Forum::READ, Forum::POST etc.),
|
154
|
+
We want to assign forum permissions. We have several privileges (Forum::ADMIN, Forum::READ, Forum::POST etc.),
|
155
|
+
the afore mentioned User and UserGroup models as well as a Forum and a Category model for grouping the forums.
|
113
156
|
|
114
|
-
If we want to check if a certain user may read in a certain forum, it is not sufficient to check
|
157
|
+
If we want to check if a certain user may read in a certain forum, it is not sufficient to check
|
158
|
+
<code>test_user.has_privilege?(Forum::READ)</code> as the target object - in this case a forum - is needed
|
159
|
+
to make a decision. The code to do the check is like <code>test_user.has_privilege?(Forum::READ, :on => teamforum)</code>.
|
115
160
|
|
116
|
-
To make this work you create a new ACL entry, add Forum::POST and Forum::READ as privileges, set 'allow' to
|
161
|
+
To make this work you create a new ACL entry, add Forum::POST and Forum::READ as privileges, set 'allow' to
|
162
|
+
true, add the registered users group as a requester group and the public forums category as a target group
|
163
|
+
to the acl. Now every user belonging to the registered users group or a subgroup of it gains post and read
|
164
|
+
privileges on all forums of the public forums category or a subcategory of it.
|
117
165
|
|
118
166
|
====Object level permissions example
|
119
167
|
|
@@ -152,43 +200,71 @@ To make this work you create a new ACL entry, add Forum::POST and Forum::READ as
|
|
152
200
|
anonymous.has_privilege?(Forum::READ, :on => speakers) #=> false
|
153
201
|
|
154
202
|
==CAUTION
|
155
|
-
Do not create ACL entries that are on different branches of the inheritance hierarchy and have
|
156
|
-
|
157
|
-
|
203
|
+
Do not create ACL entries that are on different branches of the inheritance hierarchy and have
|
204
|
+
allow/deny set differently on the same privilege objects. This way it's impossible to tell which
|
205
|
+
permission should take precedence. At present this is by creation date, later entries superceding older
|
206
|
+
ones, but this is most certainly not what you want.
|
158
207
|
|
159
208
|
==Controller Actions
|
160
|
-
Defining permissions on controller actions (like "may user x execute AdminController.list ?") is quite a
|
209
|
+
Defining permissions on controller actions (like "may user x execute AdminController.list ?") is quite a
|
210
|
+
common case but we are facing a problem here: Controller actions have no corresponding DB models so
|
211
|
+
permissions on them can't be easily defined.
|
161
212
|
|
162
|
-
ActiveAclPlus solves this by adding a ControllerAction and ControllerGroup model. For every public
|
213
|
+
ActiveAclPlus solves this by adding a ControllerAction and ControllerGroup model. For every public
|
214
|
+
controller method (=action) there is one ControllerAction object in the DB.
|
163
215
|
|
164
|
-
On application startup, the plugin loader checks all controller files in app/controllers and loads
|
216
|
+
On application startup, the plugin loader checks all controller files in app/controllers and loads
|
217
|
+
or creates a ControllerAction object for every action it finds. These objects get cached in a hash
|
218
|
+
in the ActiveAclPlus module. Every controller now has a method <code>current_action</code> that looks
|
219
|
+
up and returns the access object for the current action, so it can be used for access checks like
|
220
|
+
<code>current_user.has_privilege?(ActiveAcl::ControllerAction::EXECUTE, :on => current_action)</code>.
|
165
221
|
|
166
222
|
This works nicely for before_filters with authorization checks.
|
167
223
|
|
168
|
-
A word on the load mechanism: If the action has no corresponding DB entry (it's looked up on method creation
|
224
|
+
A word on the load mechanism: If the action has no corresponding DB entry (it's looked up on method creation
|
225
|
+
by controller and action name) the loader searches for a controller group with the same name as the
|
226
|
+
controller. If it is found, the action is created and assigned to this group. Else the controller group
|
227
|
+
is created as a subgroup to the "unassigned controller actions" group (this name can be changed in the
|
228
|
+
options) and the unassigned action is added to the controller group.
|
169
229
|
|
170
|
-
So you are free on how to organize your controllers. Maybe create an admin group and a public group and
|
230
|
+
So you are free on how to organize your controllers. Maybe create an admin group and a public group and
|
231
|
+
move controllers as a subgroup inside them?
|
171
232
|
|
172
233
|
==Caching
|
173
|
-
The plugin provides two levels of caching. The instance cache is a hash inside the access object. The object
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
234
|
+
The plugin provides two levels of caching. The instance cache is a hash inside the access object. The object
|
235
|
+
first tries to serve a permission request from the instance cache. If it is not found and a simple permission
|
236
|
+
is requested, the query fetches all simple permissions (2D) of the object and puts them in the instance cache. The
|
237
|
+
reason for this is that there is no noticable speed penalty in fetching all 2D permissions at once compared to
|
238
|
+
fetching only one, so this will save time and DB IO later on. Complex 3D queries are fetched independently
|
239
|
+
and also saved to the instance cache. The instance cache lives inside the access object, so it has it's
|
240
|
+
lifetime, too - which in rails usually is no more than a single request.
|
241
|
+
|
242
|
+
The second level cache tries to overcome this limitation by putting the instance cache of an access object
|
243
|
+
in an external cache. It tries to get the instance cache from there if it is not set, and sets it if it was
|
244
|
+
changed. The only real implementation for now is with the memcache daemon. The second level cache uses a timeout
|
245
|
+
(which can be defined in the options) to expire the cached permissions.
|
246
|
+
|
247
|
+
Instance and second level cache can be expired explicitly by calling <code>active_acl_clear_cache!</code>
|
248
|
+
on the access object. Calling <code>reload</code> on the object also purges the caches.
|
178
249
|
|
179
250
|
See ActiveAcl::Cache::MemcacheAdapter on how to set it up.
|
180
251
|
|
181
252
|
|
182
253
|
==Preloader
|
183
|
-
The plugin includes a <code>load_files_from filenames</code> function. It can be used to preload source files
|
254
|
+
The plugin includes a <code>load_files_from filenames</code> function. It can be used to preload source files
|
255
|
+
(and therefore the classes in it) from an application path and should be used from environment.rb.
|
184
256
|
|
185
257
|
load_files_from("#{RAILS_ROOT}/app/controllers/**/[^.]*.rb")
|
186
258
|
load_files_from("#{RAILS_ROOT}/app/models/**/[^.]*.rb")
|
187
259
|
|
188
|
-
will load all models and controllers inside these folders and their subfolders. This way you can be shure they
|
260
|
+
will load all models and controllers inside these folders and their subfolders. This way you can be shure they
|
261
|
+
are registered with the ACL system at rails boot time - else they will be registered when they are called for
|
262
|
+
the first time. This means that new controllers will not show up in the admin screens until they were accessed
|
263
|
+
if not using the preloader.
|
189
264
|
|
190
265
|
==Options
|
191
|
-
<code>ActiveAcl::OPTIONS</code> is an array that can be used to override various options for the system by setting
|
266
|
+
<code>ActiveAcl::OPTIONS</code> is an array that can be used to override various options for the system by setting
|
267
|
+
the values in environment.rb. <code>ActiveAcl::DEFAULT_OPTIONS</code> is as follows:
|
192
268
|
|
193
269
|
DEFAULT_OPTIONS = {
|
194
270
|
:acl_sections_table => 'acl_sections',
|
@@ -202,7 +278,8 @@ will load all models and controllers inside these folders and their subfolders.
|
|
202
278
|
:controller_actions_table => 'controller_actions',
|
203
279
|
:controller_groups_table => 'controller_groups',
|
204
280
|
|
205
|
-
:controllers_group_name => 'unassigned_controller_actions', # the name of the base group
|
281
|
+
:controllers_group_name => 'unassigned_controller_actions', # the name of the base group
|
282
|
+
# that newly created controller groups get assigned to
|
206
283
|
:controller_group_name_suffix => '_controller', # name suffix for generated controller groups
|
207
284
|
|
208
285
|
:cache_permission_timeout => 10, # timeout in seconds for the second level cache
|
@@ -212,30 +289,29 @@ will load all models and controllers inside these folders and their subfolders.
|
|
212
289
|
}
|
213
290
|
|
214
291
|
==Tests
|
215
|
-
|
292
|
+
Not anymore, sorry. I'm using RSpec for testing. A repository
|
293
|
+
is/will be setup at http://github.com/popel/active_acl_plus_rspec/tree/master . Check it out and move it to "spec". Run
|
294
|
+
rake spec
|
216
295
|
|
217
296
|
==Credits
|
218
297
|
* Gregor Melhorn implemented this and maintained it up to Version 0.2.1. Thanks for releasing this!
|
219
|
-
* Evan for writing that great polymorph plugin and beeing so kind to add namespace and tablename support on
|
298
|
+
* Evan for writing that great polymorph plugin and beeing so kind to add namespace and tablename support on Gregor's request.
|
220
299
|
* ReinH and markmeves for great support and suggestions at the rubyonrails channel on freenode.org.
|
221
300
|
* http://phpgacl.sourceforge.net as a great source of inspiration
|
222
|
-
* Obrie for writing plugin_migrations and loaded_plugins and also very nice support when
|
301
|
+
* Obrie for writing plugin_migrations and loaded_plugins and also very nice support when Gregor got stuck with using them.
|
223
302
|
|
224
303
|
==ToDo/Ideas
|
225
304
|
|
226
305
|
in no particular order, just a reminder...
|
227
306
|
|
307
|
+
* add materialized_tree_support
|
308
|
+
* use Moneta as key/value store
|
228
309
|
* direct PostgreSQL interface
|
229
|
-
* example on how to integrate with
|
310
|
+
* example on how to integrate with authentication
|
230
311
|
* example on controller actions
|
231
|
-
* make grouping optional
|
232
|
-
* add interface generators (started)
|
233
312
|
* error checking for conflicting ACL entries
|
234
|
-
* permissions should have more attributes (like :until,:left_boni,...)
|
235
313
|
* get all permissions for a requester within a section
|
236
314
|
* get all permissions of a requester (with one query)
|
237
315
|
* get all permissions of a requester on a target (with one query)
|
238
316
|
* get all requester with a given privilege on a target (one query)
|
239
317
|
* get all targets on which a requester has a certain privilege (one query)
|
240
|
-
|
241
|
-
|
data/Rakefile
CHANGED
@@ -18,13 +18,8 @@ Rake::GemPackageTask.new(PKG_GEM) do |p|
|
|
18
18
|
p.need_zip = true
|
19
19
|
end
|
20
20
|
|
21
|
-
desc 'Default: run
|
22
|
-
task :default => :
|
23
|
-
|
24
|
-
#desc "Publish the beta gem"
|
25
|
-
#task :pgem => [:package] do
|
26
|
-
# Rake::SshFilePublisher.new("pluginaweek@pluginaweek.org", "/home/pluginaweek/gems.pluginaweek.org/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
|
27
|
-
#end
|
21
|
+
desc 'Default: run specs'
|
22
|
+
task :default => :spec
|
28
23
|
|
29
24
|
desc "Publish the API documentation"
|
30
25
|
task :pdoc => [:rdoc] do
|
@@ -67,11 +62,16 @@ task :coverage_diff do
|
|
67
62
|
sh "#{RCOV} --rails -T -Ilib -x db/**/* --text-coverage-diff ../../../coverage/active_acl/coverage.info --output ../../../coverage/active_acl test/all_tests.rb"
|
68
63
|
end
|
69
64
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
65
|
+
begin #no spec or spec-rails? ok no tasks
|
66
|
+
require 'spec/rake/spectask'
|
67
|
+
|
68
|
+
desc 'Test the active_acl_plus plugin.'
|
69
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
70
|
+
#t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""]
|
71
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
72
|
+
end
|
73
|
+
rescue LoadError => e
|
74
|
+
puts "No spec tasks! - gem install rspec-rails (#{__FILE__})"
|
75
75
|
end
|
76
76
|
|
77
77
|
desc 'Generate documentation for the active_acl_plus plugin.'
|
@@ -79,6 +79,5 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
79
79
|
rdoc.rdoc_dir = 'rdoc'
|
80
80
|
rdoc.title = 'ActiveAclPlus'
|
81
81
|
rdoc.options << '--line-numbers' << '--inline-source'
|
82
|
-
rdoc.rdoc_files.include('README')
|
83
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
82
|
+
rdoc.rdoc_files.include('README.rdoc','lib/**/*.rb','app/**/*.rb')
|
84
83
|
end
|
@@ -14,8 +14,8 @@ module ActiveAcl
|
|
14
14
|
has_many :requester_group_links, :dependent => :delete_all,:class_name => 'ActiveAcl::RequesterGroupLink'
|
15
15
|
has_many :target_group_links, :dependent => :delete_all,:class_name => 'ActiveAcl::TargetGroupLink'
|
16
16
|
|
17
|
-
validates_uniqueness_of :
|
18
|
-
validates_presence_of :
|
17
|
+
validates_uniqueness_of :iname
|
18
|
+
validates_presence_of :iname
|
19
19
|
|
20
20
|
def self.reloadable? #:nodoc:
|
21
21
|
return false
|
@@ -23,11 +23,11 @@ module ActiveAcl
|
|
23
23
|
|
24
24
|
# used as instance description in admin screen
|
25
25
|
def active_acl_description
|
26
|
-
if
|
26
|
+
if iname
|
27
27
|
if section
|
28
|
-
'/' + section.description + '/' +
|
28
|
+
'/' + section.description + '/' + iname
|
29
29
|
else
|
30
|
-
return
|
30
|
+
return iname
|
31
31
|
end
|
32
32
|
else
|
33
33
|
return nil
|
@@ -6,11 +6,11 @@ module ActiveAcl
|
|
6
6
|
|
7
7
|
has_many :members, :class_name => 'ActiveAcl::Acl', :foreign_key => 'section_id'
|
8
8
|
|
9
|
-
validates_presence_of :
|
10
|
-
validates_uniqueness_of :
|
9
|
+
validates_presence_of :iname
|
10
|
+
validates_uniqueness_of :iname
|
11
11
|
|
12
12
|
# Make shure there are no associated acls before destroying a section
|
13
|
-
def before_destroy
|
13
|
+
def before_destroy #:nodoc:
|
14
14
|
if members.empty?
|
15
15
|
true
|
16
16
|
else
|
@@ -3,7 +3,7 @@
|
|
3
3
|
class ActiveAcl::ControllerAction < ActiveRecord::Base
|
4
4
|
set_table_name ActiveAcl::OPTIONS[:controller_actions_table]
|
5
5
|
privilege_const_set('EXECUTE')
|
6
|
-
|
6
|
+
|
7
7
|
belongs_to :controller_group, :class_name => 'ActiveAcl::ControllerGroup'
|
8
8
|
acts_as_access_object :grouped_by => :"active_acl/controller_group"
|
9
9
|
validates_presence_of :action, :controller, :controller_group
|
@@ -3,7 +3,7 @@ class ActiveAcl::ControllerGroup < ActiveRecord::Base
|
|
3
3
|
set_table_name ActiveAcl::OPTIONS[:controller_groups_table]
|
4
4
|
acts_as_nested_set
|
5
5
|
has_many :controller_actions,:class_name => 'ActiveAcl::ControllerAction'
|
6
|
-
acts_as_access_group
|
6
|
+
acts_as_access_group :type => ActiveAcl::Acts::AccessGroup::NestedSet
|
7
7
|
|
8
8
|
validates_presence_of :description
|
9
9
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -2,22 +2,25 @@ class BaseTableSetup < ActiveRecord::Migration
|
|
2
2
|
def self.up
|
3
3
|
create_table ActiveAcl::OPTIONS[:acls_table] do |t|
|
4
4
|
t.column :section_id, :int
|
5
|
+
t.column :iname, :string,:null => false
|
5
6
|
t.column :allow, :boolean, :null => false, :default => true
|
6
7
|
t.column :enabled, :boolean, :null => false, :default => true
|
7
|
-
t.column :
|
8
|
+
t.column :description, :text, :null => true
|
8
9
|
t.column :updated_at, :datetime, :null => false
|
9
10
|
end
|
10
11
|
|
11
12
|
add_index ActiveAcl::OPTIONS[:acls_table], :enabled
|
12
13
|
add_index ActiveAcl::OPTIONS[:acls_table], :section_id
|
13
14
|
add_index ActiveAcl::OPTIONS[:acls_table], :updated_at
|
14
|
-
add_index ActiveAcl::OPTIONS[:acls_table], :
|
15
|
+
add_index ActiveAcl::OPTIONS[:acls_table], :iname, :unique
|
16
|
+
|
15
17
|
|
16
18
|
create_table ActiveAcl::OPTIONS[:acl_sections_table] do |t|
|
17
|
-
t.column :
|
19
|
+
t.column :iname, :string, :null => false
|
20
|
+
t.column :description, :text, :null => true
|
18
21
|
end
|
19
22
|
|
20
|
-
add_index ActiveAcl::OPTIONS[:acl_sections_table], :
|
23
|
+
add_index ActiveAcl::OPTIONS[:acl_sections_table], :iname, :unique
|
21
24
|
|
22
25
|
create_table ActiveAcl::OPTIONS[:privileges_table] do |t|
|
23
26
|
t.column :section, :string, :limit => 230, :null => false
|
data/init.rb
CHANGED
@@ -1 +1,7 @@
|
|
1
|
-
|
1
|
+
raise "This Rails version is not supported by ActiveAclPlus" if Rails.version < "2.1.0"
|
2
|
+
|
3
|
+
if Rails.version < "2.3.0"
|
4
|
+
model_path=File.join(File.dirname(__FILE__),'app','models')
|
5
|
+
ActiveSupport::Dependencies.load_paths << model_path
|
6
|
+
end
|
7
|
+
require 'active_acl'
|
@@ -7,38 +7,33 @@ module ActiveAcl #:nodoc:
|
|
7
7
|
def self.included(base)
|
8
8
|
base.extend(ClassMethods)
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
module ClassMethods
|
12
|
-
# Extend self with access group capabilites.
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
12
|
+
# Extend self with access group capabilites.
|
13
|
+
# Options can be:
|
14
|
+
# type:: is mandatory and is one of the group handler classes
|
15
|
+
# left_column:: for ActiveAcl::Acts::AccessGroup::NestedSet grouped objects
|
16
|
+
# right_column:: for ActiveAcl::Acts::AccessGroup::NestedSet grouped objects
|
17
|
+
|
17
18
|
def acts_as_access_group(options = {})
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
type=options.delete(:type) || ActiveAcl::Acts::AccessGroup::NestedSet
|
20
|
+
ActiveAcl::GROUP_CLASSES[self.name] = type.new(options)
|
21
|
+
|
22
|
+
include ActiveAcl::Acts::Grant
|
23
|
+
include InstanceMethods
|
24
|
+
extend SingletonMethods
|
23
25
|
|
24
|
-
from_classes = ActiveAcl::GROUP_CLASSES.keys.collect do |x|
|
25
|
-
x.split('::').join('/').underscore.pluralize.to_sym
|
26
|
-
end
|
27
|
-
|
28
26
|
ActiveAcl::Acl.instance_eval do
|
29
|
-
has_many_polymorphs :requester_groups, {:from => from_classes,
|
27
|
+
has_many_polymorphs :requester_groups, {:from => ActiveAcl.from_classes,
|
30
28
|
:through => :"active_acl/requester_group_links",
|
31
29
|
:rename_individual_collections => true}
|
32
|
-
|
33
|
-
has_many_polymorphs :target_groups, {:from => from_classes,
|
30
|
+
|
31
|
+
has_many_polymorphs :target_groups, {:from => ActiveAcl.from_classes,
|
34
32
|
:through => :"active_acl/target_group_links",
|
35
33
|
:rename_individual_collections => true}
|
36
34
|
end
|
37
35
|
|
38
|
-
|
39
|
-
extend SingletonMethods
|
40
|
-
|
41
|
-
end
|
36
|
+
end
|
42
37
|
end
|
43
38
|
|
44
39
|
module SingletonMethods
|