webhookr 0.2.0 → 0.3.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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +1937 -0
  3. data/.travis.yml +8 -8
  4. data/Gemfile +12 -15
  5. data/Guardfile +12 -15
  6. data/MIT-LICENSE +1 -1
  7. data/README.md +8 -7
  8. data/Rakefile +3 -3
  9. data/app/controllers/webhookr/events_controller.rb +23 -16
  10. data/config/routes.rb +9 -8
  11. data/lib/generators/webhookr/add_route_generator.rb +4 -4
  12. data/lib/generators/webhookr/init_generator.rb +14 -12
  13. data/lib/tasks/webhookr_tasks.rake +7 -7
  14. data/lib/webhookr.rb +13 -6
  15. data/lib/webhookr/adapter_response.rb +3 -1
  16. data/lib/webhookr/engine.rb +5 -4
  17. data/lib/webhookr/invalid_payload_error.rb +8 -2
  18. data/lib/webhookr/invalid_security_token_error.rb +3 -1
  19. data/lib/webhookr/invalid_service_name_error.rb +9 -0
  20. data/lib/webhookr/missing_callback_class_error.rb +9 -0
  21. data/lib/webhookr/ostruct_utils.rb +19 -19
  22. data/lib/webhookr/service.rb +28 -24
  23. data/lib/webhookr/services.rb +1 -1
  24. data/lib/webhookr/services/adapter.rb +1 -1
  25. data/lib/webhookr/services/adapter/base.rb +2 -2
  26. data/lib/webhookr/version.rb +3 -1
  27. data/test/dummy/Rakefile +0 -1
  28. data/test/dummy/app/controllers/application_controller.rb +2 -0
  29. data/test/dummy/app/helpers/application_helper.rb +2 -0
  30. data/test/dummy/config.ru +1 -1
  31. data/test/dummy/config/application.rb +8 -8
  32. data/test/dummy/config/boot.rb +4 -1
  33. data/test/dummy/config/environment.rb +2 -0
  34. data/test/dummy/config/environments/development.rb +2 -1
  35. data/test/dummy/config/environments/production.rb +2 -1
  36. data/test/dummy/config/environments/test.rb +5 -4
  37. data/test/dummy/config/initializers/backtrace_silencers.rb +2 -0
  38. data/test/dummy/config/initializers/inflections.rb +2 -0
  39. data/test/dummy/config/initializers/mime_types.rb +2 -0
  40. data/test/dummy/config/initializers/secret_token.rb +3 -1
  41. data/test/dummy/config/initializers/session_store.rb +3 -1
  42. data/test/dummy/config/initializers/webhookr.rb +3 -1
  43. data/test/dummy/config/initializers/wrap_parameters.rb +3 -2
  44. data/test/dummy/config/routes.rb +3 -1
  45. data/test/dummy/script/rails +2 -2
  46. data/test/functional/webhookr/events_controller_test.rb +38 -42
  47. data/test/functional/webhookr/events_routes_test.rb +22 -15
  48. data/test/functional/webhookr/service_test.rb +53 -48
  49. data/test/integration/webhookr/add_route_generator_test.rb +5 -4
  50. data/test/integration/webhookr/init_generator_test.rb +7 -6
  51. data/test/stubs/service_under_test_stubs.rb +26 -33
  52. data/test/test_helper.rb +10 -9
  53. data/test/unit/webhookr/adapter_response_test.rb +7 -6
  54. data/test/unit/webhookr/ostruct_utils_test.rb +14 -14
  55. data/test/unit/webhookr/{Services/ServiceUnderTest → services/service_under_test}/adapter_test.rb +14 -14
  56. data/test/webhookr_test.rb +5 -3
  57. data/webhookr.gemspec +3 -4
  58. metadata +24 -27
@@ -1,28 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Webhookr
2
4
  # Adapted from http://www.rebeccamiller-webster.com/2012/06/recursively-convert-a-ruby-hash-to-openstruct/
3
5
  module OstructUtils
