simple_crowd 1.0.5 → 1.1.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/.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
|