cpaas-sdk 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,10 @@
1
- require 'dotenv'
2
- require 'rubygems'
3
- require 'bundler'
4
-
5
- require './app'
6
-
7
- Bundler.require
8
- Dotenv.load
9
-
10
- run App
1
+ require 'dotenv'
2
+ require 'rubygems'
3
+ require 'bundler'
4
+
5
+ require './app'
6
+
7
+ Bundler.require
8
+ Dotenv.load
9
+
10
+ run App
@@ -1,37 +1,37 @@
1
- def valid_credentials?(params)
2
- ENV['EMAIL'] == params['email'] && ENV['PASSWORD'] == params['password']
3
- end
4
-
5
- def error_message(error)
6
- "#{error[:name]}: #{error[:message]} (#{error[:exception_id]})"
7
- end
8
-
9
- def set_credentials_verified(session)
10
- session[:credentials_verified] = true
11
- session[:code_verified] = false
12
- end
13
-
14
- def is_credentials_verified?(session)
15
- session[:credentials_verified] && !session[:code_verified]
16
- end
17
-
18
- def is_logged_in?(session)
19
- session[:credentials_verified] && session[:code_verified]
20
- end
21
-
22
- def logout(session)
23
- session[:credentials_verified] = true
24
- session[:code_verified] = false
25
- session[:code_id] = nil
26
- end
27
-
28
- def set_default_state(session)
29
- session[:credentials_verified] = false
30
- session[:code_verified] = false
31
- end
32
-
33
-
34
- def login(session)
35
- session[:credentials_verified] = true
36
- session[:code_verified] = true
37
- end
1
+ def valid_credentials?(params)
2
+ ENV['EMAIL'] == params['email'] && ENV['PASSWORD'] == params['password']
3
+ end
4
+
5
+ def error_message(error)
6
+ "#{error[:name]}: #{error[:message]} (#{error[:exception_id]})"
7
+ end
8
+
9
+ def set_credentials_verified(session)
10
+ session[:credentials_verified] = true
11
+ session[:code_verified] = false
12
+ end
13
+
14
+ def is_credentials_verified?(session)
15
+ session[:credentials_verified] && !session[:code_verified]
16
+ end
17
+
18
+ def is_logged_in?(session)
19
+ session[:credentials_verified] && session[:code_verified]
20
+ end
21
+
22
+ def logout(session)
23
+ session[:credentials_verified] = true
24
+ session[:code_verified] = false
25
+ session[:code_id] = nil
26
+ end
27
+
28
+ def set_default_state(session)
29
+ session[:credentials_verified] = false
30
+ session[:code_verified] = false
31
+ end
32
+
33
+
34
+ def login(session)
35
+ session[:credentials_verified] = true
36
+ session[:code_verified] = true
37
+ end
@@ -25,4 +25,10 @@ button {
25
25
  margin: 8px 0;
26
26
  padding: 14px 20px;
27
27
  width: 100%;
28
+ }
29
+
30
+ .verify-button {
31
+ display: block;
32
+ margin: 20px auto;
33
+ width: 50%;
28
34
  }
@@ -1,5 +1,5 @@
1
- <% if locals[:alert] %>
2
- <div class="alert alert-<%= alert[:type] %>">
3
- <p><%= alert[:message] %></p>
4
- </div>
1
+ <% if locals[:alert] %>
2
+ <div class="alert alert-<%= alert[:type] %>">
3
+ <p><%= alert[:message] %></p>
4
+ </div>
5
5
  <% end %>
@@ -1,4 +1,4 @@
1
- <form action="/logout" method="get" class="box centered-box">
2
- <p>You are now logged in.</p>
3
- <button type="submit">Logout</button>
4
- </form>
1
+ <form action="/logout" method="get" class="box centered-box">
2
+ <p>You are now logged in.</p>
3
+ <button type="submit">Logout</button>
4
+ </form>
@@ -1,17 +1,17 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
7
- <link rel="stylesheet" type="text/css" href="stylesheets/main.css">
8
- <title>2FA</title>
9
- </head>
10
- <body>
11
- <%= erb :alert, locals: locals %>
12
-
13
- <div class="main">
14
- <%= yield %>
15
- </div>
16
- </body>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
7
+ <link rel="stylesheet" type="text/css" href="stylesheets/main.css">
8
+ <title>2FA</title>
9
+ </head>
10
+ <body>
11
+ <%= erb :alert, locals: locals %>
12
+
13
+ <div class="main">
14
+ <%= yield %>
15
+ </div>
16
+ </body>
17
17
  </html>
