sms_candy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +34 -0
  4. data/lib/sms_candy.rb +16 -0
  5. data/lib/sms_candy/authentication/strategies.rb +39 -0
  6. data/lib/sms_candy/authentication/strategies/o_auth_2.rb +44 -0
  7. data/lib/sms_candy/config.rb +16 -0
  8. data/lib/sms_candy/helpers/get_message_response_helper.rb +40 -0
  9. data/lib/sms_candy/helpers/get_message_status_helper.rb +40 -0
  10. data/lib/sms_candy/helpers/message_callback_renderer_helper.rb +20 -0
  11. data/lib/sms_candy/helpers/send_message_helper.rb +43 -0
  12. data/lib/sms_candy/manager.rb +34 -0
  13. data/lib/sms_candy/version.rb +3 -0
  14. data/lib/tasks/sms_candy_tasks.rake +4 -0
  15. data/spec/authentication/strategies/o_auth_2_spec.rb +10 -0
  16. data/spec/authentication/strategies/strategy_behaviors.rb +32 -0
  17. data/spec/authentication/strategies_spec.rb +38 -0
  18. data/spec/config_spec.rb +15 -0
  19. data/spec/dummy/README.rdoc +28 -0
  20. data/spec/dummy/Rakefile +6 -0
  21. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  22. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  23. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  24. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  25. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  26. data/spec/dummy/bin/bundle +3 -0
  27. data/spec/dummy/bin/rails +4 -0
  28. data/spec/dummy/bin/rake +4 -0
  29. data/spec/dummy/bin/setup +29 -0
  30. data/spec/dummy/config.ru +4 -0
  31. data/spec/dummy/config/application.rb +34 -0
  32. data/spec/dummy/config/boot.rb +5 -0
  33. data/spec/dummy/config/database.yml +25 -0
  34. data/spec/dummy/config/environment.rb +5 -0
  35. data/spec/dummy/config/environments/development.rb +41 -0
  36. data/spec/dummy/config/environments/production.rb +79 -0
  37. data/spec/dummy/config/environments/test.rb +42 -0
  38. data/spec/dummy/config/initializers/assets.rb +11 -0
  39. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  40. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  41. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  42. data/spec/dummy/config/initializers/inflections.rb +16 -0
  43. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  44. data/spec/dummy/config/initializers/session_store.rb +3 -0
  45. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  46. data/spec/dummy/config/local_env.yml +4 -0
  47. data/spec/dummy/config/locales/en.yml +23 -0
  48. data/spec/dummy/config/routes.rb +56 -0
  49. data/spec/dummy/config/secrets.yml +22 -0
  50. data/spec/dummy/log/test.log +0 -0
  51. data/spec/dummy/public/404.html +67 -0
  52. data/spec/dummy/public/422.html +67 -0
  53. data/spec/dummy/public/500.html +66 -0
  54. data/spec/dummy/public/favicon.ico +0 -0
  55. data/spec/helpers/common_methods.rb +16 -0
  56. data/spec/helpers/get_message_response_helper_spec.rb +13 -0
  57. data/spec/helpers/get_message_status_helper_spec.rb +30 -0
  58. data/spec/helpers/message_callback_renderer_helper_spec.rb +23 -0
  59. data/spec/helpers/send_message_helper_spec.rb +22 -0
  60. data/spec/manager_spec.rb +75 -0
  61. data/spec/spec_helper.rb +21 -0
  62. metadata +181 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: edc4fc03b0dcaf99dea9c019802f39ca54900491
