activedirectory 0.9.3 → 1.0.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.
@@ -0,0 +1,38 @@
1
+ #-- license
2
+ #
3
+ # This file is part of the Ruby Active Directory Project
4
+ # on the web at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # Copyright (c) 2008, James Hunt <filefrog@gmail.com>
7
+ # based on original code by Justin Mecham
8
+ #
9
+ # This program is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # This program is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
21
+ #
22
+ #++ license
23
+
24
+ module ActiveDirectory
25
+ class Computer < Base
26
+ def self.filter # :nodoc:
27
+ Net::LDAP::Filter.eq(:objectClass,'computer')
28
+ end
29
+
30
+ def self.required_attributes # :nodoc:
31
+ { :objectClass => [ 'top', 'person', 'organizationalPerson', 'user', 'computer' ] }
32
+ end
33
+
34
+ def hostname
35
+ dNSHostName || name
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,117 @@
1
+ #-- license
2
+ #
3
+ # This file is part of the Ruby Active Directory Project
4
+ # on the web at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # Copyright (c) 2008, James Hunt <filefrog@gmail.com>
7
+ # based on original code by Justin Mecham
8
+ #
9
+ # This program is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # This program is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
21
+ #
22
+ #++ license
23
+
24
+ module ActiveDirectory
25
+ #
26
+ # The ActiveDirectory::Container class represents a more malleable way
27
+ # of dealing with LDAP Distinguished Names (dn), like
28
+ # "cn=UserName,ou=Users,dc=example,dc=org".
29
+ #
30
+ # The following two representations of the above dn are identical:
31
+ #
32
+ # dn = "cn=UserName,ou=Users,dc=example,dc=org"
33
+ # dn = ActiveDirectory::Container.dc('org').dc('example').ou('Users').cn('UserName').to_s
34
+ #
35
+ class Container
36
+ attr_reader :type
37
+ attr_reader :name
38
+ attr_reader :parent
39
+
40
+ def initialize(type, name, node = nil) #:nodoc:
41
+ @type = type
42
+ @name = name
43
+ @node = node
44
+ end
45
+
46
+ #
47
+ # Creates a starting OU (Organizational Unit) dn part.
48
+ #
49
+ # # ou_part = "ou=OrganizationalUnit"
50
+ # ou_part = ActiveDirectory::Container.ou('OrganizationalUnit').to_s
51
+ #
52
+ def self.ou(name)
53
+ new(:ou, name, nil)
54
+ end
55
+
56
+ #
57
+ # Creates a starting DC (Domain Component) dn part.
58
+ #
59
+ # # dc_part = "dc=net"
60
+ # dc_part = ActiveDirectory::Container.dc('net').to_s
61
+ #
62
+ def self.dc(name)
63
+ new(:dc, name, nil)
64
+ end
65
+
66
+ #
67
+ # Creates a starting CN (Canonical Name) dn part.
68
+ #
69
+ # # cn_part = "cn=CanonicalName"
70
+ # cn_part = ActiveDirectory::Container.cn('CanonicalName').to_s
71
+ #
72
+ def self.cn(name)
73
+ new(:cn, name, nil)
74
+ end
75
+
76
+ #
77
+ # Appends an OU (Organizational Unit) dn part to another Container.
78
+ #
79
+ # # ou = "ou=InfoTech,dc=net"
80
+ # ou = ActiveDirectory::Container.dc("net").ou("InfoTech").to_s
81
+ #
82
+ def ou(name)
83
+ self.class.new(:ou, name, self)
84
+ end
85
+
86
+ #
87
+ # Appends a DC (Domain Component) dn part to another Container.
88
+ #
89
+ # # base = "dc=example,dc=net"
90
+ # base = ActiveDirectory::Container.dc("net").dc("example").to_s
91
+ #
92
+ def dc(name)
93
+ self.class.new(:dc, name, self)
94
+ end
95
+
96
+ #
97
+ # Appends a CN (Canonical Name) dn part to another Container.
98
+ #
99
+ # # user = "cn=UID,ou=Users"
100
+ # user = ActiveDirectory::Container.ou("Users").cn("UID")
101
+ #
102
+ def cn(name)
103
+ self.class.new(:cn, name, self)
104
+ end
105
+
106
+ #
107
+ # Converts the Container object to its String representation.
108
+ #
109
+ def to_s
110
+ @node ? "#{@type}=#{name},#{@node.to_s}" : "#{@type}=#{name}"
111
+ end
112
+
113
+ def ==(other) #:nodoc:
114
+ to_s.downcase == other.to_s.downcase
115
+ end
116
+ end
117
+ end
@@ -1,109 +1,162 @@
1
- #--
2
- # Active Directory Module for Ruby
1
+ #-- license
3
2
  #
