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