cjbottaro-aegis 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +182 -0
- data/Rakefile +37 -0
- data/VERSION +1 -0
- data/aegis.gemspec +117 -0
- data/lib/aegis.rb +11 -0
- data/lib/aegis/constants.rb +6 -0
- data/lib/aegis/has_role.rb +156 -0
- data/lib/aegis/meta_class.rb +13 -0
- data/lib/aegis/normalization.rb +26 -0
- data/lib/aegis/permission_error.rb +5 -0
- data/lib/aegis/permission_evaluator.rb +41 -0
- data/lib/aegis/permissions.rb +108 -0
- data/lib/aegis/role.rb +57 -0
- data/lib/aegis/role_assignments.rb +10 -0
- data/lib/rails/active_record.rb +5 -0
- data/test/app_root/app/controllers/application_controller.rb +2 -0
- data/test/app_root/app/models/account.rb +3 -0
- data/test/app_root/app/models/forum.rb +8 -0
- data/test/app_root/app/models/permissions.rb +70 -0
- data/test/app_root/app/models/post.rb +7 -0
- data/test/app_root/app/models/soldier.rb +5 -0
- data/test/app_root/app/models/user.rb +7 -0
- data/test/app_root/config/boot.rb +114 -0
- data/test/app_root/config/database.yml +21 -0
- data/test/app_root/config/environment.rb +14 -0
- data/test/app_root/config/environments/in_memory.rb +0 -0
- data/test/app_root/config/environments/mysql.rb +0 -0
- data/test/app_root/config/environments/postgresql.rb +0 -0
- data/test/app_root/config/environments/sqlite.rb +0 -0
- data/test/app_root/config/environments/sqlite3.rb +0 -0
- data/test/app_root/config/routes.rb +4 -0
- data/test/app_root/db/migrate/20090408115228_create_users.rb +15 -0
- data/test/app_root/db/migrate/20090429075648_create_soldiers.rb +16 -0
- data/test/app_root/db/migrate/20090903234709_create_role_assignments.rb +16 -0
- data/test/app_root/db/migrate/20090903234759_create_accounts.rb +11 -0
- data/test/app_root/db/migrate/20090903234821_create_forums.rb +12 -0
- data/test/app_root/db/migrate/20090903234828_create_posts.rb +12 -0
- data/test/app_root/lib/console_with_fixtures.rb +4 -0
- data/test/app_root/log/.gitignore +1 -0
- data/test/app_root/script/console +7 -0
- data/test/fixtures/accounts.yml +5 -0
- data/test/fixtures/forums.yml +11 -0
- data/test/fixtures/posts.yml +23 -0
- data/test/fixtures/role_assignments.yml +0 -0
- data/test/fixtures/users.yml +2 -0
- data/test/has_role_options_test.rb +33 -0
- data/test/has_role_test.rb +88 -0
- data/test/permissions_test.rb +117 -0
- data/test/test_helper.rb +44 -0
- data/test/validation_test.rb +49 -0
- metadata +130 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
in_memory:
|
2
|
+
adapter: sqlite3
|
3
|
+
database: ":memory:"
|
4
|
+
verbosity: quiet
|
5
|
+
sqlite:
|
6
|
+
adapter: sqlite
|
7
|
+
dbfile: plugin_test.sqlite.db
|
8
|
+
sqlite3:
|
9
|
+
adapter: sqlite3
|
10
|
+
dbfile: plugin_test.sqlite3.db
|
11
|
+
postgresql:
|
12
|
+
adapter: postgresql
|
13
|
+
username: postgres
|
14
|
+
password: postgres
|
15
|
+
database: plugin_test
|
16
|
+
mysql:
|
17
|
+
adapter: mysql
|
18
|
+
host: localhost
|
19
|
+
username: root
|
20
|
+
password:
|
21
|
+
database: plugin_test
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'boot')
|
2
|
+
|
3
|
+
Rails::Initializer.run do |config|
|
4
|
+
config.cache_classes = false
|
5
|
+
config.whiny_nils = true
|
6
|
+
config.action_controller.session = { :key => "_myapp_session", :secret => "gwirofjweroijger8924rt2zfwehfuiwehb1378rifowenfoqwphf23" }
|
7
|
+
config.plugin_locators.unshift(
|
8
|
+
Class.new(Rails::Plugin::Locator) do
|
9
|
+
def plugins
|
10
|
+
[Rails::Plugin.new(File.expand_path('.'))]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
) unless defined?(PluginTestHelper::PluginLocator)
|
14
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateUsers < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
create_table :users do |t|
|
5
|
+
t.string "role_name"
|
6
|
+
t.boolean "is_admin", :null => false, :default => false
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.down
|
12
|
+
drop_table :users
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateRoleAssignments < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :role_assignments do |t|
|
4
|
+
t.string :actor_type, :null => false
|
5
|
+
t.integer :actor_id, :null => false
|
6
|
+
t.string :role_name, :null => false
|
7
|
+
t.string :context_type, :null => false
|
8
|
+
t.integer :context_id, :null => false
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :role_assignments
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
# Loads fixtures into the database when running the test app via the console
|
2
|
+
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(Rails.root, '../fixtures/*.{yml,csv}'))).each do |fixture_file|
|
3
|
+
Fixtures.create_fixtures(File.join(Rails.root, '../fixtures'), File.basename(fixture_file, '.*'))
|
4
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
*.log
|
@@ -0,0 +1,23 @@
|
|
1
|
+
searching101:
|
2
|
+
forum: searching
|
3
|
+
title: searching101
|
4
|
+
|
5
|
+
searching102:
|
6
|
+
forum: searching
|
7
|
+
title: searching102
|
8
|
+
|
9
|
+
crawling101:
|
10
|
+
forum: crawling
|
11
|
+
title: crawling101
|
12
|
+
|
13
|
+
crawling102:
|
14
|
+
forum: crawling
|
15
|
+
title: crawling102
|
16
|
+
|
17
|
+
advertising101:
|
18
|
+
forum: advertising
|
19
|
+
title: advertising101
|
20
|
+
|
21
|
+
advertising102:
|
22
|
+
forum: advertising
|
23
|
+
title: advertising102
|
File without changes
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
|
3
|
+
class HasRoleOptionsTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
context "A record with a custom role field" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@soldier = Soldier.new
|
9
|
+
end
|
10
|
+
|
11
|
+
should "allow its role to be written and read" do
|
12
|
+
@soldier.role = "guest"
|
13
|
+
assert "guest", @soldier.role.name
|
14
|
+
end
|
15
|
+
|
16
|
+
should "store the role name in the custom field" do
|
17
|
+
assert "guest", @soldier.rank
|
18
|
+
end
|
19
|
+
|
20
|
+
should "still work with permissions" do
|
21
|
+
@soldier.role = "guest"
|
22
|
+
assert @soldier.may_hug?
|
23
|
+
assert !@soldier.may_update_users?
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_setting_hierarchy
|
29
|
+
assert_equal "forum", User.aegis_role_hierarchy["Post"]
|
30
|
+
assert_equal "account", User.aegis_role_hierarchy["Forum"]
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
|
3
|
+
class HasRoleTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
context "Objects that have an aegis role" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@guest = User.new(:role_name => "guest")
|
9
|
+
@student = User.new(:role_name => "student")
|
10
|
+
@admin = User.new(:role_name => "admin")
|
11
|
+
end
|
12
|
+
|
13
|
+
should "know their role" do
|
14
|
+
assert :guest, @guest.role.name
|
15
|
+
assert :student, @student.role.name
|
16
|
+
assert :admin, @admin.role.name
|
17
|
+
end
|
18
|
+
|
19
|
+
should "know if they belong to a role" do
|
20
|
+
assert @guest.guest?
|
21
|
+
assert !@guest.student?
|
22
|
+
assert !@guest.admin?
|
23
|
+
assert !@student.guest?
|
24
|
+
assert @student.student?
|
25
|
+
assert !@student.admin?
|
26
|
+
assert !@admin.guest?
|
27
|
+
assert !@admin.student?
|
28
|
+
assert @admin.admin?
|
29
|
+
end
|
30
|
+
|
31
|
+
should "still behave as usual when a method ending in a '?' does not map to a role query" do
|
32
|
+
assert_raise NoMethodError do
|
33
|
+
@guest.nonexisting_method?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_role_in
|
40
|
+
create_role_assignments
|
41
|
+
user = users(:with_hierarchy)
|
42
|
+
do_test_role_in(user)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_role_in_using_hierarchy_accessor
|
46
|
+
create_role_assignments
|
47
|
+
saved_role_heirarchy = User.aegis_role_hierarchy
|
48
|
+
|
49
|
+
assert_not_nil User.aegis_role_hierarchy
|
50
|
+
User.instance_variable_set("@aegis_role_hierarchy", nil)
|
51
|
+
assert_nil User.aegis_role_hierarchy
|
52
|
+
|
53
|
+
User.instance_variable_set("@aegis_role_hierarchy_accessor", "parent")
|
54
|
+
assert_equal "parent", User.aegis_role_hierarchy_accessor
|
55
|
+
|
56
|
+
do_test_role_in(users(:with_hierarchy))
|
57
|
+
|
58
|
+
# So the rest of the tests don't break.
|
59
|
+
User.instance_variable_set("@aegis_role_hierarchy", saved_role_heirarchy)
|
60
|
+
User.instance_variable_set("@aegis_role_hierarchy_accessor", nil)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_forced_role
|
64
|
+
create_role_assignments
|
65
|
+
user = users(:with_hierarchy)
|
66
|
+
user.update_attribute(:is_admin, true)
|
67
|
+
assert_equal "superuser", user.role
|
68
|
+
assert_equal "superuser", user.role_in(accounts(:google))
|
69
|
+
assert_equal "superuser", user.role_in(forums(:searching))
|
70
|
+
assert_equal "superuser", user.role_in(posts(:searching101))
|
71
|
+
assert_equal "superuser", user.role_in(posts(:searching102))
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def do_test_role_in(user)
|
77
|
+
assert_equal :admin, user.role_in(accounts(:google)).name
|
78
|
+
|
79
|
+
assert_equal :writer, user.role_in(forums(:searching)).name
|
80
|
+
assert_equal :writer, user.role_in(posts(:searching101)).name
|
81
|
+
assert_equal :reader, user.role_in(posts(:searching102)).name
|
82
|
+
|
83
|
+
assert_equal :admin, user.role_in(forums(:crawling)).name
|
84
|
+
assert_equal :admin, user.role_in(posts(:crawling101)).name
|
85
|
+
assert_equal :admin, user.role_in(posts(:crawling102)).name
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require "test/test_helper"
|
2
|
+
|
3
|
+
class PermissionsTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
context "Aegis permissions" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@guest = User.new(:role_name => "guest")
|
9
|
+
@student = User.new(:role_name => "student")
|
10
|
+
@admin = User.new(:role_name => "admin")
|
11
|
+
end
|
12
|
+
|
13
|
+
should "use the default permission for actions without any allow or grant directives" do
|
14
|
+
assert !@guest.may_use_empty?
|
15
|
+
assert !@student.may_use_empty?
|
16
|
+
assert @admin.may_use_empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
should "understand simple allow and deny directives" do
|
20
|
+
assert !@guest.may_use_simple?
|
21
|
+
assert @student.may_use_simple?
|
22
|
+
assert !@admin.may_use_simple?
|
23
|
+
end
|
24
|
+
|
25
|
+
should 'raise exceptions when a denied action is queried with an exclamation mark' do
|
26
|
+
assert_raise Aegis::PermissionError do
|
27
|
+
@guest.may_use_simple!
|
28
|
+
end
|
29
|
+
assert_raise Aegis::PermissionError do
|
30
|
+
@admin.may_use_simple!
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'do nothing if an allowed action is queried with an exclamation mark' do
|
35
|
+
assert_nothing_raised do
|
36
|
+
@student.may_use_simple!
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
should "implicate the singular form of an action described in plural form" do
|
41
|
+
assert !@guest.may_update_users?
|
42
|
+
assert !@guest.may_update_user?("foo")
|
43
|
+
assert @student.may_update_users?
|
44
|
+
assert @student.may_update_user?("foo")
|
45
|
+
assert !@admin.may_update_users?
|
46
|
+
assert !@admin.may_update_user?("foo")
|
47
|
+
end
|
48
|
+
|
49
|
+
should 'implicate create, read, update and destroy forms for actions named "crud_..."' do
|
50
|
+
assert @student.may_create_projects?
|
51
|
+
assert @student.may_read_projects?
|
52
|
+
assert @student.may_update_projects?
|
53
|
+
assert @student.may_destroy_projects?
|
54
|
+
end
|
55
|
+
|
56
|
+
should 'perform normalization of CRUD verbs (e.g. "edit" and "update")' do
|
57
|
+
assert !@guest.may_edit_drinks?
|
58
|
+
assert @student.may_edit_drinks?
|
59
|
+
assert !@admin.may_edit_drinks?
|
60
|
+
assert !@guest.may_update_drinks?
|
61
|
+
assert @student.may_update_drinks?
|
62
|
+
assert !@admin.may_update_drinks?
|
63
|
+
end
|
64
|
+
|
65
|
+
should "be able to grant or deny actions to all roles using :everyone" do
|
66
|
+
assert @guest.may_hug?
|
67
|
+
assert @student.may_hug?
|
68
|
+
assert @admin.may_hug?
|
69
|
+
end
|
70
|
+
|
71
|
+
should "allow the definition of parametrized actions" do
|
72
|
+
assert !@guest.may_divide?(10, 2)
|
73
|
+
assert @student.may_divide?(10, 2)
|
74
|
+
assert !@student.may_divide?(10, 0)
|
75
|
+
assert @admin.may_divide?(10, 2)
|
76
|
+
assert @admin.may_divide?(10, 0)
|
77
|
+
end
|
78
|
+
|
79
|
+
should 'use default permissions for undefined actions' do
|
80
|
+
!@student.may_do_undefined_stuff?("foo")
|
81
|
+
@admin.may_do_undefined_stuff?("foo")
|
82
|
+
end
|
83
|
+
|
84
|
+
should 'overshadow previous action definitions with the same name' do
|
85
|
+
assert @guest.may_draw?
|
86
|
+
assert !@student.may_draw?
|
87
|
+
assert !@admin.may_draw?
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_hierarchical_permissions
|
93
|
+
create_role_assignments
|
94
|
+
user = users(:with_hierarchy)
|
95
|
+
|
96
|
+
assert user.may_edit_post_in?(posts(:searching101))
|
97
|
+
assert !user.may_edit_post_in?(posts(:searching102))
|
98
|
+
|
99
|
+
assert user.may_view_post_in?(posts(:searching101))
|
100
|
+
assert user.may_view_post_in?(posts(:searching102))
|
101
|
+
|
102
|
+
assert user.may_create_post_in?(forums(:searching))
|
103
|
+
assert user.may_create_post_in?(forums(:crawling))
|
104
|
+
|
105
|
+
assert user.may_create_forum_in?(accounts(:google))
|
106
|
+
assert !user.may_create_forum_in?(accounts(:yahoo))
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_invalid_permission_context
|
110
|
+
create_role_assignments
|
111
|
+
user = users(:with_hierarchy)
|
112
|
+
|
113
|
+
assert_nothing_raised{ user.may_create_post_in?(forums(:searching)) }
|
114
|
+
assert_raise(Aegis::PermissionError){ user.may_create_post_in?(posts(:searching101)) }
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|