simple_crowd 1.0.5 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +7 -0
- data/Rakefile +1 -1
- data/lib/simple_crowd/cache/null_store.rb +86 -0
- data/lib/simple_crowd/client.rb +334 -298
- data/lib/simple_crowd/crowd_entity.rb +199 -199
- data/lib/simple_crowd/crowd_error.rb +24 -15
- data/lib/simple_crowd/group.rb +11 -11
- data/lib/simple_crowd/mappers/soap_attributes.rb +13 -13
- data/lib/simple_crowd/mock_client.rb +3 -2
- data/lib/simple_crowd/user.rb +17 -17
- data/lib/simple_crowd/version.rb +1 -1
- data/lib/simple_crowd.rb +53 -51
- data/simple_crowd.gemspec +19 -50
- data/test/crowd_config.yml.example +6 -6
- data/test/factories.rb +11 -9
- data/test/helper.rb +32 -28
- data/test/test_client.rb +329 -331
- data/test/test_simple_crowd.rb +22 -22
- data/test/test_user.rb +69 -69
- metadata +75 -158
data/.document
ADDED
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -0,0 +1,86 @@
|
|
1
|
+
module SimpleCrowd
|
2
|
+
module Cache
|
3
|
+
|
4
|
+
# A cache store implementation which doesn't actually store anything.
|
5
|
+
#
|
6
|
+
# Implements ActiveSupport::Cache::Store interface without depending on
|
7
|
+
# the active_support gem.
|
8
|
+
class NullStore
|
9
|
+
attr_reader :silence, :options
|
10
|
+
alias :silence? :silence
|
11
|
+
|
12
|
+
def initialize(options = nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
def mute
|
16
|
+
yield
|
17
|
+
end
|
18
|
+
|
19
|
+
def silence!
|
20
|
+
end
|
21
|
+
|
22
|
+
def synchronize
|
23
|
+
yield
|
24
|
+
end
|
25
|
+
|
26
|
+
def fetch(name, options = nil)
|
27
|
+
if block_given?
|
28
|
+
yield
|
29
|
+
else
|
30
|
+
read(name, options)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def read(name, options = nil)
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def write(name, vaue, options = nil)
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete(name, options = nil)
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
def exist?(name, options = nil)
|
47
|
+
false
|
48
|
+
end
|
49
|
+
|
50
|
+
def clear(options = nil)
|
51
|
+
end
|
52
|
+
|
53
|
+
def cleanup(options = nil)
|
54
|
+
end
|
55
|
+
|
56
|
+
def increment(name, amount = 1, options = nil)
|
57
|
+
end
|
58
|
+
|
59
|
+
def decrement(name, amount = 1, options = nil)
|
60
|
+
end
|
61
|
+
|
62
|
+
def delete_matched(matcher, options = nil)
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.logger
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.logger=(logger)
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
def read_entry(key, options) # :nodoc:
|
75
|
+
end
|
76
|
+
|
77
|
+
def write_entry(key, entry, options) # :nodoc:
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
81
|
+
def delete_entry(key, options) # :nodoc:
|
82
|
+
false
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/simple_crowd/client.rb
CHANGED
@@ -1,298 +1,334 @@
|
|
1
|
-
module SimpleCrowd
|
2
|
-
class Client
|
3
|
-
|
4
|
-
attr_reader :options
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
groups
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
response.to_hash[:authenticate_application_response][:out][:token]
|
39
|
-
end
|
40
|
-
|
41
|
-
# Authenticate user by name/pass and retrieve login token
|
42
|
-
# @return [String] user token
|
43
|
-
def authenticate_user name, password, factors = nil
|
44
|
-
if factors
|
45
|
-
factors = prepare_validation_factors(factors)
|
46
|
-
simple_soap_call :authenticate_principal, {'auth:application' => @options[:app_name], 'auth:name' => name,
|
47
|
-
'auth:credential' => {'auth:credential' => password},
|
48
|
-
'auth:validationFactors' => factors}
|
49
|
-
else
|
50
|
-
simple_soap_call :authenticate_principal_simple, name, password
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def create_user_token name
|
55
|
-
simple_soap_call :create_principal_token, name, nil
|
56
|
-
end
|
57
|
-
|
58
|
-
# Invalidate an existing user token (log out)
|
59
|
-
# NOTE: call will return true even if token is invalid
|
60
|
-
# @return [Boolean] success (does not guarantee valid token)
|
61
|
-
def invalidate_user_token token
|
62
|
-
simple_soap_call :invalidate_principal_token, token do |res|
|
63
|
-
!res.soap_fault? && res.to_hash.key?(:invalidate_principal_token_response)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def is_valid_user_token? token, factors = nil
|
68
|
-
factors = prepare_validation_factors(factors)
|
69
|
-
simple_soap_call :is_valid_principal_token, token, factors
|
70
|
-
end
|
71
|
-
|
72
|
-
def is_cache_enabled?
|
73
|
-
simple_soap_call :is_cache_enabled
|
74
|
-
end
|
75
|
-
|
76
|
-
def is_group_member? group, user
|
77
|
-
simple_soap_call :is_group_member, group, user
|
78
|
-
end
|
79
|
-
|
80
|
-
def find_group_by_name name
|
81
|
-
SimpleCrowd::Group.parse_from :soap, simple_soap_call(:find_group_by_name, name)
|
82
|
-
end
|
83
|
-
|
84
|
-
def find_all_group_names
|
85
|
-
(simple_soap_call :find_all_group_names)[:string]
|
86
|
-
end
|
87
|
-
|
88
|
-
def update_group group, description, active
|
89
|
-
simple_soap_call :update_group, group, description, active do |res|
|
90
|
-
!res.soap_fault? && res.to_hash.key?(:update_group_response)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def add_user_to_group user, group
|
95
|
-
simple_soap_call :add_principal_to_group, user, group do |res|
|
96
|
-
!res.soap_fault? && res.to_hash.key?(:add_principal_to_group_response)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def remove_user_from_group user, group
|
101
|
-
simple_soap_call :remove_principal_from_group, user, group do |res|
|
102
|
-
!res.soap_fault? && res.to_hash.key?(:remove_principal_from_group_response)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def reset_user_password name
|
107
|
-
simple_soap_call :reset_principal_credential, name do |res|
|
108
|
-
!res.soap_fault? && res.to_hash.key?(:reset_principal_credential_response)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def find_all_user_names
|
113
|
-
(simple_soap_call :find_all_principal_names)[:string]
|
114
|
-
end
|
115
|
-
|
116
|
-
def find_user_by_name name
|
117
|
-
SimpleCrowd::User.parse_from :soap, simple_soap_call(:find_principal_by_name, name) rescue nil
|
118
|
-
end
|
119
|
-
|
120
|
-
def find_user_with_attributes_by_name name
|
121
|
-
SimpleCrowd::User.parse_from :soap, simple_soap_call(:find_principal_with_attributes_by_name, name) rescue nil
|
122
|
-
end
|
123
|
-
|
124
|
-
def find_user_by_token token
|
125
|
-
SimpleCrowd::User.parse_from :soap, simple_soap_call(:find_principal_by_token, token) rescue nil
|
126
|
-
end
|
127
|
-
|
128
|
-
def find_username_by_token token
|
129
|
-
user = find_user_by_token token
|
130
|
-
user && user[:username]
|
131
|
-
end
|
132
|
-
|
133
|
-
# Exact email match
|
134
|
-
def find_user_by_email email
|
135
|
-
search_users_by_email(email).find{|u| u.email
|
136
|
-
end
|
137
|
-
|
138
|
-
# Partial email match
|
139
|
-
def search_users_by_email email
|
140
|
-
search_users({'principal.email' => email})
|
141
|
-
end
|
142
|
-
|
143
|
-
def search_users restrictions
|
144
|
-
soap_restrictions = prepare_search_restrictions restrictions
|
145
|
-
users = simple_soap_call :search_principals, soap_restrictions rescue []
|
146
|
-
return [] if users.nil? || users[:soap_principal].nil?
|
147
|
-
users = users[:soap_principal].is_a?(Array) ? users[:soap_principal] : [users[:soap_principal]]
|
148
|
-
users.map{|u| SimpleCrowd::User.parse_from :soap, u}
|
149
|
-
end
|
150
|
-
|
151
|
-
def add_user user, credential
|
152
|
-
return if user.nil? || credential.nil?
|
153
|
-
[:email, :first_name, :last_name].each do |k|
|
154
|
-
user.send(:"#{k}=", "") if user.send(k).nil?
|
155
|
-
end
|
156
|
-
soap_user = user.map_to :soap
|
157
|
-
# We don't use these attributes when creating
|
158
|
-
soap_user.delete(:id)
|
159
|
-
soap_user.delete(:directory_id)
|
160
|
-
# Add blank attributes if missing
|
161
|
-
|
162
|
-
# Declare require namespaces
|
163
|
-
soap_user = soap_user.inject({}) {|hash, (k, v)| hash["int:#{k}"] = v;hash}
|
164
|
-
SimpleCrowd::User.parse_from :soap, simple_soap_call(:add_principal, soap_user, {'auth:credential' => credential, 'auth:encryptedCredential' => false})
|
165
|
-
end
|
166
|
-
|
167
|
-
def remove_user name
|
168
|
-
simple_soap_call :remove_principal, name do |res|
|
169
|
-
!res.soap_fault? && res.to_hash.key?(:remove_principal_response)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def update_user_credential user, credential, encrypted = false
|
174
|
-
simple_soap_call :update_principal_credential, user,
|
175
|
-
{'auth:credential' => credential, 'auth:encryptedCredential' => encrypted} do |res|
|
176
|
-
!res.soap_fault? && res.to_hash.key?(:update_principal_credential_response)
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
# Only supports single value attributes
|
181
|
-
# TODO: Allow value arrays
|
182
|
-
# @param user [String] name of user to update
|
183
|
-
# @param name [String] of attribute to update
|
184
|
-
# @param value [String] of attribute to update
|
185
|
-
def update_user_attribute user, name, value
|
186
|
-
return unless (name.is_a?(String) || name.is_a?(Symbol)) && (value.is_a?(String) || value.is_a?(Array))
|
187
|
-
soap_attr = SimpleCrowd::Mappers::SoapAttributes.produce({name => value})
|
188
|
-
simple_soap_call :update_principal_attribute, user, soap_attr['int:SOAPAttribute'][0] do |res|
|
189
|
-
!res.soap_fault? && res.to_hash.key?(:update_principal_attribute_response)
|
190
|
-
end
|
191
|
-
end
|
192
|
-
alias_method :add_user_attribute, :update_user_attribute
|
193
|
-
|
194
|
-
# @param user [SimpleCrowd::User] dirty user to update
|
195
|
-
def update_user user
|
196
|
-
return unless user.dirty?
|
197
|
-
# Exclude non-attribute properties (only attributes can be updated in crowd)
|
198
|
-
attrs_to_update = user.dirty_attributes
|
199
|
-
return if attrs_to_update.empty?
|
200
|
-
|
201
|
-
attrs_to_update.each do |a|
|
202
|
-
prop = SimpleCrowd::User.property_by_name a
|
203
|
-
soap_prop = prop.maps[:soap].nil? ? prop : prop.maps[:soap]
|
204
|
-
self.update_user_attribute user.username, soap_prop, user.send(a)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
end
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
end
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
end
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
end
|
1
|
+
module SimpleCrowd
|
2
|
+
class Client
|
3
|
+
|
4
|
+
attr_reader :options
|
5
|
+
attr_accessor :app_token, :cache_store
|
6
|
+
|
7
|
+
def initialize options = {}
|
8
|
+
@options = SimpleCrowd.options options
|
9
|
+
yield(@options) if block_given?
|
10
|
+
self.cache_store = @options.delete(:cache_store)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_cookie_info
|
14
|
+
@cookie_info ||= cache.fetch(cache_key(:cookie_info)) do
|
15
|
+
# Remove custom SOAP attributes from the strings
|
16
|
+
simple_soap_call(:get_cookie_info).inject({}) do |cookie_info, (key, val)|
|
17
|
+
cookie_info[key] = val ? val.to_s : val
|
18
|
+
cookie_info
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_granted_authorities
|
24
|
+
groups = simple_soap_call :get_granted_authorities
|
25
|
+
groups[:string] unless groups.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def authenticate_application(name = @options[:app_name], password = @options[:app_password])
|
29
|
+
response = convert_soap_errors do
|
30
|
+
client.request :authenticate_application do |soap|
|
31
|
+
prepare soap
|
32
|
+
soap.body = {:in0 => {
|
33
|
+
'auth:name' => name,
|
34
|
+
'auth:credential' => {'auth:credential' => password}
|
35
|
+
}.merge(no_validation_factors)}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
response.to_hash[:authenticate_application_response][:out][:token].to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
# Authenticate user by name/pass and retrieve login token
|
42
|
+
# @return [String] user token
|
43
|
+
def authenticate_user name, password, factors = nil
|
44
|
+
if factors
|
45
|
+
factors = prepare_validation_factors(factors)
|
46
|
+
simple_soap_call :authenticate_principal, {'auth:application' => @options[:app_name], 'auth:name' => name,
|
47
|
+
'auth:credential' => {'auth:credential' => password},
|
48
|
+
'auth:validationFactors' => factors}
|
49
|
+
else
|
50
|
+
simple_soap_call :authenticate_principal_simple, name, password
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_user_token name
|
55
|
+
simple_soap_call :create_principal_token, name, nil
|
56
|
+
end
|
57
|
+
|
58
|
+
# Invalidate an existing user token (log out)
|
59
|
+
# NOTE: call will return true even if token is invalid
|
60
|
+
# @return [Boolean] success (does not guarantee valid token)
|
61
|
+
def invalidate_user_token token
|
62
|
+
simple_soap_call :invalidate_principal_token, token do |res|
|
63
|
+
!res.soap_fault? && res.to_hash.key?(:invalidate_principal_token_response)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def is_valid_user_token? token, factors = nil
|
68
|
+
factors = prepare_validation_factors(factors)
|
69
|
+
simple_soap_call :is_valid_principal_token, token, factors
|
70
|
+
end
|
71
|
+
|
72
|
+
def is_cache_enabled?
|
73
|
+
simple_soap_call :is_cache_enabled
|
74
|
+
end
|
75
|
+
|
76
|
+
def is_group_member? group, user
|
77
|
+
simple_soap_call :is_group_member, group, user
|
78
|
+
end
|
79
|
+
|
80
|
+
def find_group_by_name name
|
81
|
+
SimpleCrowd::Group.parse_from :soap, simple_soap_call(:find_group_by_name, name)
|
82
|
+
end
|
83
|
+
|
84
|
+
def find_all_group_names
|
85
|
+
(simple_soap_call :find_all_group_names)[:string]
|
86
|
+
end
|
87
|
+
|
88
|
+
def update_group group, description, active
|
89
|
+
simple_soap_call :update_group, group, description, active do |res|
|
90
|
+
!res.soap_fault? && res.to_hash.key?(:update_group_response)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def add_user_to_group user, group
|
95
|
+
simple_soap_call :add_principal_to_group, user, group do |res|
|
96
|
+
!res.soap_fault? && res.to_hash.key?(:add_principal_to_group_response)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def remove_user_from_group user, group
|
101
|
+
simple_soap_call :remove_principal_from_group, user, group do |res|
|
102
|
+
!res.soap_fault? && res.to_hash.key?(:remove_principal_from_group_response)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def reset_user_password name
|
107
|
+
simple_soap_call :reset_principal_credential, name do |res|
|
108
|
+
!res.soap_fault? && res.to_hash.key?(:reset_principal_credential_response)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def find_all_user_names
|
113
|
+
(simple_soap_call :find_all_principal_names)[:string]
|
114
|
+
end
|
115
|
+
|
116
|
+
def find_user_by_name name
|
117
|
+
SimpleCrowd::User.parse_from :soap, simple_soap_call(:find_principal_by_name, name) rescue nil
|
118
|
+
end
|
119
|
+
|
120
|
+
def find_user_with_attributes_by_name name
|
121
|
+
SimpleCrowd::User.parse_from :soap, simple_soap_call(:find_principal_with_attributes_by_name, name) rescue nil
|
122
|
+
end
|
123
|
+
|
124
|
+
def find_user_by_token token
|
125
|
+
SimpleCrowd::User.parse_from :soap, simple_soap_call(:find_principal_by_token, token) rescue nil
|
126
|
+
end
|
127
|
+
|
128
|
+
def find_username_by_token token
|
129
|
+
user = find_user_by_token token
|
130
|
+
user && user[:username]
|
131
|
+
end
|
132
|
+
|
133
|
+
# Exact email match
|
134
|
+
def find_user_by_email email
|
135
|
+
search_users_by_email(email).find{|u| u.email == email}
|
136
|
+
end
|
137
|
+
|
138
|
+
# Partial email match
|
139
|
+
def search_users_by_email email
|
140
|
+
search_users({'principal.email' => email})
|
141
|
+
end
|
142
|
+
|
143
|
+
def search_users restrictions
|
144
|
+
soap_restrictions = prepare_search_restrictions restrictions
|
145
|
+
users = simple_soap_call :search_principals, soap_restrictions rescue []
|
146
|
+
return [] if users.nil? || users[:soap_principal].nil?
|
147
|
+
users = users[:soap_principal].is_a?(Array) ? users[:soap_principal] : [users[:soap_principal]]
|
148
|
+
users.map{|u| SimpleCrowd::User.parse_from :soap, u}
|
149
|
+
end
|
150
|
+
|
151
|
+
def add_user user, credential
|
152
|
+
return if user.nil? || credential.nil?
|
153
|
+
[:email, :first_name, :last_name].each do |k|
|
154
|
+
user.send(:"#{k}=", "") if user.send(k).nil?
|
155
|
+
end
|
156
|
+
soap_user = user.map_to :soap
|
157
|
+
# We don't use these attributes when creating
|
158
|
+
soap_user.delete(:id)
|
159
|
+
soap_user.delete(:directory_id)
|
160
|
+
# Add blank attributes if missing
|
161
|
+
|
162
|
+
# Declare require namespaces
|
163
|
+
soap_user = soap_user.inject({}) {|hash, (k, v)| hash["int:#{k}"] = v;hash}
|
164
|
+
SimpleCrowd::User.parse_from :soap, simple_soap_call(:add_principal, soap_user, {'auth:credential' => credential, 'auth:encryptedCredential' => false})
|
165
|
+
end
|
166
|
+
|
167
|
+
def remove_user name
|
168
|
+
simple_soap_call :remove_principal, name do |res|
|
169
|
+
!res.soap_fault? && res.to_hash.key?(:remove_principal_response)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def update_user_credential user, credential, encrypted = false
|
174
|
+
simple_soap_call :update_principal_credential, user,
|
175
|
+
{'auth:credential' => credential, 'auth:encryptedCredential' => encrypted} do |res|
|
176
|
+
!res.soap_fault? && res.to_hash.key?(:update_principal_credential_response)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# Only supports single value attributes
|
181
|
+
# TODO: Allow value arrays
|
182
|
+
# @param user [String] name of user to update
|
183
|
+
# @param name [String] of attribute to update
|
184
|
+
# @param value [String] of attribute to update
|
185
|
+
def update_user_attribute user, name, value
|
186
|
+
return unless (name.is_a?(String) || name.is_a?(Symbol)) && (value.is_a?(String) || value.is_a?(Array))
|
187
|
+
soap_attr = SimpleCrowd::Mappers::SoapAttributes.produce({name => value})
|
188
|
+
simple_soap_call :update_principal_attribute, user, soap_attr['int:SOAPAttribute'][0] do |res|
|
189
|
+
!res.soap_fault? && res.to_hash.key?(:update_principal_attribute_response)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
alias_method :add_user_attribute, :update_user_attribute
|
193
|
+
|
194
|
+
# @param user [SimpleCrowd::User] dirty user to update
|
195
|
+
def update_user user
|
196
|
+
return unless user.dirty?
|
197
|
+
# Exclude non-attribute properties (only attributes can be updated in crowd)
|
198
|
+
attrs_to_update = user.dirty_attributes
|
199
|
+
return if attrs_to_update.empty?
|
200
|
+
|
201
|
+
attrs_to_update.each do |a|
|
202
|
+
prop = SimpleCrowd::User.property_by_name a
|
203
|
+
soap_prop = prop.maps[:soap].nil? ? prop : prop.maps[:soap]
|
204
|
+
self.update_user_attribute user.username, soap_prop, user.send(a)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def app_token
|
209
|
+
@app_token ||= cache.read(cache_key(:app_token))
|
210
|
+
end
|
211
|
+
|
212
|
+
def app_token=(token)
|
213
|
+
cache.write(cache_key(:app_token), token)
|
214
|
+
@app_token = token
|
215
|
+
end
|
216
|
+
|
217
|
+
def cache_store=(store)
|
218
|
+
@cache_store = store || Cache::NullStore.new
|
219
|
+
end
|
220
|
+
alias_method :cache, :cache_store
|
221
|
+
|
222
|
+
def reset_cache
|
223
|
+
[:app_token, :cookie_info].each do |key|
|
224
|
+
cache.delete(cache_key(key))
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
# Simplify the duplicated soap calls across methods
|
231
|
+
# @param [Symbol] action the soap action to call
|
232
|
+
# @param data the list of args to pass to the server as "in" args (in1, in2, etc.)
|
233
|
+
def simple_soap_call action, *data
|
234
|
+
# Take each arg and assign it to "in" keys for SOAP call starting with in1 (in0 is app token)
|
235
|
+
soap_args = data.inject({}){|hash, arg| hash[:"in#{hash.length + 1}"] = arg; hash }
|
236
|
+
# Ordered "in" keys ex. in1, in2, etc. for SOAP ordering
|
237
|
+
in_keys = soap_args.length ? (1..soap_args.length).collect {|v| :"in#{v}" } : []
|
238
|
+
# Make the SOAP call to the dynamic action
|
239
|
+
response = client_with_app_token do |client|
|
240
|
+
convert_soap_errors do
|
241
|
+
client.request :"#{action}" do |soap|
|
242
|
+
prepare soap
|
243
|
+
# Pass in all the args as "in" vars
|
244
|
+
soap.body = {:in0 => hash_authenticated_token}.merge(soap_args).merge({:order! => [:in0, *in_keys]})
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
# If a block is given then call it and pass in the response object, otherwise get the default out value
|
249
|
+
block_given? ? yield(response) : response.to_hash[:"#{action}_response"][:out]
|
250
|
+
end
|
251
|
+
|
252
|
+
def convert_soap_errors
|
253
|
+
begin
|
254
|
+
old_raise_errors = Savon.raise_errors?
|
255
|
+
Savon.raise_errors = true
|
256
|
+
yield
|
257
|
+
rescue Savon::SOAP::Fault => fault
|
258
|
+
raise CrowdError.new(fault.to_s, fault)
|
259
|
+
rescue Savon::HTTP::Error => e
|
260
|
+
raise CrowdError.new(e.to_s)
|
261
|
+
ensure
|
262
|
+
Savon.raise_errors = old_raise_errors
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def client
|
267
|
+
@client ||= Savon::Client.new do
|
268
|
+
wsdl.endpoint = options[:service_url]
|
269
|
+
wsdl.namespace = options[:service_ns]
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def client_with_app_token retries = 1
|
274
|
+
self.app_token = authenticate_application unless self.app_token
|
275
|
+
begin
|
276
|
+
yield client
|
277
|
+
rescue CrowdError => e
|
278
|
+
if retries > 0 && e.type?(:invalid_authorization_token_exception)
|
279
|
+
# Refresh the app token
|
280
|
+
self.app_token = authenticate_application
|
281
|
+
retries -= 1
|
282
|
+
retry
|
283
|
+
end
|
284
|
+
raise
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
# Setup soap object for request
|
289
|
+
def prepare soap
|
290
|
+
soap.namespaces.merge! options[:service_namespaces]
|
291
|
+
end
|
292
|
+
|
293
|
+
# Take Crowd SOAP attribute format and return a simple ruby hash
|
294
|
+
# @param attributes the soap attributes array
|
295
|
+
def process_soap_attributes attributes
|
296
|
+
soap = attributes[:soap_attribute]
|
297
|
+
(soap && soap.inject({}) {|hash, attr| hash[attr[:name].to_sym] = attr[:values][:string]; hash }) || {}
|
298
|
+
end
|
299
|
+
|
300
|
+
def map_group_hash group
|
301
|
+
attributes = process_soap_attributes group[:attributes]
|
302
|
+
supported_keys = attributes.keys & SimpleCrowd::Group.mapped_properties(:soap)
|
303
|
+
group = group.merge attributes.inject({}) {|map, (k, v)| map[k] = v if supported_keys.include? k; map}
|
304
|
+
group[:attributes] = attributes.inject({}) {|map, (k, v)| map[k] = v unless supported_keys.include? k; map}
|
305
|
+
group.delete :attributes if group[:attributes].empty?
|
306
|
+
SimpleCrowd::Group.new group
|
307
|
+
end
|
308
|
+
|
309
|
+
def prepare_validation_factors factors
|
310
|
+
{'auth:validationFactor' =>
|
311
|
+
(factors || []).inject([]) {|arr, factor| arr << {'auth:name' => factor[0], 'auth:value' => factor[1]} }
|
312
|
+
}
|
313
|
+
end
|
314
|
+
|
315
|
+
def prepare_search_restrictions restrictions
|
316
|
+
{'int:searchRestriction' =>
|
317
|
+
restrictions.inject([]) {|arr, restrict| arr << {'int:name' => restrict[0], 'int:value' => restrict[1]}}
|
318
|
+
}
|
319
|
+
end
|
320
|
+
|
321
|
+
def hash_authenticated_token name = @options[:app_name], token = nil
|
322
|
+
token ||= app_token
|
323
|
+
{'auth:name' => name, 'auth:token' => token}
|
324
|
+
end
|
325
|
+
|
326
|
+
def no_validation_factors
|
327
|
+
{'auth:validationFactors' => {}, :attributes! => {'auth:validationFactors' => {'xsi:nil' => true}}}
|
328
|
+
end
|
329
|
+
|
330
|
+
def cache_key(key)
|
331
|
+
"#{@options[:cache_prefix]}#{key}"
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|