ad-framework 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +12 -0
  3. data/README.markdown +36 -0
  4. data/Rakefile +19 -0
  5. data/ad-framework.gemspec +25 -0
  6. data/doc/open_ldap_server.markdown +17 -0
  7. data/extras/adtest.schema +304 -0
  8. data/extras/slapd.conf +10 -0
  9. data/lib/ad-framework.rb +53 -0
  10. data/lib/ad-framework/attribute.rb +35 -0
  11. data/lib/ad-framework/attribute_type.rb +133 -0
  12. data/lib/ad-framework/auxiliary_class.rb +24 -0
  13. data/lib/ad-framework/config.rb +72 -0
  14. data/lib/ad-framework/config/attribute_definition.rb +18 -0
  15. data/lib/ad-framework/config/mapping.rb +26 -0
  16. data/lib/ad-framework/exceptions.rb +17 -0
  17. data/lib/ad-framework/fields.rb +44 -0
  18. data/lib/ad-framework/patterns/callbacks.rb +47 -0
  19. data/lib/ad-framework/patterns/has_schema.rb +127 -0
  20. data/lib/ad-framework/patterns/persistence.rb +67 -0
  21. data/lib/ad-framework/patterns/searchable.rb +117 -0
  22. data/lib/ad-framework/patterns/validations.rb +50 -0
  23. data/lib/ad-framework/schema.rb +118 -0
  24. data/lib/ad-framework/structural_class.rb +61 -0
  25. data/lib/ad-framework/utilities/entry_builder.rb +77 -0
  26. data/lib/ad-framework/utilities/transaction.rb +32 -0
  27. data/lib/ad-framework/utilities/validator.rb +26 -0
  28. data/lib/ad-framework/version.rb +5 -0
  29. data/test/helper.rb +71 -0
  30. data/test/integration/defined_array_test.rb +49 -0
  31. data/test/integration/defined_integer_test.rb +48 -0
  32. data/test/integration/defined_string_test.rb +48 -0
  33. data/test/integration/defined_top_test.rb +101 -0
  34. data/test/integration/defined_user_test.rb +140 -0
  35. data/test/irb.rb +2 -0
  36. data/test/support/factory.rb +67 -0
  37. data/test/support/ldap.yml +6 -0
  38. data/test/support/schema/attribute_types.rb +67 -0
  39. data/test/support/schema/attributes.rb +10 -0
  40. data/test/support/schema/auxiliary_classes.rb +12 -0
  41. data/test/support/schema/structural_classes.rb +46 -0
  42. data/test/support/seed.rb +28 -0
  43. data/test/support/state.rb +29 -0
  44. data/test/unit/ad-framework/attribute_test.rb +84 -0
  45. data/test/unit/ad-framework/attribute_type/class_methods_test.rb +146 -0
  46. data/test/unit/ad-framework/attribute_type_test.rb +114 -0
  47. data/test/unit/ad-framework/auxiliary_class_test.rb +39 -0
  48. data/test/unit/ad-framework/config/attribute_definition_test.rb +26 -0
  49. data/test/unit/ad-framework/config/mapping_test.rb +41 -0
  50. data/test/unit/ad-framework/config_test.rb +121 -0
  51. data/test/unit/ad-framework/fields_test.rb +44 -0
  52. data/test/unit/ad-framework/patterns/callbacks_test.rb +90 -0
  53. data/test/unit/ad-framework/patterns/has_schema/class_methods_test.rb +214 -0
  54. data/test/unit/ad-framework/patterns/has_schema_test.rb +96 -0
  55. data/test/unit/ad-framework/patterns/persistence_test.rb +126 -0
  56. data/test/unit/ad-framework/patterns/searchable_test.rb +201 -0
  57. data/test/unit/ad-framework/patterns/validations_test.rb +113 -0
  58. data/test/unit/ad-framework/schema_test.rb +268 -0
  59. data/test/unit/ad-framework/structural_class_test.rb +64 -0
  60. data/test/unit/ad-framework/utilities/entry_builder_test.rb +107 -0
  61. data/test/unit/ad-framework/utilities/transaction_test.rb +50 -0
  62. data/test/unit/ad-framework/utilities/validator_test.rb +46 -0
  63. data/test/unit/ad-framework_test.rb +116 -0
  64. metadata +225 -0