4
-
5
- def self.to_ostruct(obj)
6
- case
7
- when obj.kind_of?(Hash)
8
- return hash_to_ostruct(obj)
9
- when obj.kind_of?(Array)
10
- return array_to_ostruct(obj)
6
+ def self.to_ostruct(obj)
7
+ case obj
8
+ when Hash
9
+ hash_to_ostruct(obj)
10
+ when Array
11
+ array_to_ostruct(obj)
11
12
  else
12
- return obj
13
- end
14
- end
15
-
16
- def self.hash_to_ostruct(hash)
17
- hash.each do |key, val|
18
- hash[key] = to_ostruct(val)
19
- end
20
- OpenStruct.new(hash)
13
+ obj
21
14
  end
15
+ end
22
16
 
23
- def self.array_to_ostruct(array)
24
- array.map { |r| to_ostruct(r) }
17
+ def self.hash_to_ostruct(hash)
18
+ hash.each do |key, val|
19
+ hash[key] = to_ostruct(val)
25
20
  end
21
+ OpenStruct.new(hash)
22
+ end
26
23
 
24
+ def self.array_to_ostruct(array)
25
+ array.map { |r| to_ostruct(r) }
26
+ end
27
27
  end
28
- end
28
+ end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Webhookr
2
4
  class Service
3
5
  attr_reader :service_name
4
6
 
5
7
  def initialize(service_name, options = {})
6
- @service_name = (service_name || "").downcase
8
+ @service_name = (service_name || '').downcase
7
9
  @raw_payload = options[:payload]
8
10
  available?
9
11
  validate_security_token(options[:security_token]) if configured_security_token
@@ -17,35 +19,37 @@ module Webhookr
17
19
 
18
20
  private
19
21
 
20
- def callback(object, payload)
21
- method = method_for(payload)
22
- object.send(method, payload) if object.respond_to?(method)
23
- end
22
+ def callback(object, payload)
23
+ method = method_for(payload)
24
+ object.send(method, payload) if object.respond_to?(method)
25
+ end
24
26
 
25
- def method_for(payload)
26
- "on_" + payload.event_type
27
- end
27
+ def method_for(payload)
28
+ "on_#{payload.event_type}"
29
+ end
28
30
 
29
- def callback_class
30
- callback = Webhookr.config[service_name].try(:callback)
31
- raise "No callback is configured for the service '#{service_name}'." if callback.nil?
32
- @call_back_class || callback.new
33
- end
31
+ def callback_class
32
+ callback = Webhookr.config[service_name].try(:callback)
33
+ raise Webhookr::MissingCallbackClassError, service_name if callback.nil?
34
34
 
35
- def configured_security_token
36
- Webhookr.config[service_name].try(:security_token)
37
- end
35
+ @call_back_class || callback.new
36
+ end
38
37
 
39
- def validate_security_token(token)
40
- raise Webhookr::InvalidSecurityTokenError if token.nil? || !SecureCompare.compare(token, configured_security_token)
41
- end
38
+ def configured_security_token
39
+ Webhookr.config[service_name].try(:security_token)
40
+ end
42
41
 
43
- def service_adapter
44
- raise NameError.new(%{Bad service name "#{service_name}"}) unless Webhookr.adapters[service_name]
45
- @service_adapter ||= Webhookr.adapters[service_name]
46
- end
42
+ def validate_security_token(token)
43
+ raise Webhookr::InvalidSecurityTokenError if token.nil? || !SecureCompare.compare(token, configured_security_token)
44
+ end
47
45
 
48
- alias_method :available?, :service_adapter
46
+ def service_adapter
47
+ raise Webhookr::InvalidServiceNameError, service_name unless Webhookr.adapters[service_name]
48
+ @service_adapter ||= Webhookr.adapters[service_name]
49
+ end
49
50
 
51
+ def available?
52
+ !!service_adapter
53
+ end
50
54
  end
51
55
  end
@@ -1,7 +1,7 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Webhookr::Services
3
4
  extend ActiveSupport::Autoload
4
5
 
5
6
  autoload :Adapter
6
7
  end
7
-
@@ -1,7 +1,7 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Webhookr::Services::Adapter
3
4
  extend ActiveSupport::Autoload
4
5
 
5
6
  autoload :Base
6
7
  end
7
-
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Webhookr::Services::Adapter::Base
3
4
  extend ActiveSupport::Concern
