crowd-stefanwille 0.5.8
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/.gitignore +4 -0
- data/History.txt +37 -0
- data/README.rdoc +122 -0
- data/Rakefile +44 -0
- data/demo/crowd_demo.rb +24 -0
- data/lib/crowd/http/request.rb +6 -0
- data/lib/crowd/http/response.rb +5 -0
- data/lib/crowd/http/sso.rb +101 -0
- data/lib/crowd/soap/SecurityServerClient.rb +844 -0
- data/lib/crowd/soap/crowd-2.0.5.wsdl +3158 -0
- data/lib/crowd/soap/default.rb +1525 -0
- data/lib/crowd/soap/driver.rb +423 -0
- data/lib/crowd/soap/mapping_registry.rb +1614 -0
- data/lib/crowd/version.rb +9 -0
- data/lib/crowd.rb +669 -0
- data/spec/crowd_spec.rb +149 -0
- data/stefanwille-crowd.gemspec +62 -0
- metadata +112 -0
data/lib/crowd.rb
ADDED
@@ -0,0 +1,669 @@
|
|
1
|
+
#
|
2
|
+
# Updated by Stefan Wille, post@stefanwille.com on 2010-07-13
|
3
|
+
# Updated by Evgeny Zislis, evgeny.zislis@gmail.con on 2008-05-15
|
4
|
+
# Created by Jason Rimmer, jrimmer@irth.net on 2007-10-16.
|
5
|
+
# I hereby place this work that I have authored into the public domain
|
6
|
+
# and in the process abandon all copyright protection.
|
7
|
+
#
|
8
|
+
require 'sha1'
|
9
|
+
require 'base64'
|
10
|
+
require 'rubygems'
|
11
|
+
gem 'soap4r'
|
12
|
+
|
13
|
+
require File.join(File.dirname(__FILE__), 'crowd', 'version')
|
14
|
+
require File.join(File.dirname(__FILE__), 'crowd', 'soap', 'driver.rb')
|
15
|
+
|
16
|
+
#
|
17
|
+
# Place 'server.wiredump_dev = STDERR' after any to see
|
18
|
+
# the raw SOAP calls and responses in a test console
|
19
|
+
#
|
20
|
+
|
21
|
+
# public static final String USERNAME = "username";
|
22
|
+
# public static final String FIRSTNAME = "givenName";
|
23
|
+
# public static final String LASTNAME = "sn";
|
24
|
+
# public static final String DISPLAYNAME = "displayName";
|
25
|
+
# public static final String EMAIL = "mail";
|
26
|
+
# public static final String ICON_LOCATION = "iconLocation";
|
27
|
+
# public static final String PASSWORD_LASTCHANGED = "passwordLastChanged";
|
28
|
+
# public static final String LAST_AUTHENTICATED = "lastAuthenticated";
|
29
|
+
# public static final String INVALID_PASSWORD_ATTEMPTS = "invalidPasswordAttempts";
|
30
|
+
# public static final String REQUIRES_PASSWORD_CHANGE = "requiresPasswordChange";
|
31
|
+
# public static final String ACTIVE = "active";
|
32
|
+
#
|
33
|
+
|
34
|
+
class Crowd
|
35
|
+
|
36
|
+
#
|
37
|
+
# shortcircuit Crowd::SOAP
|
38
|
+
#
|
39
|
+
include SOAP
|
40
|
+
|
41
|
+
#
|
42
|
+
# Class variables
|
43
|
+
#
|
44
|
+
private
|
45
|
+
|
46
|
+
@@application_token = nil
|
47
|
+
@@crowd_app_name = nil
|
48
|
+
@@crowd_app_pword = nil
|
49
|
+
|
50
|
+
public
|
51
|
+
|
52
|
+
@@crowd_url = nil
|
53
|
+
|
54
|
+
def self.crowd_url=(value); @@crowd_url = value; end
|
55
|
+
def self.crowd_app_name=(value); @@crowd_app_name = value; end
|
56
|
+
def self.crowd_app_pword=(value); @@crowd_app_pword = value; end
|
57
|
+
|
58
|
+
|
59
|
+
# for testing
|
60
|
+
def self.crowd_url; @@crowd_url; end
|
61
|
+
def self.crowd_app_name; @@crowd_app_name; end
|
62
|
+
def self.crowd_app_pword; @@crowd_app_pword; end
|
63
|
+
def self.application_token; @@application_token; end
|
64
|
+
|
65
|
+
public
|
66
|
+
|
67
|
+
#
|
68
|
+
# Exceptions
|
69
|
+
#
|
70
|
+
class AuthenticationException < StandardError; end
|
71
|
+
class AuthenticationConnectionException < ::Errno::ECONNREFUSED; end
|
72
|
+
class AuthenticationInvalidCredentialException < AuthenticationException; end
|
73
|
+
class AuthenticationInvalidException < AuthenticationException; end
|
74
|
+
class AuthenticationObjectNotFoundException < AuthenticationException; end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Public methods
|
78
|
+
#
|
79
|
+
|
80
|
+
##
|
81
|
+
# Authenticates an application client to the Crowd security server.
|
82
|
+
def self.authenticate_application(validation_factors = {})
|
83
|
+
pword = PasswordCredential.new(@@crowd_app_pword, false)
|
84
|
+
aovf = helper_validation_factors(validation_factors)
|
85
|
+
ctx = ApplicationAuthenticationContext.new(pword, @@crowd_app_name, aovf)
|
86
|
+
arg = AuthenticateApplication.new(ctx)
|
87
|
+
begin
|
88
|
+
response = server.authenticateApplication(arg)
|
89
|
+
rescue Errno::ECONNREFUSED => e
|
90
|
+
raise AuthenticationConnectionException, e
|
91
|
+
end
|
92
|
+
@@application_token = response.out
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# Authenticates a principal verses the calling who is in the application's assigned directory.
|
97
|
+
#
|
98
|
+
# To use SSO, set:
|
99
|
+
# validation_factors = { 'USER_AGENT' => '...', 'REMOTE_ADDRESS' => '...' }
|
100
|
+
# for proxy users { 'X_FORWARDED_FOR" => '...' } might be useful as well.
|
101
|
+
def self.authenticate_principal(username, password, validation_factors = {})
|
102
|
+
response = authenticated_connection do
|
103
|
+
pword = PasswordCredential.new(password, false)
|
104
|
+
aovf = helper_validation_factors(validation_factors)
|
105
|
+
ctx = UserAuthenticationContext.new(@@application_token.name, pword, username, aovf)
|
106
|
+
arg = AuthenticatePrincipal.new(@@application_token, ctx)
|
107
|
+
|
108
|
+
server.authenticatePrincipal(arg)
|
109
|
+
end
|
110
|
+
|
111
|
+
#evaluate the response. ideally, the authenticatePrincipal call should
|
112
|
+
#return an AuthenticationInvalidCredentialException and we can handle it more
|
113
|
+
#nicely below.
|
114
|
+
case response
|
115
|
+
when AuthenticatePrincipalResponse
|
116
|
+
return response.out
|
117
|
+
when InvalidAuthenticationException
|
118
|
+
return nil
|
119
|
+
when InactiveAccountException
|
120
|
+
return nil
|
121
|
+
when nil #no reponse
|
122
|
+
raise AuthenticationInvalidCredentialException, response
|
123
|
+
when ::AuthenticationException
|
124
|
+
raise AuthenticationInvalidCredentialException, response
|
125
|
+
else
|
126
|
+
raise AuthenticationException, response
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
##
|
132
|
+
# Authenticates a principal without validating a password.
|
133
|
+
def self.create_principal_token(username, validation_factors = {})
|
134
|
+
response = authenticated_connection do
|
135
|
+
aovf = helper_validation_factors(validation_factors)
|
136
|
+
arg = CreatePrincipalToken.new(@@application_token, username, aovf)
|
137
|
+
server.createPrincipalToken(arg)
|
138
|
+
end
|
139
|
+
response.out
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# Checks if the principal's current token is still valid.
|
144
|
+
def self.is_valid_principal_token?(principal_token, validation_factors = {})
|
145
|
+
response = authenticated_connection do
|
146
|
+
aovf = ArrayOfValidationFactor.new
|
147
|
+
validation_factors.each { |name,value| aovf << ValidationFactor.new(name, value)}
|
148
|
+
arg = IsValidPrincipalToken.new(@@application_token, principal_token, aovf)
|
149
|
+
server.isValidPrincipalToken(arg)
|
150
|
+
end
|
151
|
+
|
152
|
+
case response
|
153
|
+
when IsValidPrincipalTokenResponse
|
154
|
+
return response.out
|
155
|
+
else
|
156
|
+
raise AuthenticationException, response
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
##
|
161
|
+
# Add Principal
|
162
|
+
def self.add_principal(username, password, description, is_active, attributes)
|
163
|
+
response = authenticated_connection do
|
164
|
+
|
165
|
+
attrs = ArrayOfSOAPAttribute.new()
|
166
|
+
attributes.each do |key, val|
|
167
|
+
if (val.class == Array)
|
168
|
+
attrVal = ArrayOfString.new(val)
|
169
|
+
else
|
170
|
+
attrVal = ArrayOfString.new
|
171
|
+
attrVal << val
|
172
|
+
end
|
173
|
+
attrs << SOAPAttribute.new(key, attrVal)
|
174
|
+
end
|
175
|
+
|
176
|
+
principal = SOAPPrincipal.new(nil, is_active, attrs, nil, description, nil, nil, username)
|
177
|
+
pword = PasswordCredential.new(password, false)
|
178
|
+
arg = AddPrincipal.new(@@application_token, principal, pword)
|
179
|
+
|
180
|
+
server.addPrincipal(arg)
|
181
|
+
end
|
182
|
+
|
183
|
+
case response
|
184
|
+
when AddPrincipalResponse
|
185
|
+
return true
|
186
|
+
when InvalidCredentialException
|
187
|
+
raise AuthenticationInvalidCredentalException
|
188
|
+
when InvalidUserException
|
189
|
+
raise AuthenticationInvalidException, response
|
190
|
+
else
|
191
|
+
raise AuthenticationException, response
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
##
|
196
|
+
# Find Principal via username
|
197
|
+
def self.find_principal_by_username(username)
|
198
|
+
response = authenticated_connection do
|
199
|
+
arg = FindPrincipalByName.new(@@application_token, username)
|
200
|
+
server.findPrincipalByName(arg)
|
201
|
+
end
|
202
|
+
|
203
|
+
case response
|
204
|
+
when FindPrincipalByNameResponse
|
205
|
+
return parse_principal(response.out)
|
206
|
+
when ObjectNotFoundException
|
207
|
+
return nil
|
208
|
+
else
|
209
|
+
raise AuthenticationException, response
|
210
|
+
end
|
211
|
+
rescue AuthenticationException => e
|
212
|
+
raise AuthenticationObjectNotFoundException, e
|
213
|
+
end
|
214
|
+
|
215
|
+
##
|
216
|
+
# Find Principal via token
|
217
|
+
def self.find_principal_by_token(token)
|
218
|
+
response = authenticated_connection do
|
219
|
+
arg = FindPrincipalByToken.new(@@application_token, token)
|
220
|
+
server.findPrincipalByToken(arg)
|
221
|
+
end
|
222
|
+
case response
|
223
|
+
when FindPrincipalByTokenResponse
|
224
|
+
return parse_principal(response.out)
|
225
|
+
when ObjectNotFoundException
|
226
|
+
return nil
|
227
|
+
else
|
228
|
+
raise AuthenticationException, response
|
229
|
+
end
|
230
|
+
rescue AuthenticationObjectNotFoundException
|
231
|
+
return nil
|
232
|
+
rescue AuthenticationException => e
|
233
|
+
nil
|
234
|
+
rescue ::SOAP::FaultError => e
|
235
|
+
raise AuthenticationException, e.message
|
236
|
+
end
|
237
|
+
|
238
|
+
##
|
239
|
+
# Invalidate Principal Token
|
240
|
+
def self.invalidate_principal_token(token)
|
241
|
+
response = authenticated_connection do
|
242
|
+
arg = InvalidatePrincipalToken.new(@@application_token, token)
|
243
|
+
server.invalidatePrincipalToken(arg)
|
244
|
+
end
|
245
|
+
|
246
|
+
case response
|
247
|
+
when InvalidatePrincipalTokenResponse
|
248
|
+
return true
|
249
|
+
else
|
250
|
+
raise AuthenticationException, response
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
##
|
255
|
+
# Remove principal attribute
|
256
|
+
def self.remove_attribute_principal(username, attributes)
|
257
|
+
if(attributes.class != Array)
|
258
|
+
attributes = [attributes]
|
259
|
+
end
|
260
|
+
|
261
|
+
attributes.each do |attr|
|
262
|
+
response = authenticated_connection do
|
263
|
+
arg = RemoveAttributeFromPrincipal.new(@@application_token, username, attr)
|
264
|
+
server.removeAttributeFromPrincipal(arg)
|
265
|
+
end
|
266
|
+
|
267
|
+
case response
|
268
|
+
when RemoveAttributeFromPrincipalResponse
|
269
|
+
# Burying as this means it succeeded
|
270
|
+
when ObjectNotFoundException
|
271
|
+
raise AuthenticationObjectNotFoundException
|
272
|
+
else
|
273
|
+
raise AuthenticationException, response
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
##
|
279
|
+
# Add attribute to principal
|
280
|
+
def self.add_attribute_principal(username, attributes)
|
281
|
+
attributes.each do |key, val|
|
282
|
+
response = authenticated_connection do
|
283
|
+
if(val.class == Array)
|
284
|
+
valArray = ArrayOfString.new(val)
|
285
|
+
else
|
286
|
+
valArray = ArrayOfString.new
|
287
|
+
valArray << val
|
288
|
+
end
|
289
|
+
|
290
|
+
tuple = SOAPAttribute.new(key, valArray)
|
291
|
+
arg = AddAttributeToPrincipal.new(@@application_token, username, tuple)
|
292
|
+
|
293
|
+
server.addAttributeToPrincipal(arg)
|
294
|
+
end
|
295
|
+
|
296
|
+
case response
|
297
|
+
when AddAttributeToPrincipalResponse
|
298
|
+
# Burying it because this means it was successful
|
299
|
+
when ObjectNotFoundException
|
300
|
+
raise AuthenticationObjectNotFoundException
|
301
|
+
else
|
302
|
+
raise AuthenticationException, response
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
true
|
307
|
+
end
|
308
|
+
|
309
|
+
##
|
310
|
+
# Update attribute on principal
|
311
|
+
def self.update_attribute_principal(username, attributes)
|
312
|
+
attributes.each do |key, val|
|
313
|
+
response = authenticated_connection do
|
314
|
+
if val.is_a?(Array)
|
315
|
+
valArray = ArrayOfString.new(val)
|
316
|
+
else
|
317
|
+
valArray = ArrayOfString.new
|
318
|
+
valArray << val
|
319
|
+
end
|
320
|
+
|
321
|
+
tuple = SOAPAttribute.new(key, valArray)
|
322
|
+
arg = UpdatePrincipalAttribute.new(@@application_token, username, tuple)
|
323
|
+
|
324
|
+
server.updatePrincipalAttribute(arg)
|
325
|
+
end
|
326
|
+
|
327
|
+
case response
|
328
|
+
when UpdatePrincipalAttributeResponse
|
329
|
+
# Burying as it worked
|
330
|
+
when ObjectNotFoundException
|
331
|
+
raise AuthenticationObjectNotFoundException
|
332
|
+
else
|
333
|
+
raise AuthenticationException, response
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
true
|
338
|
+
end
|
339
|
+
|
340
|
+
##
|
341
|
+
# Remove principal
|
342
|
+
def self.remove_principal(username)
|
343
|
+
response = authenticated_connection do
|
344
|
+
arg = RemovePrincipal.new(@@application_token, username)
|
345
|
+
server.removePrincipal(arg)
|
346
|
+
end
|
347
|
+
|
348
|
+
case response
|
349
|
+
when RemovePrincipalResponse
|
350
|
+
return true
|
351
|
+
when ObjectNotFoundException
|
352
|
+
raise AuthenticationObjectNotFoundException
|
353
|
+
else
|
354
|
+
raise AuthenticationException, response
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
##
|
359
|
+
# Find all principal names
|
360
|
+
def self.find_all_principal_names
|
361
|
+
response = authenticated_connection do
|
362
|
+
arg = FindAllPrincipalNames.new(@@application_token)
|
363
|
+
server.findAllPrincipalNames(arg)
|
364
|
+
end
|
365
|
+
|
366
|
+
case response
|
367
|
+
when FindAllPrincipalNamesResponse
|
368
|
+
return response.out
|
369
|
+
when ObjectNotFoundException
|
370
|
+
return {}
|
371
|
+
else
|
372
|
+
raise AuthenticationException, response
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
##
|
377
|
+
# Find all role names
|
378
|
+
def self.find_all_role_names
|
379
|
+
response = authenticated_connection do
|
380
|
+
arg = FindAllRoleNames.new(@@application_token)
|
381
|
+
server.findAllRoleNames(arg)
|
382
|
+
end
|
383
|
+
|
384
|
+
case response
|
385
|
+
when FindAllRoleNamesResponse
|
386
|
+
return response.out
|
387
|
+
when ObjectNotFoundException
|
388
|
+
return {}
|
389
|
+
else
|
390
|
+
raise AuthenticationException, response
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
##
|
395
|
+
# Add Role
|
396
|
+
def self.add_role(name, description, is_active)
|
397
|
+
response = authenticated_connection do
|
398
|
+
role = SOAPRole.new(nil, is_active, nil, nil, description, nil, nil, nil, name)
|
399
|
+
arg = AddRole.new(@@application_token, role)
|
400
|
+
server.addRole(arg)
|
401
|
+
end
|
402
|
+
|
403
|
+
case response
|
404
|
+
when AddRoleResponse
|
405
|
+
return true
|
406
|
+
when ObjectNotFoundException
|
407
|
+
return AuthenticationObjectNotFoundException
|
408
|
+
else
|
409
|
+
raise AuthenticationException, response
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
##
|
414
|
+
# Add Principal to Role
|
415
|
+
def self.add_principal_to_role(username, role)
|
416
|
+
response = authenticated_connection do
|
417
|
+
arg = AddPrincipalToRole.new(@@application_token, username, role)
|
418
|
+
#raise arg.to_yaml
|
419
|
+
server.addPrincipalToRole(arg)
|
420
|
+
end
|
421
|
+
|
422
|
+
case response
|
423
|
+
when AddPrincipalToRoleResponse
|
424
|
+
return true
|
425
|
+
when ObjectNotFoundException
|
426
|
+
return AuthenticationObjectNotFoundException
|
427
|
+
else
|
428
|
+
raise AuthenticationException, response
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
##
|
433
|
+
# Remove Principal form Role
|
434
|
+
def self.remove_principal_from_role(username, role)
|
435
|
+
response = authenticated_connection do
|
436
|
+
arg = RemovePrincipalFromRole.new(@@application_token, username, role)
|
437
|
+
server.removePrincipalFromRole(arg)
|
438
|
+
end
|
439
|
+
|
440
|
+
case response
|
441
|
+
when RemovePrincipalFromRoleResponse
|
442
|
+
return true
|
443
|
+
when ObjectNotFoundException
|
444
|
+
return AuthenticationObjectNotFoundException
|
445
|
+
else
|
446
|
+
raise AuthenticationException, response
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
##
|
451
|
+
# Is Role Member
|
452
|
+
def self.is_role_member(username, role)
|
453
|
+
response = authenticated_connection do
|
454
|
+
arg = IsRoleMember.new(@@application_token, username, role )
|
455
|
+
server.isRoleMember(arg)
|
456
|
+
end
|
457
|
+
|
458
|
+
case response
|
459
|
+
when IsRoleMemberResponse
|
460
|
+
return response.out
|
461
|
+
when ObjectNotFoundException
|
462
|
+
return AuthenticationObjectNotFoundException
|
463
|
+
else
|
464
|
+
raise AuthenticationException, response
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
|
469
|
+
|
470
|
+
##
|
471
|
+
# Remove Role
|
472
|
+
def self.remove_role(role)
|
473
|
+
response = authenticated_connection do
|
474
|
+
arg = RemoveRole.new(@@application_token, role)
|
475
|
+
server.removeRole(arg)
|
476
|
+
end
|
477
|
+
|
478
|
+
case response
|
479
|
+
when RemoveRoleResponse
|
480
|
+
return true
|
481
|
+
when ObjectNotFoundException
|
482
|
+
return AuthenticationObjectNotFoundException
|
483
|
+
else
|
484
|
+
raise AuthenticationException, response
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
##
|
489
|
+
# Is Group Member
|
490
|
+
def self.is_group_member(username, group)
|
491
|
+
response = authenticated_connection do
|
492
|
+
arg = IsGroupMember.new(@@application_token, group, username )
|
493
|
+
server.isGroupMember(arg)
|
494
|
+
end
|
495
|
+
|
496
|
+
case response
|
497
|
+
when IsGroupMemberResponse
|
498
|
+
return response.out
|
499
|
+
when ObjectNotFoundException
|
500
|
+
return AuthenticationObjectNotFoundException
|
501
|
+
else
|
502
|
+
raise AuthenticationException, response
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
def self.find_all_group_names
|
507
|
+
response = authenticated_connection do
|
508
|
+
arg = FindAllGroupNames.new(@@application_token)
|
509
|
+
server.findAllGroupNames(arg)
|
510
|
+
end
|
511
|
+
|
512
|
+
case response
|
513
|
+
when FindAllGroupNamesResponse
|
514
|
+
return response.out
|
515
|
+
when ObjectNotFoundException
|
516
|
+
return AuthenticationObjectNotFoundException
|
517
|
+
else
|
518
|
+
raise AuthenticationException, response
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
def self.find_all_groups_for_principal(username)
|
523
|
+
response = authenticated_connection do
|
524
|
+
arg = FindGroupMemberships.new(@@application_token, username)
|
525
|
+
server.findGroupMemberships(arg)
|
526
|
+
end
|
527
|
+
|
528
|
+
case response
|
529
|
+
when FindGroupMembershipsResponse
|
530
|
+
return response.out
|
531
|
+
when ObjectNotFoundException
|
532
|
+
return AuthenticationObjectNotFoundException
|
533
|
+
else
|
534
|
+
raise AuthenticationException, response
|
535
|
+
end
|
536
|
+
end
|
537
|
+
|
538
|
+
def self.get_group(name)
|
539
|
+
response = authenticated_connection do
|
540
|
+
arg = FindGroupByName.new(@@application_token, name)
|
541
|
+
server.findGroupByName(arg)
|
542
|
+
end
|
543
|
+
|
544
|
+
case response
|
545
|
+
when FindGroupByNameResponse
|
546
|
+
return response.out
|
547
|
+
when ObjectNotFoundException
|
548
|
+
return AuthenticationObjectNotFoundException
|
549
|
+
else
|
550
|
+
raise AuthenticationException, response
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
private
|
555
|
+
|
556
|
+
# Parse the user
|
557
|
+
def self.parse_principal(rp)
|
558
|
+
p = {}
|
559
|
+
p[:id] = rp.iD
|
560
|
+
p[:active] = rp.active
|
561
|
+
p[:conception] = rp.conception
|
562
|
+
p[:description] = rp.description
|
563
|
+
p[:directoryID] = rp.directoryId
|
564
|
+
p[:lastModified] = rp.lastModified
|
565
|
+
p[:name] = rp.name
|
566
|
+
|
567
|
+
p[:attributes] = {}
|
568
|
+
|
569
|
+
rp.attributes.each do |attr|
|
570
|
+
case attr.values.size
|
571
|
+
when 0
|
572
|
+
p[:attributes][attr.name.to_sym] = nil
|
573
|
+
when 1
|
574
|
+
p[:attributes][attr.name.to_sym] = attr.values[0]
|
575
|
+
else
|
576
|
+
p[:attributes][attr.name.to_sym] = attr.values.to_a
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
return p
|
581
|
+
end
|
582
|
+
|
583
|
+
# Create ArrayOfValidationFactor from a ruby key=>value hash
|
584
|
+
def self.helper_validation_factors(validation_factors = {})
|
585
|
+
aovf = ArrayOfValidationFactor.new
|
586
|
+
validation_factors.each { |name,value| aovf << ValidationFactor.new(name, value)}
|
587
|
+
end
|
588
|
+
|
589
|
+
# Has the application been authenticated?
|
590
|
+
def self.application_auth_check
|
591
|
+
authenticate_application if @@application_token.nil?
|
592
|
+
end
|
593
|
+
|
594
|
+
# Shorthand for getting the security server object
|
595
|
+
def self.server
|
596
|
+
@@server ||= SecurityServerPortType.new(@@crowd_url)
|
597
|
+
end
|
598
|
+
|
599
|
+
# Wrapper for catching common exceptions. Also allows the application a chance
|
600
|
+
# to re-authenticate if the token is invalid.
|
601
|
+
def self.authenticated_connection
|
602
|
+
raise ArgumentError unless block_given?
|
603
|
+
|
604
|
+
application_auth_check
|
605
|
+
|
606
|
+
response = yield
|
607
|
+
rescue AuthenticationException => e
|
608
|
+
# Push the response into the exception message
|
609
|
+
raise AuthenticationException, e
|
610
|
+
rescue Errno::ECONNREFUSED => e
|
611
|
+
raise AuthenticationConnectionException, e
|
612
|
+
rescue ::SOAP::FaultError => e
|
613
|
+
# We'll retry once more on any fault.
|
614
|
+
begin
|
615
|
+
authenticate_application
|
616
|
+
response = yield
|
617
|
+
rescue AuthenticationException => e
|
618
|
+
raise AuthenticationException, e
|
619
|
+
rescue Errno::ECONNREFUSED => e
|
620
|
+
raise AuthenticationConnectionException, e
|
621
|
+
rescue Exception => e
|
622
|
+
raise AuthenticationException, e
|
623
|
+
end
|
624
|
+
rescue Exception => e
|
625
|
+
raise AuthenticationException, e
|
626
|
+
ensure
|
627
|
+
if response.is_a?(InvalidAuthorizationTokenException)
|
628
|
+
authenticate_application
|
629
|
+
response = yield
|
630
|
+
end
|
631
|
+
response
|
632
|
+
end
|
633
|
+
|
634
|
+
##
|
635
|
+
# Returns the domain configured in Crowd or null if no domain has been set.
|
636
|
+
#
|
637
|
+
# *Deprecated:* This method has been superceded by get_cookie_config.
|
638
|
+
def self.get_domain
|
639
|
+
response = authenticated_connection do
|
640
|
+
arg = GetDomain.new(@@application_token)
|
641
|
+
server.getDomain(arg)
|
642
|
+
end
|
643
|
+
|
644
|
+
case response
|
645
|
+
when GetDomainResponse
|
646
|
+
return response.out
|
647
|
+
else
|
648
|
+
raise AuthenticationException, response
|
649
|
+
end
|
650
|
+
end
|
651
|
+
|
652
|
+
##
|
653
|
+
# Updates the password credential for a principal who is in the application's assigned directory.
|
654
|
+
def self.update_principal_credential(principal, password)
|
655
|
+
response = authenticated_connection do
|
656
|
+
hash = Digest::SHA512.new.update(password).digest
|
657
|
+
cred = PasswordCredential.new(Base64::encode64(hash).gsub(/\n/, ''))
|
658
|
+
arg = UpdatePrincipalCredential.new(@@application_token, principal, cred)
|
659
|
+
server.updatePrincipalCredential(arg)
|
660
|
+
end
|
661
|
+
|
662
|
+
case response
|
663
|
+
when UpdatePrincipalCredentialResponse
|
664
|
+
return nil
|
665
|
+
else
|
666
|
+
raise AuthenticationException, response
|
667
|
+
end
|
668
|
+
end
|
669
|
+
end
|