authorize 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +42 -0
- data/LICENSE +20 -0
- data/README +155 -0
- data/Rakefile +25 -0
- data/TODO.txt +9 -0
- data/authorize.gemspec +25 -0
- data/generators/authorize/USAGE +8 -0
- data/generators/authorize/authorize_generator.rb +7 -0
- data/generators/authorize/templates/migrate/create_authorizations.rb +26 -0
- data/install.rb +1 -0
- data/lib/authorize.rb +2 -0
- data/lib/authorize/action_controller.rb +59 -0
- data/lib/authorize/action_view.rb +4 -0
- data/lib/authorize/active_record.rb +37 -0
- data/lib/authorize/bitmask.rb +84 -0
- data/lib/authorize/exceptions.rb +30 -0
- data/lib/authorize/graph.rb +4 -0
- data/lib/authorize/graph/directed_acyclic_graph.rb +10 -0
- data/lib/authorize/graph/directed_acyclic_graph_reverse_traverser.rb +27 -0
- data/lib/authorize/graph/directed_acyclic_graph_traverser.rb +30 -0
- data/lib/authorize/graph/directed_graph.rb +27 -0
- data/lib/authorize/graph/edge.rb +58 -0
- data/lib/authorize/graph/factory.rb +39 -0
- data/lib/authorize/graph/fixtures.rb +33 -0
- data/lib/authorize/graph/graph.rb +55 -0
- data/lib/authorize/graph/traverser.rb +89 -0
- data/lib/authorize/graph/undirected_graph.rb +14 -0
- data/lib/authorize/graph/vertex.rb +53 -0
- data/lib/authorize/permission.rb +97 -0
- data/lib/authorize/redis.rb +2 -0
- data/lib/authorize/redis/array.rb +36 -0
- data/lib/authorize/redis/base.rb +165 -0
- data/lib/authorize/redis/connection_manager.rb +88 -0
- data/lib/authorize/redis/connection_specification.rb +16 -0
- data/lib/authorize/redis/factory.rb +64 -0
- data/lib/authorize/redis/fixtures.rb +22 -0
- data/lib/authorize/redis/hash.rb +34 -0
- data/lib/authorize/redis/model_reference.rb +21 -0
- data/lib/authorize/redis/model_set.rb +19 -0
- data/lib/authorize/redis/set.rb +42 -0
- data/lib/authorize/redis/string.rb +17 -0
- data/lib/authorize/resource.rb +4 -0
- data/lib/authorize/resource_pool.rb +87 -0
- data/lib/authorize/role.rb +115 -0
- data/lib/authorize/test_helper.rb +42 -0
- data/lib/authorize/trustee.rb +4 -0
- data/lib/authorize/version.rb +3 -0
- data/rails/init.rb +5 -0
- data/tasks/authorize_tasks.rake +4 -0
- data/test/Rakefile +7 -0
- data/test/app/controllers/application_controller.rb +5 -0
- data/test/app/controllers/thingy_controller.rb +11 -0
- data/test/app/controllers/widgets_controller.rb +2 -0
- data/test/app/models/public.rb +14 -0
- data/test/app/models/user.rb +8 -0
- data/test/app/models/widget.rb +7 -0
- data/test/config/boot.rb +109 -0
- data/test/config/database.yml +25 -0
- data/test/config/environment.rb +28 -0
- data/test/config/environments/development.rb +4 -0
- data/test/config/environments/test.rb +0 -0
- data/test/config/initializers/mask.rb +1 -0
- data/test/config/initializers/redis.rb +8 -0
- data/test/config/routes.rb +5 -0
- data/test/db/.gitignore +1 -0
- data/test/db/schema.rb +26 -0
- data/test/log/.gitignore +2 -0
- data/test/public/javascripts/application.js +2 -0
- data/test/public/javascripts/controls.js +963 -0
- data/test/public/javascripts/dragdrop.js +972 -0
- data/test/public/javascripts/effects.js +1120 -0
- data/test/public/javascripts/prototype.js +4225 -0
- data/test/script/about +3 -0
- data/test/script/console +3 -0
- data/test/script/dbconsole +3 -0
- data/test/script/destroy +3 -0
- data/test/script/generate +3 -0
- data/test/script/performance/benchmarker +3 -0
- data/test/script/performance/profiler +3 -0
- data/test/script/performance/request +3 -0
- data/test/script/plugin +3 -0
- data/test/script/process/inspector +3 -0
- data/test/script/process/reaper +3 -0
- data/test/script/process/spawner +3 -0
- data/test/script/runner +3 -0
- data/test/script/server +3 -0
- data/test/test/fixtures/authorize/role_graph.yml +11 -0
- data/test/test/fixtures/permissions.yml +27 -0
- data/test/test/fixtures/redis/redis.yml +8 -0
- data/test/test/fixtures/redis/role_graph.yml +29 -0
- data/test/test/fixtures/roles.yml +28 -0
- data/test/test/fixtures/users.yml +12 -0
- data/test/test/fixtures/widgets.yml +12 -0
- data/test/test/functional/controller_class_test.rb +36 -0
- data/test/test/functional/controller_test.rb +46 -0
- data/test/test/test_helper.rb +35 -0
- data/test/test/unit/bitmask_test.rb +112 -0
- data/test/test/unit/fixture_test.rb +59 -0
- data/test/test/unit/graph_directed_acyclic_graph_reverse_traverser_test.rb +43 -0
- data/test/test/unit/graph_directed_acyclic_graph_traverser_test.rb +57 -0
- data/test/test/unit/graph_directed_graph_test.rb +66 -0
- data/test/test/unit/graph_edge_test.rb +53 -0
- data/test/test/unit/graph_graph_test.rb +50 -0
- data/test/test/unit/graph_traverser_test.rb +43 -0
- data/test/test/unit/graph_vertex_test.rb +57 -0
- data/test/test/unit/permission_test.rb +123 -0
- data/test/test/unit/redis_array_test.rb +60 -0
- data/test/test/unit/redis_connection_manager_test.rb +54 -0
- data/test/test/unit/redis_factory_test.rb +85 -0
- data/test/test/unit/redis_fixture_test.rb +18 -0
- data/test/test/unit/redis_hash_test.rb +43 -0
- data/test/test/unit/redis_model_reference_test.rb +39 -0
- data/test/test/unit/redis_set_test.rb +68 -0
- data/test/test/unit/redis_string_test.rb +25 -0
- data/test/test/unit/redis_test.rb +121 -0
- data/test/test/unit/resource_pool_test.rb +93 -0
- data/test/test/unit/resource_test.rb +33 -0
- data/test/test/unit/role_test.rb +143 -0
- data/test/test/unit/trustee_test.rb +35 -0
- data/test/tmp/.gitignore +2 -0
- data/uninstall.rb +1 -0
- metadata +319 -0
data/test/script/about
ADDED
data/test/script/console
ADDED
data/test/script/destroy
ADDED
data/test/script/plugin
ADDED
data/test/script/runner
ADDED
data/test/script/server
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
a_read_foo:
|
2
|
+
mask: <%= Authorize::Permission::Mask[:list, :read].to_i %>
|
3
|
+
role: a
|
4
|
+
_resource: foo (Widget)
|
5
|
+
a_list_bar:
|
6
|
+
mask: <%= Authorize::Permission::Mask[:list].to_i %>
|
7
|
+
role: a
|
8
|
+
_resource: bar (Widget)
|
9
|
+
b_overlord:
|
10
|
+
mask: <%= Authorize::Permission::Mask[:all].to_i %>
|
11
|
+
role: administrator
|
12
|
+
c_all_widgets:
|
13
|
+
mask: <%= Authorize::Permission::Mask[:all].to_i %>
|
14
|
+
role: c
|
15
|
+
resource_type: Widget
|
16
|
+
d_update_bar:
|
17
|
+
mask: <%= Authorize::Permission::Mask[:list, :read, :update].to_i %>
|
18
|
+
role: d
|
19
|
+
_resource: bar (Widget)
|
20
|
+
e_delete_bar:
|
21
|
+
mask: <%= Authorize::Permission::Mask[:list, :delete].to_i %>
|
22
|
+
role: e
|
23
|
+
_resource: bar (Widget)
|
24
|
+
user_chris_all_chris:
|
25
|
+
mask: <%= Authorize::Permission::Mask[:all].to_i %>
|
26
|
+
role: user_chris
|
27
|
+
_resource: chris (User)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Vertices (just markers)
|
2
|
+
- <%= "Authorize::Role::vertices::#{Fixtures.identify(:user_chris)}::_" %>: ~
|
3
|
+
- <%= "Authorize::Role::vertices::#{Fixtures.identify(:public)}::_" %>: ~
|
4
|
+
- <%= "Authorize::Role::vertices::#{Fixtures.identify(:registered_users)}::_" %>: ~
|
5
|
+
# Edge counter
|
6
|
+
- "Authorize::Role::graph::_edges": "10"
|
7
|
+
# Edges
|
8
|
+
- Authorize::Role::graph::_edges::1::l_id: <%= "Authorize::Role::vertices::#{Fixtures.identify(:user_chris)}" %>
|
9
|
+
- Authorize::Role::graph::_edges::1::r_id: <%= "Authorize::Role::vertices::#{Fixtures.identify(:registered_users)}" %>
|
10
|
+
- Authorize::Role::graph::_edges::2::l_id: <%= "Authorize::Role::vertices::#{Fixtures.identify(:registered_users)}" %>
|
11
|
+
- Authorize::Role::graph::_edges::2::r_id: <%= "Authorize::Role::vertices::#{Fixtures.identify(:public)}" %>
|
12
|
+
# Set of vertices belonging to the role graph
|
13
|
+
- "Authorize::Role::graph": !ruby/object:Set
|
14
|
+
hash:
|
15
|
+
<%= "Authorize::Role::vertices::#{Fixtures.identify(:public)}" %>: true
|
16
|
+
<%= "Authorize::Role::vertices::#{Fixtures.identify(:registered_users)}" %>: true
|
17
|
+
<%= "Authorize::Role::vertices::#{Fixtures.identify(:user_chris)}" %>: true
|
18
|
+
# Set of edges belonging to the role graph
|
19
|
+
- "Authorize::Role::graph::edge_ids": !ruby/object:Set
|
20
|
+
hash:
|
21
|
+
Authorize::Role::graph::edges::1: true
|
22
|
+
Authorize::Role::graph::edges::2: true
|
23
|
+
# Set of edges per vertex
|
24
|
+
- <%= "Authorize::Role::vertices::#{Fixtures.identify(:user_chris)}::edge_ids" %>: !ruby/object:Set
|
25
|
+
hash:
|
26
|
+
Authorize::Role::graph::_edges::1: true
|
27
|
+
- <%= "Authorize::Role::vertices::#{Fixtures.identify(:registered_users)}::edge_ids" %>: !ruby/object:Set
|
28
|
+
hash:
|
29
|
+
Authorize::Role::graph::_edges::2: true
|
@@ -0,0 +1,28 @@
|
|
1
|
+
a:
|
2
|
+
name: a
|
3
|
+
resource: foo (Widget)
|
4
|
+
administrator:
|
5
|
+
name: administrator
|
6
|
+
relation: ADM
|
7
|
+
c:
|
8
|
+
name: "%s administrator"
|
9
|
+
resource_type: Widget
|
10
|
+
d:
|
11
|
+
name: "owner of %s"
|
12
|
+
resource: bar (Widget)
|
13
|
+
e:
|
14
|
+
name: "housekeeper of %s"
|
15
|
+
relation: HSK
|
16
|
+
resource: bar (Widget)
|
17
|
+
user_chris:
|
18
|
+
name: ~
|
19
|
+
resource: chris (User)
|
20
|
+
user_pascale:
|
21
|
+
name: ~
|
22
|
+
resource: pascale (User)
|
23
|
+
registered_users:
|
24
|
+
name: Registered Users
|
25
|
+
relation: RUS
|
26
|
+
public:
|
27
|
+
name: Public
|
28
|
+
relation: PUB
|
@@ -0,0 +1,12 @@
|
|
1
|
+
chris:
|
2
|
+
login: cch1
|
3
|
+
created_at: <%= 2.days.ago.to_s :db %>
|
4
|
+
updated_at: <%= 1.days.ago.to_s :db %>
|
5
|
+
pascale:
|
6
|
+
login: pah1
|
7
|
+
created_at: <%= 2.days.ago.to_s :db %>
|
8
|
+
updated_at: <%= 1.days.ago.to_s :db %>
|
9
|
+
alex:
|
10
|
+
login: ach1
|
11
|
+
created_at: <%= 2.days.ago.to_s :db %>
|
12
|
+
updated_at: <%= 1.days.ago.to_s :db %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
foo:
|
2
|
+
name: super
|
3
|
+
created_at: <%= 2.days.ago.to_s :db %>
|
4
|
+
updated_at: <%= 1.days.ago.to_s :db %>
|
5
|
+
bar:
|
6
|
+
name: deluxe
|
7
|
+
created_at: <%= 2.days.ago.to_s :db %>
|
8
|
+
updated_at: <%= 1.days.ago.to_s :db %>
|
9
|
+
baz:
|
10
|
+
name: baz
|
11
|
+
created_at: <%= 2.days.ago.to_s :db %>
|
12
|
+
updated_at: <%= 1.days.ago.to_s :db %>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ControllerClassTest < ActionController::TestCase
|
4
|
+
fixtures :all
|
5
|
+
|
6
|
+
tests ThingyController
|
7
|
+
|
8
|
+
test 'raise exception when not permitted' do
|
9
|
+
@controller.expects(:roles).returns([])
|
10
|
+
assert_raises Authorize::AuthorizationError do
|
11
|
+
get :index
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
test 'rescue response' do
|
16
|
+
@controller.expects(:roles).returns([])
|
17
|
+
@request.remote_addr = "192.168.1.1"
|
18
|
+
get :index
|
19
|
+
assert_response :forbidden
|
20
|
+
end
|
21
|
+
|
22
|
+
test 'skip filter' do
|
23
|
+
assert_nothing_raised do
|
24
|
+
get :show
|
25
|
+
assert_response :success
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
test 'should perform action because of authorization' do
|
30
|
+
@controller.expects(:roles).returns([roles(:administrator)])
|
31
|
+
assert_nothing_raised do
|
32
|
+
get :index
|
33
|
+
assert_response :success
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'authorize/graph/fixtures'
|
3
|
+
|
4
|
+
class ControllerTest < ActionController::TestCase
|
5
|
+
fixtures :all
|
6
|
+
|
7
|
+
tests WidgetsController
|
8
|
+
|
9
|
+
def setup
|
10
|
+
::Authorize::Graph::Fixtures.create_fixtures
|
11
|
+
end
|
12
|
+
|
13
|
+
test 'predicate not stuck on false when permitted' do
|
14
|
+
assert @controller.permit?({:list => widgets(:foo)}, {:roles => [roles(:administrator)]})
|
15
|
+
end
|
16
|
+
|
17
|
+
test 'predicate not stuck on true when not permitted' do
|
18
|
+
assert !@controller.permit?({:all => Widget}, {:roles => []})
|
19
|
+
end
|
20
|
+
|
21
|
+
test 'query controller for default roles' do
|
22
|
+
@controller.expects(:roles).returns([roles(:administrator)])
|
23
|
+
@controller.permit?(:update => widgets(:foo))
|
24
|
+
end
|
25
|
+
|
26
|
+
test 'yields to block when permitted' do
|
27
|
+
sentinel = mock('sentinel', {:trip! => true})
|
28
|
+
@controller.permit({:list => widgets(:foo)}, {:roles => [roles(:administrator)]}) {sentinel.trip!}
|
29
|
+
end
|
30
|
+
|
31
|
+
test 'calls handler and does not yield to block when not permitted' do
|
32
|
+
sentinel = mock('sentinel')
|
33
|
+
@controller.expects(:handle_authorization_failure).returns(true)
|
34
|
+
@controller.permit({:all => Widget}, {:roles => []}) {sentinel.trip!}
|
35
|
+
end
|
36
|
+
|
37
|
+
test 'handler raises authorization exception' do
|
38
|
+
assert_raises Authorize::AuthorizationError do
|
39
|
+
@controller.permit({:all => Widget}, {:roles => []}) {sentinel.trip!}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
test 'mutiple authorization hash pairs' do
|
44
|
+
assert @controller.permit?({:list => widgets(:foo), :update => users(:chris)}, {:roles => [roles(:user_chris)]})
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
ENV['RAILS_ENV'] = 'test'
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
|
3
|
+
require 'test_help'
|
4
|
+
|
5
|
+
# Set Test::Unit options for optimal performance/fidelity.
|
6
|
+
class ActiveSupport::TestCase
|
7
|
+
self.use_transactional_fixtures = true
|
8
|
+
self.use_instantiated_fixtures = false
|
9
|
+
|
10
|
+
set_fixture_class :permissions => Authorize::Permission, :roles => Authorize::Role
|
11
|
+
|
12
|
+
def self.uses_mocha(description)
|
13
|
+
require 'mocha'
|
14
|
+
yield
|
15
|
+
rescue LoadError
|
16
|
+
$stderr.puts "Skipping #{description} tests. `gem install mocha` and try again."
|
17
|
+
end
|
18
|
+
setup {Authorize::Redis::Base.db.flushdb}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Unfortunately, setting expectations on any instance for #initialize causes #mocha_teardown
|
22
|
+
# to squirt out errors that cannot easily be suppressed in a less intrusive manner.
|
23
|
+
module Mocha
|
24
|
+
module API
|
25
|
+
def mocha_teardown_with_warning_suppression
|
26
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
27
|
+
mocha_teardown_without_warning_suppression
|
28
|
+
$VERBOSE = old_verbose
|
29
|
+
end
|
30
|
+
alias_method :mocha_teardown_without_warning_suppression, :mocha_teardown
|
31
|
+
alias_method :mocha_teardown, :mocha_teardown_with_warning_suppression
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
raise "Test Database doesn't look safe (#{Authorize::Redis::Base.db.inspect} has #{Authorize::Redis::Base.db.dbsize} keys)" unless Authorize::Redis::Base.db.dbsize < 100
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class BitmaskTest < ActiveSupport::TestCase
|
4
|
+
def setup
|
5
|
+
@bitmask = Class.new(Authorize::Bitmask)
|
6
|
+
@bitmask.name_values = {:none => 0, :first => 1, :second => 2, :third => 4, :fourth => 8, :first_nibble => 15, :fifth => 16, :sixth => 32, :seventh => 64, :eighth => 128, :all => 255}
|
7
|
+
end
|
8
|
+
|
9
|
+
test 'create degenerate' do
|
10
|
+
b = @bitmask[]
|
11
|
+
assert b.empty?
|
12
|
+
end
|
13
|
+
|
14
|
+
test 'create with integer' do
|
15
|
+
b = @bitmask.new(4)
|
16
|
+
assert_equal Set[:none, :third], b
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'create with invalid integer' do
|
20
|
+
assert_raises RangeError do
|
21
|
+
b = @bitmask.new(256)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
test 'create with enum' do
|
26
|
+
b = @bitmask[:first, :third]
|
27
|
+
assert_equal Set[:first, :third], b
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'create with invalid enum' do
|
31
|
+
assert_raises ArgumentError do
|
32
|
+
@bitmask[:first, :third, :ninth]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
test 'add bit' do
|
37
|
+
b = @bitmask[]
|
38
|
+
b << :first_nibble
|
39
|
+
assert_equal 15, b.to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
test 'add invalid bit' do
|
43
|
+
b = @bitmask[]
|
44
|
+
assert_raises ArgumentError do
|
45
|
+
b.add :first_word
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
test 'comparable' do
|
50
|
+
b0 = @bitmask[]
|
51
|
+
b1 = @bitmask[:first, :second, :third, :fourth]
|
52
|
+
b2 = @bitmask[:first_nibble]
|
53
|
+
assert_operator b0, :<, b1
|
54
|
+
assert_operator b2, :==, b1
|
55
|
+
end
|
56
|
+
|
57
|
+
test 'comparable with integers' do
|
58
|
+
b0 = @bitmask[:all]
|
59
|
+
assert_operator b0, :==, 255
|
60
|
+
assert_operator 255, :==, b0
|
61
|
+
end
|
62
|
+
|
63
|
+
test 'dynamic bit getters' do
|
64
|
+
b = @bitmask[:first, :second]
|
65
|
+
assert b._first
|
66
|
+
assert !b._third
|
67
|
+
end
|
68
|
+
|
69
|
+
test 'dynamic bit setters' do
|
70
|
+
b = @bitmask[:first, :second]
|
71
|
+
b._first = false
|
72
|
+
assert !b.include?(:first)
|
73
|
+
b._third = false
|
74
|
+
assert !b.include?(:third)
|
75
|
+
end
|
76
|
+
|
77
|
+
test 'dynamic bit predicates' do
|
78
|
+
b = @bitmask[:first, :second]
|
79
|
+
assert b._first?
|
80
|
+
assert !b._third?
|
81
|
+
end
|
82
|
+
|
83
|
+
test 'complete' do
|
84
|
+
b = @bitmask[]
|
85
|
+
assert_equal Set[:none], b.complete
|
86
|
+
b = @bitmask[:first_nibble]
|
87
|
+
assert_equal Set[:none, :first, :second, :third, :fourth, :first_nibble], b.complete
|
88
|
+
b = @bitmask[:first, :second, :third, :fourth]
|
89
|
+
assert_equal Set[:none, :first, :second, :third, :fourth, :first_nibble], b.complete
|
90
|
+
end
|
91
|
+
|
92
|
+
test 'fundamental' do
|
93
|
+
b = @bitmask[:first_nibble]
|
94
|
+
assert_equal Set[:first, :second, :third, :fourth], b.fundamental
|
95
|
+
end
|
96
|
+
|
97
|
+
test 'minimal' do
|
98
|
+
b = @bitmask[:none, :first, :second, :third, :fourth]
|
99
|
+
assert_equal Set[:first_nibble], b.minimal
|
100
|
+
end
|
101
|
+
|
102
|
+
test 'stringify' do
|
103
|
+
b = @bitmask.new(7)
|
104
|
+
assert_match /\w+(\|\w+){3}/, b.to_s
|
105
|
+
assert_match /none.*third/, b.to_s # canonical order
|
106
|
+
end
|
107
|
+
|
108
|
+
test 'stringify empty set' do
|
109
|
+
b = @bitmask[]
|
110
|
+
assert_equal "", b.to_s
|
111
|
+
end
|
112
|
+
end
|