crowd 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,508 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
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 'rubygems'
9
+ gem 'soap4r'
10
+
11
+ require File.join(File.dirname(__FILE__), 'defaultDriver.rb')
12
+ require 'crowd/version'
13
+
14
+ #
15
+ # Place 'obj.wiredump_dev = STDERR' after any SecurityServerPortType
16
+ # instantiation to see the raw SOAP calls and responses in a test
17
+ # console
18
+ #
19
+
20
+ class Crowd
21
+ #
22
+ # Class variables
23
+ #
24
+
25
+ private
26
+
27
+ @@application_token = nil
28
+
29
+ public
30
+
31
+ @@crowd_url = nil
32
+ @@crowd_app_name = nil
33
+ @@crowd_app_pword = nil
34
+
35
+ def self.crowd_url=(value); @@crowd_url = value; end
36
+ def self.crowd_app_name=(value); @@crowd_app_name = value; end
37
+ def self.crowd_app_pword=(value); @@crowd_app_pword = value; end
38
+
39
+ public
40
+
41
+ #
42
+ # Exceptions
43
+ #
44
+ class AuthenticationException < Exception; end
45
+ class AuthenticationConnectionException < AuthenticationException; end
46
+ class AuthenticationInvalidCredentialException < AuthenticationException; end
47
+ class AuthenticationInvalidException < AuthenticationException; end
48
+ class AuthenticationObjectNotFoundException < AuthenticationException; end
49
+ class AuthenticationInvalidObject < AuthenticationException; end
50
+
51
+ #
52
+ # Public methods
53
+ #
54
+
55
+ ##
56
+ # Authenticate application
57
+ def self.authenticate_application()
58
+ @@application_token = nil
59
+
60
+ if @@crowd_app_name.nil?
61
+ @@crowd_app_name = CROWD_APPLICATION_NAME
62
+ end
63
+ if @@crowd_app_pword.nil?
64
+ @@crowd_app_pword = CROWD_APPLICATION_PASSWORD
65
+ end
66
+
67
+ pword = PasswordCredential.new(@@crowd_app_pword, false)
68
+ ctx = ApplicationAuthenticationContext.new(pword, @@crowd_app_name, nil)
69
+ arg = AuthenticateApplication.new(ctx)
70
+
71
+ begin
72
+ response = server.authenticateApplication(arg)
73
+ rescue Errno::ECONNREFUSED
74
+ raise AuthenticationConnectionException
75
+ rescue Exception
76
+ raise AuthenticationException, response
77
+ end
78
+
79
+ if !response.is_a?(AuthenticateApplicationResponse)
80
+ raise AuthenticationException, response
81
+ end
82
+
83
+ @@application_token = AuthenticatedToken.new(@@crowd_app_name, response.out.token)
84
+
85
+ response.out.token
86
+ end
87
+
88
+ ##
89
+ # Authenticate principal
90
+ def self.authenticate_principal(username, password)
91
+ response = authenticated_connection do
92
+ pword = PasswordCredential.new(password, false)
93
+ ctx = PrincipalAuthenticationContext.new(@@application_token.name, pword, username, nil)
94
+ arg = AuthenticatePrincipal.new(@@application_token, ctx)
95
+
96
+ server.authenticatePrincipal(arg)
97
+ end
98
+
99
+ #evaluate the response. ideally, the authenticatePrincipal call should
100
+ #return an AuthenticationInvalidCredentialException and we can handle it more
101
+ #nicely below.
102
+ case response
103
+ when AuthenticatePrincipalResponse
104
+ return response.out
105
+ when InvalidAuthenticationException
106
+ return nil
107
+ when nil #no reponse
108
+ raise AuthenticationInvalidCredentialException, response
109
+ else
110
+ raise AuthenticationException, response
111
+ end
112
+ end
113
+
114
+ ##
115
+ # Add Principal
116
+ def self.add_principal(username, password, description, is_active, attributes)
117
+ response = authenticated_connection do
118
+ attrs = ArrayOfSOAPAttribute.new()
119
+
120
+ attributes.each do |key, val|
121
+ if (val.class == Array)
122
+ attrVal = ArrayOfString.new(val)
123
+ else
124
+ attrVal = ArrayOfString.new
125
+ attrVal << val
126
+ end
127
+ attrs << SOAPAttribute.new(key, attrVal)
128
+ end
129
+
130
+ principal = SOAPPrincipal.new(nil, is_active, attrs, nil, description, nil, nil, username)
131
+ pword = PasswordCredential.new(password, false)
132
+ arg = AddPrincipal.new(@@application_token, principal, pword)
133
+
134
+ server.addPrincipal(arg)
135
+ end
136
+
137
+ case response
138
+ when AddPrincipalResponse
139
+ return true
140
+ when InvalidCredentialException
141
+ raise AuthenticationInvalidCredentalException
142
+ when InvalidPrincipalException
143
+ raise AuthenticationInvalidException, response
144
+ else
145
+ raise AuthenticationException, response
146
+ end
147
+ end
148
+
149
+ ##
150
+ # Find Principal via username
151
+ def self.find_principal_by_username(username)
152
+ response = authenticated_connection do
153
+ arg = FindPrincipalByName.new(@@application_token, username)
154
+ server.findPrincipalByName(arg)
155
+ end
156
+
157
+ case response
158
+ when FindPrincipalByNameResponse
159
+ return parse_principal(response.out)
160
+ when ObjectNotFoundException
161
+ return {}
162
+ else
163
+ raise AuthenticationException, response
164
+ end
165
+ end
166
+
167
+ ##
168
+ # Find Principal via token
169
+ def self.find_principal_by_token(token)
170
+ response = authenticated_connection do
171
+ arg = FindPrincipalByToken.new(@@application_token, token)
172
+ server.findPrincipalByToken(arg)
173
+ end
174
+
175
+ case response
176
+ when FindPrincipalByTokenResponse
177
+ return parse_principal(response.out)
178
+ when ObjectNotFoundException
179
+ return {}
180
+ else
181
+ raise AuthenticationException, response
182
+ end
183
+ end
184
+
185
+ ##
186
+ # Remove principal attribute
187
+ def self.remove_attribute_principal(username, attributes)
188
+ if(attributes.class != Array)
189
+ attributes = [attributes]
190
+ end
191
+
192
+ attributes.each do |attr|
193
+ response = authenticated_connection do
194
+ arg = RemoveAttributeFromPrincipal.new(@@application_token, username, attr)
195
+ server.removeAttributeFromPrincipal(arg)
196
+ end
197
+
198
+ case response
199
+ when RemoveAttributeFromPrincipalResponse
200
+ # Burying as this means it succeeded
201
+ when ObjectNotFoundException
202
+ raise AuthenticationObjectNotFoundException
203
+ else
204
+ raise AuthenticationException, response
205
+ end
206
+ end
207
+ end
208
+
209
+ ##
210
+ # Add attribute to principal
211
+ def self.add_attribute_principal(username, attributes)
212
+ attributes.each do |key, val|
213
+ response = authenticated_connection do
214
+ if(val.class == Array)
215
+ valArray = ArrayOfString.new(val)
216
+ else
217
+ valArray = ArrayOfString.new
218
+ valArray << val
219
+ end
220
+
221
+ tuple = SOAPAttribute.new(key, valArray)
222
+ arg = AddAttributeToPrincipal.new(@@application_token, username, tuple)
223
+
224
+ server.addAttributeToPrincipal(arg)
225
+ end
226
+
227
+ case response
228
+ when AddAttributeToPrincipalResponse
229
+ # Burying it because this means it was successful
230
+ when ObjectNotFoundException
231
+ raise AuthenticationObjectNotFoundException
232
+ else
233
+ raise AuthenticationException, response
234
+ end
235
+ end
236
+
237
+ true
238
+ end
239
+
240
+ ##
241
+ # Update attribute on principal
242
+ def self.update_attribute_principal(username, attributes)
243
+ attributes.each do |key, val|
244
+ response = authenticated_connection do
245
+ if val.is_a?(Array)
246
+ valArray = ArrayOfString.new(val)
247
+ else
248
+ valArray = ArrayOfString.new
249
+ valArray << val
250
+ end
251
+
252
+ tuple = SOAPAttribute.new(key, valArray)
253
+ arg = UpdatePrincipalAttribute.new(@@application_token, username, tuple)
254
+
255
+ server.updatePrincipalAttribute(arg)
256
+ end
257
+
258
+ case response
259
+ when UpdatePrincipalAttributeResponse
260
+ # Burying as it worked
261
+ when ObjectNotFoundException
262
+ raise AuthenticationObjectNotFoundException
263
+ else
264
+ raise AuthenticationException, response
265
+ end
266
+ end
267
+
268
+ true
269
+ end
270
+
271
+ ##
272
+ # Remove principal
273
+ def self.remove_principal(username)
274
+ response = authenticated_connection do
275
+ arg = RemovePrincipal.new(@@application_token, username)
276
+ server.removePrincipal(arg)
277
+ end
278
+
279
+ case response
280
+ when RemovePrincipalResponse
281
+ return true
282
+ when ObjectNotFoundException
283
+ raise AuthenticationObjectNotFoundException
284
+ else
285
+ raise AuthenticationException, response
286
+ end
287
+ end
288
+
289
+ ##
290
+ # Find all principal names
291
+ def self.find_all_principal_names
292
+ response = authenticated_connection do
293
+ arg = FindAllPrincipalNames.new(@@application_token)
294
+ server.findAllPrincipalNames(arg)
295
+ end
296
+
297
+ case response
298
+ when FindAllPrincipalNamesResponse
299
+ return response.out
300
+ when ObjectNotFoundException
301
+ return {}
302
+ else
303
+ raise AuthenticationException, response
304
+ end
305
+ end
306
+
307
+ ##
308
+ # Find all role names
309
+ def self.find_all_role_names
310
+ response = authenticated_connection do
311
+ arg = FindAllRoleNames.new(@@application_token)
312
+ server.findAllRoleNames(arg)
313
+ end
314
+
315
+ case response
316
+ when FindAllRoleNamesResponse
317
+ return response.out
318
+ when ObjectNotFoundException
319
+ return {}
320
+ else
321
+ raise AuthenticationException, response
322
+ end
323
+ end
324
+
325
+ ##
326
+ # Add Role
327
+ def self.add_role(name, description, is_active)
328
+ response = authenticated_connection do
329
+ role = SOAPRole.new(nil, is_active, nil, nil, description, nil, nil, nil, name)
330
+ arg = AddRole.new(@@application_token, role)
331
+ server.addRole(arg)
332
+ end
333
+
334
+ case response
335
+ when AddRoleResponse
336
+ return true
337
+ when ObjectNotFoundException
338
+ return AuthenticationObjectNotFoundException
339
+ else
340
+ raise AuthenticationException, response
341
+ end
342
+ end
343
+
344
+ ##
345
+ # Add Principal to Role
346
+ def self.add_principal_to_role(username, role)
347
+ response = authenticated_connection do
348
+ arg = AddPrincipalToRole.new(@@application_token, username, role)
349
+ #raise arg.to_yaml
350
+ server.addPrincipalToRole(arg)
351
+ end
352
+
353
+ case response
354
+ when AddPrincipalToRoleResponse
355
+ return true
356
+ when ObjectNotFoundException
357
+ return AuthenticationObjectNotFoundException
358
+ else
359
+ raise AuthenticationException, response
360
+ end
361
+ end
362
+
363
+ ##
364
+ # Remove Principal form Role
365
+ def self.remove_principal_from_role(username, role)
366
+ response = authenticated_connection do
367
+ arg = RemovePrincipalFromRole.new(@@application_token, username, role)
368
+ server.removePrincipalFromRole(arg)
369
+ end
370
+
371
+ case response
372
+ when RemovePrincipalFromRoleResponse
373
+ return true
374
+ when ObjectNotFoundException
375
+ return AuthenticationObjectNotFoundException
376
+ else
377
+ raise AuthenticationException, response
378
+ end
379
+ end
380
+
381
+ ##
382
+ # Is Role Member
383
+ def self.is_role_member(username, role)
384
+ response = authenticated_connection do
385
+ arg = IsRoleMember.new(@@application_token, username, role )
386
+ server.isRoleMember(arg)
387
+ end
388
+
389
+ case response
390
+ when IsRoleMemberResponse
391
+ return response.out
392
+ when ObjectNotFoundException
393
+ return AuthenticationObjectNotFoundException
394
+ else
395
+ raise AuthenticationException, response
396
+ end
397
+ end
398
+
399
+
400
+
401
+ ##
402
+ # Remove Role
403
+ def self.remove_role(role)
404
+ response = authenticated_connection do
405
+ arg = RemoveRole.new(@@application_token, role)
406
+ server.removeRole(arg)
407
+ end
408
+
409
+ case response
410
+ when RemoveRoleResponse
411
+ return true
412
+ when ObjectNotFoundException
413
+ return AuthenticationObjectNotFoundException
414
+ else
415
+ raise AuthenticationException, response
416
+ end
417
+ end
418
+
419
+ ##
420
+ # Is Group Member
421
+ def self.is_group_member(username, group)
422
+ response = authenticated_connection do
423
+ arg = IsGroupMember.new(@@application_token, group, username )
424
+ server.isGroupMember(arg)
425
+ end
426
+
427
+ case response
428
+ when IsGroupMemberResponse
429
+ return response.out
430
+ when ObjectNotFoundException
431
+ return AuthenticationObjectNotFoundException
432
+ else
433
+ raise AuthenticationException, response
434
+ end
435
+ end
436
+
437
+ private
438
+
439
+ # Parse the user
440
+ def self.parse_principal(rp)
441
+ p = {}
442
+
443
+ p[:id] = rp.iD
444
+ p[:active] = rp.active
445
+ p[:conception] = rp.conception
446
+ p[:description] = rp.description
447
+ p[:directoryID] = rp.directoryID
448
+ p[:lastModified] = rp.lastModified
449
+ p[:name] = rp.name
450
+
451
+ p[:attributes] = {}
452
+
453
+ rp.attributes.each do |attr|
454
+ case attr.values.size
455
+ when 0
456
+ p[:attributes][attr.name.to_sym] = nil
457
+ when 1
458
+ p[:attributes][attr.name.to_sym] = attr.values[0]
459
+ else
460
+ p[:attributes][attr.name.to_sym] = attr.values.to_a
461
+ end
462
+ end
463
+
464
+ return p
465
+ end
466
+
467
+ # Has the application been authenticated?
468
+ def self.application_auth_check
469
+ authenticate_application if @@application_token.nil?
470
+ end
471
+
472
+ # Shorthand for getting the security server object
473
+ def self.server
474
+ SecurityServerPortType.new(@@crowd_url)
475
+ end
476
+
477
+ # Wrapper for catching common exceptions. Also allows the application a chance
478
+ # to re-authenticate if the token is invalid.
479
+ def self.authenticated_connection
480
+ raise ArgumentError unless block_given?
481
+
482
+ application_auth_check
483
+ response = yield
484
+ rescue AuthenticationException
485
+ # Push the response into the exception message
486
+ raise AuthenticationException, response
487
+ rescue Errno::ECONNREFUSED
488
+ raise AuthenticationConnectionException
489
+ rescue SOAP::FaultError => e
490
+ # If the application token is invalid/expired, we'll give it one more shot.
491
+ if e.message =~ /Invalid application client/
492
+ authenticate_application
493
+ response = yield
494
+ else
495
+ # It may not always be a not found case but until the type of
496
+ # FaultError is known, which has not been able to be determined
497
+ raise AuthenticationObjectNotFoundException, e.message
498
+ end
499
+ rescue Exception
500
+ raise AuthenticationException, response
501
+
502
+ if response.is_a?(InvalidAuthorizationTokenException)
503
+ authenticate_application
504
+ response = yield
505
+ end
506
+ response
507
+ end
508
+ end