has_roles 0.0.2 → 0.3.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/CHANGELOG.rdoc +46 -0
- data/{MIT-LICENSE → LICENSE} +2 -2
- data/README.rdoc +92 -0
- data/Rakefile +49 -39
- data/app/models/permission.rb +48 -31
- data/app/models/role.rb +32 -24
- data/app/models/role_assignment.rb +5 -6
- data/app/models/role_permission.rb +25 -0
- data/db/migrate/{002_create_permissions.rb → 001_create_permissions.rb} +4 -5
- data/db/migrate/{003_create_roles.rb → 002_create_roles.rb} +1 -3
- data/db/migrate/003_create_role_permissions.rb +11 -0
- data/db/migrate/{005_create_role_assignments.rb → 004_create_role_assignments.rb} +2 -3
- data/lib/has_roles/authorization_helper.rb +66 -47
- data/lib/has_roles/url_helper.rb +38 -0
- data/lib/has_roles.rb +29 -56
- data/test/app_root/app/controllers/admin/base_controller.rb +2 -0
- data/test/app_root/app/controllers/admin/users_controller.rb +10 -1
- data/test/app_root/app/controllers/application_controller.rb +7 -0
- data/test/app_root/config/environment.rb +6 -19
- data/test/app_root/config/routes.rb +1 -0
- data/test/app_root/db/migrate/001_create_users.rb +1 -1
- data/test/app_root/db/migrate/002_migrate_has_roles_to_version_4.rb +13 -0
- data/test/factory.rb +63 -0
- data/test/functional/application_controller_test.rb +45 -0
- data/test/functional/has_roles_test.rb +68 -0
- data/test/helpers/authorization_helper_test.rb +92 -0
- data/test/helpers/url_helper_test.rb +35 -0
- data/test/test_helper.rb +13 -4
- data/test/unit/permission_test.rb +92 -27
- data/test/unit/role_assignment_test.rb +46 -15
- data/test/unit/role_permission_test.rb +34 -0
- data/test/unit/role_test.rb +122 -20
- metadata +93 -78
- data/CHANGELOG +0 -19
- data/README +0 -83
- data/app/models/controller.rb +0 -82
- data/db/migrate/001_create_controllers.rb +0 -13
- data/db/migrate/004_create_permissions_roles.rb +0 -13
- data/test/app_root/app/controllers/payment/pay_pal/transactions_controller.rb +0 -2
- data/test/app_root/app/controllers/payment/transactions_controller.rb +0 -2
- data/test/fixtures/controllers.yml +0 -19
- data/test/fixtures/permissions.yml +0 -27
- data/test/fixtures/permissions_roles.yml +0 -15
- data/test/fixtures/role_assignments.yml +0 -17
- data/test/fixtures/roles.yml +0 -11
- data/test/fixtures/users.yml +0 -11
- data/test/unit/authorization_helper_test.rb +0 -40
- data/test/unit/controller_test.rb +0 -95
- data/test/unit/has_roles_test.rb +0 -49
data/README
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
= has_roles
|
2
|
-
|
3
|
-
+has_roles+ provides simple role management based on controllers/actions.
|
4
|
-
|
5
|
-
== Resources
|
6
|
-
|
7
|
-
API
|
8
|
-
|
9
|
-
* http://api.pluginaweek.org/has_roles
|
10
|
-
|
11
|
-
Wiki
|
12
|
-
|
13
|
-
* http://wiki.pluginaweek.org/Has_roles
|
14
|
-
|
15
|
-
Announcement
|
16
|
-
|
17
|
-
* http://www.pluginaweek.org
|
18
|
-
|
19
|
-
Source
|
20
|
-
|
21
|
-
* http://svn.pluginaweek.org/trunk/plugins/active_record/has/has_roles
|
22
|
-
|
23
|
-
Development
|
24
|
-
|
25
|
-
* http://dev.pluginaweek.org/browser/trunk/plugins/active_record/has/has_roles
|
26
|
-
|
27
|
-
== Description
|
28
|
-
|
29
|
-
One of the easiest and most straightforward techniques for adding role management
|
30
|
-
and authorization to specific parts of your application is restricting usage on
|
31
|
-
controller/action-basis. Each role defined in your system is mapped to one or
|
32
|
-
more permissions. Each permission is a combination of a controller and action.
|
33
|
-
|
34
|
-
== Usage
|
35
|
-
|
36
|
-
=== Checking a user's authorization
|
37
|
-
|
38
|
-
Below is an example of checking a user's authorization for a url before display
|
39
|
-
information:
|
40
|
-
|
41
|
-
app/views/layouts/application.rhtml:
|
42
|
-
|
43
|
-
<% if authorized_for?(:controller => 'admin/users') -%>
|
44
|
-
<p>Read to start administering your website?</p>
|
45
|
-
<% end -%>
|
46
|
-
|
47
|
-
=== Global authorization
|
48
|
-
|
49
|
-
You can define a global permission that will add access for all controllers by
|
50
|
-
defining a controller with the path 'application'. See the test fixtures for
|
51
|
-
more information.
|
52
|
-
|
53
|
-
=== Running migrations
|
54
|
-
|
55
|
-
To migrate the tables required for this plugin, you can either run the
|
56
|
-
migration from the command line like so:
|
57
|
-
|
58
|
-
rake db:migrate:plugins PLUGIN=has_roles
|
59
|
-
|
60
|
-
or (more ideally) generate a migration file that will integrate into your main
|
61
|
-
application's migration path:
|
62
|
-
|
63
|
-
ruby script/generate plugin_migration has_roles
|
64
|
-
|
65
|
-
== Testing
|
66
|
-
|
67
|
-
Before you can run any tests, the following gems must be installed:
|
68
|
-
* plugin_test_helper[http://wiki.pluginaweek.org/Plugin_test_helper]
|
69
|
-
* dry_validity_assertions[http://wiki.pluginaweek.org/Dry_validity_assertions]
|
70
|
-
|
71
|
-
== Dependencies
|
72
|
-
|
73
|
-
This plugin is a plugin+. That means that it contains a slice of an
|
74
|
-
application, such as models and migrations. To test or use a plugin+, you
|
75
|
-
must have the following plugins/gems installed:
|
76
|
-
* plugin_dependencies[http://wiki.pluginaweek.org/Plugin_dependencies]
|
77
|
-
* loaded_plugins[http://wiki.pluginaweek.org/Loaded_plugins]
|
78
|
-
* appable_plugins[http://wiki.pluginaweek.org/Appable_plugins]
|
79
|
-
* plugin_migrations[http://wiki.pluginaweek.org/Plugin_migrations]
|
80
|
-
|
81
|
-
Instead of installing each individual plugin+ feature, you can install them all
|
82
|
-
at once using the plugins+[http://wiki.pluginaweek.org/Plugins_plus] meta package,
|
83
|
-
which contains all additional features.
|
data/app/models/controller.rb
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
# Represents the name of a controller in the application. The path of the controller
|
2
|
-
# includes its namespace, if any. For example:
|
3
|
-
#
|
4
|
-
# users # => UsersController
|
5
|
-
# admin/users # => Admin::UsersController
|
6
|
-
class Controller < ActiveRecord::Base
|
7
|
-
has_many :permissions,
|
8
|
-
:dependent => :destroy
|
9
|
-
|
10
|
-
validates_presence_of :path
|
11
|
-
validates_format_of :path,
|
12
|
-
:with => /^[a-z]+(\/[a-z]+)*$/i,
|
13
|
-
:allow_nil => true
|
14
|
-
validates_uniqueness_of :path,
|
15
|
-
:allow_nil => true
|
16
|
-
|
17
|
-
class << self
|
18
|
-
# Finds all of the permissioned controllers and maps/orders them by parent
|
19
|
-
def find_all_mapped_by_parent
|
20
|
-
controllers_by_parent = Controller.find(:all).inject(ActiveSupport::OrderedHash.new) do |controllers, controller|
|
21
|
-
controller.klass.parents.each {|parent| controllers[parent] ||= []}
|
22
|
-
controllers[controller.klass.parent] << controller
|
23
|
-
controllers
|
24
|
-
end
|
25
|
-
|
26
|
-
# Sort all the controllers within each parent alphabetically
|
27
|
-
controllers_by_parent.each do |parent, controllers|
|
28
|
-
controllers.sort! do |c1, c2|
|
29
|
-
c1.name <=> c2.name
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# Sort the parents (first by closest to Object, then alphabetically)
|
34
|
-
controllers_by_parent.sort! do |c1, c2|
|
35
|
-
if c1.first == Object
|
36
|
-
-1
|
37
|
-
elsif c2.first == Object
|
38
|
-
1
|
39
|
-
else
|
40
|
-
c1.first.name <=> c2.first.name
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Parses the controller path and action from the given options
|
46
|
-
def recognize_path(options = '')
|
47
|
-
options = ActionController::Routing::Routes.recognize_path(URI.parse(options).path) if options.is_a?(String)
|
48
|
-
controller_path, action = options[:controller], options[:action]
|
49
|
-
controller_path = controller_path.controller_path if controller_path.is_a?(Class)
|
50
|
-
|
51
|
-
return controller_path, action ? action.to_s : 'index'
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Returns the class that this controller represents
|
56
|
-
def klass
|
57
|
-
@klass ||= "#{path.camelize}Controller".constantize
|
58
|
-
end
|
59
|
-
|
60
|
-
# The humanized name of this controller. This will not include the parent's name.
|
61
|
-
def name
|
62
|
-
@name ||= klass.controller_name.titleize
|
63
|
-
end
|
64
|
-
|
65
|
-
# Possible paths that can match this controller. This includes paths from all
|
66
|
-
# superclasses up to ApplicationController.
|
67
|
-
def possible_path_matches
|
68
|
-
klass.ancestors.select {|c| Class === c && c < ActionController::Base}.map(&:controller_path)
|
69
|
-
end
|
70
|
-
|
71
|
-
# Is this a global controller? If a user has a permission on the global
|
72
|
-
# controller, then he has permissions on all controllers. At least one user
|
73
|
-
# in the system should have global access.
|
74
|
-
def global?
|
75
|
-
path == 'application'
|
76
|
-
end
|
77
|
-
|
78
|
-
# Returns the name of the controller
|
79
|
-
def to_s #:nodoc
|
80
|
-
name
|
81
|
-
end
|
82
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
class CreateControllers < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :controllers do |t|
|
4
|
-
t.column :path, :string, :null => false
|
5
|
-
t.column :description, :text
|
6
|
-
end
|
7
|
-
add_index :controllers, :path, :unique => true
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.down
|
11
|
-
drop_table :controllers
|
12
|
-
end
|
13
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
class CreatePermissionsRoles < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :permissions_roles, :id => false do |t|
|
4
|
-
t.column :permission_id, :integer, :null => false
|
5
|
-
t.column :role_id, :integer, :null => false
|
6
|
-
end
|
7
|
-
add_index :permissions_roles, [:permission_id, :role_id], :unique => true
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.down
|
11
|
-
drop_table :permissions_roles
|
12
|
-
end
|
13
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
application:
|
2
|
-
id: 1
|
3
|
-
path: application
|
4
|
-
|
5
|
-
users:
|
6
|
-
id: 2
|
7
|
-
path: users
|
8
|
-
|
9
|
-
admin_users:
|
10
|
-
id: 3
|
11
|
-
path: admin/users
|
12
|
-
|
13
|
-
payment_transactions:
|
14
|
-
id: 4
|
15
|
-
path: payment/transactions
|
16
|
-
|
17
|
-
payment_pay_pal_transactions:
|
18
|
-
id: 5
|
19
|
-
path: payment/pay_pal/transactions
|
@@ -1,27 +0,0 @@
|
|
1
|
-
crud_application:
|
2
|
-
id: 1
|
3
|
-
controller_id: 1
|
4
|
-
|
5
|
-
read_application:
|
6
|
-
id: 2
|
7
|
-
controller_id: 1
|
8
|
-
action: index
|
9
|
-
|
10
|
-
read_users:
|
11
|
-
id: 3
|
12
|
-
controller_id: 2
|
13
|
-
action: index
|
14
|
-
|
15
|
-
update_users:
|
16
|
-
id: 4
|
17
|
-
controller_id: 2
|
18
|
-
action: update
|
19
|
-
|
20
|
-
crud_admin_users:
|
21
|
-
id: 5
|
22
|
-
controller_id: 3
|
23
|
-
|
24
|
-
create_pay_pal_payment_transactions:
|
25
|
-
id: 6
|
26
|
-
controller_id: 5
|
27
|
-
action: create
|
@@ -1,15 +0,0 @@
|
|
1
|
-
administrator_crud_application:
|
2
|
-
role_id: 1
|
3
|
-
permission_id: 1
|
4
|
-
|
5
|
-
moderator_crud_admin_users:
|
6
|
-
role_id: 2
|
7
|
-
permission_id: 5
|
8
|
-
|
9
|
-
guest_read_application:
|
10
|
-
role_id: 3
|
11
|
-
permission_id: 2
|
12
|
-
|
13
|
-
guest_create_pay_pal_payment_transactions:
|
14
|
-
role_id: 3
|
15
|
-
permission_id: 6
|
data/test/fixtures/roles.yml
DELETED
data/test/fixtures/users.yml
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/../test_helper"
|
2
|
-
|
3
|
-
class AuthorizationHelperTest < Test::Unit::TestCase
|
4
|
-
include ActionView::Helpers::TagHelper
|
5
|
-
include ActionView::Helpers::UrlHelper
|
6
|
-
include PluginAWeek::Has::Roles::AuthorizationHelper
|
7
|
-
|
8
|
-
fixtures :controllers, :permissions, :roles, :permissions_roles, :users, :role_assignments
|
9
|
-
|
10
|
-
def setup
|
11
|
-
@controller = HomeController.new
|
12
|
-
@controller.request = ActionController::TestRequest.new
|
13
|
-
@controller.instance_eval {@_params = request.path_parameters}
|
14
|
-
@controller.send(:initialize_current_url)
|
15
|
-
end
|
16
|
-
|
17
|
-
def current_user
|
18
|
-
users(:guest)
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_should_be_authorized_if_user_has_proper_permissions
|
22
|
-
assert authorized_for?('/users/index')
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_should_not_be_authorized_if_user_doesnt_have_proper_permissions
|
26
|
-
assert !authorized_for?('/admin/users/destroy')
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_should_link_to_nothing_if_not_authorized_and_not_showing_text
|
30
|
-
assert_equal '', link_to_if_authorized('Destroy User', '/admin/users/destroy', :show_text => false)
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_should_display_text_if_not_authorized_and_showing_text
|
34
|
-
assert_equal 'Destroy User', link_to_if_authorized('Destroy User', '/admin/users/destroy', :show_text => true)
|
35
|
-
end
|
36
|
-
|
37
|
-
def test_should_link_to_url_if_authorized
|
38
|
-
assert_equal '<a href="/users">Destroy User</a>', link_to_if_authorized('Destroy User', {:controller => 'users', :action => 'index'}, :show_text => false)
|
39
|
-
end
|
40
|
-
end
|
@@ -1,95 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/../test_helper"
|
2
|
-
|
3
|
-
class ControllerTest < Test::Unit::TestCase
|
4
|
-
fixtures :controllers, :permissions
|
5
|
-
|
6
|
-
def test_should_be_valid
|
7
|
-
assert_valid controllers(:users)
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_should_require_path
|
11
|
-
assert_invalid controllers(:users), :path, nil, ''
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_should_require_specific_format_for_paths
|
15
|
-
assert_invalid controllers(:users), :path, '/users', '//users', 'users/', 'admin//users', '1'
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_should_require_unique_path
|
19
|
-
assert_invalid controllers(:users).clone, :path
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_should_have_associated_permissions
|
23
|
-
assert_equal [permissions(:read_users), permissions(:update_users)], controllers(:users).permissions
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_should_destroy_associated_permissions_when_destroyed
|
27
|
-
controllers(:users).destroy
|
28
|
-
assert_nil Permission.find_by_controller_id(2)
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_should_use_path_for_klass
|
32
|
-
assert_equal UsersController, controllers(:users).klass
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_should_use_namespaced_path_for_klass
|
36
|
-
assert_equal Admin::UsersController, controllers(:admin_users).klass
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_should_use_controller_name_for_name_if_controller_is_not_namespaced
|
40
|
-
assert_equal 'Users', controllers(:users).name
|
41
|
-
end
|
42
|
-
|
43
|
-
def test_should_use_demodulized_controller_name_for_name_if_controller_is_namespaced
|
44
|
-
assert_equal 'Users', controllers(:admin_users).name
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_possible_path_matches_should_include_all_superclasses_except_base_controller
|
48
|
-
assert_equal %w(users application), controllers(:users).possible_path_matches
|
49
|
-
assert_equal %w(admin/users application), controllers(:admin_users).possible_path_matches
|
50
|
-
assert_equal %w(payment/pay_pal/transactions payment/transactions application), controllers(:payment_pay_pal_transactions).possible_path_matches
|
51
|
-
end
|
52
|
-
|
53
|
-
def test_should_be_global_if_path_is_application
|
54
|
-
assert controllers(:application).global?
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_should_not_be_global_if_path_is_not_application
|
58
|
-
assert !controllers(:users).global?
|
59
|
-
assert !controllers(:admin_users).global?
|
60
|
-
end
|
61
|
-
|
62
|
-
def test_stringification_should_use_name
|
63
|
-
assert_equal 'Users', controllers(:users).to_s
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_should_map_parents_for_all_controllers
|
67
|
-
expected = [
|
68
|
-
[Object, [controllers(:application), controllers(:users)]],
|
69
|
-
[Admin, [controllers(:admin_users)]],
|
70
|
-
[Payment, [controllers(:payment_transactions)]],
|
71
|
-
[Payment::PayPal, [controllers(:payment_pay_pal_transactions)]]
|
72
|
-
]
|
73
|
-
assert_equal expected, Controller.find_all_mapped_by_parent
|
74
|
-
end
|
75
|
-
|
76
|
-
def test_should_recognize_path_by_string
|
77
|
-
assert_equal ['users', 'index'], Controller.recognize_path('/users')
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_should_recognize_namespaced_path_by_string
|
81
|
-
assert_equal ['admin/users', 'update'], Controller.recognize_path('/admin/users/update')
|
82
|
-
end
|
83
|
-
|
84
|
-
def test_should_recognize_path_by_hash
|
85
|
-
assert_equal ['users', 'index'], Controller.recognize_path(:controller => 'users', :action => 'index')
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_should_recognize_namespaced_path_by_hash
|
89
|
-
assert_equal ['admin/users', 'update'], Controller.recognize_path(:controller => 'admin/users', :action => 'update', :id => 1)
|
90
|
-
end
|
91
|
-
|
92
|
-
def test_should_recognize_path_if_action_not_specified
|
93
|
-
assert_equal ['users', 'index'], Controller.recognize_path(:controller => 'users')
|
94
|
-
end
|
95
|
-
end
|
data/test/unit/has_roles_test.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/../test_helper"
|
2
|
-
|
3
|
-
class HasRolesTest < Test::Unit::TestCase
|
4
|
-
fixtures :controllers, :permissions, :roles, :permissions_roles, :users, :role_assignments
|
5
|
-
|
6
|
-
def test_should_have_role_assignments_association
|
7
|
-
assert_equal [role_assignments(:administrator)], users(:administrator).role_assignments
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_should_destroy_role_assignments_when_destroyed
|
11
|
-
users(:administrator).destroy
|
12
|
-
assert_nil RoleAssignment.find_by_assignee_id(1)
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_should_have_roles_association
|
16
|
-
assert_equal [roles(:administrator)], users(:administrator).roles
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_should_be_authorized_if_user_has_proper_permissions
|
20
|
-
assert users(:guest).authorized_for?('/users/index')
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_should_not_be_authorized_if_user_doesnt_have_proper_permissions
|
24
|
-
assert !users(:guest).authorized_for?('/admin/users/destroy')
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_roles_ids_should_map_all_ids
|
28
|
-
assert_equal [1], users(:administrator).role_ids
|
29
|
-
end
|
30
|
-
|
31
|
-
|
32
|
-
def test_should_destroy_old_roles_when_replaced
|
33
|
-
user = users(:administrator)
|
34
|
-
user.role_ids = []
|
35
|
-
assert_equal [], user.roles
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_should_add_new_roles_when_replaced
|
39
|
-
user = users(:administrator)
|
40
|
-
user.role_ids = [1, 2]
|
41
|
-
assert_equal [roles(:administrator), roles(:moderator)], user.roles
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_should_destroy_old_roles_and_add_new_roles_when_replaced
|
45
|
-
user = users(:administrator)
|
46
|
-
user.role_ids = [2]
|
47
|
-
assert_equal [roles(:moderator)], user.roles
|
48
|
-
end
|
49
|
-
end
|