ad-framework 0.1.0

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.
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