4
+ data.tar.gz: 914cedaacb9ec271946bd4b518b5440798e26046
5
+ SHA512:
6
+ metadata.gz: 592e6f9036008b2cb5b9b295010e3348feefc7a2f376eeccf6db0cd7950cb8b4b6864221701bfb72038fed405c29cee9e11d4e2a6f4a614f8fb8900a4541c14c
7
+ data.tar.gz: 565fa33a2b60336198036c8fcaff70d258a38ab7e40c21096bce5c2fc3ea56d7708b50de059e3959516e512d9190312bf09a971826ca7a4ed03111e3de554d6b
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 Hadi Badjian
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'SmsCandy'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
data/lib/sms_candy.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'rest_client'
2
+ require 'sms_candy/config'
3
+ require 'sms_candy/authentication/strategies'
4
+ require 'sms_candy/helpers/send_message_helper'
5
+ require 'sms_candy/helpers/get_message_status_helper'
6
+ require 'sms_candy/helpers/get_message_response_helper'
7
+ require 'sms_candy/helpers/message_callback_renderer_helper'
8
+ require 'sms_candy/manager'
9
+
10
+ module SmsCandy
11
+ module Authentication
12
+ module Strategies
13
+ autoload :OAuth2, 'sms_candy/authentication/strategies/o_auth_2'
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module SmsCandy
2
+
3
+ module Authentication
4
+
5
+ module Strategies
6
+
7
+ class << self
8
+
9
+ def add(label, strategy = nil)
10
+ strategy ||= SmsCandy::Authentication::Strategies::OAuth2.new
11
+
12
+ unless strategy.class.method_defined?(:authenticate!)
13
+ raise NoMethodError, "authenticate! is not declared in the #{label.inspect} strategy"
14
+ end
15
+
16
+ _strategies[label] = strategy
17
+ end
18
+
19
+ def clear!
20
+ _strategies.clear
21
+ end
22
+
23
+ def list
24
+ _strategies
25
+ end
26
+
27
+ private
28
+
29
+ def _strategies
30
+ @strategies ||= {}
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,44 @@
1
+ module SmsCandy
2
+
3
+ module Authentication
4
+
5
+ module Strategies
6
+
7
+ class OAuth2
8
+ attr_reader :access_token
9
+ attr_reader :expires_at
10
+
11
+ #Obtain these keys from the Telstra Developer Portal
12
+ # APP_KEY="yourapikey"
13
+ # APP_SECRET="yourapisecret"
14
+
15
+ # curl "https://api.telstra.com/v1/oauth/token?client_id=$APP_KEY&client_secret=$APP_SECRET&grant_type=client_credentials&scope=SMS"
16
+ def authenticate!
17
+ response = RestClient.get(base_url, { params: authentication_params })
18
+
19
+ json_response = JSON.parse response.body
20
+ @expires_at = Time.zone.now + json_response["expires_in"].to_i
21
+ @access_token = json_response["access_token"]
22
+ end
23
+
24
+ private
25
+
26
+ def authentication_params
27
+ {
28
+ client_id: ENV["TELSTRA_SMS_CLIENT_ID"],
29
+ client_secret: ENV["TELSTRA_SMS_CLIENT_SECRET"],
30
+ grant_type: ENV["TELSTRA_SMS_GRANT_TYPE"],
31
+ scope: ENV["TELSTRA_SMS_SCOPE"]
32
+ }
33
+ end
34
+
35
+ def base_url
36
+ SmsCandy::Config.base_url + "oauth/token"
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,16 @@
1
+ module SmsCandy
2
+
3
+ class Config
4
+
5
+ class << self
6
+
7
+ def base_url
8
+ "https://api.telstra.com/v1/"
9
+ # Rails.env.test? ? "https://staging.api.telstra.com/v1/" : "https://api.telstra.com/v1/"
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,40 @@
1
+ module SmsCandy
2
+
3
+ module Helpers
4
+
5
+ class GetMessageResponseHelper
6
+
7
+ class << self
8
+
9
+ # * MESSAGE_ID value is the value returned from a previous POST https://api.telstra.com/v1/sms/messages call
10
+ # * Authorization header value should be in the format of "Bearer xxx" where xxx is access token returned
11
+ # from a previous GET https://api.telstra.com/v1/oauth/token request.
12
+ # MESSAGE_ID="6F0B6030D7309137"
13
+ # TOKEN=your_token
14
+
15
+ # curl -H "Authorization: Bearer $TOKEN" \
16
+ # "https://api.telstra.com/v1/sms/messages/$MESSAGE_ID/response"
17
+ def response(message_id, access_token)
18
+ headers = {
19
+ "authorization" => "Bearer #{access_token}",
20
+ "Accept" => "application/json"
21
+ }
22
+
23
+ response = RestClient.get(_base_url(message_id), headers)
24
+ json_response = JSON.parse response
25
+ json_response.map { |response| response.map { |l,v| { l.underscore.to_sym => v } }.inject(:merge) }
26
+ end
27
+
28
+ private
29
+
30
+ def _base_url(message_id)
31
+ SmsCandy::Config.base_url + "sms/messages/#{message_id}/response"
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,40 @@
1
+ module SmsCandy
2
+
3
+ module Helpers
4
+
5
+ class GetMessageStatusHelper
6
+
7
+ class << self
8
+
9
+ # * MESSAGE_ID value is the value returned from a previous POST https://api.telstra.com/v1/sms/messages call
10
+ # * Authorization header value should be in the format of "Bearer xxx" where xxx is access token returned
11
+ # from a previous GET https://api.telstra.com/v1/oauth/token request.
12
+ # MESSAGE_ID="6F0B6030D7309137"
13
+ # TOKEN=your_token
14
+
15
+ # curl -H "Authorization: Bearer $TOKEN" \
16
+ # "https://api.telstra.com/v1/sms/messages/$MESSAGE_ID"
17
+ def status(message_id, access_token)
18
+ headers = {
19
+ "authorization" => "Bearer #{access_token}",
20
+ "Accept" => "application/json"
21
+ }
22
+
23
+ response = RestClient.get(_base_url(message_id), headers)
24
+ json_response = JSON.parse response
25
+ json_response.map { |l,v| { l.underscore.to_sym => v } }.inject(:merge)
26
+ end
27
+
28
+ private
29
+
30
+ def _base_url(message_id)
31
+ SmsCandy::Config.base_url + "sms/messages/#{message_id}"
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,20 @@
1
+ module SmsCandy
2
+
3
+ module Helpers
4
+
5
+ class MessageCallbackRendererHelper
6
+
7
+ class << self
8
+
9
+ def render(message)
10
+ json_response = JSON.parse message
11
+ json_response.map { |l,v| { l.underscore.to_sym => v } }.inject(:merge)
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,43 @@
1
+ module SmsCandy
2
+
3
+ module Helpers
4
+
5
+ class SendMessageHelper
6
+
7
+ class << self
8
+
9
+ # * Recipient number should be in the format of "04xxxxxxxx" where x is a digit
10
+ # * Authorization header value should be in the format of "Bearer xxx" where xxx is access token returned
11
+ # from a previous GET https://api.telstra.com/v1/oauth/token request.
12
+ # RECIPIENT_NUMBER=your_number
13
+ # TOKEN=your_token
14
+
15
+ # curl -H "Content-Type: application/json" \
16
+ # -H "Authorization: Bearer $TOKEN" \
17
+ # -d "{\"to\":\"$RECIPIENT_NUMBER\", \"body\":\"Hello!\"}" \
18
+ # "https://api.telstra.com/v1/sms/messages"
19
+ def send_sms(number, message, access_token)
20
+ headers = {
21
+ "authorization" => "Bearer #{access_token}",
22
+ "Content-Type" => "application/json",
23
+ "Accept" => "application/json"
24
+ }
25
+ data = { to: number, body: message }.to_json
26
+
27
+ response = RestClient.post(_base_url, data, headers)
28
+ JSON.parse(response)['messageId']
29
+ end
30
+
31
+ private
32
+
33
+ def _base_url
34
+ SmsCandy::Config.base_url + "sms/messages"
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,34 @@
1
+ module SmsCandy
2
+
3
+ class Manager
4
+
5
+ class << self
6
+
7
+ def authenticate
8
+ SmsCandy::Authentication::Strategies.list.each do |label, strategy|
9
+ access_token = strategy.authenticate!
10
+ return access_token if access_token
11
+ end
12
+ end
13
+
14
+ def send_sms(number, message, access_token)
15
+ SmsCandy::Helpers::SendMessageHelper.send_sms(number, message, access_token)
16
+ end
17
+
18
+ def message_status(message_id, access_token)
19
+ SmsCandy::Helpers::GetMessageStatusHelper.status(message_id, access_token)
20
+ end
21
+
22
+ def message_response(message_id, access_token)
23
+ SmsCandy::Helpers::GetMessageResponseHelper.response(message_id, access_token)
24
+ end
25
+
26
+ def message_callback(message)
27
+ SmsCandy::Helpers::MessageCallbackRendererHelper.render(message)
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,3 @@
1
+ module SmsCandy
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :sms_candy do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'authentication/strategies/strategy_behaviors'
3
+
4
+ RSpec.describe SmsCandy::Authentication::Strategies::OAuth2 do
5
+
6
+ let(:subject) { SmsCandy::Authentication::Strategies::OAuth2.new }
7
+
8
+ it_behaves_like "an authentication strategy"
9
+
10
+ end
@@ -0,0 +1,32 @@
1
+ shared_examples_for "an authentication strategy" do
2
+ let(:strategy) { described_class.new }
3
+
4
+ context "interface" do
5
+
6
+ it "should respond to authenticate!" do
7
+ expect(strategy).to respond_to(:authenticate!)
8
+ end
9
+
10
+ it "should have access_token reader" do
11
+ expect(strategy).to respond_to(:access_token)
12
+ end
13
+
14
+ it "should have expires_at reader" do
15
+ expect(strategy).to respond_to(:expires_at)
16
+ end
17
+
18
+ it "should not have access_token writer" do
19
+ expect {
20
+ strategy.access_token = ""
21
+ }.to raise_error
22
+ end
23
+
24
+ it "should not have expires_at writer" do
25
+ expect {
26
+ strategy.expires_at = Time.zone.now
27
+ }.to raise_error
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ class InvalidStrategyWithoutAuthenticate
4
+ end
5
+
6
+ RSpec.describe SmsCandy::Authentication::Strategies do
7
+
8
+ let(:subject) { SmsCandy::Authentication::Strategies }
9
+ let(:strategy) { SmsCandy::Authentication::Strategies::OAuth2.new }
10
+
11
+ after(:each) do
12
+ SmsCandy::Authentication::Strategies.clear!
13
+ end
14
+
15
+ context "#add" do
16
+
17
+ it "should add new strategies" do
18
+ expect(subject.add :oauth2, strategy).to eql(strategy)
19
+ end
20
+
21
+ it "should fail adding a strategy without authenticate! method" do
22
+ expect {
23
+ subject.add :invalid_strategy, InvalidStrategyWithoutAuthenticate.new
24
+ }.to raise_error
25
+ end
26
+
27
+ end
28
+
29
+ context "#clear!" do
30
+
31
+ it "should be able to clear strategies" do
32
+ subject.add :oauth2, strategy
33
+ expect(subject.clear!).to eql({})
34
+ end
35
+
36
+ end
37
+
38
+ end