socialcast_ldap_integration 1.1.5
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,157 @@
|
|
|
1
|
+
require "net/ldap"
|
|
2
|
+
|
|
3
|
+
module Socialcast
|
|
4
|
+
module LdapIntegration
|
|
5
|
+
|
|
6
|
+
NULL_FILTER = ::Net::LDAP::Filter.pres("objectclass")
|
|
7
|
+
|
|
8
|
+
def self.config
|
|
9
|
+
@@config
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.config=(config)
|
|
13
|
+
@@config = config
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.available?
|
|
17
|
+
return false unless self.config
|
|
18
|
+
return self.config['connections'].all? do |connection|
|
|
19
|
+
['searcher_username', 'searcher_password', 'filter_string', 'base', 'host', 'port', 'ssl', 'map'].all? { |field| !connection[field].to_s.blank? } && self.required_fields.all? { |field| !connection['map'][field].blank? }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.scheduled?
|
|
24
|
+
self.config['enableLdapSchedule']
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.mirror_lazily?
|
|
28
|
+
return true unless self.available?
|
|
29
|
+
!self.config['lazy_mirroring']
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.schedule
|
|
33
|
+
config = Socialcast::LdapIntegration.config
|
|
34
|
+
cron_line = nil
|
|
35
|
+
if config['enableLdapSchedule']
|
|
36
|
+
case config['schedule']['checkFreq']
|
|
37
|
+
when 'Hourly'
|
|
38
|
+
cron_line = "0 */#{config['schedule']['hourInterval'].to_i} * * *"
|
|
39
|
+
when 'Daily'
|
|
40
|
+
cron_line = "0 #{config['schedule']['timeHour']} * * *"
|
|
41
|
+
when 'Weekly'
|
|
42
|
+
cron_line = "0 #{config['schedule']['timeHour']} * * #{config['schedule']['timeDay'].to_i + 1}"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
return cron_line
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Connects to the Directory servers specified in the configuration.
|
|
50
|
+
#
|
|
51
|
+
# Supported Options:
|
|
52
|
+
# [:config] One or more LDAP connection specifications to connect to, overrides those in LdapIntegration.config
|
|
53
|
+
#
|
|
54
|
+
# Yields:
|
|
55
|
+
# - Connected and authenticated Net::LDAP object
|
|
56
|
+
# - Connection settings for the connection
|
|
57
|
+
def self.connect(options={})
|
|
58
|
+
raise ArgumentError.new("connect requires a block, see connect_to") unless block_given?
|
|
59
|
+
config = options[:config] ? [options[:config]] : Socialcast::LdapIntegration.config['connections']
|
|
60
|
+
config.each do |connection_options|
|
|
61
|
+
ldap = connect_to(connection_options)
|
|
62
|
+
yield(ldap, connection_options)
|
|
63
|
+
end
|
|
64
|
+
nil
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.connect_to(connection_options)
|
|
68
|
+
searcher_username = connection_options['searcher_username']
|
|
69
|
+
searcher_password = connection_options['searcher_password']
|
|
70
|
+
base = connection_options['base']
|
|
71
|
+
host = connection_options['host']
|
|
72
|
+
port = connection_options['port']
|
|
73
|
+
ssl = connection_options['ssl']
|
|
74
|
+
|
|
75
|
+
ldap = Net::LDAP.new :host => host, :port => port, :base => base
|
|
76
|
+
ldap.auth searcher_username, searcher_password
|
|
77
|
+
|
|
78
|
+
return ldap
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Supported options
|
|
82
|
+
# [:filter] A string representing the search filter to use instead of the default search filter. Overrides any :auxiliary_filter option.
|
|
83
|
+
# [:auxiliary_filter] A string representing a search filter to use in addition to the defualt search filter. The two filters will be combined
|
|
84
|
+
# using a logical AND.
|
|
85
|
+
# [:limit] A number representing the maxmimum number of records to return, defaults to unlimited.
|
|
86
|
+
def self.search(options={})
|
|
87
|
+
options.reverse_merge! :connect_options => {}
|
|
88
|
+
Socialcast::LdapIntegration.connect(options.delete(:connect_options) || {}) do |ldap, connection|
|
|
89
|
+
ldap_search_options = self.construct_filter_for_search(connection, options.delete(:filter), options.delete(:auxiliary_filter))
|
|
90
|
+
ldap_search_options[:size] = options[:limit] if options.has_key?(:limit)
|
|
91
|
+
ldap.search(ldap_search_options) do |entry|
|
|
92
|
+
yield(entry, connection) if block_given?
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Supported options:
|
|
98
|
+
# [:identifying_field] the field which is being used to look up the user. Should probably be 'company_login' or 'email'.
|
|
99
|
+
# Defaults to 'company_login'
|
|
100
|
+
def self.authenticated?(identifier, password, options = {})
|
|
101
|
+
return false if password.blank?
|
|
102
|
+
identifying_field = options.reverse_merge!({:identifying_field => 'company_login'}).delete(:identifying_field)
|
|
103
|
+
|
|
104
|
+
Socialcast::LdapIntegration.connect do |ldap, connection|
|
|
105
|
+
connection_options = {}
|
|
106
|
+
connection_options.reverse_merge! options
|
|
107
|
+
base = connection['base']
|
|
108
|
+
host = connection['host']
|
|
109
|
+
port = connection['port']
|
|
110
|
+
map = connection['map']
|
|
111
|
+
connection_options.reverse_merge! :host => host, :port => port, :base => base, :filter => "#{map[identifying_field]}=#{identifier}", :password => password
|
|
112
|
+
return true if !ldap.bind_as(connection_options).blank?
|
|
113
|
+
end
|
|
114
|
+
return false
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Returns true if LDAP will manage the user field with the given name
|
|
118
|
+
def self.mirroring_field?(field)
|
|
119
|
+
string_field = field.to_s
|
|
120
|
+
self.available? && (["password", "email"].include?(string_field))
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def self.fetch_account_info(identifier, options = {})
|
|
125
|
+
identifying_field = options.delete(:identifying_field) || 'company_login'
|
|
126
|
+
matched_account = nil
|
|
127
|
+
|
|
128
|
+
self.connect do |ldap, connection|
|
|
129
|
+
map = connection['map']
|
|
130
|
+
ldap.search(self.construct_filter_for_search(connection, nil, "#{map[identifying_field]}=#{identifier}")) do |entry, connection|
|
|
131
|
+
matched_account = entry
|
|
132
|
+
end
|
|
133
|
+
if matched_account
|
|
134
|
+
mapped_account_info = HashWithIndifferentAccess.new
|
|
135
|
+
map.each_pair do |sc_field, ldap_field|
|
|
136
|
+
mapped_account_info[sc_field] = matched_account[ldap_field].first unless ldap_field.blank?
|
|
137
|
+
end
|
|
138
|
+
return mapped_account_info
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
nil
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
protected
|
|
145
|
+
def self.construct_filter_for_search(connection, filter_options=nil, auxiliary_filter=nil)
|
|
146
|
+
unless filter_options
|
|
147
|
+
search_filter = connection['filter_string'].blank? ? NULL_FILTER : Net::LDAP::Filter.construct(connection['filter_string'])
|
|
148
|
+
search_filter = search_filter & Net::LDAP::Filter.construct(auxiliary_filter) if auxiliary_filter
|
|
149
|
+
return {:filter => search_filter}
|
|
150
|
+
end
|
|
151
|
+
{:filter => filter_options}
|
|
152
|
+
end
|
|
153
|
+
def self.required_fields
|
|
154
|
+
['email', 'company_login']
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: socialcast_ldap_integration
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: 25
|
|
5
|
+
prerelease:
|
|
6
|
+
segments:
|
|
7
|
+
- 1
|
|
8
|
+
- 1
|
|
9
|
+
- 5
|
|
10
|
+
version: 1.1.5
|
|
11
|
+
platform: ruby
|
|
12
|
+
authors:
|
|
13
|
+
- Mitch Williams
|
|
14
|
+
- Sean Cashin
|
|
15
|
+
- Socialcast Inc.
|
|
16
|
+
autorequire:
|
|
17
|
+
bindir: bin
|
|
18
|
+
cert_chain: []
|
|
19
|
+
|
|
20
|
+
date: 2011-02-15 00:00:00 -08:00
|
|
21
|
+
default_executable:
|
|
22
|
+
dependencies:
|
|
23
|
+
- !ruby/object:Gem::Dependency
|
|
24
|
+
name: scashin133-net-ldap
|
|
25
|
+
prerelease: false
|
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
27
|
+
none: false
|
|
28
|
+
requirements:
|
|
29
|
+
- - "="
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
hash: 19
|
|
32
|
+
segments:
|
|
33
|
+
- 0
|
|
34
|
+
- 1
|
|
35
|
+
- 4
|
|
36
|
+
version: 0.1.4
|
|
37
|
+
type: :runtime
|
|
38
|
+
version_requirements: *id001
|
|
39
|
+
description: "BLAH. "
|
|
40
|
+
email:
|
|
41
|
+
- mitch@socialcast.com
|
|
42
|
+
- sean@socialcast.com
|
|
43
|
+
- support@socialcast.com
|
|
44
|
+
executables: []
|
|
45
|
+
|
|
46
|
+
extensions: []
|
|
47
|
+
|
|
48
|
+
extra_rdoc_files: []
|
|
49
|
+
|
|
50
|
+
files:
|
|
51
|
+
- lib/socialcast/ldap_integration/version.rb
|
|
52
|
+
- lib/socialcast/ldap_integration.rb
|
|
53
|
+
has_rdoc: true
|
|
54
|
+
homepage: http://github.com/socialcast/socialcast_ldap_integration
|
|
55
|
+
licenses: []
|
|
56
|
+
|
|
57
|
+
post_install_message:
|
|
58
|
+
rdoc_options: []
|
|
59
|
+
|
|
60
|
+
require_paths:
|
|
61
|
+
- lib
|
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
63
|
+
none: false
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
hash: 3
|
|
68
|
+
segments:
|
|
69
|
+
- 0
|
|
70
|
+
version: "0"
|
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
|
+
none: false
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
hash: 3
|
|
77
|
+
segments:
|
|
78
|
+
- 0
|
|
79
|
+
version: "0"
|
|
80
|
+
requirements: []
|
|
81
|
+
|
|
82
|
+
rubyforge_project: socialcast_ldap_integration
|
|
83
|
+
rubygems_version: 1.4.2
|
|
84
|
+
signing_key:
|
|
85
|
+
specification_version: 3
|
|
86
|
+
summary: Provides support for connecting to and traversing LDAP trees.
|
|
87
|
+
test_files: []
|
|
88
|
+
|