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,32 @@
1
+ module AD
2
+ module Framework
3
+ module Utilities
4
+
5
+ class Transaction
6
+ attr_accessor :callbacks, :entry, :block
7
+
8
+ def initialize(action, entry, &block)
9
+ self.entry = entry
10
+ self.callbacks = (self.entry.schema.callbacks[action.to_sym] || {})
11
+ self.block = block
12
+ end
13
+
14
+ def run
15
+ self.run_callbacks(self.callbacks[:before])
16
+ self.entry.instance_eval(&self.block)
17
+ self.run_callbacks(self.callbacks[:after])
18
+ end
19
+
20
+ protected
21
+
22
+ def run_callbacks(methods)
23
+ (methods || []).each do |method|
24
+ self.entry.send(method)
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ module AD
2
+ module Framework
3
+ module Utilities
4
+
5
+ class Validator
6
+ attr_accessor :entry
7
+
8
+ def initialize(entry)
9
+ self.entry = entry
10
+ end
11
+
12
+ def errors
13
+ self.entry.schema.mandatory.inject({}) do |errors, attribute_name|
14
+ attribute_type = self.entry.send("#{attribute_name}_attribute_type")
15
+ if !attribute_type.is_set?
16
+ errors[attribute_name.to_s] = "was not set"
17
+ end
18
+ errors
19
+ end
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ module Ad
2
+ module Framework
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,71 @@
1
+ if RUBY_VERSION =~ /^1.9/ && ENV["COVERAGE"]
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+ end
5
+
6
+ require 'assert'
7
+ require 'log4r'
8
+ require 'mocha'
9
+ require 'yaml'
10
+
11
+ if RUBY_VERSION =~ /^1.9/
12
+ YAML::ENGINE.yamler= 'syck'
13
+ end
14
+
15
+ root_path = File.expand_path("../..", __FILE__)
16
+ ldap_config = YAML.load(File.open(File.join(root_path, "test", "support", "ldap.yml")))
17
+
18
+ FileUtils.mkdir_p(File.join(root_path, "log"))
19
+ TEST_LOGGER = Log4r::Logger.new("AD::Framework")
20
+ TEST_LOGGER.add(Log4r::FileOutputter.new('fileOutputter', {
21
+ :filename => File.join(root_path, "log", "test.log"),
22
+ :trunc => false,
23
+ :formatter => Log4r::PatternFormatter.new(:pattern => "[%l] %d :: %m")
24
+ }))
25
+
26
+ # add the current gem root path to the LOAD_PATH
27
+ root_path = File.expand_path("../..", __FILE__)
28
+ if !$LOAD_PATH.include?(root_path)
29
+ $LOAD_PATH.unshift(root_path)
30
+ end
31
+ require 'ad-framework'
32
+
33
+ require 'test/support/schema/attributes'
34
+ require 'test/support/schema/attribute_types'
35
+ require 'test/support/schema/auxiliary_classes'
36
+ require 'test/support/schema/structural_classes'
37
+
38
+ require 'test/support/state'
39
+ require 'test/support/factory'
40
+ require 'test/support/seed'
41
+
42
+ class Assert::Context
43
+ include Mocha::API
44
+ end
45
+
46
+ AD::Framework.configure do |config|
47
+ config.ldap do |ldap|
48
+ ldap.host = ldap_config[:host]
49
+ ldap.port = ldap_config[:port]
50
+ ldap.encryption = ldap_config[:encryption]
51
+ ldap.auth = ldap_config[:auth]
52
+ end
53
+ config.treebase = ldap_config[:base]
54
+ config.logger = TEST_LOGGER
55
+ config.search_size_supported = false
56
+ config.run_commands = true
57
+ config.ldap_prefix = "adtest-"
58
+ end
59
+
60
+ Assert.suite.setup do
61
+ puts "\nSeeding the ldap database..."
62
+ time = Benchmark.measure{ Seed.up }
63
+ puts ("Done (%.6f seconds)" % [ time.real ])
64
+ end
65
+
66
+ Assert.suite.teardown do
67
+ puts "\nCleaning up the ldap database..."
68
+ time = Benchmark.measure{ Seed.down }
69
+ puts ("Done (%.6f seconds)\n\n" % [ time.real ])
70
+ end
71
+
@@ -0,0 +1,49 @@
1
+ require 'assert'
2
+
3
+ class AD::Array
4
+
5
+ class BaseTest < Assert::Context
6
+ desc "AD::Array"
7
+ setup do
8
+ @attribute_type_class = AD::Array
9
+ end
10
+ subject{ @attribute_type_class }
11
+
12
+ should "return 'array' with it's key" do
13
+ assert_equal 'array', subject.key
14
+ end
15
+ should "be registered with AD::Framework" do
16
+ registered = AD::Framework.defined_attribute_types[subject.key]
17
+ assert_equal registered, subject
18
+ end
19
+ end
20
+
21
+ class InstanceTest < BaseTest
22
+ desc "instance"
23
+ setup do
24
+ @attr_name = "proxy_addresses"
25
+ @proxy_addresses = [ "a@example.com", "b@example.com" ]
26
+ mock_fields = { @attr_name => @proxy_addresses }
27
+ mock_object = mock()
28
+ mock_object.stubs(:fields).returns(mock_fields)
29
+ mock_object.stubs(:dn).returns("CN=something")
30
+ @array = @attribute_type_class.new(mock_object, @attr_name)
31
+ end
32
+ subject{ @array }
33
+
34
+ should "return the name with a call to value" do
35
+ assert_equal @proxy_addresses, subject.value
36
+ assert_equal @proxy_addresses, subject.ldap_value
37
+ end
38
+ should "return an empty array when setting value to nil" do
39
+ subject.value = nil
40
+ assert_empty subject.value
41
+ assert_empty subject.ldap_value
42
+ end
43
+
44
+ teardown do
45
+ @array.value = @proxy_addresses
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,48 @@
1
+ require 'assert'
2
+
3
+ class AD::Integer
4
+
5
+ class BaseTest < Assert::Context
6
+ desc "AD::Integer"
7
+ setup do
8
+ @attribute_type_class = AD::Integer
9
+ end
10
+ subject{ @attribute_type_class }
11
+
12
+ should "return 'integer' with it's key" do
13
+ assert_equal 'integer', subject.key
14
+ end
15
+ should "be registered with AD::Framework" do
16
+ registered = AD::Framework.defined_attribute_types[subject.key]
17
+ assert_equal registered, subject
18
+ end
19
+ end
20
+
21
+ class InstanceTest < BaseTest
22
+ desc "instance"
23
+ setup do
24
+ @attr_name = "system_flags"
25
+ @system_flags = 123456789
26
+ mock_fields = { @attr_name => [ @system_flags ] }
27
+ mock_object = mock()
28
+ mock_object.stubs(:fields).returns(mock_fields)
29
+ @integer = @attribute_type_class.new(mock_object, @attr_name)
30
+ end
31
+ subject{ @integer }
32
+
33
+ should "return the name with a call to value" do
34
+ assert_equal @system_flags, subject.value
35
+ assert_equal @system_flags, subject.ldap_value
36
+ end
37
+ should "return nil when setting value to nil" do
38
+ subject.value = nil
39
+ assert_nil subject.value
40
+ assert_nil subject.ldap_value
41
+ end
42
+
43
+ teardown do
44
+ @integer.value = @system_flags
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,48 @@
1
+ require 'assert'
2
+
3
+ class AD::String
4
+
5
+ class BaseTest < Assert::Context
6
+ desc "AD::String"
7
+ setup do
8
+ @attribute_type_class = AD::String
9
+ end
10
+ subject{ @attribute_type_class }
11
+
12
+ should "return 'string' with it's key" do
13
+ assert_equal 'string', subject.key
14
+ end
15
+ should "be registered with AD::Framework" do
16
+ registered = AD::Framework.defined_attribute_types[subject.key]
17
+ assert_equal registered, subject
18
+ end
19
+ end
20
+
21
+ class InstanceTest < BaseTest
22
+ desc "instance"
23
+ setup do
24
+ @attr_name = "name"
25
+ @name = "someone"
26
+ mock_fields = { @attr_name => [ @name ] }
27
+ mock_object = mock()
28
+ mock_object.stubs(:fields).returns(mock_fields)
29
+ @string = @attribute_type_class.new(mock_object, @attr_name)
30
+ end
31
+ subject{ @string }
32
+
33
+ should "return the name with a call to value" do
34
+ assert_equal @name, subject.value
35
+ assert_equal @name, subject.ldap_value
36
+ end
37
+ should "return nil when setting value to nil" do
38
+ subject.value = nil
39
+ assert_nil subject.value
40
+ assert_nil subject.ldap_value
41
+ end
42
+
43
+ teardown do
44
+ @string.value = @name
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,101 @@
1
+ require 'assert'
2
+
3
+ class AD::Top
4
+
5
+ class BaseTest < Assert::Context
6
+ desc "top"
7
+ setup do
8
+ @structural_class = AD::Top
9
+ end
10
+ subject{ @structural_class }
11
+
12
+ should "be registered with AD::Framework's config" do
13
+ assert_equal AD::Framework.config.object_classes[subject.ldap_name], subject
14
+ end
15
+ end
16
+
17
+ class SchemaTest < BaseTest
18
+ desc "schema"
19
+ setup do
20
+ @ldap_name = "top"
21
+ @rdn = :name
22
+ @attrs = [ :name, :system_flags, :display_name, :description ]
23
+ @schema = @structural_class.schema
24
+ end
25
+ subject{ @schema }
26
+
27
+ should "store the ldap name defined on the class" do
28
+ expected = [ AD::Framework.config.ldap_prefix, @ldap_name ].compact.join
29
+ assert_equal expected, subject.ldap_name
30
+ end
31
+ should "store the rdn defined on the class" do
32
+ assert_equal @rdn, subject.rdn
33
+ end
34
+ should "contain all the attributes defined on the class" do
35
+ @attrs.each do |attr|
36
+ assert_includes attr, subject.attributes
37
+ end
38
+ end
39
+ end
40
+
41
+ class InstanceTest < BaseTest
42
+ desc "instance"
43
+ setup do
44
+ @name = "joe test"
45
+ @system_flags = 123456789
46
+ @display_name = "Joe Test"
47
+ @description = "A relevant description."
48
+ @dn = [ "CN=#{@name}", @structural_class.treebase ].join(", ")
49
+ @top = @structural_class.new({ :name => @name, :system_flags => @system_flags,
50
+ :display_name => @display_name, :description => @description
51
+ })
52
+ end
53
+ subject{ @top }
54
+
55
+ should have_readers :dn
56
+ should have_accessors :name, :system_flags, :display_name, :description
57
+
58
+ should "return it's rdn with its treebase in it's dn" do
59
+ assert_equal @dn, subject.dn
60
+ end
61
+ should "return the name set on it" do
62
+ assert_equal @name, subject.name
63
+ assert_equal [ @name ], subject.fields[:cn]
64
+ end
65
+ should "return the system_flags set on it" do
66
+ assert_equal @system_flags, subject.system_flags
67
+ assert_equal [ @system_flags.to_s ], subject.fields[:systemflags]
68
+ end
69
+ should "return the display_name set on it" do
70
+ assert_equal @display_name, subject.display_name
71
+ assert_equal [ @display_name ], subject.fields[:displayname]
72
+ end
73
+ should "return the description set on it" do
74
+ assert_equal @description, subject.description
75
+ assert_equal [ @description ], subject.fields[:description]
76
+ end
77
+ end
78
+
79
+ class SearchingTest < BaseTest
80
+ desc "searching for an entry"
81
+ setup do
82
+ @current = @structural_class.schema.treebase
83
+ @structural_class.schema.treebase = nil
84
+ @top = @structural_class.find("CN=joe test, #{AD::User.schema.treebase}")
85
+ end
86
+ subject{ @top }
87
+
88
+ should "find the user" do
89
+ assert subject
90
+ assert_kind_of AD::User, subject
91
+ end
92
+ should "set his name correctly" do
93
+ assert_equal "joe test", subject.name
94
+ end
95
+
96
+ teardown do
97
+ @structural_class.schema.treebase = @current
98
+ end
99
+ end
100
+
101
+ end
@@ -0,0 +1,140 @@
1
+ require 'assert'
2
+
3
+ class AD::User
4
+
5
+ class BaseTest < Assert::Context
6
+ desc "user"
7
+ setup do
8
+ @structural_class = AD::User
9
+ end
10
+ subject{ @structural_class }
11
+
12
+ should "be registered with AD::Framework's config" do
13
+ assert_equal AD::Framework.config.object_classes[subject.ldap_name], subject
14
+ end
15
+ end
16
+
17
+ class SchemaTest < BaseTest
18
+ desc "schema"
19
+ setup do
20
+ @ldap_name = "user"
21
+ @rdn = :name
22
+ @treebase = [ "CN=Users, CN=AD Framework Tests", AD::Framework.config.treebase ].join(", ")
23
+ @attrs = [ :name, :system_flags, :display_name, :description, :proxy_addresses,
24
+ :sam_account_name ]
25
+ @schema = @structural_class.schema
26
+ end
27
+ subject{ @schema }
28
+
29
+ should "store the ldap name defined on the class" do
30
+ expected = [ AD::Framework.config.ldap_prefix, @ldap_name ].compact.join
31
+ assert_equal expected, subject.ldap_name
32
+ end
33
+ should "store the rdn defined on the class" do
34
+ assert_equal @rdn, subject.rdn
35
+ end
36
+ should "store the treebase defined on the class" do
37
+ assert_equal @treebase, subject.treebase
38
+ end
39
+ should "contain all the attributes defined on the class" do
40
+ @attrs.each do |attr|
41
+ assert_includes attr, subject.attributes
42
+ end
43
+ end
44
+ end
45
+
46
+ class InstanceTest < BaseTest
47
+ desc "instance"
48
+ setup do
49
+ @proxy_addresses = [ "developer@example.com", "dev@example.com" ]
50
+ @sam_account_name = "dev"
51
+ @user = @structural_class.new({
52
+ :proxy_addresses => @proxy_addresses,
53
+ :sam_account_name => @sam_account_name
54
+ })
55
+ end
56
+ subject{ @user }
57
+
58
+ should have_readers :dn
59
+ should have_accessors :name, :system_flags, :display_name, :description
60
+ should have_accessors :proxy_addresses, :sam_account_name
61
+
62
+ should "return the proxy addresses set on it" do
63
+ assert_equal @proxy_addresses, subject.proxy_addresses
64
+ assert_equal @proxy_addresses, subject.fields[:proxyaddresses]
65
+ end
66
+ should "return the sam account name set on it" do
67
+ assert_equal @sam_account_name, subject.sam_account_name
68
+ assert_equal [ @sam_account_name ], subject.fields[:samaccountname]
69
+ end
70
+ end
71
+
72
+ class SearchingTest < BaseTest
73
+ desc "searching for an entry"
74
+ subject{ @structural_class }
75
+
76
+ should "find the user from his dn with a call to #find" do
77
+ name = "joe test"
78
+ @user = subject.find("CN=#{name}, #{subject.schema.treebase}")
79
+
80
+ assert @user
81
+ assert_equal name, @user.name
82
+ end
83
+ should "find the user from his rdn with a call to #find" do
84
+ name = "joe test"
85
+ @user = subject.find(name)
86
+
87
+ assert @user
88
+ assert_equal name, @user.name
89
+ end
90
+ should "find the first matching user with a call to #first" do
91
+ name = "joe test"
92
+ @user = subject.first({ :name => name })
93
+
94
+ assert @user
95
+ assert_equal name, @user.name
96
+ end
97
+ should "find the first matching user using a ldap attribute with a call to #first" do
98
+ user_name = "jtest"
99
+ @user = subject.first({ :sam_account_name => user_name })
100
+
101
+ assert @user
102
+ assert_equal user_name, @user.sam_account_name
103
+ end
104
+ should "return a collection of matching users with a call to #all" do
105
+ name = "*test*"
106
+ @users = subject.all({ :where => { :name => name }, :size => 5 })
107
+
108
+ assert_not_empty @users
109
+ @users.each do |user|
110
+ assert_match user.name, /test/
111
+ end
112
+ end
113
+ should "return a collection of matching users with complicated filters with a call to #all" do
114
+ system_flags = 500
115
+ objectclass = "adtest-securityPrincipal"
116
+ @users = subject.all({
117
+ :where => { :systemflags__ge => system_flags, :objectclass__eq => objectclass },
118
+ :limit => 5
119
+ })
120
+
121
+ assert_not_empty @users
122
+ @users.each do |user|
123
+ assert user.fields[:systemflags].first.to_i >= system_flags
124
+ end
125
+ end
126
+ should "reload the user's fields and attributes with a call to #reload" do
127
+ name = "joe test"
128
+ new_name = "yo test"
129
+ @user = subject.find(name)
130
+
131
+ assert @user
132
+ @user.name = new_name
133
+ assert_equal new_name, @user.name
134
+ @user.reload
135
+ assert_not_equal new_name, @user.name
136
+ assert_equal name, @user.name
137
+ end
138
+ end
139
+
140
+ end