4
5
 
5
6
  included do
6
- self.initialize! if self.respond_to?(:initialize!)
7
+ initialize! if respond_to?(:initialize!)
7
8
  Webhookr.adapters[self::SERVICE_NAME] = self
8
9
  end
9
10
 
@@ -17,4 +18,3 @@ module Webhookr::Services::Adapter::Base
17
18
  end
18
19
  end
19
20
  end
20
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Webhookr
2
- VERSION = "0.2.0"
4
+ VERSION = '0.3.0'
3
5
  end
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env rake
2
1
  # Add your own tasks in files placed in lib/tasks ending in .rake,
3
2
  # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
3
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ApplicationController < ActionController::Base
2
4
  protect_from_forgery
3
5
  end
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ApplicationHelper
2
4
  end
@@ -1,4 +1,4 @@
1
1
  # This file is used by Rack-based servers to start the application.
2
2
 
3
- require ::File.expand_path('../config/environment', __FILE__)
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
4
  run Dummy::Application
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('../boot', __FILE__)
2
4
 
3
5
  # Pick the frameworks you want:
4
6
  # require "active_record/railtie"
5
- require "action_controller/railtie"
6
- require "sprockets/railtie"
7
- require "rails/test_unit/railtie"
7
+ require 'action_controller/railtie'
8
+ require 'sprockets/railtie'
9
+ require 'rails/test_unit/railtie'
8
10
 
9
11
  Bundler.require
10
- require "webhookr"
12
+ require 'webhookr'
11
13
 
12
14
  module Dummy
13
15
  class Application < Rails::Application
@@ -16,7 +18,7 @@ module Dummy
16
18
  # -- all .rb files in that directory are automatically loaded.
17
19
 
18
20
  # Custom directories with classes and modules you want to be autoloadable.
