-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
close #766 add webhook subscriber rule
- Loading branch information
Showing
25 changed files
with
454 additions
and
1 deletion.
There are no files selected for viewing
44 changes: 44 additions & 0 deletions
44
app/controllers/spree/admin/webhooks_subscriber_rules_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
module Spree | ||
module Admin | ||
class WebhooksSubscriberRulesController < Spree::Admin::ResourceController | ||
before_action :load_webhooks_subscriber | ||
|
||
def load_webhooks_subscriber | ||
@webhooks_subscriber = Spree::Webhooks::Subscriber.find(params[:webhooks_subscriber_id]) | ||
end | ||
|
||
def scope | ||
load_webhooks_subscriber | ||
|
||
@webhooks_subscriber.rules | ||
end | ||
|
||
# @overrided | ||
def collection | ||
scope | ||
end | ||
|
||
# @overrided | ||
def load_resource_instance | ||
return scope.new if new_actions.include?(action) | ||
|
||
scope.find(params[:id]) | ||
end | ||
|
||
def collection_url(options = {}) | ||
edit_admin_webhooks_subscriber_url(params[:webhooks_subscriber_id], options) | ||
end | ||
|
||
# @overrided | ||
def model_class | ||
SpreeCmCommissioner::Webhooks::SubscriberRule | ||
end | ||
|
||
# @overrided | ||
# depend on type of rule eg. spree_cm_commissioner_webhooks_rules_vendors | ||
def object_name | ||
@object.class.to_s.underscore.tr('/', '_') | ||
end | ||
end | ||
end | ||
end |
53 changes: 53 additions & 0 deletions
53
app/models/concerns/spree_cm_commissioner/webhooks/subscriber_rulable.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
module SpreeCmCommissioner | ||
module Webhooks | ||
module SubscriberRulable | ||
extend ActiveSupport::Concern | ||
|
||
MATCH_POLICIES = %i[all any].freeze | ||
|
||
SUPPORTED_RULE_TYPES = [ | ||
SpreeCmCommissioner::Webhooks::Rules::OrderStates, | ||
SpreeCmCommissioner::Webhooks::Rules::OrderVendors | ||
].map(&:to_s) | ||
|
||
included do | ||
enum match_policy: MATCH_POLICIES, _prefix: true | ||
|
||
has_many :rules, autosave: true, dependent: :destroy, class_name: 'SpreeCmCommissioner::Webhooks::SubscriberRule' | ||
end | ||
|
||
def available_rule_types | ||
existing = rules.pluck(:type) | ||
|
||
SUPPORTED_RULE_TYPES.reject { |r| existing.include? r } | ||
end | ||
|
||
def match_all? | ||
match_policy == 'all' | ||
end | ||
|
||
def match_any? | ||
match_policy == 'any' | ||
end | ||
|
||
def matches?(event, webhook_payload_body, options = {}) | ||
# Subscriber without rules are always match by default. | ||
return true if rules.none? | ||
|
||
# Reject if event is not supported by rules | ||
supported_rules = rules.select { |rule| rule.supported?(event) } | ||
return false if supported_rules.none? | ||
|
||
if match_all? | ||
supported_rules.all? do |rule| | ||
rule.matches?(event, webhook_payload_body, options) | ||
end | ||
elsif match_any? | ||
supported_rules.any? do |rule| | ||
rule.matches?(event, webhook_payload_body, options) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module SpreeCmCommissioner | ||
module Webhooks | ||
def self.table_name_prefix | ||
'cm_webhooks_' | ||
end | ||
end | ||
end |
43 changes: 43 additions & 0 deletions
43
app/models/spree_cm_commissioner/webhooks/rules/order_states.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
module SpreeCmCommissioner | ||
module Webhooks | ||
module Rules | ||
class OrderStates < SubscriberRule | ||
SUPPORTED_EVENTS = [ | ||
'order.create', | ||
'order.delete', | ||
'order.update', | ||
'order.canceled', | ||
'order.placed', | ||
'order.resumed', | ||
'order.shipped' | ||
].freeze | ||
|
||
DEFAULT_STATES = %w[ | ||
cart | ||
address | ||
payment | ||
complete | ||
delivery | ||
awaiting_return | ||
canceled | ||
returned | ||
resumed | ||
].freeze | ||
|
||
preference :states, :array, default: DEFAULT_STATES | ||
|
||
def supported?(event) | ||
SUPPORTED_EVENTS.includes?(event) | ||
end | ||
|
||
def matches?(_event, webhook_payload_body, _options = {}) | ||
payload_body = JSON.parse(webhook_payload_body) | ||
|
||
state = payload_body['data']['attributes']['state'] | ||
|
||
preferred_states.contains(state) | ||
end | ||
end | ||
end | ||
end | ||
end |
41 changes: 41 additions & 0 deletions
41
app/models/spree_cm_commissioner/webhooks/rules/order_vendors.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
module SpreeCmCommissioner | ||
module Webhooks | ||
module Rules | ||
class OrderVendors < SubscriberRule | ||
MATCH_POLICIES = %w[any all].freeze | ||
|
||
SUPPORTED_EVENTS = [ | ||
'order.create', | ||
'order.delete', | ||
'order.update', | ||
'order.canceled', | ||
'order.placed', | ||
'order.resumed', | ||
'order.shipped' | ||
].freeze | ||
|
||
preference :match_policy, :string, default: MATCH_POLICIES.first | ||
preference :vendors, :array | ||
|
||
def supported?(event) | ||
SUPPORTED_EVENTS.includes?(event) | ||
end | ||
|
||
def matches?(_event, webhook_payload_body, _options = {}) | ||
payload_body = JSON.parse(webhook_payload_body) | ||
|
||
vendor_ids = payload_body['included'].filter_map do |include| | ||
return include['id'] if include['type'] == 'vendor' | ||
end | ||
|
||
case preferred_match_policy | ||
when 'any' | ||
preferred_vendors.any? { |vendor_id| vendor_ids.includes?(vendor_id) } | ||
when 'all' | ||
preferred_vendors.all? { |vendor_id| vendor_ids.includes?(vendor_id) } | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
13 changes: 13 additions & 0 deletions
13
app/models/spree_cm_commissioner/webhooks/subscriber_decorator.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module SpreeCmCommissioner | ||
module Webhooks | ||
module SubscriberDecorator | ||
def self.prepended(base) | ||
base.include SpreeCmCommissioner::Webhooks::SubscriberRulable | ||
end | ||
end | ||
end | ||
end | ||
|
||
unless Spree::Webhooks::Subscriber.included_modules.include?(SpreeCmCommissioner::Webhooks::SubscriberDecorator) | ||
Spree::Webhooks::Subscriber.prepend(SpreeCmCommissioner::Webhooks::SubscriberDecorator) | ||
end |
11 changes: 11 additions & 0 deletions
11
app/models/spree_cm_commissioner/webhooks/subscriber_rule.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
module SpreeCmCommissioner | ||
module Webhooks | ||
class SubscriberRule < Base | ||
belongs_to :subscriber, class_name: 'Spree::Webhooks::Subscriber', inverse_of: :rules | ||
|
||
def matches?(_event, _webhook_payload_body, _options = {}) | ||
raise 'matches? should be implemented in a sub-class of SpreeCmCommissioner::Webhooks::SubscriberRule' | ||
end | ||
end | ||
end | ||
end |
7 changes: 7 additions & 0 deletions
7
app/overrides/spree/admin/webhooks_subscribers/_form/api_key.html.erb.deface
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<!-- insert_top "[data-hook='admin_webhooks_subscriber_form_fields']" --> | ||
|
||
<%= f.field_container :api_key, class: ['form-group'] do %> | ||
<%= f.label :api_key, '3rd API key' %> | ||
<%= f.text_field :api_key, class: 'form-control', placeholder: 'Headers : X-Api-key' %> | ||
<%= f.error_message_on :api_key %> | ||
<% end %> |
51 changes: 51 additions & 0 deletions
51
app/overrides/spree/admin/webhooks_subscribers/_form/rules.html.erb.deface
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<!-- insert_bottom "[data-hook='admin_webhooks_subscriber_form_fields']" --> | ||
|
||
<div class="mb-4"> | ||
<div class="mb-2 d-flex justify-content-between align-items-center"> | ||
<div>Rules</div> | ||
<%= button_link_to Spree.t(:new), new_admin_webhooks_subscriber_rule_path(@webhooks_subscriber), class: "btn-light", icon: 'add.svg' %> | ||
</div> | ||
|
||
<% if @webhooks_subscriber.rules.any? %> | ||
<table class="table border" id="admin_webhooks_subscriber_rules"> | ||
<thead class="text-muted"> | ||
<tr data-hook="admin_webhooks_subscriber_rules_index_headers"> | ||
<th><%= Spree.t(:id) %></th> | ||
<th><%= Spree.t(:rule) %></th> | ||
<th><%= Spree.t(:preferences) %></th> | ||
<th><%= Spree.t(:supported_events) %></th> | ||
<th><%= Spree.t(:created_at) %></th> | ||
<th><%= Spree.t(:updated_at) %></th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<% @webhooks_subscriber.rules.each do |rule| %> | ||
<tr id="<%= spree_dom_id rule %>" data-hook="admin_webhooks_subscriber_rules_index_rows"> | ||
<td><%= rule.id %></td> | ||
<td><%= rule.class.name.demodulize %></td> | ||
<td><%= rule.preferences %></td> | ||
<td><%= rule.class::SUPPORTED_EVENTS.to_sentence %></td> | ||
<td><%= rule.created_at %></td> | ||
<td><%= rule.updated_at %></td> | ||
<td data-hook="admin_webhooks_subscriber_rules_index_row_actions" class="actions"> | ||
<span class="d-flex justify-content-end"> | ||
<%= link_to_edit rule, url: edit_admin_webhooks_subscriber_rule_path(@webhooks_subscriber, rule), no_text: true if can?(:edit, rule) %> | ||
<%= link_to_delete rule, url: admin_webhooks_subscriber_rule_path(@webhooks_subscriber, rule), no_text: true if can?(:delete, rule) %> | ||
</span> | ||
</td> | ||
</tr> | ||
<% end %> | ||
</tbody> | ||
</table> | ||
<% else %> | ||
<small class="form-text text-muted"> | ||
<%= raw I18n.t('webhooks_subscriber_rules.empty_info') %> | ||
</small> | ||
<% end %> | ||
</div> | ||
|
||
<%= f.field_container :match_policy, class: ['form-group'] do %> | ||
<%= f.label :match_policy, Spree.t(:match_policy) %></span> | ||
<%= f.select :match_policy, @object.class::MATCH_POLICIES, {}, :class => "fullwidth select2" %> | ||
<%= f.error_message_on :match_policy %> | ||
<% end %> |
19 changes: 19 additions & 0 deletions
19
app/services/spree_cm_commissioner/webhooks/subscribers/handle_request_decorator.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
module SpreeCmCommissioner | ||
module Webhooks | ||
module Subscribers | ||
module HandleRequestDecorator | ||
def self.prepended(_base) | ||
delegate :api_key, to: :subscriber | ||
end | ||
|
||
# override | ||
def request | ||
@request ||= | ||
SpreeCmCommissioner::Webhooks::Subscribers::MakeRequest.new(url: url, api_key: api_key, webhook_payload_body: body_with_event_metadata) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
Spree::Webhooks::Subscribers::HandleRequest.prepend SpreeCmCommissioner::Webhooks::Subscribers::HandleRequestDecorator |
43 changes: 43 additions & 0 deletions
43
app/services/spree_cm_commissioner/webhooks/subscribers/make_request.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# frozen_string_literal: true | ||
|
||
module SpreeCmCommissioner | ||
module Webhooks | ||
module Subscribers | ||
class MakeRequest < Spree::Webhooks::Subscribers::MakeRequest | ||
attr_reader :api_key | ||
|
||
def initialize(url:, api_key:, webhook_payload_body:) | ||
@api_key = api_key | ||
super(url: url, webhook_payload_body: webhook_payload_body) | ||
end | ||
|
||
def headers | ||
headers = {} | ||
|
||
headers['Content-Type'] = 'application/json' | ||
headers['X-Api-Key'] = api_key if api_key.present? | ||
|
||
headers | ||
end | ||
|
||
# overrided | ||
def request | ||
req = Net::HTTP::Post.new(uri_path, headers) | ||
req.body = webhook_payload_body | ||
@request ||= begin | ||
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
request_result = http.request(req) | ||
@execution_time_in_milliseconds = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time).in_milliseconds | ||
request_result | ||
end | ||
rescue Errno::ECONNREFUSED, Net::ReadTimeout, SocketError | ||
Class.new do | ||
def self.code | ||
'0' | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
16 changes: 16 additions & 0 deletions
16
app/services/spree_cm_commissioner/webhooks/subscribers/queue_requests_decorator.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
module SpreeCmCommissioner | ||
module Webhooks | ||
module Subscribers | ||
module QueueRequestsDecorator | ||
# override | ||
def filtered_subscribers(event_name, webhook_payload_body, options) | ||
Spree::Webhooks::Subscriber.active.with_urls_for(event_name).filter do |subscriber| | ||
subscriber.matches?(event_name, webhook_payload_body, options) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
Spree::Webhooks::Subscribers::QueueRequests.prepend SpreeCmCommissioner::Webhooks::Subscribers::QueueRequestsDecorator |
18 changes: 18 additions & 0 deletions
18
app/views/spree/admin/webhooks_subscriber_rules/_form.html.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<div data-hook="admin_webhooks_subscriber_rules_form_fields"> | ||
<% unless @object.persisted? %> | ||
<%= f.field_container :type, class: ['form-group'] do %> | ||
<%= f.label :type, Spree.t(:type) %> <span class="required">*</span> | ||
<%= f.select :type, @webhooks_subscriber.available_rule_types.map { |type| [type.demodulize, type] }, {}, :class => "fullwidth select2" %> | ||
<%= f.error_message_on :type %> | ||
<% end %> | ||
<% else %> | ||
<%= f.field_container :type, class: ['form-group'] do %> | ||
<%= f.label :type, Spree.t(:type) %> <span class="required">*</span> | ||
<%= f.text_field :type, value: @object.type.demodulize,class: 'form-control', disabled: true %> | ||
<% end %> | ||
<% end %> | ||
|
||
<% if @object.persisted? %> | ||
<%= render partial: @object.class.name.demodulize.underscore, locals: { rule: @object, f: f } %> | ||
<% end %> | ||
</div> |
Oops, something went wrong.