@@ -0,0 +1,2 @@
1
+ require 'ad-framework'
2
+ require 'test/helper'
@@ -0,0 +1,67 @@
1
+ module Factory
2
+ extend Mocha::API
3
+
4
+ class << self
5
+
6
+ def attribute_definition(args = {})
7
+ args[:name] ||= "test_attr"
8
+ args[:ldap_name] ||= "testattr"
9
+ args[:type] ||= "test_string"
10
+ AD::Framework::Config::AttributeDefinition.new(args)
11
+ end
12
+
13
+ def mock_attribute(methods = {})
14
+ attribute = mock()
15
+ methods[:name] ||= "test_attr"
16
+ methods[:ldap_name] ||= "testattr"
17
+ methods[:attribute_type] ||= self.mock_attribute_type
18
+ methods.each do |method, value|
19
+ attribute.stubs(method).returns(value)
20
+ end
21
+ attribute
22
+ end
23
+
24
+ def mock_attribute_type(methods = {})
25
+ attribute_type = mock()
26
+ methods[:key] ||= "test_string"
27
+ methods.each do |method, value|
28
+ attribute_type.stubs(method).returns(value)
29
+ end
30
+ attribute_type
31
+ end
32
+
33
+ def structural_class(methods = {}, &block)
34
+ block ||= ::Proc.new do
35
+ ldap_name "testObjectClass"
36
+ end
37
+ structural_class = Class.new(AD::Framework::StructuralClass, &block)
38
+ structural_class
39
+ end
40
+
41
+ def mock_structural_class_instance(methods = {})
42
+ structural_class = mock()
43
+ methods[:dn] ||= "CN=test object, DC=example, DC=com"
44
+ methods[:fields] ||= {}
45
+ methods.each do |method, value|
46
+ structural_class.stubs(method).returns(value)
47
+ end
48
+ structural_class
49
+ end
50
+
51
+ def attribute_type(methods = {}, &block)
52
+ block ||= ::Proc.new{}
53
+ attribute_type = Class.new(AD::Framework::AttributeType, &block)
54
+ attribute_type
55
+ end
56
+
57
+ def auxiliary_class(&block)
58
+ block ||= ::Proc.new{}
59
+ auxiliary_class = Module.new do
60
+ include AD::Framework::AuxiliaryClass
61
+ end
62
+ auxiliary_class.class_eval(&block)
63
+ auxiliary_class
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,6 @@
1
+ :host: "127.0.0.1"
2
+ :port: 389
3
+ :base: "DC=localhost"
4
+ :auth:
5
+ :username: "CN=root,DC=localhost"
6
+ :password: "secret"
@@ -0,0 +1,67 @@
1
+ module AD
2
+ class String < AD::Framework::AttributeType
3
+
4
+ key "string"
5
+
6
+ def value=(new_value)
7
+ super(new_value ? new_value.to_s : new_value)
8
+ end
9
+
10
+ end
11
+ end
12
+ AD::Framework.register_attribute_type(AD::String)
13
+
14
+ module AD
15
+ class Integer < AD::Framework::AttributeType
16
+
17
+ key "integer"
18
+
19
+ def value=(new_value)
20
+ super(new_value ? new_value.to_i : new_value)
21
+ end
22
+
23
+ end
24
+ end
25
+ AD::Framework.register_attribute_type(AD::Integer)
26
+
27
+ module AD
28
+ class Array < AD::Framework::AttributeType
29
+ key "array"
30
+
31
+ attr_accessor :item_class
32
+
33
+ def initialize(object, attr_ldap_name)
34
+ self.item_class = AD::String
35
+ super
36
+ end
37
+
38
+ def value_from_field
39
+ (self.object.fields[self.attr_ldap_name] || [])
40
+ end
41
+
42
+ def value
43
+ self.get_items_values(@value)
44
+ end
45
+
46
+ def value=(new_value)
47
+ values = [*new_value].compact.collect do |value|
48
+ self.item_class.new(self.object, attr_ldap_name, value)
49
+ end
50
+ super(values)
51
+ end
52
+
53
+ def ldap_value=(new_value)
54
+ super(self.get_items_values(new_value))
55
+ end
56
+
57
+ protected
58
+
59
+ def get_items_values(items)
60
+ [*items].compact.collect(&:value)
61
+ end
62
+
63
+ end
64
+ end
65
+
66
+ AD::Framework.register_attribute_type(AD::Array)
67
+
@@ -0,0 +1,10 @@
1
+ AD::Framework.register_attributes([
2
+ { :name => "name", :ldap_name => "cn", :type => "string" },
3
+ { :name => "system_flags", :ldap_name => "systemflags", :type => "integer" },
4
+ { :name => "display_name", :ldap_name => "displayname", :type => "string" },
5
+ { :name => "description", :ldap_name => "description", :type => "string" },
6
+ { :name => "proxy_addresses", :ldap_name => "proxyaddresses", :type => "array" },
7
+ { :name => "unix_member_of", :ldap_name => "mssfu30posixmemberof", :type => "array" },
8
+ { :name => "sam_account_name", :ldap_name => "samaccountname", :type => "string" },
9
+ { :name => "object_sid", :ldap_name => "objectsid", :type => "integer" }
10
+ ])
@@ -0,0 +1,12 @@
1
+ module AD
2
+ module SecurityPrincipal
3
+ include AD::Framework::AuxiliaryClass
4
+
5
+ ldap_name "securityPrincipal"
6
+ attributes :sam_account_name, :object_sid
7
+
8
+ must_set :sam_account_name, :object_sid
9
+
10
+ end
11
+ end
12
+ AD::Framework.register_auxiliary_class(AD::SecurityPrincipal)
@@ -0,0 +1,46 @@
1
+ module AD
2
+ class Top < AD::Framework::StructuralClass
3
+
4
+ ldap_name "top"
5
+ rdn :name
6
+ attributes :name, :system_flags, :display_name, :description
7
+
8
+ must_set :name
9
+
10
+ end
11
+ end
12
+ AD::Framework.register_structural_class(AD::Top)
13
+
14
+ module AD
15
+ class Container < AD::Top
16
+ ldap_name "container"
17
+ end
18
+ end
19
+ AD::Framework.register_structural_class(AD::Container)
20
+
21
+ module AD
22
+ class Person < AD::Top
23
+ ldap_name "person"
24
+ end
25
+ end
26
+ AD::Framework.register_structural_class(AD::Person)
27
+
28
+ module AD
29
+ class OrganizationalPerson < AD::Person
30
+ ldap_name "organizationalPerson"
31
+ end
32
+ end
33
+ AD::Framework.register_structural_class(AD::OrganizationalPerson)
34
+
35
+ module AD
36
+ class User < AD::OrganizationalPerson
37
+ include AD::SecurityPrincipal
38
+
39
+ ldap_name "user"
40
+ treebase "CN=Users, CN=AD Framework Tests"
41
+ rdn :name
42
+ attributes :proxy_addresses
43
+
44
+ end
45
+ end
46
+ AD::Framework.register_structural_class(AD::User)
@@ -0,0 +1,28 @@
1
+ module Seed
2
+ class << self
3
+
4
+ def up
5
+ self.down
6
+ container = AD::Container.create({ :name => "AD Framework Tests" })
7
+ users_container = AD::Container.create({
8
+ :name => "Users", :treebase => "CN=AD Framework Tests"
9
+ })
10
+ user = AD::User.create({
11
+ :name => "joe test", :system_flags => 1000, :sam_account_name => "jtest",
12
+ :object_sid => 1
13
+ })
14
+ end
15
+
16
+ def down
17
+ container = AD::Container.first({ :name => "AD Framework Tests" })
18
+ dn = "CN=Users, CN=AD Framework Tests, #{AD::Container.treebase}"
19
+ users_container = AD::Container.first({ :dn => dn }) if container
20
+ user = AD::User.first({ :name => "joe test" }) if users_container
21
+
22
+ user.destroy if user
23
+ users_container.destroy if users_container
24
+ container.destroy if container
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ module State
2
+ class << self
3
+ attr_accessor :current_framework_config, :current_ldap_config
4
+
5
+ def preserve
6
+ self.current_framework_config = AD::Framework.config.dup
7
+ self.current_ldap_config = AD::LDAP.config.dup
8
+ self.nullify
9
+ load("test/support/schema/attribute_types.rb")
10
+ load("test/support/schema/attributes.rb")
11
+ end
12
+
13
+ def restore
14
+ self.nullify
15
+ AD::LDAP.instance_variable_set("@config", self.current_ldap_config)
16
+ AD::Framework.instance_variable_set("@config", self.current_framework_config)
17
+ end
18
+
19
+ protected
20
+
21
+ def nullify
22
+ AD::Framework.instance_variable_set("@config", nil)
23
+ AD::LDAP.instance_variable_set("@logger", nil)
24
+ AD::LDAP.instance_variable_set("@adapter", nil)
25
+ AD::LDAP.instance_variable_set("@config", nil)
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,84 @@
1
+ require 'assert'
2
+
3
+ class AD::Framework::Attribute
4
+
5
+ class BaseTest < Assert::Context
6
+ desc "AD::Framework::Attribute"
7
+ setup do
8
+ @class = AD::Framework::Attribute
9
+ @definition = Factory.attribute_definition
10
+ AD::Framework.config.attributes[@definition.name] = @definition
11
+ @attribute_type = Factory.mock_attribute_type
12
+ AD::Framework.config.attribute_types[@attribute_type.key] = @attribute_type
13
+ @attribute = @class.new(@definition.name.to_s)
14
+ end
15
+ subject{ @attribute }
16
+
17
+ should have_accessors :name, :ldap_name, :attribute_type
18
+ should have_instance_methods :define_reader, :define_writer
19
+
20
+ should "set the name correctly" do
21
+ assert_equal @definition.name, subject.name
22
+ end
23
+ should "set the ldap name correctly" do
24
+ assert_equal @definition.ldap_name, subject.ldap_name
25
+ end
26
+ should "set the attribute type correctly" do
27
+ assert_equal @attribute_type, subject.attribute_type
28
+ end
29
+
30
+ teardown do
31
+ AD::Framework.config.attribute_types.delete(@attribute_type.key.to_sym)
32
+ AD::Framework.config.attributes.delete(@definition.name.to_sym)
33
+ end
34
+ end
35
+
36
+ class DefineReaderTest < BaseTest
37
+ desc "define_reader method"
38
+ setup do
39
+ @structural_class = Factory.structural_class
40
+ @attribute.attribute_type.expects(:define_reader).with(@attribute, @structural_class)
41
+ end
42
+
43
+ should "call define_reader on it's attribute type" do
44
+ assert_nothing_raised{ subject.define_reader(@structural_class) }
45
+ end
46
+ end
47
+
48
+ class DefineWriterTest < BaseTest
49
+ desc "define_writer method"
50
+ setup do
51
+ @structural_class = Factory.structural_class
52
+ @attribute.attribute_type.expects(:define_writer).with(@attribute, @structural_class)
53
+ end
54
+
55
+ should "call define_writer on it's attribute type with a call to #define_writer" do
56
+ assert_nothing_raised{ subject.define_writer(@structural_class) }
57
+ end
58
+ end
59
+
60
+ class CreatedWithoutADefinitionTest < BaseTest
61
+ desc "created without a definition"
62
+
63
+ should "raise an exception" do
64
+ assert_raises(AD::Framework::AttributeNotDefined){ @class.new("not_defined") }
65
+ end
66
+ end
67
+
68
+ class CreatedWithABadAttributeTypeTest < BaseTest
69
+ desc "created with a bad attribute type test"
70
+ setup do
71
+ @definition = Factory.attribute_definition({ :type => "not_defined" })
72
+ AD::Framework.config.attributes[@definition.name] = @definition
73
+ end
74
+
75
+ should "raise an exception" do
76
+ assert_raises(AD::Framework::AttributeTypeNotDefined){ @class.new(@definition.name) }
77
+ end
78
+
79
+ teardown do
80
+ AD::Framework.config.attributes.delete(@definition.name.to_sym)
81
+ end
82
+ end
83
+
84
+ end
@@ -0,0 +1,146 @@
1
+ require 'assert'
2
+
3
+ class AD::Framework::AttributeType
4
+
5
+ class ClassMethodsTest < Assert::Context
6
+ desc "AD::Framework::AttributeType class"
7
+ setup do
8
+ @class = AD::Framework::AttributeType
9
+ @key = "some key"
10
+ @class.key(@key)
11
+ end
12
+ subject{ @class }
13
+
14
+ should "set the class's key" do
15
+ assert_equal @key, subject.key
16
+ end
17
+ end
18
+
19
+ class DefineMethodsTest < ClassMethodsTest
20
+ setup do
21
+ @attribute = Factory.mock_attribute({ :attribute_type => @class })
22
+ @fields = { @attribute.ldap_name => [ "some value" ] }
23
+ @structural_class = Factory.structural_class
24
+ @instance = @structural_class.new({ :fields => @fields })
25
+
26
+ @defined_attr_type_method = "#{@attribute.name}_attribute_type"
27
+ @defined_reader_method = @attribute.name
28
+ @defined_writer_method = "#{@attribute.name}="
29
+ end
30
+ subject{ @instance }
31
+ end
32
+
33
+ class DefineAttributeTypeTest < DefineMethodsTest
34
+ desc "define_attribute_type method"
35
+ setup do
36
+ @class.define_attribute_type(@attribute, @instance.class)
37
+ @attribute_type = subject.send(@defined_attr_type_method)
38
+ end
39
+
40
+ should "respond to the defined method" do
41
+ assert_respond_to @defined_attr_type_method, subject
42
+ end
43
+ should "return an instance of the attribute type with a call to the defined method" do
44
+ assert_instance_of @class, @attribute_type
45
+ assert_equal subject, @attribute_type.object
46
+ assert_equal @attribute.ldap_name, @attribute_type.attr_ldap_name
47
+ end
48
+ end
49
+
50
+ class DefineReaderTest < DefineMethodsTest
51
+ desc "define_reader method"
52
+ setup do
53
+ @class.define_reader(@attribute, @instance.class)
54
+ @reader = subject.send(@defined_reader_method)
55
+ @attribute_type = subject.send(@defined_attr_type_method)
56
+ end
57
+
58
+ should "respond to the defined method" do
59
+ assert_respond_to @defined_reader_method, subject
60
+ end
61
+ should "return the attribute type value with a call to the defined method" do
62
+ assert_equal @attribute_type.value, @reader
63
+ end
64
+ end
65
+
66
+ class DefineWriterTest < DefineMethodsTest
67
+ desc "define_writer method"
68
+ setup do
69
+ @class.define_writer(@attribute, @instance.class)
70
+ @new_value = "a new value"
71
+ subject.send(@defined_writer_method, @new_value)
72
+ @attribute_type = subject.send(@defined_attr_type_method)
73
+ end
74
+
75
+ should "respond to the defined method" do
76
+ assert_respond_to @defined_writer_method, subject
77
+ end
78
+ should "set the attribute type value with a call to the defined method" do
79
+ assert_equal @new_value, @attribute_type.value
80
+ end
81
+ end
82
+
83
+ class DefineMethodsAsProcTest < DefineMethodsTest
84
+ setup do
85
+ @class = Factory.attribute_type do
86
+ def self.attribute_type_method(a, n)
87
+ Proc.new{ define_method(n){ true } }
88
+ end
89
+ def self.reader_method(a)
90
+ Proc.new{ define_method(a.name){ true } }
91
+ end
92
+ def self.writer_method(a)
93
+ Proc.new{ define_method("#{a.name}="){|value| value } }
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ class AttributeTypeMethodAsProcTest < DefineMethodsAsProcTest
100
+ desc "with an attribute type method as a proc"
101
+ setup do
102
+ @class.define_attribute_type(@attribute, @instance.class)
103
+ @attribute_type = subject.send(@defined_attr_type_method)
104
+ end
105
+
106
+ should "respond to the defined method" do
107
+ assert_respond_to @defined_attr_type_method, subject
108
+ end
109
+ should "return true with a call to the defined method" do
110
+ assert_equal true, @attribute_type
111
+ end
112
+ end
113
+
114
+ class ReaderMethodAsProcTest < DefineMethodsAsProcTest
115
+ desc "with a reader method as a proc"
116
+ setup do
117
+ @class.define_reader(@attribute, @instance.class)
118
+ @reader = subject.send(@defined_reader_method)
119
+ end
120
+ subject{ @instance }
121
+
122
+ should "respond to the defined method" do
123
+ assert_respond_to @defined_reader_method, subject
124
+ end
125
+ should "return true with a call to the defined method" do
126
+ assert_equal true, @reader
127
+ end
128
+ end
129
+
130
+ class WriterMethodAsProcTest < DefineMethodsAsProcTest
131
+ desc "with a writer method as a proc"
132
+ setup do
133
+ @class.define_writer(@attribute, @instance.class)
134
+ @writer = subject.send(@defined_writer_method, true)
135
+ end
136
+ subject{ @instance }
137
+
138
+ should "respond to the defined method" do
139
+ assert_respond_to @defined_writer_method, subject
140
+ end
141
+ should "return true with a call to the defined method" do
142
+ assert_equal true, @writer
143
+ end
144
+ end
145
+
146
+ end