19
- config.autoload_paths += %W(#{config.root}/../../lib)
21
+ config.autoload_paths += %W{#{config.root}/../../lib}
20
22
 
21
23
  # Only load the plugins named here, in the order given (default is alphabetical).
22
24
  # :all can be used as a placeholder for all plugins not explicitly named.
@@ -34,7 +36,7 @@ module Dummy
34
36
  # config.i18n.default_locale = :de
35
37
 
36
38
  # Configure the default encoding used in templates for Ruby 1.9.
37
- config.encoding = "utf-8"
39
+ config.encoding = 'utf-8'
38
40
 
39
41
  # Configure sensitive parameters which will be filtered from the log file.
40
42
  config.filter_parameters += [:password]
@@ -58,7 +60,5 @@ module Dummy
58
60
 
59
61
  # Version of your assets, change this if you want to expire all your assets
60
62
  config.assets.version = '1.0'
61
-
62
63
  end
63
64
  end
64
-
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rubygems'
4
+
2
5
  gemfile = File.expand_path('../../../../Gemfile', __FILE__)
3
6
 
4
7
  if File.exist?(gemfile)
@@ -7,4 +10,4 @@ if File.exist?(gemfile)
7
10
  Bundler.setup
8
11
  end
9
12
 
10
- $:.unshift File.expand_path('../../../../lib', __FILE__)
13
+ $LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Load the rails application
2
4
  require File.expand_path('../application', __FILE__)
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Dummy::Application.configure do
2
4
  # Settings specified here will take precedence over those in config/application.rb
3
5
 
@@ -19,7 +21,6 @@ Dummy::Application.configure do
19
21
  # Only use best-standards-support built into browsers
20
22
  config.action_dispatch.best_standards_support = :builtin
21
23
 
22
-
23
24
  # Do not compress assets
24
25
  config.assets.compress = false
25
26
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Dummy::Application.configure do
2
4
  # Settings specified here will take precedence over those in config/application.rb
3
5
 
@@ -60,5 +62,4 @@ Dummy::Application.configure do
60
62
 
61
63
  # Send deprecation notices to registered listeners
62
64
  config.active_support.deprecation = :notify
63
-
64
65
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Dummy::Application.configure do
2
4
  # Settings specified here will take precedence over those in config/application.rb
3
5
 
@@ -9,27 +11,26 @@ Dummy::Application.configure do
9
11
 
10
12
  # Configure static asset server for tests with Cache-Control for performance
11
13
  config.serve_static_assets = true
12
- config.static_cache_control = "public, max-age=3600"
14
+ config.static_cache_control = 'public, max-age=3600'
13
15
 
14
16
  # Rails 4.0
15
17
  config.eager_load = false
16
18
 
17
19
  # Show full error reports and disable caching
18
- config.consider_all_requests_local = true
20
+ config.consider_all_requests_local = true
19
21
  config.action_controller.perform_caching = false
20
22
 
21
23
  # Raise exceptions instead of rendering exception templates
22
24
  config.action_dispatch.show_exceptions = false
23
25
 
24
26
  # Disable request forgery protection in test environment
25
- config.action_controller.allow_forgery_protection = false
27
+ config.action_controller.allow_forgery_protection = false
26
28
 
27
29
  # Tell Action Mailer not to deliver emails to the real world.
28
30
  # The :test delivery method accumulates sent emails in the
29
31
  # ActionMailer::Base.deliveries array.
30
32
  # config.action_mailer.delivery_method = :test
31
33
 
32
-
33
34
  # Print deprecation notices to the stderr
34
35
  config.active_support.deprecation = :stderr
35
36
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Be sure to restart your server when you modify this file.
2
4
 
3
5
  # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Be sure to restart your server when you modify this file.
2
4
 
3
5
  # Add new inflection rules using the following format
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Be sure to restart your server when you modify this file.
2
4
 
3
5
  # Add new mime types for use in respond_to blocks:
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Be sure to restart your server when you modify this file.
2
4
 
3
5
  # Your secret key for verifying the integrity of signed cookies.
4
6
  # If you change this key, all old signed cookies will become invalid!
5
7
  # Make sure the secret is at least 30 characters and all random,
6
8
  # no regular words or you'll be exposed to dictionary attacks.
7
- Dummy::Application.config.secret_key_base = '37ef70b5f837f7a433cdd2a24cfac821c9e6624bccad494de69557a4d95e70d6400afb6c291fed109e417492c84c39d4325f35716fdc6c57cc376aacc72ad512'
9
+ Dummy::Application.config.secret_key_base = '37ef70b5f837f7a433cdd2a24cfac821c9e6624bccad494de69557a4d95e70d6400afb6c291fed109e417492c84c39d4325f35716fdc6c57cc376aacc72ad512'
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Be sure to restart your server when you modify this file.
2
4
 
3
- Dummy::Application.config.session_store :cookie_store, :key => '_dummy_session'
5
+ Dummy::Application.config.session_store :cookie_store, key: '_dummy_session'
4
6
 
5
7
  # Use the database for sessions instead of the cookie-based default,
6
8
  # which shouldn't be used to store highly confidential information
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Webhookr.config.basic_auth.username = "admin"
2
- # Webhookr.config.basic_auth.password = "pass"
4
+ # Webhookr.config.basic_auth.password = "pass"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Be sure to restart your server when you modify this file.
2
4
  #
3
5
  # This file contains settings for ActionController::ParamsWrapper which
@@ -5,6 +7,5 @@
5
7
 
6
8
  # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7
9
  ActiveSupport.on_load(:action_controller) do
8
- wrap_parameters :format => [:json]
10
+ wrap_parameters format: [:json]
9
11
  end
10
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Rails.application.routes.draw do
2
- mount Webhookr::Engine => "/webhookr", :as => "webhookr"
4
+ mount Webhookr::Engine => '/webhookr', as: 'webhookr'
3
5
  end
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
3
 
4
- APP_PATH = File.expand_path('../../config/application', __FILE__)
5
- require File.expand_path('../../config/boot', __FILE__)
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
6
  require 'rails/commands'
@@ -1,76 +1,72 @@
1
+ # frozen_string_literal: true
1
2
 
2
- $: << File.join(File.dirname(__FILE__), %w{ .. .. })
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), %w{ .. .. })
3
4
  require 'test_helper'
4
5
  require 'stubs/service_under_test_stubs'
5
6
 
6
7
  module Webhookr