4
- # Copyright (c) 2005-2006 Justin Mecham
3
+ # This file is part of the Ruby Active Directory Project
4
+ # on the web at http://rubyforge.org/projects/activedirectory
5
5
  #
6
- # Permission is hereby granted, free of charge, to any person obtaining a copy
7
- # of this software and associated documentation files (the "Software"), to
8
- # deal in the Software without restriction, including without limitation the
9
- # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
- # sell copies of the Software, and to permit persons to whom the Software is
11
- # furnished to do so, subject to the following conditions:
6
+ # Copyright (c) 2008, James Hunt <filefrog@gmail.com>
7
+ # based on original code by Justin Mecham
12
8
  #
13
- # The above copyright notice and this permission notice shall be included in
14
- # all copies or substantial portions of the Software.
9
+ # This program is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
15
13
  #
16
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
- # IN THE SOFTWARE.
23
- #++
14
+ # This program is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
21
+ #
22
+ #++ license
24
23
 
25
24
  module ActiveDirectory
26
-
27
- #
28
- # Represents a Group object within an Active Directory instance.
29
- #
30
- class Group < Base
31
-
32
- # Distinguished Name (DN)
33
- attr_accessor :dn
34
-
35
- # Description
36
- attr_accessor :description
37
-
38
- # Common Name (CN)
39
- attr_accessor :name
40
-
41
- # Users who are members of this Group
42
- attr :members
43
-
44
- #
45
- # Attributes that we wish to pull from Active Directory for any Group that
46
- # can be located within the directory.
47
- #
48
- ATTRIBUTES = ["distinguishedName", # DN of Group
49
- "name", # Group Name
50
- "member", # DN References to Members
51
- "description"] #:nodoc: # Description
52
-
53
- #
54
- # Attempts to load a Group by a Distinguished Name (DN).
55
- #
56
- def initialize(identifier)
57
-
58
- identifier = identifier.delete("\\")
59
-
60
- load_by_dn(identifier)
61
-
62
- end
63
-
64
- #
65
- # Proxy for loading and returning the members of this group.
66
- #
67
- def members #:nodoc:
68
- members = Array.new
69
- unless @members.nil?
70
- for user_dn in @members
71
- members << User.new(user_dn)
72
- end
73
- end
74
- members
75
- end
76
-
77
- private
78
-
79
- #
80
- # Attempt to load a Group by its Distinguished Name (DN).
81
- #
82
- def load_by_dn(dn)
83
-
84
- if dn.nil? or dn.length == 0
85
- raise ArgumentError, "No distinguished name provided."
86
- end
87
-
88
- # De-escape the DN
89
- dn = dn.gsub(/"/, "\\\"")
90
-
91
- entries = Base.search(dn, LDAP::LDAP_SCOPE_BASE,
92
- "(&(objectClass=group))", ATTRIBUTES)
93
-
94
- raise UnknownGroupError if (entries.nil? or entries.length != 1)
95
-
96
- parse_ldap_entry(entries[0])
97
-
98
- end
99
-
100
- def parse_ldap_entry(entry)
101
- @dn = entry['distinguishedName'][0].delete("\\")
102
- @name = entry['name'][0].delete("\\")
103
- @description = entry['description'][0] unless entry['description'].nil?
104
- @members = entry['member']
105
- end
106
-
107
- end
108
-
109
- end
25
+ class Group < Base
26
+ include Member
27
+
28
+ def self.filter # :nodoc:
29
+ Net::LDAP::Filter.eq(:objectClass,'group')
30
+ end
31
+
32
+ def self.required_attributes # :nodoc:
33
+ { :objectClass => [ 'top', 'group' ] }
34
+ end
35
+
36
+ def reload # :nodoc:
37
+ @member_users_non_r = nil
38
+ @member_users_r = nil
39
+ @member_groups_non_r = nil
40
+ @member_groups_r = nil
41
+ @groups = nil
42
+ super
43
+ end
44
+
45
+ #
46
+ # Returns true if the passed User or Group object belongs to
47
+ # this group. For performance reasons, the check is handled
48
+ # by the User or Group object passed.
49
+ #
50
+ def has_member?(user)
51
+ user.member_of?(self)
52
+ end
53
+
54
+ #
55
+ # Add the passed User or Group object to this Group. Returns true if
56
+ # the User or Group is already a member of the group, or if the operation
57
+ # to add them succeeds.
58
+ #
59
+ def add(new_member)
60
+ return false unless new_member.is_a?(User) || new_member.is_a?(Group)
61
+ if @@ldap.modify(:dn => distinguishedName, :operations => [
62
+ [ :add, :member, new_member.distinguishedName ]
63
+ ])
64
+ return true
65
+ else
66
+ return has_member?(new_member)
67
+ end
68
+ end
69
+
70
+ #
71
+ # Remove a User or Group from this Group. Returns true if the User or
72
+ # Group does not belong to this Group, or if the oepration to remove them
73
+ # succeeds.
74
+ #
75
+ def remove(member)
76
+ return false unless member.is_a?(User) || member.is_a?(Group)
77
+ if @@ldap.modify(:dn => distinguishedName, :operations => [
78
+ [ :delete, :member, member.distinguishedName ]
79
+ ])
80
+ return true
81
+ else
82
+ return !has_member?(member)
83
+ end
84
+ end
85
+
86
+ def has_members?
87
+ begin
88
+ return (@entry.member.nil? || @entry.member.empty?) ? false : true
89
+ rescue NoMethodError
90
+ return false
91
+ end
92
+ end
93
+
94
+ #
95
+ # Returns an array of all User objects that belong to this group.
96
+ #
97
+ # If the recursive argument is passed as false, then only Users who
98
+ # belong explicitly to this Group are returned.
99
+ #
100
+ # If the recursive argument is passed as true, then all Users who
101
+ # belong to this Group, or any of its subgroups, are returned.
102
+ #
103
+ def member_users(recursive = false)
104
+ return [] unless has_members?
105
+ if recursive
106
+ if @member_users_r.nil?
107
+ @member_users_r = []
108
+ @entry.member.each do |member_dn|
109
+ subuser = User.find_by_distinguishedName(member_dn)
110
+ if subuser
111
+ @member_users_r << subuser
112
+ else
113
+ subgroup = Group.find_by_distinguishedName(member_dn)
114
+ if subgroup
115
+ @member_users_r = @member_users_r.concat(subgroup.member_users(true))
116
+ end
117
+ end
118
+ end
119
+ end
120
+ return @member_users_r
121
+ else
122
+ @member_users_non_r ||= @entry.member.collect { |dn| User.find_by_distinguishedName(dn) }.delete_if { |u| u.nil? }
123
+ end
124
+ end
125
+
126
+ #
127
+ # Returns an array of all Group objects that belong to this group.
128
+ #
129
+ # If the recursive argument is passed as false, then only Groups that
130
+ # belong explicitly to this Group are returned.
131
+ #
132
+ # If the recursive argument is passed as true, then all Groups that
133
+ # belong to this Group, or any of its subgroups, are returned.
134
+ #
135
+ def member_groups(recursive = false)
136
+ return [] unless has_members?
137
+ if recursive
138
+ if @member_groups_r.nil?
139
+ @member_groups_r = []
140
+ @entry.member.each do |member_dn|
141
+ subgroup = Group.find_by_distinguishedName(member_dn)
142
+ if subgroup
143
+ @member_groups_r << subgroup
144
+ @member_groups_r = @member_groups_r.concat(subgroup.member_groups(true))
145
+ end
146
+ end
147
+ end
148
+ return @member_groups_r
149
+ else
150
+ @member_groups_non_r ||= @entry.member.collect { |dn| Group.find_by_distinguishedName(dn) }.delete_if { |g| g.nil? }
151
+ end
152
+ end
153
+
154
+ #
155
+ # Returns an array of Group objects that this Group belongs to.
156
+ #
157
+ def groups
158
+ return [] if memberOf.nil?
159
+ @groups ||= memberOf.collect { |group_dn| Group.find_by_distinguishedName(group_dn) }
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,56 @@
1
+ #-- license
2
+ #
3
+ # This file is part of the Ruby Active Directory Project
4
+ # on the web at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # Copyright (c) 2008, James Hunt <filefrog@gmail.com>
7
+ # based on original code by Justin Mecham
8
+ #
9
+ # This program is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # This program is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
21
+ #
22
+ #++ license
23
+
24
+ module ActiveDirectory
25
+ module Member
26
+ #
27
+ # Returns true if this member (User or Group) is a member of
28
+ # the passed Group object.
29
+ #
30
+ def member_of?(usergroup)
31
+ group_dns = memberOf
32
+ return false if group_dns.nil? || group_dns.empty?
33
+ #group_dns = [group_dns] unless group_dns.is_a?(Array)
34
+ group_dns.include?(usergroup.dn)
35
+ end
36
+
37
+ #
38
+ # Add the member to the passed Group object. Returns true if this object
39
+ # is already a member of the Group, or if the operation to add it succeeded.
40
+ #
41
+ def join(group)
42
+ return false unless group.is_a?(Group)
43
+ group.add(self)
44
+ end
45
+
46
+ #
47
+ # Remove the member from the passed Group object. Returns true if this
48
+ # object is not a member of the Group, or if the operation to remove it
49
+ # succeeded.
50
+ #
51
+ def unjoin(group)
52
+ return false unless group.is_a?(Group)
53
+ group.remove(self)
54
+ end
55
+ end
56
+ end