cpaas-sdk 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 (84) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +7 -0
  5. data/CHANGELOG.md +11 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.md +1 -0
  8. data/README.md +25 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/cpaas-sdk.gemspec +32 -0
  13. data/docs/Cpaas.html +446 -0
  14. data/docs/Cpaas/Conversation.html +1742 -0
  15. data/docs/Cpaas/Notification.html +301 -0
  16. data/docs/Cpaas/TwoFactor.html +908 -0
  17. data/docs/_index.html +146 -0
  18. data/docs/_index.md +21 -0
  19. data/docs/class_list.html +51 -0
  20. data/docs/css/common.css +1 -0
  21. data/docs/css/full_list.css +58 -0
  22. data/docs/css/style.css +496 -0
  23. data/docs/file.README.html +102 -0
  24. data/docs/file._index.html +94 -0
  25. data/docs/file_list.html +56 -0
  26. data/docs/frames.html +17 -0
  27. data/docs/index.html +94 -0
  28. data/docs/js/app.js +303 -0
  29. data/docs/js/full_list.js +216 -0
  30. data/docs/js/jquery.js +4 -0
  31. data/docs/method_list.html +251 -0
  32. data/docs/mv_index.html +102 -0
  33. data/docs/top-level-namespace.html +663 -0
  34. data/examples/2fa/.env.example +6 -0
  35. data/examples/2fa/.gitignore +159 -0
  36. data/examples/2fa/.ruby-gemset +1 -0
  37. data/examples/2fa/.ruby-version +1 -0
  38. data/examples/2fa/Gemfile +8 -0
  39. data/examples/2fa/README.md +34 -0
  40. data/examples/2fa/app.rb +134 -0
  41. data/examples/2fa/config.ru +10 -0
  42. data/examples/2fa/helper.rb +37 -0
  43. data/examples/2fa/public/stylesheets/forms.css +28 -0
  44. data/examples/2fa/public/stylesheets/global.css +7 -0
  45. data/examples/2fa/public/stylesheets/layout.css +45 -0
  46. data/examples/2fa/public/stylesheets/main.css +3 -0
  47. data/examples/2fa/views/alert.erb +5 -0
  48. data/examples/2fa/views/dashboard.erb +4 -0
  49. data/examples/2fa/views/index.erb +17 -0
  50. data/examples/2fa/views/login.erb +13 -0
  51. data/examples/2fa/views/verify.erb +8 -0
  52. data/examples/sms/.env.example +4 -0
  53. data/examples/sms/.gitignore +159 -0
  54. data/examples/sms/.ruby-gemset +1 -0
  55. data/examples/sms/.ruby-version +1 -0
  56. data/examples/sms/Gemfile +8 -0
  57. data/examples/sms/README.md +80 -0
  58. data/examples/sms/app.rb +87 -0
  59. data/examples/sms/config.ru +10 -0
  60. data/examples/sms/helper.rb +33 -0
  61. data/examples/sms/public/scripts/notification.js +46 -0
  62. data/examples/sms/public/stylesheets/forms.css +28 -0
  63. data/examples/sms/public/stylesheets/global.css +7 -0
  64. data/examples/sms/public/stylesheets/layout.css +74 -0
  65. data/examples/sms/public/stylesheets/main.css +3 -0
  66. data/examples/sms/views/alert.erb +5 -0
  67. data/examples/sms/views/index.erb +48 -0
  68. data/lib/cpaas-sdk.rb +30 -0
  69. data/lib/cpaas-sdk/api.rb +139 -0
  70. data/lib/cpaas-sdk/config.rb +9 -0
  71. data/lib/cpaas-sdk/resources.rb +4 -0
  72. data/lib/cpaas-sdk/resources/conversation.rb +268 -0
  73. data/lib/cpaas-sdk/resources/notification.rb +62 -0
  74. data/lib/cpaas-sdk/resources/notification_channel.rb +39 -0
  75. data/lib/cpaas-sdk/resources/twofactor.rb +136 -0
  76. data/lib/cpaas-sdk/util.rb +93 -0
  77. data/lib/cpaas-sdk/version.rb +3 -0
  78. data/tutorials/2FA.md +109 -0
  79. data/tutorials/2fa-flow.png +0 -0
  80. data/tutorials/GetStarted.md +86 -0
  81. data/tutorials/SMSMessaging.md +132 -0
  82. data/tutorials/index.html +86 -0
  83. data/tutorials/quickstarts.yml +15 -0
  84. metadata +238 -0