7
8
  class EventsControllerTest < ActionController::TestCase
8
-
9
9
  include Webhookr::ServiceUnderTest
10
10
 
11
11
  def setup
12
12
  @routes = Webhookr::Engine.routes
13
13
  PlainOldCallBackClass.reset!
14
14
  Webhookr::ServiceUnderTest::Adapter.config.security_token = nil
15
- @security_token = "secure_blort"
15
+ @security_token = 'secure_blort'
16
16
  end
17
17
 
18
- test ":get with no service id should return a ActionController::RoutingError" do
19
- assert_raise(ActionController::RoutingError) {
20
- get(:show, {:service_id => ""})
21
- }
18
+ test ':get with no service id should return a ActionController::RoutingError' do
19
+ assert_raise(ActionController::RoutingError) do
20
+ get(:show, params: { service_id: '' })
21
+ end
22
22
  end
23
23
 
24
- test ":get with an unknown service id should return a ActionController::RoutingError" do
25
- assert_raise(ActionController::RoutingError) {
26
- get(:show, {:service_id => "blort"})
27
- }
24
+ test ':get with an unknown service id should return a ActionController::RoutingError' do
25
+ assert_raise(ActionController::RoutingError) do
26
+ get(:show, params: { service_id: 'blort' })
27
+ end
28
28
  end
29
29
 
30
- test ":get with known service id should return success and an empty body" do
31
- get(:show, {:service_id => stub.service_name})
30
+ test ':get with known service id should return success and an empty body' do
31
+ get(:show, params: { service_id: stub.service_name })
32
32
  assert_response :success
33
- assert(@response.body.blank?, "Expected an empty reponse, but got'#{@response.body}'")
33
+ assert(@response.body.blank?, "Expected an empty reponse, but got '#{@response.body}'")
34
34
  end
35
35
 
36
- test ":post with valid payload should return success" do
36
+ test ':post with valid payload should return success' do
37
37
  PlainOldCallBackClass.reset!
38
38
  Webhookr::ServiceUnderTest::Adapter.config.callback = PlainOldCallBackClass
39
- post(:create, {
40
- :service_id => stub.service_name,
41
- :event => stub.event_type,
42
- :data => { :email => stub.email }
43
- }
44
- )
39
+ post(
40
+ :create,
41
+ params: {
42
+ service_id: stub.service_name,
43
+ event: stub.event_type,
44
+ data: {
45
+ email: stub.email
46
+ }
47
+ }
48
+ )
45
49
  assert_equal 1, PlainOldCallBackClass.call_count
46
50
  end
47
51
 
48
- test ":get with :security_token configured and not passed should return :InvalidAuthenticityToken" do
52
+ test ':get with :security_token configured and not passed should return :InvalidAuthenticityToken' do
49
53
  Webhookr::ServiceUnderTest::Adapter.config.security_token = @security_token
50
- assert_raise(ActionController::InvalidAuthenticityToken) {
51
- get(:show, {:service_id => stub.service_name})
52
- }
54
+
55
+ assert_raise(ActionController::InvalidAuthenticityToken) do
56
+ get(:show, params: { service_id: stub.service_name })
57
+ end
53
58
  end
54
59
 
55
- test ":get with :security_token configured and passed should return :success" do
60
+ test ':get with :security_token configured and passed should return :success' do
56
61
  Webhookr::ServiceUnderTest::Adapter.config.security_token = @security_token
57
- get(:show, {:service_id => stub.service_name, :security_token => @security_token})
62
+ get(
63
+ :show,
64
+ params: {
65
+ service_id: stub.service_name,
66
+ security_token: @security_token
67
+ }
68
+ )
58
69
  assert_response(:success)
59
70
  end
60
-
61
- test "basic auth will prevent unauthorized access" do
62
- # pending "more time" do
63
- # Webhookr.config.basic_auth.username = "admin"
64
- # Webhookr.config.basic_auth.password = "password"
65
- #
66
- # post(:create, {
67
- # :service_id => stub.service_name,
68
- # :event => stub.event
69
- # }
70
- # )
71
- # assert_response :unauthorized
72
- # end
73
- end
74
-
75
71
  end
76
72
  end