soteria 1.0.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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +2 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +77 -0
  9. data/Rakefile +5 -0
  10. data/bin/bundler +17 -0
  11. data/bin/console +17 -0
  12. data/bin/htmldiff +17 -0
  13. data/bin/ldiff +17 -0
  14. data/bin/nokogiri +17 -0
  15. data/bin/rackup +17 -0
  16. data/bin/rake +17 -0
  17. data/bin/rspec +17 -0
  18. data/bin/setup +17 -0
  19. data/bin/socksify_ruby +17 -0
  20. data/lib/soteria.rb +10 -0
  21. data/lib/soteria/client.rb +326 -0
  22. data/lib/soteria/credential.rb +154 -0
  23. data/lib/soteria/credential_types.rb +13 -0
  24. data/lib/soteria/push.rb +141 -0
  25. data/lib/soteria/sms.rb +81 -0
  26. data/lib/soteria/user.rb +409 -0
  27. data/lib/soteria/utilities.rb +45 -0
  28. data/lib/soteria/version.rb +4 -0
  29. data/soteria.gemspec +26 -0
  30. data/spec/credential_spec.rb +121 -0
  31. data/spec/fixtures/credential/authenticate_credentials_response.xml +13 -0
  32. data/spec/fixtures/credential/credential_fail.xml +11 -0
  33. data/spec/fixtures/credential/credential_success.xml +12 -0
  34. data/spec/fixtures/credential/get_cred_info_response.xml +40 -0
  35. data/spec/fixtures/credential/get_server_time_response.xml +11 -0
  36. data/spec/fixtures/credential/register_sms_response.xml +12 -0
  37. data/spec/fixtures/push/authenticate_with_push_error.xml +9 -0
  38. data/spec/fixtures/push/authenticate_with_push_response.xml +14 -0
  39. data/spec/fixtures/sms/check_otp_success_response.xml +13 -0
  40. data/spec/fixtures/sms/send_sms_success_response.xml +10 -0
  41. data/spec/fixtures/user/add_credential_response.xml +9 -0
  42. data/spec/fixtures/user/clear_temp_password_response.xml +10 -0
  43. data/spec/fixtures/user/clear_user_pin_response.xml +10 -0
  44. data/spec/fixtures/user/create_user_response.xml +9 -0
  45. data/spec/fixtures/user/delete_user_response.xml +10 -0
  46. data/spec/fixtures/user/get_temp_pass_attr_response.xml +14 -0
  47. data/spec/fixtures/user/remove_credential_response.xml +10 -0
  48. data/spec/fixtures/user/set_temp_pass_attr_response.xml +10 -0
  49. data/spec/fixtures/user/set_temp_pass_response.xml +11 -0
  50. data/spec/fixtures/user/update_credential_response.xml +10 -0
  51. data/spec/fixtures/user/update_user_response.xml +10 -0
  52. data/spec/fixtures/wsdl/vipuserservices-1.7.xsd +1015 -0
  53. data/spec/fixtures/wsdl/vipuserservices-auth-1.7.wsdl +155 -0
  54. data/spec/fixtures/wsdl/vipuserservices-mgmt-1.7.wsdl +246 -0
  55. data/spec/fixtures/wsdl/vipuserservices-query-1.7.wsdl +114 -0
  56. data/spec/push_spec.rb +148 -0
  57. data/spec/sms_spec.rb +84 -0
  58. data/spec/soteria_spec.rb +8 -0
  59. data/spec/spec_helper.rb +2 -0
  60. data/spec/user_spec.rb +245 -0
  61. metadata +206 -0