@@ -1,13 +1,13 @@
1
- <form action="/login" method="post" class="box centered-box">
2
- <h2 class="text-center">Login</h2>
3
- <div class="input-group">
4
- <label for="email">Email</label>
5
- <input type="text" id="email" name="email" />
6
- </div>
7
- <div class="input-group">
8
- <label for="password">Password</label>
9
- <input type="password" id="password" name="password" />
10
- </div>
11
- <button type="submit">Login</button>
12
- </form>
13
-
1
+ <form action="/login" method="post" class="box centered-box">
2
+ <h2 class="text-center">Login</h2>
3
+ <div class="input-group">
4
+ <label for="email">Email</label>
5
+ <input type="text" id="email" name="email" />
6
+ </div>
7
+ <div class="input-group">
8
+ <label for="password">Password</label>
9
+ <input type="password" id="password" name="password" />
10
+ </div>
11
+ <button type="submit">Login</button>
12
+ </form>
13
+
@@ -1,8 +1,18 @@
1
- <form action="/verify" method="post" class="box centered-box">
2
- <h2 class="text-center">Verify</h2>
3
- <div class="input-group">
4
- <label for="code">Verification code</label>
5
- <input type="text" id="code" maxlength="6" name="code" />
6
- <button type="submit">Verify</button>
7
- </div>
8
- </form>
1
+ <div class="box centered-box">
2
+ <form action="/verify" method="post">
3
+ <h2 class="text-center">Verify</h2>
4
+ <div class="input-group">
5
+ <label for="code">Verification code</label>
6
+ <input type="text" id="code" maxlength="6" name="code" />
7
+ <button type="submit">Verify</button>
8
+ </div>
9
+ </form>
10
+ <hr>
11
+ <form action="/sendtwofactor" method="post">
12
+ <div class="input-group:nowrap">
13
+ <input type="radio" name="otp" value="sms" checked/> 2FA via sms
14
+ <input type="radio" name="otp" value="email" /> 2FA via email
15
+ <button class='verify-button' type="submit">Send 2FA</button>
16
+ </div>
17
+ </form>
18
+ </div>
@@ -11,20 +11,33 @@ module Cpaas
11
11
  #
12
12
  # Configure the SDK with client_id and client_secret.
13
13
  #
14
- # @param client_id [String] Private project secret
15
- # @param client_secret [String] Private project secret
16
- # @param base_url [String] JSON URL of the server to be used.
14
+ # @param client_id [String] Private project key / Account client ID. If Private project key is used then client_secret is mandatory. If account client ID is used then email and password are mandatory.
15
+ # @param base_url [String] URL of the server to be used.
16
+ # @param client_secret [String] +optional Private project secret
17
+ # @param email [String] +optional Account login email
18
+ # @param password [String] +optional Account login password
17
19
  #
18
20
  # @example
19
21
  # Cpaas.configure do |config|
20
- # config.client_id: '<private project key>',
21
- # config.client_secret: '<private project secret>',
22
- # config.base_url: '<base url>'
22
+ # config.client_id = '<private project key>'
23
+ # config.client_secret = '<private project secret>'
24
+ # config.base_url = 'https://$KANDYFQDN$'
23
25
  # end
24
26
  #
27
+ # # or
28
+ #
29
+ # Cpaas.configure do |config|
30
+ # config.client_id = '<account client ID>'
31
+ # config.email = '<account email>'
32
+ # config.password = '<account password>'
33
+ # config.base_url = 'https://$KANDYFQDN$'
34
+ # end
35
+
25
36
  def self.configure
26
37
  yield self.config = Cpaas::Config.new
27
38
 
39
+ config.validate
40
+
28
41
  self.api = Cpaas::Api.new(config)
29
42
  end
30
43
  end
@@ -12,12 +12,11 @@ module Cpaas
12
12
  attr_accessor :user_id, :client_correlator
13
13
 
14
14
  def initialize(config)
15
- @client_id = config.client_id
16
- @client_secret = config.client_secret
15
+ @config = config
17
16
  @id_token_parsed = nil
18
17
  @access_token = nil
19
- self.user_id = nil
20
- self.client_correlator = "#{config.client_id}-ruby"
18
+ @user_id = nil
19
+ @client_correlator = "#{config.client_id}-ruby"
21
20
 
22
21
  self.class.base_uri config.base_url
23
22
 
@@ -87,9 +86,7 @@ module Cpaas
87
86
  def get_auth_token
88
87
  options = {
89
88
  body: {
90
- grant_type: 'client_credentials',
91
- client_id: @client_id,
92
- client_secret: @client_secret,
89
+ client_id: @config.client_id,
93
90
  scope: 'openid'
94
91
  },
95
92
  headers: {
@@ -97,6 +94,21 @@ module Cpaas
97
94
  }
98
95
  }
99
96
 
