authorize 0.0.1
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 +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
|