@@ -0,0 +1,154 @@
1
+ module Soteria
2
+
3
+ class Credential
4
+
5
+
6
+ def get_return_hash(response_hash)
7
+ success = response_hash[:status] == '0000'
8
+
9
+ {
10
+ success: success,
11
+ message: response_hash[:status_message],
12
+ id: response_hash[:request_id],
13
+ auth_id: response_hash[:authn_id],
14
+ detail: response_hash[:detail_message]
15
+ }
16
+ end
17
+
18
+
19
+ # Authenticate a user with a credential. A credential includes a physical token, the desktop VIP credential app or
20
+ # the mobile VIP credential app. Users must link their credential id to their user id for this authentication to work.
21
+ #
22
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP authentication WSDL.
23
+ # @param [String] user_id Id of the user to authenticate. This is the user id that is stored in the Symantec db.
24
+ # @param [String] credential_code The code from the users credential that was entered into the website.
25
+ # @return [Hash] A hash with information on if the authentication was successful.
26
+ def authenticate_user_credential(client, user_id, credential_code)
27
+ result = client.call(:authenticate_user,
28
+ message: {
29
+ 'vip:requestId': Utilities.get_request_id('authenticate_user_credential'),
30
+ 'vip:userId': user_id,
31
+ 'vip:otpAuthData':
32
+ {
33
+ 'vip:otp': credential_code
34
+ }
35
+ })
36
+
37
+ get_return_hash(result.body[:authenticate_user_response])
38
+
39
+ end
40
+
41
+
42
+ # Create the body for the authenticate credentials request.
43
+ #
44
+ # @param [Integer] otp The One Time Password to check if valid.
45
+ # @param [Array] credentials An array of hashes, with between 1 and 5 credentials. Each hash should contain 2 values :id - the id of the credential and :type - the type of the credential.
46
+ # @return [Hash] A hash representing the request body for the authenticate credentials request.
47
+ def get_auth_body(otp, credentials)
48
+
49
+ credential_array = []
50
+
51
+ credentials.each do |credential|
52
+ credential_array.push({'vip:credentialId': credential[:id], 'vip:credentialType': credential[:type]})
53
+ end
54
+
55
+ {
56
+ 'vip:requestId': Utilities.get_request_id('authenticate_credentials'),
57
+ 'vip:credentials': credential_array,
58
+ 'vip:otpAuthData': {
59
+ 'vip:otp': otp
60
+ }
61
+ }
62
+
63
+ end
64
+
65
+
66
+ # Check if a otp is valid for a given credential.
67
+ #
68
+ # @param [Integer] otp The One Time Password to check if valid.
69
+ # @param [Array] credentials An array of hashes, with between 1 and 5 credentials. Each hash should contain 2 values :id - the id of the credential and :type - the type of the credential.
70
+ # @see CredentialTypes
71
+ # @return [Hash] A hash with all information about if the otp was successful
72
+ def authenticate_credentials(client, otp, credentials)
73
+ result = client.call(:authenticate_credentials, message: get_auth_body(otp, credentials))
74
+ get_return_hash(result.body[:authenticate_credentials_response])
75
+ end
76
+
77
+
78
+ # Register a SMS credential to the VIP Account. This must be done before you can add a SMS credential to a user.
79
+ #
80
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
81
+ # @param [Object] phone_number The phone number to register.
82
+ def register_sms(client, phone_number)
83
+ result = client.call(:register, message: {
84
+ 'vip:requestId': Utilities.get_request_id('register_credential'),
85
+ 'vip:smsDeliveryInfo': {
86
+ 'vip:phoneNumber': phone_number
87
+ }
88
+ } )
89
+
90
+ get_return_hash(result.body[:register_response])
91
+ end
92
+
93
+
94
+ # Use getCredentialInfo to get the credential that was last bound to the user, When the credential was last authenticated and
95
+ # the friendly name for the credential.
96
+ #
97
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP query WSDL.
98
+ # @param [String] credential_id The unique ID for the credential.
99
+ # @param [String] credential_type The type of the credential.
100
+ # @param [Boolean] include_push If this flag is present and set to be true, the response contains all the push attributes in the field pushAttributes.
101
+ # @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes. Also contains :credential which is a hash with info about the credential.
102
+ def get_credential_info(client, credential_id, credential_type, include_push)
103
+ message = {
104
+ 'vip:requestId': Utilities.get_request_id('get_credential_info'),
105
+ 'vip:credentialId': credential_id,
106
+ 'vip:credentialType': credential_type
107
+ }
108
+
109
+ unless include_push == nil
110
+ message[:'vip:includePushAttributes'] = include_push
111
+ end
112
+
113
+ response = client.call(:get_credential_info, message: message)
114
+ response_hash = response.body[:get_credential_info_response]
115
+
116
+ ret = get_return_hash(response_hash)
117
+
118
+ # get the credential info
119
+ credential = {
120
+ id: response_hash[:credential_id],
121
+ type: response_hash[:credential_type],
122
+ enabled: response_hash[:credential_status] == 'ENABLED'
123
+ }
124
+
125
+ # add the bindings if they exist
126
+ unless response_hash[:num_bindings] == '0'
127
+ credential[:user_binding] = response_hash[:user_binding_detail]
128
+ end
129
+
130
+ ret[:credential] = credential
131
+
132
+ ret
133
+ end
134
+
135
+
136
+ # Use getServerTime to obtain the current server time.
137
+ #
138
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP query WSDL.
139
+ # @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes. Also contains :time which is current server time.
140
+ def get_server_time(client)
141
+ response = client.call(:get_server_time, message: {'vip:requestId': Utilities.get_request_id('get_server_time')})
142
+ response_body = response.body[:get_server_time_response]
143
+ ret = get_return_hash(response_body)
144
+
145
+ unless response_body[:timestamp] == nil
146
+ ret[:time] = response_body[:timestamp]
147
+ end
148
+
149
+ ret
150
+ end
151
+
152
+ end
153
+
154
+ end
@@ -0,0 +1,13 @@
1
+ module Soteria
2
+
3
+ class CredentialTypes
4
+
5
+ STANDARD = 'STANDARD_OTP'
6
+ CERTIFICATE = 'CERTIFICATE'
7
+ SMS = 'SMS_OTP'
8
+ VOICE = 'VOICE_OTP'
9
+ SERVICE = 'SERVICE_OTP'
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,141 @@
1
+ require_relative 'utilities'
2
+ module Soteria
3
+
4
+ class Push
5
+
6
+
7
+ # Creates the body for a send push request.
8
+ #
9
+ # @param [String] user_id The id of the user to send the push to
10
+ # @param [Hash] options
11
+ # @return [Hash] A hash representing the body of the soap request to send a push notification.
12
+ def get_push_request_body(user_id, options)
13
+
14
+ # add in required values
15
+ message = {
16
+ 'vip:requestId': Utilities.get_request_id('send_push_request'),
17
+ 'vip:userId': user_id,
18
+ }
19
+
20
+ # no extra options so set the push auth data to nothing
21
+ # and return the body
22
+ if options == nil
23
+ message[:'vip:pushAuthData'] = ''
24
+ return message
25
+ end
26
+
27
+ #check if the user passed a pin, if so add it
28
+ if options.key?(:pin)
29
+ message[:'vip:pin'] = options[:pin]
30
+ end
31
+
32
+ # check for all push auth data options and add them
33
+ if options.key?(:title) || options.key?(:message) || options.key?(:profile) || options.key?(:time_out)
34
+ inner = []
35
+ if options.key?(:title)
36
+ inner.push({'vip:Key': 'display.message.title', 'vip:Value': options[:title]})
37
+ end
38
+ if options.key?(:message)
39
+ inner.push({'vip:Key': 'display.message.text', 'vip:Value': options[:message]})
40
+ end
41
+ if options.key?(:profile)
42
+ inner.push({'vip:Key': 'display.message.profile', 'vip:Value': options[:profile]})
43
+ end
44
+
45
+ # Add the options to the push auth data
46
+ if options.key?(:time_out)
47
+ message[:'vip:pushAuthData'] = {
48
+ 'vip:displayParameters': inner,
49
+ 'vip:requestParameters':
50
+ {
51
+ 'vip:Key': 'request.timeout',
52
+ 'vip:Value': options[:time_out]
53
+ }
54
+ }
55
+
56
+ else
57
+ message[:'vip:pushAuthData'] = {'vip:displayParameters': inner}
58
+ end
59
+
60
+ else
61
+ # dont add any push auth data
62
+ message[:'vip:pushAuthData'] = ''
63
+ end
64
+
65
+ # if options.key?(:level)
66
+ # message['authContext'] = {'params': {'Key': 'authLevel.level', 'Value': options[:level]}}
67
+ # end
68
+
69
+ message
70
+ end
71
+
72
+
73
+ # Send a push notification to the specified user for authentication.
74
+ #
75
+ # @param [Savon::Client] client A Savon client object to make the call with.
76
+ # @see Savon::Client
77
+ # @param [String] user_id The id of the user to send the push to
78
+ # @param [Hash] options
79
+ def send_push(client, user_id, options)
80
+
81
+ # get the body of the request
82
+ request_body = get_push_request_body(user_id, options)
83
+ push_res = client.call(:authenticate_user_with_push, message: request_body)
84
+ result_hash = push_res.body[:authenticate_user_with_push_response]
85
+
86
+ # 6040 is the status code for a push being sent, any other code the push was not sent
87
+ success = result_hash[:status] == '6040'
88
+
89
+ {
90
+ success: success,
91
+ id: result_hash[:request_id],
92
+ transaction_id: result_hash[:transaction_id],
93
+ message: result_hash[:status_message]
94
+ }
95
+
96
+ end
97
+
98
+
99
+ # Polls for the status of the push notification. This is necessary because VIP does not have push support.
100
+ # This will poll until the response is no longer push in progress, then it will return a hash with the results.
101
+ #
102
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP query WSDL.
103
+ # @param [String] transaction_id The id of the push transaction. id is in the hash returned from the send_push call
104
+ # @param [Int] interval An integer value in seconds that is the interval between polling VIP Services for a push response.
105
+ # @param [Int] time_out An integer value in seconds that is the timeout for polling. This should match the timeout that was set for the push message.
106
+ # @return [Hash] A hash with information on if the authentication was successful.
107
+ def poll_for_response(client, transaction_id, interval, time_out)
108
+
109
+ 1.upto(time_out/interval) do
110
+
111
+ response = client.call(:poll_push_status,
112
+ message: {
113
+ 'vip:requestId': Utilities.get_request_id("poll_push_status"),
114
+ 'vip:transactionId': transaction_id
115
+ })
116
+
117
+ # The status of the push is called transaciton status
118
+ transaction_status = response.body[:poll_push_status_response][:transaction_status]
119
+ call_status = response.body[:poll_push_status_response]
120
+
121
+ # 7001 is in progress so we are waiting for that to change
122
+ if transaction_status[:status] != '7001'
123
+
124
+ success = transaction_status[:status] == '7000'
125
+ return {
126
+ success: success,
127
+ message: transaction_status[:status_message],
128
+ id: call_status[:request_id]
129
+ }
130
+
131
+ end
132
+
133
+ sleep interval
134
+
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+
141
+ end
@@ -0,0 +1,81 @@
1
+ module Soteria
2
+
3
+ class SMS
4
+
5
+
6
+ # Creates the body for a send SMS otp request.
7
+ #
8
+ # @param [String] user_id Id of the user to authenticate. This is the user id that is stored in the Symantec database.
9
+ # @param [Int] phone_number The phone number that the sms code should be sent to.
10
+ # @return [Hash] A hash with all information about if the otp was successful.
11
+ def create_send_sms_body(user_id, phone_number)
12
+ {
13
+ 'vip:requestId': Utilities.get_request_id('send_sms_otp'),
14
+ 'vip:userId': user_id,
15
+ 'vip:smsDeliveryInfo':
16
+ {
17
+ 'vip:phoneNumber': phone_number
18
+ }
19
+ }
20
+ end
21
+
22
+
23
+ # Send a sms One Time Password to a user.
24
+ #
25
+ # @param [String] user_id Id of the user to authenticate. This is the user id that is stored in the Symantec database.
26
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
27
+ # @param [Int] phone_number The phone number that the sms code should be sent to.
28
+ # @return [Hash] A hash with all the appropriate information about the status of the SMS.
29
+ def send_sms(client, user_id, phone_number)
30
+ sms_res = client.call(:send_otp, message: create_send_sms_body(user_id, phone_number))
31
+ result_hash = sms_res.body[:send_otp_response]
32
+ success = result_hash[:status] == '0000'
33
+
34
+ {
35
+ success: success,
36
+ id: result_hash[:request_id],
37
+ message: result_hash[:status_message]
38
+ }
39
+ end
40
+
41
+
42
+ # Creates the body for a check otp request.
43
+ #
44
+ # @param [String] user_id Id of the user to authenticate. This is the user id that is stored in the Symantec db.
45
+ # @param [Object] otp The otp that was sent to the user via sms or voice
46
+ # @return [Hash] A hash representing the body of the soap request to check if an otp is valid.
47
+ def create_check_otp_body(user_id, otp)
48
+ {
49
+ 'vip:requestId': Utilities.get_request_id('check_sms_otp'),
50
+ 'vip:userId': user_id,
51
+ 'vip:otpAuthData':
52
+ {
53
+ 'vip:otp': otp
54
+ }
55
+ }
56
+ end
57
+
58
+
59
+ # Check if the otp that a user entered is valid or not.
60
+ #
61
+ # @param [String] user_id Id of the user to authenticate. This is the user id that is stored in the Symantec db.
62
+ # @param [Object] otp The otp that was sent to the user via sms or voice
63
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP authentication WSDL.
64
+ # @return [Hash] A hash with all information about if the otp was successful
65
+ def check_otp(client, user_id, otp)
66
+ check_otp_response = client.call(:check_otp, message: create_check_otp_body(user_id, otp))
67
+ result_hash = check_otp_response.body[:check_otp_response]
68
+
69
+ success = result_hash[:status] == '0000'
70
+
71
+ {
72
+ success: success,
73
+ id: result_hash[:request_id],
74
+ message: result_hash[:status_message]
75
+ }
76
+ end
77
+
78
+
79
+ end
80
+
81
+ end
@@ -0,0 +1,409 @@
1
+ module Soteria
2
+
3
+ class User
4
+
5
+
6
+ # Add a new user to the list of users in Symantec VIP database.
7
+ #
8
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
9
+ # @param [String] user_id Id of the user to create.
10
+ # @param [String] pin an optional value that is a pin for the user. The PIN may be 4 to 128 international characters in length, depending on restrictions of the PIN policy.
11
+ # @return [Hash] A hash that contains: :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
12
+ def create(client, user_id, pin)
13
+ message = {
14
+ 'vip:requestId': Utilities.get_request_id('create_user'),
15
+ 'vip:userId': user_id
16
+ }
17
+
18
+ unless pin.nil?
19
+ message['vip:pin'] = pin
20
+ end
21
+
22
+ response = client.call(:create_user, message: message)
23
+
24
+ get_return_hash(response.body[:create_user_response])
25
+ end
26
+
27
+
28
+ # Delete a user from the database of Symantec VIP users.
29
+ #
30
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
31
+ # @param [String] user_id Id of the user to delete.
32
+ # @return [Hash] A hash that contains: :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
33
+ def delete(client, user_id)
34
+ response = client.call(:delete_user,
35
+ message: {
36
+ 'vip:requestId': Utilities.get_request_id('delete_user'),
37
+ 'vip:userId': user_id
38
+ })
39
+
40
+ get_return_hash(response.body[:delete_user_response])
41
+ end
42
+
43
+
44
+ # Creates the body for a add credential request.
45
+ #
46
+ # @param [String] user_id Id of the user to add a credential to.
47
+ # @param [String] credential_id
48
+ # @param [String] credential_type must be one of the keys to the credential types from the Utilities class.
49
+ # @see Utilities::CREDENTIAL_TYPES
50
+ # @param [Hash] options A hash that can contain the following. :name adds a friendly name to the credential added to vip, :otp sends a otp from the credential with the request to verify that the user actually has possession of the credential
51
+ # @return [Hash] A hash representing the body of the soap request to add a credential.
52
+ def get_add_credential_message(user_id, credential_id, credential_type, options)
53
+ message = {
54
+ 'vip:requestId': Utilities.get_request_id('add_credential'),
55
+ 'vip:userId': user_id
56
+ }
57
+
58
+ credential_detail = {
59
+ 'vip:credentialId': credential_id,
60
+ 'vip:credentialType': credential_type
61
+ }
62
+
63
+ unless options == nil
64
+ if options.key?(:name)
65
+ credential_detail[:'vip:friendlyName'] = options[:name]
66
+ end
67
+
68
+ if options.key?(:otp)
69
+ message[:'vip:otpAuthData'] = {
70
+ 'vip:otp': options[:otp]
71
+ }
72
+ end
73
+ end
74
+
75
+ message[:'vip:credentialDetail'] = credential_detail
76
+
77
+ message
78
+ end
79
+
80
+
81
+ # Add a credential to an existing user in the Symantec VIP database.
82
+ #
83
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
84
+ # @param [String] user_id Id of the user to add a credential to.
85
+ # @param [String] credential_id Unique identifier of the credential.
86
+ # @param [String] credential_type must be one of the keys to the credential types from the Utilities class.
87
+ # @see Utilities::CREDENTIAL_TYPES
88
+ # @param [Hash] options A hash that can contain the following. :name adds a friendly name to the credential added to vip, :otp sends a otp from the credential with the request to verify that the user actually has possession of the credential
89
+ # @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
90
+ def add_credential(client, user_id, credential_id, credential_type, options)
91
+ response = client.call(:add_credential, message: get_add_credential_message(user_id, credential_id, credential_type, options))
92
+ get_return_hash(response.body[:add_credential_response])
93
+ end
94
+
95
+
96
+ # Remove a credential from a given user. If the Device deletion policy for Remembered Devices is set to Admin Only,
97
+ # credentials can only be removed through VIP Manager. The removeCredential API will return the error 6010: This
98
+ # account is not authorized to perform the requested operation
99
+ #
100
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
101
+ # @param [String] user_id Id of the user to remove a credential from.
102
+ # @param [String] credential_id Unique identifier of the credential.
103
+ # @param [String] credential_type must be one of the keys to the credential types from the Utilities class.
104
+ # @see Utilities::CREDENTIAL_TYPES
105
+ # @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
106
+ def remove_credential(client, user_id, credential_id, credential_type)
107
+ response = client.call(:remove_credential, message: {
108
+ 'vip:requestId': Utilities.get_request_id('remove_credential'),
109
+ 'vip:userId': user_id,
110
+ 'vip:credentialId': credential_id,
111
+ 'vip:credentialType': credential_type
112
+ })
113
+
114
+ get_return_hash(response.body[:remove_credential_response])
115
+ end
116
+
117
+
118
+ # Updates the friendly name of a users credential.
119
+ #
120
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
121
+ # @param [String] user_id Id of the user to remove a credential from.
122
+ # @param [String] credential_id Unique identifier of the credential.
123
+ # @param [String] credential_type must be one of the keys to the credential types from the Utilities class.
124
+ # @see Utilities::CREDENTIAL_TYPES
125
+ # @param [Object] name A user-defined name to identify the credential.
126
+ # @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
127
+ def update_credential(client, user_id, credential_id, credential_type, name)
128
+ response = client.call(:update_credential, message: {
129
+ 'vip:requestId': Utilities.get_request_id('update_credential'),
130
+ 'vip:userId': user_id,
131
+ 'vip:credentialId': credential_id,
132
+ 'vip:credentialType': credential_type,
133
+ 'vip:friendlyName': name
134
+ })
135
+
136
+ get_return_hash(response.body[:update_credential_response])
137
+ end
138
+
139
+
140
+ # Get all the credentials that have been last bound to a user or the last authentication, as well as the friendly
141
+ # name for the user's credential.
142
+ #
143
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP query WSDL.
144
+ # @param [String] user_id Id of the user to get information about.
145
+ # @param [Boolean] include_push If the users push details should be returned.
146
+ # @return [Hash] A hash that contains; :credentials a array of credentials available, :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
147
+ def get_user_info(client, user_id, include_push)
148
+ response = client.call(:get_user_info, message: {
149
+ 'vip:requestId': Utilities.get_request_id('get_user_info'),
150
+ 'vip:userId': user_id,
151
+ 'vip:includePushAttributes': include_push
152
+ })
153
+
154
+ response_hash = response.body[:get_user_info_response]
155
+
156
+ credentials = []
157
+
158
+ if response_hash[:num_bindings] == nil || response_hash[:num_bindings] == '0'
159
+ credentials = nil
160
+
161
+ else
162
+ response_hash[:credential_binding_detail].each do |credential|
163
+
164
+ bind_detail = credential[:binding_detail]
165
+
166
+ if credential[:credential_type] == 'STANDARD_OTP'
167
+ push_attrs = credential[:push_attributes]
168
+ credentials.push({
169
+ type: 'STANDARD_OTP',
170
+ enabled: response_hash[:credential_status] == 'ENABLED' && bind_detail[:bind_status] == 'ENABLED',
171
+ friendly_name: bind_detail[:friendly_name],
172
+ push: push_check(push_attrs),
173
+ credential_id: credential[:credential_id]
174
+ })
175
+
176
+ elsif credential[:credential_type] == 'SMS_OTP'
177
+ credentials.push({
178
+ type: 'SMS_OTP',
179
+ enabled: response_hash[:credential_status] == 'ENABLED' && bind_detail[:bind_status] == 'ENABLED',
180
+ friendly_name: bind_detail[:friendly_name],
181
+ push: false,
182
+ credential_id: credential[:credential_id]
183
+ })
184
+ elsif credential[:credential_type] == 'VOICE_OTP'
185
+ credentials.push({
186
+ type: 'VOICE_OTP',
187
+ enabled: response_hash[:credential_status] == 'ENABLED' && bind_detail[:bind_status] == 'ENABLED',
188
+ friendly_name: bind_detail[:friendly_name],
189
+ push: false,
190
+ credential_id: credential[:credential_id]
191
+ })
192
+ end
193
+
194
+ end
195
+
196
+ end
197
+
198
+ ret = get_return_hash(response_hash)
199
+ ret[:credentials] = credentials
200
+ ret
201
+ end
202
+
203
+
204
+ # Use updateUser to update information about a user in VIP User Services.
205
+ #
206
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
207
+ # @param [String] user_id The unique ID for the user.
208
+ # @param [Object] options
209
+ # @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
210
+ def update_user(client, user_id, options)
211
+ message = {
212
+ 'vip:requestId': Utilities.get_request_id('update_user'),
213
+ 'vip:userId': user_id
214
+ }
215
+
216
+ unless options == nil
217
+ if options.key?(:newId)
218
+ message[:'vip:newUserId'] = options[:newId]
219
+ end
220
+
221
+ if options.key?(:status)
222
+ message[:'vip:newUserStatus'] = options[:status]
223
+ end
224
+
225
+ if options.key?(:oldPin)
226
+ message[:'vip:oldPin'] = options[:oldPin]
227
+ end
228
+
229
+ if options.key?(:newPin)
230
+ message[:'vip:newPin'] = options[:newPin]
231
+ end
232
+
233
+ if options.key?(:pinReset)
234
+ message[:'vip:forcePinReset'] = options[:pinReset]
235
+ end
236
+
237
+ end
238
+
239
+ response = client.call(:update_user, message: message)
240
+ get_return_hash(response.body[:update_user_response])
241
+ end
242
+
243
+
244
+ # Use clearUserPin to remove an assigned PIN from a user.
245
+ #
246
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
247
+ # @param [String] user_id The unique ID for the user.
248
+ # @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
249
+ def clear_user_pin(client, user_id)
250
+ response = client.call(:clear_user_pin, message: {
251
+ 'vip:requestId': Utilities.get_request_id('clear_pin'),
252
+ 'vip:userId': user_id
253
+ })
254
+
255
+ get_return_hash(response.body[:clear_user_pin_response])
256
+ end
257
+
258
+
259
+ # Use setTemporaryPasswordAttributes to change the expiration date for a temporary security code you previously set.
260
+ #
261
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
262
+ # @param [String] user_id The unique ID for the user.
263
+ # @param [Object] options
264
+ # @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
265
+ def set_temp_pass_attr(client, user_id, options)
266
+ message = {
267
+ 'vip:requestId': Utilities.get_request_id('set_temp_pass_attr'),
268
+ 'vip:userId': user_id
269
+ }
270
+
271
+ unless options == nil
272
+ inner = {}
273
+ if options.key?(:oneTime)
274
+ inner[:'vip:oneTimeUseOnly'] = options[:oneTime]
275
+ end
276
+
277
+ if options.key?(:expireTime)
278
+ inner[:'vip:expirationTime'] = options[:expireTime]
279
+ end
280
+
281
+ message[:'vip:temporaryPasswordAttributes'] = inner
282
+ end
283
+
284
+ response = client.call(:set_temporary_password_attributes, message: message)
285
+ get_return_hash(response.body[:set_temporary_password_attributes_response])
286
+ end
287
+
288
+
289
+ # Use getTemporaryPasswordAttributes to poll VIP User Services every three to five seconds to check the status of a
290
+ # push notification. The push notification is validated against the notification’s unique transaction ID.
291
+ #
292
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP query WSDL.
293
+ # @param [String] user_id The unique ID for the user.
294
+ # @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
295
+ def get_temp_pass_attr(client, user_id)
296
+ response = client.call(:get_temporary_password_attributes, message: {
297
+ 'vip:requestId': Utilities.get_request_id('get_temp_pass_attr'),
298
+ 'vip:userId': user_id
299
+ })
300
+ response_hash = response.body[:get_temporary_password_attributes_response]
301
+
302
+ ret = get_return_hash(response_hash)
303
+
304
+ unless response_hash[:temp_pwd_attributes] == nil
305
+ ret[:oneTime] = response_hash[:temp_pwd_attributes][:one_time_use_only]
306
+ ret[:expiration] = response_hash[:temp_pwd_attributes][:expiration_time]
307
+ end
308
+
309
+ ret
310
+ end
311
+
312
+
313
+ # Use setTemporaryPassword to set a temporary security code for a user. You can optionally set an
314
+ # expiration date for the security code, or set it for one-time use only. The request requires the user ID and
315
+ # optionally, the temporary security code string. If you do not provide a security code, VIP User Services generates
316
+ # one for you.
317
+ #
318
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
319
+ # @param [String] user_id The unique ID for the user.
320
+ # @param [Int] phone The phone or mobile device number to which the VIP User Service should deliver the security code.
321
+ # @param [Hash] options
322
+ # @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
323
+ def set_temp_password(client, user_id, phone, options)
324
+ message = {
325
+ 'vip:requestId': Utilities.get_request_id('set_temp_pass'),
326
+ 'vip:userId': user_id
327
+ }
328
+
329
+ phone_options = {'vip:phoneNumber': phone}
330
+
331
+ unless options == nil
332
+ if options.key?(:otp)
333
+ message[:'vip:temporaryPassword'] = options[:otp]
334
+ end
335
+
336
+ if options.key?(:expireTime)
337
+ message[:'vip:expirationTime'] = options[:expireTime]
338
+ end
339
+
340
+ if options.key?(:oneTime)
341
+ message[:'vip:temporaryPasswordAttributes'] = { 'vip:oneTimeUseOnly': options[:oneTime] }
342
+ end
343
+
344
+ if options.key?(:from)
345
+ phone_options[:'vip:expirationTime'] = options[:from]
346
+ end
347
+ end
348
+
349
+ message[:'vip:smsDeliveryInfo'] = phone_options
350
+
351
+ response = client.call(:set_temporary_password, message: message)
352
+
353
+ ret = get_return_hash(response.body[:set_temporary_password_response])
354
+ ret[:password] = response.body[:set_temporary_password_response][:temporary_password]
355
+
356
+ ret
357
+ end
358
+
359
+
360
+ # Use clearTemporaryPassword to add users to VIP User Services.to remove a temporary security code from a user. If the
361
+ # user attempts to use a temporary security that has been cleared, VIP User Services returns an error stating the
362
+ # security code is not set. If the user validates a security code using a valid credential, any temporary security
363
+ # code that is set for that user is automatically cleared.
364
+ #
365
+ # @param [Savon::Client] client A Savon client object to make the call with. This needs to be created with the VIP management WSDL.
366
+ # @param [String] user_id The unique ID for the user.
367
+ # @return [Hash] A hash that contains; :success a boolean if the call succeeded, :message a string with any error message, :id the id of the call for debugging purposes
368
+ def clear_temp_pass(client, user_id)
369
+ message = {
370
+ 'vip:requestId': Utilities.get_request_id('clear_temp_pass'),
371
+ 'vip:userId': user_id
372
+ }
373
+
374
+ response = client.call(:clear_temporary_password, message: message)
375
+ get_return_hash(response.body[:clear_temporary_password_response])
376
+ end
377
+
378
+
379
+ # Helper function to loop through an array of hashes with key value pairs and return if push is enabled.
380
+ #
381
+ # @param [Array] attrs A array of hash attributes
382
+ # @return [Boolean] If push is enabled for the give attributes
383
+ def push_check(attrs)
384
+ attrs.each do |a|
385
+ if a[:key] == 'PUSH_ENABLED'
386
+ return a[:value]
387
+ end
388
+ end
389
+ false
390
+ end
391
+
392
+
393
+ # Helper function to create the hash to return. All user calls have the same return values.
394
+ #
395
+ # @param [Hash] response_hash
396
+ # @return [Hash] A hash with the appropriate values. Included are: :success - a boolean if the operation was successful,
397
+ def get_return_hash(response_hash)
398
+ success = response_hash[:status] == '0000'
399
+
400
+ {
401
+ success: success,
402
+ message: response_hash[:status_message],
403
+ id: response_hash[:request_id]
404
+ }
405
+ end
406
+
407
+ end
408
+
409
+ end