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