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
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'authorize/graph/fixtures'
|
3
|
+
|
4
|
+
class FixtureTest < ActiveSupport::TestCase
|
5
|
+
def setup
|
6
|
+
Authorize::Graph::Graph.index.clear # Clear the cache
|
7
|
+
Authorize::Graph::Vertex.index.clear # Clear the cache
|
8
|
+
Authorize::Graph::Edge.index.clear # Clear the cache
|
9
|
+
Authorize::Redis::String.index.clear
|
10
|
+
Authorize::Redis::Set.index.clear
|
11
|
+
Authorize::Redis::Hash.index.clear
|
12
|
+
@type_id = 'hapgoods.com,2010/graph'
|
13
|
+
@taguri = YAML.tagurize(@type_id)
|
14
|
+
end
|
15
|
+
|
16
|
+
test 'key translation' do
|
17
|
+
assert_equal "207907133", Authorize::Graph::Fixtures.name_to_key(:chris)
|
18
|
+
end
|
19
|
+
|
20
|
+
test 'registered type' do
|
21
|
+
assert_not_nil YAML.tagged_classes[@taguri]
|
22
|
+
end
|
23
|
+
|
24
|
+
test 'parser' do
|
25
|
+
document = <<-HERE
|
26
|
+
--- !hapgoods.com,2010/graph
|
27
|
+
- one
|
28
|
+
- two: [one]
|
29
|
+
HERE
|
30
|
+
assert result = YAML.parse(document)
|
31
|
+
assert_equal @taguri, result.type_id
|
32
|
+
end
|
33
|
+
|
34
|
+
test 'load node' do
|
35
|
+
document = <<-HERE
|
36
|
+
--- !hapgoods.com,2010/graph
|
37
|
+
- user_chris
|
38
|
+
HERE
|
39
|
+
v = stub('vertex')
|
40
|
+
Authorize::Role.graph.expects(:vertex).with(name_to_key(:user_chris)).returns(v)
|
41
|
+
YAML.load(document)
|
42
|
+
end
|
43
|
+
|
44
|
+
test 'link subordinate node without prior reference' do
|
45
|
+
document = <<-HERE
|
46
|
+
--- !hapgoods.com,2010/graph
|
47
|
+
- user_chris: [registered_user]
|
48
|
+
HERE
|
49
|
+
v0, v1 = stub('vertex0'), stub('vertex1')
|
50
|
+
Authorize::Role.graph.expects(:vertex).with(name_to_key(:user_chris)).returns(v0)
|
51
|
+
Authorize::Role.graph.expects(:vertex).with(name_to_key(:registered_user)).returns(v1)
|
52
|
+
Authorize::Role.graph.expects(:edge).with(nil, v0, v1)
|
53
|
+
assert result = YAML.load(document)
|
54
|
+
end
|
55
|
+
|
56
|
+
def name_to_key(name)
|
57
|
+
Authorize::Graph::Fixtures.name_to_key(name)
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'authorize/graph/directed_acyclic_graph_reverse_traverser'
|
3
|
+
|
4
|
+
class GraphDirectedAcyclicGraphReverseTraverserTest < ActiveSupport::TestCase
|
5
|
+
include Authorize::Graph
|
6
|
+
|
7
|
+
def setup
|
8
|
+
Authorize::Redis::String.index.clear # Clear the cache
|
9
|
+
Authorize::Redis::Set.index.clear
|
10
|
+
Authorize::Redis::Hash.index.clear
|
11
|
+
DirectedAcyclicGraph.index.clear
|
12
|
+
Authorize::Graph::Vertex.index.clear
|
13
|
+
Authorize::Graph::Edge.index.clear
|
14
|
+
build_simpsons_geneaology_graph
|
15
|
+
end
|
16
|
+
|
17
|
+
test 'reverse traverse DAG' do
|
18
|
+
assert_equal Set[@H, @A, @O], DirectedAcyclicGraphReverseTraverser.traverse(@H).to_set
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
# http://en.wikipedia.org/wiki/List_of_characters_in_The_Simpsons
|
23
|
+
# http://simpsons.wikia.com/wiki/Abraham_Simpson
|
24
|
+
def build_simpsons_geneaology_graph
|
25
|
+
@g0 = DirectedAcyclicGraph.new
|
26
|
+
@O = @g0.vertex("Orville")
|
27
|
+
@A = @g0.vertex("Abraham")
|
28
|
+
@J = @g0.vertex("Jacqueline")
|
29
|
+
@H = @g0.vertex("Homer")
|
30
|
+
@M = @g0.vertex("Marge")
|
31
|
+
@S = @g0.vertex("Selma")
|
32
|
+
@B = @g0.vertex("Bart")
|
33
|
+
@L = @g0.vertex("Lisa")
|
34
|
+
e0 = @g0.edge(nil, @O, @A, :name => "father")
|
35
|
+
e1 = @g0.edge(nil, @A, @H, :name => "father")
|
36
|
+
e2 = @g0.edge(nil, @H, @B, :name => "father")
|
37
|
+
e3 = @g0.edge(nil, @H, @L, :name => "father")
|
38
|
+
e4 = @g0.edge(nil, @J, @M, :name => "mother")
|
39
|
+
e5 = @g0.edge(nil, @J, @S, :name => "mother")
|
40
|
+
e6 = @g0.edge(nil, @M, @B, :name => "mother")
|
41
|
+
e7 = @g0.edge(nil, @M, @L, :name => "mother")
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "set"
|
2
|
+
require 'test_helper'
|
3
|
+
require 'authorize/graph/directed_acyclic_graph_traverser'
|
4
|
+
|
5
|
+
class GraphDirectedAcyclicGraphTraverserTest < ActiveSupport::TestCase
|
6
|
+
include Authorize::Graph
|
7
|
+
|
8
|
+
def setup
|
9
|
+
Authorize::Redis::String.index.clear # Clear the cache
|
10
|
+
Authorize::Redis::Set.index.clear
|
11
|
+
Authorize::Redis::Hash.index.clear
|
12
|
+
DirectedAcyclicGraph.index.clear
|
13
|
+
Authorize::Graph::Vertex.index.clear
|
14
|
+
Authorize::Graph::Edge.index.clear
|
15
|
+
build_simpsons_geneaology_graph
|
16
|
+
end
|
17
|
+
|
18
|
+
test 'traverse DAG' do
|
19
|
+
assert_equal Set[@A, @H, @B, @L], DirectedAcyclicGraphTraverser.traverse(@A).to_set
|
20
|
+
end
|
21
|
+
|
22
|
+
test 'traverse cyclic DAG with checking' do
|
23
|
+
@g0.edge(nil, @H, @O, :name => "grandfathergrandson") # Introduce a cycle
|
24
|
+
assert_raises RuntimeError do
|
25
|
+
DirectedAcyclicGraphTraverser.traverse(@H, true).to_set
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
test 'traverse non-polytree DAG with checking' do
|
30
|
+
@g0.edge(nil, @O, @H, :name => "songrandson") # Introduce an undirected cycle
|
31
|
+
assert_equal Set[@O, @A, @H, @B, @L], DirectedAcyclicGraphTraverser.traverse(@O, true).to_set
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
# http://en.wikipedia.org/wiki/List_of_characters_in_The_Simpsons
|
36
|
+
# http://simpsons.wikia.com/wiki/Abraham_Simpson
|
37
|
+
# This graph is, more precisely, a tree (or ordered directed tree if you talk to a mathematician).
|
38
|
+
def build_simpsons_geneaology_graph
|
39
|
+
@g0 = DirectedAcyclicGraph.new
|
40
|
+
@O = @g0.vertex("Orville")
|
41
|
+
@A = @g0.vertex("Abraham")
|
42
|
+
@J = @g0.vertex("Jacqueline")
|
43
|
+
@H = @g0.vertex("Homer")
|
44
|
+
@M = @g0.vertex("Marge")
|
45
|
+
@S = @g0.vertex("Selma")
|
46
|
+
@B = @g0.vertex("Bart")
|
47
|
+
@L = @g0.vertex("Lisa")
|
48
|
+
e0 = @g0.edge(nil, @O, @A, :name => "father")
|
49
|
+
e1 = @g0.edge(nil, @A, @H, :name => "father")
|
50
|
+
e2 = @g0.edge(nil, @H, @B, :name => "father")
|
51
|
+
e3 = @g0.edge(nil, @H, @L, :name => "father")
|
52
|
+
e4 = @g0.edge(nil, @J, @M, :name => "mother")
|
53
|
+
e5 = @g0.edge(nil, @J, @S, :name => "mother")
|
54
|
+
e6 = @g0.edge(nil, @M, @B, :name => "mother")
|
55
|
+
e7 = @g0.edge(nil, @M, @L, :name => "mother")
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class GraphDirectedGraphTest < ActiveSupport::TestCase
|
4
|
+
def setup
|
5
|
+
Authorize::Redis::String.index.clear # Clear the cache
|
6
|
+
Authorize::Redis::Set.index.clear
|
7
|
+
Authorize::Redis::Hash.index.clear
|
8
|
+
Authorize::Graph::DirectedGraph.index.clear
|
9
|
+
Authorize::Graph::Vertex.index.clear
|
10
|
+
Authorize::Graph::Edge.index.clear
|
11
|
+
@factory = Authorize::Graph::Factory.new
|
12
|
+
create_interstate_graph
|
13
|
+
end
|
14
|
+
|
15
|
+
test 'edges' do
|
16
|
+
# assert @g0.edges.include?(@i64e)
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'vertices' do
|
20
|
+
# assert @g0.vertices.include?(@cho)
|
21
|
+
end
|
22
|
+
|
23
|
+
test 'join' do
|
24
|
+
assert_kind_of Authorize::Graph::Edge, edge = @g0.join('I95N', @ric, @spr, {'key' => 'value'})
|
25
|
+
assert_equal @ric, edge.from
|
26
|
+
assert_equal @spr, edge.to
|
27
|
+
assert @g0.edges.include?(edge)
|
28
|
+
assert_equal 'value', edge['key']
|
29
|
+
end
|
30
|
+
|
31
|
+
test 'join merges properties with existing edge' do
|
32
|
+
properties = {'lanes' => '3'}
|
33
|
+
@i64e.expects(:merge).with(properties)
|
34
|
+
assert_same @i64e, @g0.join('newI64E', @cho, @ric, properties)
|
35
|
+
end
|
36
|
+
|
37
|
+
test 'disjoin' do
|
38
|
+
@i64e.expects(:destroy)
|
39
|
+
e = @g0.disjoin(@cho, @ric)
|
40
|
+
assert_same @i64e, e
|
41
|
+
end
|
42
|
+
|
43
|
+
test 'disjoin without an existant edge' do
|
44
|
+
e = @g0.disjoin(@ric, @spr)
|
45
|
+
assert_nil e
|
46
|
+
end
|
47
|
+
|
48
|
+
test 'traverse' do
|
49
|
+
assert_equal Set[@cho, @ric], @g0.traverse(@cho).to_set
|
50
|
+
end
|
51
|
+
|
52
|
+
test 'traverse from unconnected vertex' do
|
53
|
+
assert_equal Set[@spr], @g0.traverse(@spr).to_set
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def create_interstate_graph
|
58
|
+
i64e_id, i64w_id = 'I64E', 'I64W'
|
59
|
+
@cho = @factory.vertex('Charlottesville', {'property' => 'value'}, :edge_ids => Set[i64e_id], :inbound_edge_ids => Set[i64w_id])
|
60
|
+
@ric = @factory.vertex('Richmond', {}, :edge_ids => Set[i64w_id], :inbound_edge_ids => Set[i64e_id])
|
61
|
+
@spr = @factory.vertex('Springfield', {}, :edge_ids => Set[])
|
62
|
+
@i64e = @factory.edge(i64e_id, {}, :l_id => @cho.id, :r_id => @ric.id)
|
63
|
+
@i64w = @factory.edge(i64w_id, {}, :l_id => @ric.id, :r_id => @cho.id)
|
64
|
+
@g0 = @factory.directed_graph('Interstates', Set[@cho.id, @ric.id, @spr.id], :edge_ids => Set[@i64e.id, @i64e.id])
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class GraphEdgeTest < ActiveSupport::TestCase
|
4
|
+
def setup
|
5
|
+
Authorize::Graph::Edge.index.clear # clear cache
|
6
|
+
create_graph
|
7
|
+
end
|
8
|
+
|
9
|
+
test 'create edge from one vertex to another' do
|
10
|
+
name = 'name'
|
11
|
+
property, value = 'property', 'value'
|
12
|
+
assert_kind_of Authorize::Graph::Edge, e = Authorize::Graph::Edge.new(name, @cho, @spr, property => value)
|
13
|
+
assert @cho.outbound_edges.include?(e)
|
14
|
+
assert @spr.inbound_edges.include?(e)
|
15
|
+
assert !Authorize::Graph::Edge.db.keys(e.id + '*').empty?
|
16
|
+
end
|
17
|
+
|
18
|
+
test 'exists?' do
|
19
|
+
assert Authorize::Graph::Edge.exists?(@e0.id)
|
20
|
+
end
|
21
|
+
|
22
|
+
test 'valid?' do
|
23
|
+
assert @e0.valid?
|
24
|
+
end
|
25
|
+
|
26
|
+
test 'from' do
|
27
|
+
assert_same @cho, @e0.from
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'to' do
|
31
|
+
assert_equal @ric, @e0.to
|
32
|
+
end
|
33
|
+
|
34
|
+
test 'destroy' do
|
35
|
+
@e0.destroy
|
36
|
+
assert !@cho.outbound_edges.include?(@e0)
|
37
|
+
assert !@ric.inbound_edges.include?(@e0)
|
38
|
+
assert Authorize::Graph::Edge.db.keys(@e0.id + '*').empty?
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
# Create a simple graph with edge fixtures and stubbed vertices (to decouple Vertex implementation).
|
43
|
+
def create_graph
|
44
|
+
@factory = Authorize::Graph::Factory.new
|
45
|
+
l_id, r_id = 'l_id', 'r_id'
|
46
|
+
@e0 = @factory.edge('e0', {'property' => 'value'}, :l_id => l_id, :r_id => r_id)
|
47
|
+
@cho = stub('cho', :id => l_id, :outbound_edges => Set[@e0])
|
48
|
+
@ric = stub('ric', :id => r_id, :inbound_edges => Set[@e0])
|
49
|
+
@spr = stub('spr', :id => 'spr', :inbound_edges => Set[])
|
50
|
+
Authorize::Graph::Vertex.stubs(:load).with(@cho.id).returns(@cho)
|
51
|
+
Authorize::Graph::Vertex.stubs(:load).with(@ric.id).returns(@ric)
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class GraphGraphTest < ActiveSupport::TestCase
|
4
|
+
def setup
|
5
|
+
Authorize::Redis::String.index.clear # Clear the cache
|
6
|
+
Authorize::Redis::Set.index.clear
|
7
|
+
Authorize::Redis::Hash.index.clear
|
8
|
+
Authorize::Graph::Graph.index.clear
|
9
|
+
Authorize::Graph::Vertex.index.clear
|
10
|
+
Authorize::Graph::Edge.index.clear
|
11
|
+
end
|
12
|
+
|
13
|
+
test 'create graph' do
|
14
|
+
assert_kind_of Authorize::Graph::Graph, g0 = Authorize::Graph::Graph.new
|
15
|
+
assert_kind_of Authorize::Redis::Set, g0
|
16
|
+
assert_kind_of ::Enumerable, g0.vertices
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'exists' do
|
20
|
+
name = 'name'
|
21
|
+
Authorize::Graph::Vertex.db.expects(:keys).with(name + '::*', nil).returns([name + '::something'])
|
22
|
+
assert Authorize::Graph::Graph.exists?(name)
|
23
|
+
end
|
24
|
+
|
25
|
+
test 'add vertex' do
|
26
|
+
g0 = Authorize::Graph::Graph.new
|
27
|
+
assert_kind_of Authorize::Graph::Vertex, v0 = g0.vertex("Charlottesville")
|
28
|
+
assert g0.vertices.include?(v0)
|
29
|
+
end
|
30
|
+
|
31
|
+
test 'add edge' do
|
32
|
+
g0 = Authorize::Graph::Graph.new
|
33
|
+
v0, v1 = g0.vertex("Charlottesville"), g0.vertex("Richmond")
|
34
|
+
assert_kind_of Authorize::Graph::Edge, e = g0.edge("I64", v0, v1)
|
35
|
+
assert v0.edges.include?(e)
|
36
|
+
assert v1.edges.empty?
|
37
|
+
assert_equal v0, e.from
|
38
|
+
assert_equal v1, e.to
|
39
|
+
assert g0.edges.include?(e)
|
40
|
+
end
|
41
|
+
|
42
|
+
test 'join vertices' do
|
43
|
+
g0 = Authorize::Graph::UndirectedGraph.new
|
44
|
+
v0, v1 = g0.vertex("Charlottesville"), g0.vertex("Richmond")
|
45
|
+
assert g0.join("I64", v0, v1)
|
46
|
+
[[v0, v1], [v1, v0]].each do |(vl, vr)|
|
47
|
+
assert vl.neighbors.include?(vr)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'authorize/graph/traverser'
|
3
|
+
|
4
|
+
class GraphTraverserTest < ActiveSupport::TestCase
|
5
|
+
include Authorize::Graph
|
6
|
+
|
7
|
+
def setup
|
8
|
+
Authorize::Redis::String.index.clear # Clear the cache
|
9
|
+
Authorize::Redis::Set.index.clear
|
10
|
+
Authorize::Redis::Hash.index.clear
|
11
|
+
Authorize::Graph::Graph.index.clear
|
12
|
+
Authorize::Graph::Vertex.index.clear
|
13
|
+
Authorize::Graph::Edge.index.clear
|
14
|
+
create_interstate_graph
|
15
|
+
end
|
16
|
+
|
17
|
+
test 'traverse graph' do
|
18
|
+
assert_equal Set[@cho, @ric, @spr, @dlg, @cnv, @str, @stn, @roa], Traverser.traverse(@dlg).to_set
|
19
|
+
assert_equal 8, Traverser.traverse(@dlg).count
|
20
|
+
assert_equal 8, Traverser.traverse(@dlg).each{|x|}
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_interstate_graph
|
24
|
+
@g0 = Authorize::Graph::UndirectedGraph.new("Highways")
|
25
|
+
@cho = @g0.vertex("Charlottesville")
|
26
|
+
@ric = @g0.vertex("Richmond")
|
27
|
+
@spr = @g0.vertex("Springfield")
|
28
|
+
@dlg = @g0.vertex("Dunn_Loring")
|
29
|
+
@cnv = @g0.vertex("Centreville")
|
30
|
+
@str = @g0.vertex("Strasburg")
|
31
|
+
@stn = @g0.vertex("Staunton")
|
32
|
+
@roa = @g0.vertex("Roanoke")
|
33
|
+
e0a = @g0.join(nil, @stn, @cho, :name => "I64", :cost => 95)
|
34
|
+
e0b = @g0.join(nil, @cho, @ric, :name => "I64", :cost => 100)
|
35
|
+
e1 = @g0.join(nil, @ric, @spr, :name => "I95", :cost => 85)
|
36
|
+
e2 = @g0.join(nil, @spr, @dlg, :name => "I495", :cost => 20)
|
37
|
+
e3a = @g0.join(nil, @dlg, @cnv, :name => "I66", :cost => 40)
|
38
|
+
e3b = @g0.join(nil, @cnv, @str, :name => "I66", :cost => 120)
|
39
|
+
e4 = @g0.join(nil, @str, @stn, :name => "I81", :cost => 130)
|
40
|
+
e5 = @g0.join(nil, @stn, @roa, :name => "I81", :cost => 125)
|
41
|
+
e5 = @g0.join(nil, @cho, @cnv, :name => "US29", :cost => 200)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'authorize/graph/factory'
|
3
|
+
|
4
|
+
class GraphVertexTest < ActiveSupport::TestCase
|
5
|
+
def setup
|
6
|
+
Authorize::Graph::Vertex.index.clear # clear cache
|
7
|
+
@factory = Authorize::Graph::Factory.new
|
8
|
+
end
|
9
|
+
|
10
|
+
test 'create' do
|
11
|
+
name = 'name'
|
12
|
+
property, value = 'property', 'value'
|
13
|
+
v = Authorize::Graph::Vertex.new(name, property => value)
|
14
|
+
assert_equal name, v.id
|
15
|
+
assert !Authorize::Graph::Vertex.db.keys(v.id + '*').empty?
|
16
|
+
end
|
17
|
+
|
18
|
+
test 'destroy' do
|
19
|
+
create_graph
|
20
|
+
@edge.expects(:destroy)
|
21
|
+
@v0.destroy
|
22
|
+
assert Authorize::Graph::Vertex.db.keys(@v0.id + '*').empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
test 'destroy removes inbound edges' do
|
26
|
+
create_graph
|
27
|
+
@edge.expects(:destroy)
|
28
|
+
@v1.destroy
|
29
|
+
assert Authorize::Graph::Vertex.db.keys(@v1.id + '*').empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
test 'exists?' do
|
33
|
+
create_graph
|
34
|
+
assert Authorize::Graph::Vertex.exists?(@v0.id)
|
35
|
+
end
|
36
|
+
|
37
|
+
test 'edges' do
|
38
|
+
create_graph
|
39
|
+
assert_equal Set[@edge], @v0.edges.to_set
|
40
|
+
end
|
41
|
+
|
42
|
+
test 'adjacencies' do
|
43
|
+
create_graph
|
44
|
+
assert_equal Set[@v1], @v0.adjacencies.to_set
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
# Create a simple graph with vertex fixtures and stubbed edges (to decouple Edge implementation).
|
49
|
+
def create_graph
|
50
|
+
eid = 'edge_id'
|
51
|
+
@v0 = @factory.vertex('v0', {'property' => 'value'}, :edge_ids => Set[eid])
|
52
|
+
@v1 = @factory.vertex('v1', {}, :edge_ids => Set[], :inbound_edge_ids => Set[eid])
|
53
|
+
@v2 = @factory.vertex('v2', {}, :edge_ids => Set[])
|
54
|
+
@edge = stub('edge', :id => eid, :from => @v0, :to => @v1)
|
55
|
+
Authorize::Graph::Edge.stubs(:load).with(@edge.id).returns(@edge)
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PermissionTest < ActiveSupport::TestCase
|
4
|
+
fixtures :all
|
5
|
+
|
6
|
+
test 'create' do
|
7
|
+
p = Authorize::Permission.create(:role => roles(:user_chris), :resource => widgets(:bar))
|
8
|
+
assert p.valid?, p.errors.full_messages
|
9
|
+
end
|
10
|
+
|
11
|
+
test 'resource reader' do
|
12
|
+
assert_equal widgets(:foo), permissions(:a_read_foo).resource
|
13
|
+
assert_equal Widget, permissions(:c_all_widgets).resource
|
14
|
+
assert_equal Object, permissions(:b_overlord).resource
|
15
|
+
end
|
16
|
+
|
17
|
+
test 'resource writer with instance' do
|
18
|
+
p = permissions(:a_list_bar)
|
19
|
+
p.resource = widgets(:foo)
|
20
|
+
assert_equal Widget.to_s, p[:resource_type]
|
21
|
+
assert_equal widgets(:foo).id, p[:resource_id]
|
22
|
+
assert p.changed?
|
23
|
+
end
|
24
|
+
|
25
|
+
test 'resource writer with class' do
|
26
|
+
p = permissions(:a_list_bar)
|
27
|
+
p.resource = Widget
|
28
|
+
assert_equal Widget.to_s, p[:resource_type]
|
29
|
+
assert_nil p[:resource_id]
|
30
|
+
assert p.changed?
|
31
|
+
end
|
32
|
+
|
33
|
+
test 'resource writer with Object' do
|
34
|
+
p = permissions(:a_list_bar)
|
35
|
+
p.resource = Object
|
36
|
+
assert_nil p[:resource_type]
|
37
|
+
assert_nil p[:resource_id]
|
38
|
+
assert p.changed?
|
39
|
+
end
|
40
|
+
|
41
|
+
test 'stringify' do
|
42
|
+
assert_kind_of String, permissions(:a_read_foo).to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
test 'invalid with missing role' do
|
46
|
+
p = Authorize::Permission.new
|
47
|
+
assert !p.valid?
|
48
|
+
assert p.errors.on(:role)
|
49
|
+
end
|
50
|
+
|
51
|
+
test 'invalid with missing resource' do
|
52
|
+
p = Authorize::Permission.new(:resource_type => 'Widget', :resource_id => 0)
|
53
|
+
assert !p.valid?
|
54
|
+
assert p.errors[:resource]
|
55
|
+
end
|
56
|
+
|
57
|
+
test 'mask reader' do
|
58
|
+
p = permissions(:a_read_foo)
|
59
|
+
assert_equal Set.new([:list, :read]), p.mask
|
60
|
+
end
|
61
|
+
|
62
|
+
test 'mask writer with mask' do
|
63
|
+
p = permissions(:a_read_foo)
|
64
|
+
p.mask # trigger cache
|
65
|
+
p.mask = Authorize::Permission::Mask[:delete]
|
66
|
+
assert_equal Set[:delete], p.mask
|
67
|
+
assert p.mask_changed?
|
68
|
+
end
|
69
|
+
|
70
|
+
test 'mask writer with integer' do
|
71
|
+
p = permissions(:a_read_foo)
|
72
|
+
p.mask # trigger cache
|
73
|
+
p.mask = 8
|
74
|
+
assert_equal Set[:delete], p.mask
|
75
|
+
assert p.mask_changed?
|
76
|
+
end
|
77
|
+
|
78
|
+
test 'mask conforms to dirty standards' do
|
79
|
+
p = permissions(:a_read_foo)
|
80
|
+
p.mask_will_change!
|
81
|
+
p.mask << :update
|
82
|
+
assert_equal [Authorize::Permission::Mask[:list, :read], Authorize::Permission::Mask[:list, :read, :update]], p.mask_change
|
83
|
+
end
|
84
|
+
|
85
|
+
test 'global scope' do
|
86
|
+
assert_equal Set[permissions(:b_overlord)], Authorize::Permission.global.to_set
|
87
|
+
end
|
88
|
+
|
89
|
+
test 'for scope' do
|
90
|
+
assert_equal Set[permissions(:b_overlord)], Authorize::Permission.for(Object).to_set
|
91
|
+
assert_equal Set[permissions(:c_all_widgets)], Authorize::Permission.for(Widget).to_set
|
92
|
+
assert_equal Set[permissions(:a_read_foo)], Authorize::Permission.for(widgets(:foo)).to_set
|
93
|
+
end
|
94
|
+
|
95
|
+
test 'over scope' do
|
96
|
+
assert_equal Set[permissions(:b_overlord)], Authorize::Permission.over(Object).to_set
|
97
|
+
assert_equal Set[permissions(:b_overlord), permissions(:c_all_widgets)], Authorize::Permission.over(Widget).to_set
|
98
|
+
assert_equal Set[permissions(:b_overlord), permissions(:c_all_widgets), permissions(:a_read_foo)], Authorize::Permission.over(widgets(:foo)).to_set
|
99
|
+
end
|
100
|
+
|
101
|
+
test 'aggregate_mask' do
|
102
|
+
assert_equal Set[:list, :read, :update, :delete], Authorize::Permission.over(widgets(:bar)).as([roles(:d), roles(:e)]).aggregate_mask.to_set
|
103
|
+
end
|
104
|
+
|
105
|
+
test 'aggregate mask for no permissions' do
|
106
|
+
assert_equal Authorize::Permission::Mask[], Authorize::Permission.over(widgets(:bar)).as([]).aggregate_mask
|
107
|
+
end
|
108
|
+
|
109
|
+
test 'permit predicate' do
|
110
|
+
assert Authorize::Permission.over(widgets(:bar)).as([roles(:d), roles(:e)]).permit?(Authorize::Permission::Mask[:update])
|
111
|
+
assert !Authorize::Permission.over(widgets(:bar)).as([roles(:d), roles(:e)]).permit?(Authorize::Permission::Mask[:manage])
|
112
|
+
end
|
113
|
+
|
114
|
+
test 'default includes list mode' do
|
115
|
+
assert_equal Authorize::Permission::Mask[:list], Authorize::Permission.new.mask
|
116
|
+
end
|
117
|
+
|
118
|
+
test 'list mode enforced on save' do
|
119
|
+
p = permissions(:d_update_bar)
|
120
|
+
p.update_attributes(:mask => Authorize::Permission::Mask[])
|
121
|
+
assert_equal Authorize::Permission::Mask[:list], p.reload.mask
|
122
|
+
end
|
123
|
+
end
|