activedirectory 0.9.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/active_directory.rb +34 -12
- data/lib/active_directory/base.rb +398 -362
- data/lib/active_directory/computer.rb +38 -0
- data/lib/active_directory/container.rb +117 -0
- data/lib/active_directory/group.rb +156 -103
- data/lib/active_directory/member.rb +56 -0
- data/lib/active_directory/password.rb +42 -0
- data/lib/active_directory/rails/synchronizer.rb +234 -0
- data/lib/active_directory/rails/user.rb +137 -0
- data/lib/active_directory/timestamp.rb +46 -0
- data/lib/active_directory/user.rb +149 -290
- metadata +31 -24
- data/LICENSE +0 -24
- data/README +0 -139
- data/Rakefile +0 -76
- data/install.rb +0 -27
- data/lib/active_directory/ext/class.rb +0 -50
- data/lib/active_directory/ext/hash.rb +0 -10
- data/lib/active_directory/version.rb +0 -37
@@ -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
|
-
#
|
3
|
+
# This file is part of the Ruby Active Directory Project
|
4
|
+
# on the web at http://rubyforge.org/projects/activedirectory
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
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
|
-
#
|
14
|
-
#
|
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
|
-
#
|
17
|
-
#
|
18
|
-
# FITNESS FOR A PARTICULAR PURPOSE
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|