@@ -0,0 +1,3 @@
1
+ @import './global.css';
2
+ @import './layout.css';
3
+ @import './forms.css';
@@ -0,0 +1,5 @@
1
+ <% if locals[:alert] %>
2
+ <div class="alert alert-<%= alert[:type] %>">
3
+ <p><%= alert[:message] %></p>
4
+ </div>
5
+ <% end %>
@@ -0,0 +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>
@@ -0,0 +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>
17
+ </html>
@@ -0,0 +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
+
@@ -0,0 +1,8 @@
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>
@@ -0,0 +1,4 @@
1
+ CLIENT_ID=<Private project key>
2
+ CLIENT_SECRET=<Private project secret>
3
+ BASE_URL=
4
+ PHONE_NUMBER=
@@ -0,0 +1,159 @@
1
+ # Ignore the default SQLite database.
2
+ /db/*.sqlite3
3
+ /db/*.sqlite3-journal
4
+
5
+ # Ignore all logfiles and tempfiles.
6
+ /log/*
7
+ /tmp/*
8
+ !/log/.keep
9
+ !/tmp/.keep
10
+
11
+ # Ignore uploaded files in development
12
+ /storage/*
13
+ !/storage/.keep
14
+
15
+ .byebug_history
16
+
17
+ # Ignore master key for decrypting credentials and more.
18
+ /config/master.key
19
+
20
+ ## App-Specific
21
+
22
+ # Ignore the generated sample apps folder.
23
+ /public/sample_apps
24
+
25
+ *.pdf
26
+
27
+ # Ignore the generated csv folder
28
+ /public/csv
29
+
30
+ ## Capistrano
31
+
32
+ .env.staging
33
+ .env.production
34
+ .env.china
35
+ .env.developer
36
+
37
+ ## Rails
38
+
39
+ *.rbc
40
+ *.sassc
41
+ .sass-cache
42
+ capybara-*.html
43
+ .rspec
44
+ /log
45
+ /tmp
46
+ /db/*.sqlite3
47
+ /db/*.sqlite3-journal
48
+ /public/system
49
+ /public/assets
50
+ /public/uploads
51
+ /public/docs
52
+ /coverage/
53
+ /spec/tmp
54
+ rerun.txt
55
+ pickle-email-*.html
56
+ dump.rdb
57
+
58
+ ## Environment normalisation:
59
+ /.bundle
60
+ /vendor/bundle
61
+
62
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
63
+ .rvmrc
64
+
65
+ # if using bower-rails ignore default bower_components path bower.json files
66
+ /vendor/assets/bower_components
67
+ *.bowerrc
68
+ bower.json
69
+
70
+ # Ignore pow environment settings
71
+ .powenv
72
+
73
+ ## Documentation cache and generated files:
74
+ /.yardoc/
75
+ /_yardoc/
76
+ /doc/
77
+ /rdoc/
78
+
79
+ # Developer-specific files - These have a corresponding *.example file as a template to quickly copy over
80
+ config/database.yml
81
+ .env
82
+
83
+ ## General
84
+
85
+ # Git
86
+ **.orig
87
+
88
+ # OS X
89
+ .DS_Store
90
+ .DS_Store?
91
+ .AppleDouble
92
+ .LSOverride
93
+
94
+ # Icon must end with two \r
95
+ Icon
96
+
97
+
98
+ # Thumbnails
99
+ ._*
100
+
101
+ # Files that might appear on external disk
102
+ .Spotlight-V100
103
+ .Trashes
104
+
105
+ # Directories potentially created on remote AFP share
106
+ .AppleDB
107
+ .AppleDesktop
108
+ Network Trash Folder
109
+ Temporary Items
110
+ .apdisk
111
+
112
+ # Windows image file caches
113
+ Thumbs.db
114
+ ehthumbs.db
115
+
116
+ # Folder config file
117
+ Desktop.ini
118
+
119
+ # Recycle Bin used on file shares
120
+ $RECYCLE.BIN/
121
+
122
+ # Windows Installer files
123
+ *.cab
124
+ *.msi
125
+ *.msm
126
+ *.msp
127
+
128
+ # Windows shortcuts
129
+ *.lnk
130
+
131
+ # Compiled source
132
+ *.com
133
+ *.class
134
+ *.dll
135
+ *.exe
136
+ *.o
137
+ *.so
138
+
139
+ # Packages
140
+ # it's better to unpack these files and commit the raw source
141
+ # git has its own built in compression methods
142
+ *.7z
143
+ *.dmg
144
+ *.gz
145
+ *.iso
146
+ *.jar
147
+ *.rar
148
+ *.tar
149
+ *.zip
150
+
151
+ # Logs and databases
152
+ *.log
153
+ *.sql
154
+ *.sql-e
155
+ *.sqlite
156
+
157
+ # Files generated by atom
158
+ *.tags
159
+ *.tags_swap
@@ -0,0 +1 @@
1
+ kandy-sdk-example-sms
@@ -0,0 +1 @@
1
+ ruby-2.5.0
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'sinatra'
4
+ gem 'httparty'
5
+ gem 'dotenv'
6
+ gem 'rerun'
7
+ gem 'pry'
8
+ gem 'cpaas-sdk', path: './../../'
@@ -0,0 +1,80 @@
1
+ # SMS Starter Example
2
+
3
+ This is a simple sms application where a user can send an sms, subscribe sms notification and receive real-time sms events (inbound, outbound etc notification).
4
+
5
+ ## Installation
6
+ 1. Copy `.env.example` and rename to `.env` and add the appropriate values. Check `Configuration` section for more details.
7
+ 2. To install dependencies, run:
8
+ ```bash
9
+ bundle install
10
+ ```
11
+ 3. To start the server, run:
12
+ ```bash
13
+ bundle exec rackup -p 6000
14
+ ```
15
+
16
+ ## Configuration
17
+ There are a few environment variables (check `.env` file) to make the application simpler and help us focus on the key aspects a two-factor authentication system via SMS. Some of the variables are pre-filled and some are left blank which are left on the user to place appropriate values. All the variables are mandatory.
18
+
19
+ ENV KEY | Description
20
+ ------------- | -------------
21
+ CLIENT_ID | Private project key
22
+ CLIENT_SECRET | Private project secret
23
+ BASE_URL | URL of the CPaaS server to use
24
+ PHONE_NUMBER | Phone number purchased in CPaaS portal (sender phone number)
25
+
26
+ ## Usage
27
+ The application has a single simple page with 3 section:
28
+
29
+ ### Section 1 - Send SMS
30
+ ---
31
+ There are two fields in the form
32
+
33
+ 1. Phone number - The phone number where the SMS is to be sent.
34
+ 2. Message - A text message for the SMS
35
+
36
+ When clicked on `Send` button, an SMS is sent out where the `sender` phone number is the one add in `.env` file (PHONE_NUMBER) and `destination` is the one entered in the form.
37
+
38
+ ### Section 2 - SMS notification subscription
39
+ ---
40
+ This represents the subscription to SMS notification and can be found on the top right section. Here a Webhook host URL is to be added.
41
+
42
+ As incoming notifications are to be received by the local server, there is a requirement of a web server to be running and that web server to have a public IP address. So to use this it is recommended to install and use [ngrok](https://ngrok.com/).
43
+
44
+ #### How to use ngrok
45
+ Once `ngrok` is installed, run the following command
46
+ ```bash
47
+ ngrok http 3001
48
+ ```
49
+ 3001 is the `PORT` that is defined in the `.env` file, so it has to be entered appropriately.
50
+ Once `ngrok` starts forwarding the `localhost`, you would find a similar kind of message in your screen.
51
+
52
+ ```bash
53
+ ngrok by @inconshreveable (Ctrl+C to quit)
54
+
55
+ Session Status online
56
+ Session Expires 7 hours, 58 minutes
57
+ Update update available (version 2.3.34, Ctrl-U to update)
58
+ Version 2.3.28
59
+ Region United States (us)
60
+ Web Interface http://127.0.0.1:4040
61
+ Forwarding http://29de1e3e.ngrok.io -> http://localhost:3001
62
+ Forwarding https://29de1e3e.ngrok.io -> http://localhost:3001
63
+
64
+ Connections ttl opn rt1 rt5 p50 p90
65
+ 0 0 0.00 0.00 0.00 0.00
66
+ ```
67
+ After this the usage part of `ngrok` is done and we got out public domain, let's shift out attention to the notification subscription.
68
+
69
+ Copy the `forwarding` domain, for our case it is `https://29de1e3e.ngrok.io` from above and paste it to in the `Webhook host URL` input field in out `SMS starter app`.
70
+ Click `Subscribe` and a notification channel would be created with the above domain against the phone number that is described in the `.env` file (PHONE_NUMBER) and all the sms notifications would start coming in.
71
+
72
+ > Note: While entering the ngrok domain and subscribing, make sure that there is not forward slash at the end of the domain.
73
+
74
+ > **Correct** `https://29de1e3e.ngrok.io`
75
+
76
+ > **Incorrect** `https://29de1e3e.ngrok.io/`
77
+
78
+ ### Section 3 - SMS Notification
79
+ This is the bottom half of the right section of the application. As in `section 2` we subscribed for all the SMS notification against the phone number described in the `.env` file (PHONE_NUMBER), whenever we send out an sms using the `Send SMS` section or get an sms to the phone number described in the `.env` file (PHONE_NUMBER), we would receive a notification and that notification would be printed out under the `SMS Notification` header
80
+
@@ -0,0 +1,87 @@
1
+ require 'sinatra'
2
+ require 'json'
3
+ require 'pry'
4
+ require 'cpaas-sdk'
5
+
6
+ require './helper'
7
+
8
+ class App < Sinatra::Application
9
+ enable :sessions
10
+
11
+ def initialize
12
+ super
13
+
14
+ # Initialize
15
+ Cpaas.configure do |config|
16
+ config.client_id = ENV['CLIENT_ID']
17
+ config.client_secret = ENV['CLIENT_SECRET']
18
+ config.base_url = ENV['BASE_URL']
19
+ end
20
+ end
21
+
22
+ get '/' do
23
+ type = params['success'] ? 'success' : 'error'
24
+ message = params[type]
25
+
26
+ erb :index, locals: { alert: { message: message, type: type } }
27
+ end
28
+
29
+ post '/send' do
30
+ #
31
+ # The method create_message would send an sms when the 'type' attribute is 'SMS'
32
+ #
33
+ puts ENV['PHONE_NUMBER']
34
+ response = Cpaas::Conversation.create_message({
35
+ type: Cpaas::Conversation.types[:SMS],
36
+ destination_address: params['number'],
37
+ message: params['message'],
38
+ sender_address: ENV['PHONE_NUMBER']
39
+ })
40
+
41
+ puts response
42
+
43
+ return redirect "/?error=#{error_message(response)}" if response[:exception_id]
44
+
45
+ redirect '/?success=Success'
46
+ end
47
+
48
+ post '/subscribe' do
49
+ #
50
+ # The subscribe method would enable a notification subscription for a purchased number (destination) and the
51
+ # webhook_url is the public POST endpoint where notifications would be received. For this exable the
52
+ # '/webhook' endpoint is enabled for the incoming notification.
53
+ #
54
+
55
+ response = Cpaas::Conversation.subscribe({
56
+ type: Cpaas::Conversation.types[:SMS],
57
+ destination_address: ENV['PHONE_NUMBER'],
58
+ webhook_url: "#{params['webhook']}/webhook"
59
+ })
60
+
61
+ puts response
62
+
63
+ return redirect "/?error=#{error_message(response)}" if response[:exception_id]
64
+
65
+ redirect '/?success=Created subscription'
66
+ end
67
+
68
+ post '/webhook' do
69
+ body = JSON.parse request.body.read
70
+
71
+ #
72
+ # The Cpaas::Notification.parse will parse the received notification and will return a
73
+ # simplified version of th notification to consume
74
+ #
75
+
76
+ notification = Cpaas::Notification.parse(body)
77
+
78
+ add_notification(notification) # Helper method, check helper.rb
79
+
80
+ status 200
81
+ end
82
+
83
+ get '/notifications' do
84
+ content_type :json
85
+ notifications.to_json # Helper method, check helper.rb
86
+ end
87
+ end
@@ -0,0 +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
@@ -0,0 +1,33 @@
1
+ FILE_NAME = 'notifications.json'
2
+ PATH = "#{Dir.pwd}/tmp/#{FILE_NAME}"
3
+
4
+ def error_message(error)
5
+ "#{error[:name]}: #{error[:message]} (#{error[:exception_id]})"
6
+ end
7
+
8
+ def notifications
9
+ return [] if !File.file?(PATH)
10
+
11
+ all_notifications = JSON.parse(read_file)
12
+ all_notifications[ENV['PHONE_NUMBER']]
13
+ end
14
+
15
+ def add_notification(notification)
16
+ all_notifications = JSON.parse(read_file)
17
+
18
+ all_notifications[ENV['PHONE_NUMBER']] = [] if all_notifications[ENV['PHONE_NUMBER']].nil?
19
+ all_notifications[ENV['PHONE_NUMBER']].unshift(notification)
20
+
21
+ write_file(all_notifications.to_json)
22
+ end
23
+
24
+ def read_file
25
+ File.file?(PATH) ? File.read(PATH) : "{}"
26
+ end
27
+
28
+ def write_file(content)
29
+ notification_file = File.file?(PATH) ? File.open(PATH, 'w') : File.new(PATH, 'w')
30
+
31
+ notification_file.puts(content)
32
+ notification_file.close
33
+ end