zaikio-webhooks 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5bb848ff135992c72aa0b2a6d51478644a2d75540ea64844b971f9008c8d6a77
4
+ data.tar.gz: ce31b188140afc2fd67a8abf661198ef6653ca8effd9f83f6881da052d74e7ff
5
+ SHA512:
6
+ metadata.gz: 55f9724010b083168d0673dac2a7e5260ac942ab137d2e7e30a7ca5c0cf85a1c1828d778a8495f63558e98315006069472f6c9ad8c11792c545174b8f58fce00
7
+ data.tar.gz: d38e8ca4638c8cd650a2c6e69340cbe928170582b5ac028a03f0f0cd9da7fb20a8156c6adbd3b2cfdd57292cc16d42b81b6609ac086e55fbf4796d4546858a66
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2020 Zaikio GmbH
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/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # Zaikio::Webhooks
2
+
3
+ Gem that enables you to easily subscribe to Zaikio's webhooks. It also enables other gems to subscribe to events.
4
+
5
+ ## Installation
6
+
7
+ ### 1. Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'zaikio-webhooks'
11
+ ```
12
+
13
+ And then execute:
14
+ ```bash
15
+ $ bundle
16
+ ```
17
+
18
+ Or install it yourself as:
19
+ ```bash
20
+ $ gem install zaikio-webhook
21
+ ```
22
+
23
+ ### 2. Configure the gem:
24
+
25
+ ```rb
26
+ # config/initializers/zaikio_webhooks.rb
27
+
28
+ Zaikio::Webhooks.configure do |config|
29
+ config.register_client :my_app do |my_app|
30
+ my_app.shared_secret = "test-secret"
31
+ end
32
+
33
+ config.register_client :my_other_app do |my_other_app|
34
+ my_other_app.shared_secret = "test-secret"
35
+ end
36
+ end
37
+
38
+ # Perform job immediately, for all clients
39
+ Zaikio::Webhooks.on "directory.revoked_access_token", RevokeAccessTokenJob,
40
+ perform_now: true
41
+ # Only for a specific client
42
+ Zaikio::Webhooks.on "directory.machine_added", AddMachineJob,
43
+ client_name: :my_app
44
+ ```
45
+
46
+ ### 3. Mount Engine
47
+
48
+ ```rb
49
+ mount Zaikio::Webhooks::Engine => "/zaikio/webhook"
50
+ ```
51
+
52
+ The final webhook URL will be:
53
+
54
+ ```
55
+ https://mydomain.de/zaikio/webhook/:client_name
56
+ ```
57
+
58
+ ### 4. Configure ActiveJob
59
+
60
+ It is recommended to configure background processing, if not all events are performed immediately. Read the [ActiveJob Rails Guide](https://guides.rubyonrails.org/active_job_basics.html) for more details.
61
+
62
+ ### 5. Setup Custom Jobs
63
+
64
+ Every webhook callback expects one job. The job receives the event with useful attributes:
65
+
66
+ ```rb
67
+ class AddMachineJob < ApplicationJob
68
+ def perform(event)
69
+ event.id # UUID
70
+ event.name # directory.machine_added
71
+ event.subject_type # Organization
72
+ event.subject_id # UUID of the subject
73
+ event.link # optional URL
74
+ event.payload # Hash with the payload data
75
+ event.created_at # DateTime
76
+ event.received_at # DateTime
77
+ end
78
+ end
79
+ ```
data/Rakefile ADDED
@@ -0,0 +1,37 @@
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
+ require 'rubocop/rake_task'
9
+
10
+ RDoc::Task.new(:rdoc) do |rdoc|
11
+ rdoc.rdoc_dir = 'rdoc'
12
+ rdoc.title = 'Zaikio::Webhook'
13
+ rdoc.options << '--line-numbers'
14
+ rdoc.rdoc_files.include('README.md')
15
+ rdoc.rdoc_files.include('lib/**/*.rb')
16
+ end
17
+
18
+ require 'bundler/gem_tasks'
19
+
20
+ require 'rake/testtask'
21
+
22
+ Rake::TestTask.new(:test) do |t|
23
+ t.libs << 'test'
24
+ t.pattern = 'test/**/*_test.rb'
25
+ t.verbose = false
26
+ end
27
+
28
+ task default: :test
29
+
30
+ namespace :test do
31
+ desc 'Runs RuboCop on specified directories'
32
+ RuboCop::RakeTask.new(:rubocop) do |task|
33
+ task.fail_on_error = false
34
+ end
35
+ end
36
+
37
+ Rake::Task[:test].enhance ['test:rubocop']
@@ -0,0 +1,35 @@
1
+ module Zaikio
2
+ module Webhooks
3
+ class WebhooksController < ApplicationController
4
+ before_action :verify_signature
5
+
6
+ def receive_event
7
+ Zaikio::Webhooks.webhooks_for(params[:client_name], event_params[:name]).each do |webhook|
8
+ webhook[:job_klass].public_send(webhook[:perform_now] ? :perform_now : :perform_later,
9
+ Zaikio::Webhooks::Event.new(event_params))
10
+ end
11
+
12
+ head :ok
13
+ end
14
+
15
+ private
16
+
17
+ def client_configuration
18
+ Zaikio::Webhooks.configuration.find!(params[:client_name])
19
+ end
20
+
21
+ def verify_signature
22
+ unless ActiveSupport::SecurityUtils.secure_compare(
23
+ OpenSSL::HMAC.hexdigest("SHA256", client_configuration.shared_secret, request.body.read),
24
+ request.headers["X-Loom-Signature"].to_s
25
+ )
26
+ head :ok
27
+ end
28
+ end
29
+
30
+ def event_params
31
+ params.permit(:id, :name, :subject, :timestamp, :version, :link, :received_at, payload: {})
32
+ end
33
+ end
34
+ end
35
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Zaikio::Webhooks::Engine.routes.draw do
2
+ post "/:client_name", to: "webhooks#receive_event", as: :root
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :webhook do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,9 @@
1
+ require "logger"
2
+
3
+ module Zaikio
4
+ module Webhooks
5
+ class ClientConfiguration
6
+ attr_accessor :shared_secret
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,32 @@
1
+ require "logger"
2
+ require "zaikio/webhooks/client_configuration"
3
+
4
+ module Zaikio
5
+ module Webhooks
6
+ class Configuration
7
+ attr_writer :logger
8
+ attr_reader :client_configurations
9
+
10
+ def initialize
11
+ @client_configurations = {}
12
+ end
13
+
14
+ def logger
15
+ @logger ||= Logger.new(STDOUT)
16
+ end
17
+
18
+ def register_client(name)
19
+ @client_configurations[name.to_s] ||= ClientConfiguration.new
20
+ yield(@client_configurations[name.to_s])
21
+ end
22
+
23
+ def find!(name)
24
+ @client_configurations[name.to_s] or raise ActiveRecord::RecordNotFound
25
+ end
26
+
27
+ def all_client_names
28
+ client_configurations.keys
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,9 @@
1
+ module Zaikio
2
+ module Webhooks
3
+ class Engine < ::Rails::Engine
4
+ isolate_namespace Zaikio::Webhooks
5
+ engine_name "zaikio_webhooks"
6
+ config.generators.api_only = true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,35 @@
1
+ require "ostruct"
2
+
3
+ module Zaikio
4
+ module Webhooks
5
+ class Event
6
+ extend Forwardable
7
+ attr_reader :data
8
+ def_delegators :data, :id, :name, :version, :payload, :link
9
+
10
+ def initialize(event_data)
11
+ @data = OpenStruct.new(event_data)
12
+ end
13
+
14
+ def created_at
15
+ DateTime.parse(data.timestamp)
16
+ end
17
+
18
+ def received_at
19
+ DateTime.parse(data.received_at)
20
+ end
21
+
22
+ def subject_id
23
+ data.subject.split("/").last
24
+ end
25
+
26
+ def subject_type
27
+ data.subject.split("/").first == "Org" ? "Organization" : "Person"
28
+ end
29
+
30
+ def ==(other)
31
+ data == other.data
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,5 @@
1
+ module Zaikio
2
+ module Webhooks
3
+ VERSION = "0.0.1".freeze
4
+ end
5
+ end
@@ -0,0 +1,38 @@
1
+ require "zaikio/webhooks/configuration"
2
+ require "zaikio/webhooks/event"
3
+ require "zaikio/webhooks/engine"
4
+
5
+ module Zaikio
6
+ module Webhooks
7
+ class << self
8
+ attr_accessor :configuration
9
+
10
+ def configure
11
+ self.configuration ||= Configuration.new
12
+ yield(configuration)
13
+ end
14
+
15
+ def reset
16
+ @webhooks = {}
17
+ end
18
+
19
+ def webhooks_for(client_name, event_name)
20
+ (@webhooks.dig(client_name.to_s, event_name.to_s) || [])
21
+ end
22
+
23
+ def on(event_name, job_klass, client_name: nil, perform_now: false)
24
+ @webhooks ||= {}
25
+
26
+ client_names = Array(client_name || configuration.all_client_names).map(&:to_s)
27
+ client_names.each do |name|
28
+ @webhooks[name] ||= {}
29
+ @webhooks[name][event_name.to_s] ||= []
30
+ @webhooks[name][event_name.to_s] << {
31
+ perform_now: perform_now,
32
+ job_klass: job_klass
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zaikio-webhooks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Zaikio GmbH
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-03-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 6.0.2.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '6.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 6.0.2.2
33
+ description: Handle incoming Zaikio loom webhooks
34
+ email:
35
+ - js@crispymtn.com
36
+ executables: []
37
+ extensions: []
38
+ extra_rdoc_files: []
39
+ files:
40
+ - MIT-LICENSE
41
+ - README.md
42
+ - Rakefile
43
+ - app/controllers/zaikio/webhooks/webhooks_controller.rb
44
+ - config/routes.rb
45
+ - lib/tasks/zaikio/webhook_tasks.rake
46
+ - lib/zaikio/webhooks.rb
47
+ - lib/zaikio/webhooks/client_configuration.rb
48
+ - lib/zaikio/webhooks/configuration.rb
49
+ - lib/zaikio/webhooks/engine.rb
50
+ - lib/zaikio/webhooks/event.rb
51
+ - lib/zaikio/webhooks/version.rb
52
+ homepage: https://www.zaikio.com/
53
+ licenses:
54
+ - MIT
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubygems_version: 3.1.2
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: Handle incoming Zaikio loom webhooks
75
+ test_files: []