webhookr 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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