97
+ if !@config.client_secret.nil?
98
+ credentials = {
99
+ grant_type: 'client_credentials',
100
+ client_secret: @config.client_secret
101
+ }
102
+ else
103
+ credentials = {
104
+ grant_type: 'password',
105
+ username: @config.email,
106
+ password: @config.password
107
+ }
108
+ end
109
+
110
+ options[:body].merge!(credentials)
111
+
100
112
  response = send_request('/cpaas/auth/v1/token', options, :post , false)
101
113
 
102
114
  process_response(response, false)
@@ -116,13 +128,13 @@ module Cpaas
116
128
  @access_token = nil
117
129
  @id_token = nil
118
130
  @id_token_parsed = nil
119
- @self.user_id = nil
131
+ @user_id = nil
120
132
  else
121
133
  @access_token = tokens[:access_token]
122
134
  @id_token = tokens[:id_token]
123
135
  @id_token_parsed = JWT.decode(tokens[:id_token], nil, false).first
124
136
  @token_parsed = JWT.decode(tokens[:access_token], nil, false).first
125
- self.user_id = @id_token_parsed['preferred_username']
137
+ @user_id = @id_token_parsed['preferred_username']
126
138
  end
127
139
  end
128
140
 
@@ -4,6 +4,16 @@ module Cpaas
4
4
  class Config
5
5
  attr_accessor :client_id
6
6
  attr_accessor :client_secret
7
+ attr_accessor :email
8
+ attr_accessor :password
7
9
  attr_accessor :base_url
10
+
11
+ def validate
12
+ raise ArgumentError.new('`client_id` cannot be nil') if client_id.nil?
13
+
14
+ raise ArgumentError.new('`clientSecret` or `email/password` cannot be nil') if client_secret.nil? && (email.nil? || password.nil?)
15
+
16
+ true
17
+ end
8
18
  end
9
19
  end
@@ -10,10 +10,10 @@ module Cpaas
10
10
  # Send a new outbound message
11
11
  #
12
12
  # @param params [Hash]
13
- # @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
13
+ # @option params [String] :type Type of conversation. Possible value(s) - 'sms'. Check Conversation.types for more options
14
14
  # @option params [String] :sender_address Sender address information, basically the from address. E164 formatted DID number passed as a value, which is owned by the user. If the user wants to let CPaaS uses the default assigned DID number, this field can either has "default" value or the same value as the userId.
15
- # @option params [Array[string]|String] :destination_address
16
- # @option params [String] :message text message
15
+ # @option params [Array[string]|String] :destination_address Indicates which DID number(s) used as destination for this SMS.
16
+ # @option params [String] :message SMS text message
17
17
  #
18
18
  def self.create_message(params)
19
19
  if params[:type] == types[:SMS]
@@ -48,7 +48,7 @@ module Cpaas
48
48
  # Gets all messages.
49
49
  #
50
50
  # @param params [Hash]
51
- # @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
51
+ # @option params [String] :type Type of conversation. Possible value(s) - 'sms'. Check Conversation.types for more options
52
52
  # @option params [String] :remote_address +optional+ Remote address information while retrieving the conversation history, basically the destination telephone number that user exchanged message before. E164 formatted DID number passed as a value.
53
53
  # @option params [String] :local_address +optional+ Local address information while retrieving the conversation history, basically the source telephone number that user exchanged message before.
54
54
  # @option params [String] :query[:name] +optional+ - Performs search operation on firstName and lastName fields.
@@ -89,7 +89,7 @@ module Cpaas
89
89
  # Delete conversation message
90
90
  #
91
91
  # @param params [Hash]
92
- # @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
92
+ # @option params [String] :type Type of conversation. Possible value(s) - 'sms'. Check Conversation.types for more options
93
93
  # @option params [String] :remote_address Remote address information while retrieving the conversation history, basically the destination telephone number that user exchanged message before. E164 formatted DID number passed as a value.
94
94
  # @option params [String] :local_address Local address information while retrieving the conversation history, basically the source telephone number that user exchanged message before.
95
95
  # @option params [String] :message_id +optional+ Identification of the message. If messeageId is not passsed then the conversation thread is deleted with all messages.
@@ -108,7 +108,7 @@ module Cpaas
108
108
  # Read all messages in a thread
109
109
  #
110
110
  # @param params [Hash]
111
- # @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
111
+ # @option params [String] :type Type of conversation. Possible value(s) - 'sms'. Check Conversation.types for more options
112
112
  # @option params [String] :remote_address Remote address information while retrieving the conversation history, basically the destination telephone number that user exchanged message before. E164 formatted DID number passed as a value.
113
113
  # @option params [String] :local_address Local address information while retrieving the conversation history, basically the source telephone number that user exchanged message before.
114
114
  # @option params [String] :query[:next] +optional+ - Pointer for the next page to retrieve for the messages, provided by CPaaS in previous GET response.
@@ -135,7 +135,7 @@ module Cpaas
135
135
  # Read a conversation message status
136
136
  #
137
137
  # @param params [Hash]
138
- # @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
138
+ # @option params [String] :type Type of conversation. Possible value(s) - 'sms'. Check Conversation.types for more options
139
139
  # @option params [String] :remote_address Remote address information while retrieving the conversation history, basically the destination telephone number that user exchanged message before. E164 formatted DID number passed as a value.
140
140
  # @option params [String] :local_address Local address information while retrieving the conversation history, basically the source telephone number that user exchanged message before.
141
141
  # @option params [String] :message_id Identification of the message. If messeageId is not passsed then the conversation thread is deleted with all messages.
@@ -149,7 +149,7 @@ module Cpaas
149
149
  #
150
150
  # Read all active subscriptions
151
151
  #
152
- # @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
152
+ # @option params [String] :type Type of conversation. Possible value(s) - 'sms'. Check Conversation.types for more options
153
153
  #
154
154
 
155
155
  def self.get_subscriptions(params)
@@ -173,7 +173,7 @@ module Cpaas
173
173
  # Read active subscription
174
174
  #
175
175
  # @param params [Hash]
176
- # @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
176
+ # @option params [String] :type Type of conversation. Possible value(s) - 'sms'. Check Conversation.types for more options
177
177
  # @option params [String] :subscription_id Resource ID of the subscription
178
178
  #
179
179
  def self.get_subscription(params)
@@ -196,8 +196,8 @@ module Cpaas
196
196
  # Create a new subscription
197
197
  #
198
198
  # @param params [Hash]
199
- # @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
200
- # @option params [String] :webhook_url The notification channel ID that has been acquired during /notificationchannel API subscription, either websockets, mobile push or webhooks type, which the incoming notifications supposed to be sent to.
199
+ # @option params [String] :type Type of conversation. Possible value(s) - 'sms'. Check Conversation.types for more options
200
+ # @option params [String] :webhook_url HTTPS URL that is present in your application server which is accessible from the public web where the notifications should be sent to. Note: Should be a POST endpoint.
201
201
  # @option params [String] :destination_address +optional+ The address that incoming messages are received for this subscription. If does not exist, CPaaS uses the default assigned DID number to subscribe against. It is suggested to provide the intended E164 formatted DID number within this parameter.
202
202
  #
203
203
 
@@ -235,6 +235,7 @@ module Cpaas
235
235
  # Unsubscription from conversation notification
236
236
  #
237
237
  # @param params [Hash]
238
+ # @option params [String] :type Type of conversation. Possible value(s) - 'sms'. Check Conversation.types for more options
238
239
  # @option params [String] :subscription_id Resource ID of the subscription.
239
240
  #
240
241
 
@@ -9,7 +9,7 @@ module Cpaas
9
9
  # Parse inbound sms notification received in webhook. It parses the notification and returns
10
10
  # simplified version of the response.
11
11
  #
12
- # @param notification [Hash] JSON received in the subscription webhook.
12
+ # @param notification [JSON] JSON received in the subscription webhook.
13
13
  #
14
14
  def self.parse(notification)
15
15
  parsed_notification = convert_hash_keys(notification)
@@ -3,7 +3,6 @@ require 'cpaas-sdk/util'
3
3
  module Cpaas
4
4
  ##
5
5
  # CPaaS provides Authentication API where a two-factor authentication (2FA) flow can be implemented by using that.
6
- # Sections below describe two sample use cases, two-factor authentication via SMS and two-factor authentication via e-mail
7
6
  #
8
7
 
9
8
  class Twofactor
@@ -22,26 +22,26 @@ def process_response(res, remove_outer_key = true)
22
22
  response
23
23
  end
24
24
 
25
- def compose_error_from(err_response)
26
- error_obj = deep_find(err_response, :message_id)
25
+ def compose_error_from(response)
26
+ error_obj = deep_find(response, :message_id)
27
27
 
28
28
  if (error_obj)
29
29
  message = error_obj[:text]
30
30
 
31
31
  error_obj[:variables].each_with_index { |variable, index| message.gsub!("%#{index + 1}", variable) }
32
32
 
33
- response = {
33
+ return {
34
34
  name: error_obj[:name],
35
35
  exception_id: error_obj[:message_id],
36
36
  message: message
37
37
  }
38
- else
39
- response = {
40
- name: err_response.keys.first,
41
- exception_id: 'Unknown',
42
- message: err_response[:message]
43
- }
44
38
  end
39
+
40
+
41
+ {
42
+ name: response[:error] || response.keys.first,
43
+ message: response[:error_description] || response[:message]
44
+ }
45
45
  end
46
46
 
47
47
  def id_from (url)