fuik 0.5.0 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b6a7e1fbd1184f851bc0d1cd17013aaf4d84575e8e33ad6db6c16b7a428b3c2
4
- data.tar.gz: 41ffd19e734216ca8b5503b461ffb600e9749de0610e27899c7b672922a25ae0
3
+ metadata.gz: 5c68174e847f42afee9dab0fd8777877a9b53d6166942e493b069006eddd44af
4
+ data.tar.gz: 68bb2bec0d47a7f347150ecca7330b63dd304fda52d14fca1250d7279fd56978
5
5
  SHA512:
6
- metadata.gz: 2f232b48c331815d4aa07fe0796ba7cecddeab26a835950ac1e874c5a602de8a76ad73eedd0c58dfdd0f7f7d6850205989666434ef1e76f3f709cb7297e3c710
7
- data.tar.gz: 229f5f61ec154a18e2213f3131150c3013430f1025457db1a91d84cfe4bab680c13cdb815152544b84ae32483bf6a3293c3d00a591b5f08da95258d42e330209
6
+ metadata.gz: 128b403d2748c3bf8fb268d980a946335ad98043a70c38022b717f4d367ac09c88a93984a12802400443ba2634c2f3a6a869da3f00741d61b930f25343d84f2a
7
+ data.tar.gz: '0809ff55133946fcc8c0e80849a9ad77c0e36c3c9ee951cd1b58a6e7be5b90ed67c5d3c7819c127f8be977b26c2e4c926e3b5a053cddd1c1638cbe063d3b6423'
data/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  Fuik (Dutch for fish trap) is a Rails engine that catches and stores webhooks from any provider. View all events in the admin interface, then create event classes to add your business logic.
6
6
 
7
+ <img alt="Fuik admin interface" src="https://raw.githubusercontent.com/Rails-Designer/fuik/HEAD/.github/docs/webhooks-index.jpg" style="max-width: 100%;">
8
+
7
9
 
8
10
  **Sponsored By [Rails Designer](https://railsdesigner.com/)**
9
11
 
@@ -54,7 +56,9 @@ The engine mounts at `/webhooks` automatically.
54
56
 
55
57
  Visit `/webhooks` to see all received webhooks. Click any event to see the full payload, headers and status.
56
58
 
57
- <img alt="Fuik admin interface" src="https://raw.githubusercontent.com/Rails-Designer/fuik/HEAD/.github/docs/webhooks-index.jpg" style="max-width: 100%;">
59
+ <img alt="Fuik event detail interface" src="https://raw.githubusercontent.com/Rails-Designer/fuik/HEAD/.github/docs/event-detail.jpg" style="max-width: 100%;">
60
+
61
+ ⚠️ The `/webhooks` path is by default not protected. Easiest is to set `Fuik::Engine.config.events_controller_parent` to a controller that requires authentication.
58
62
 
59
63
 
60
64
  ### Add business logic
@@ -112,7 +116,7 @@ If `Provider::Base.verify!` exists, Fuik calls it automatically. Invalid signatu
112
116
 
113
117
  ### Pre-packaged providers
114
118
 
115
- Fuik includes ready-to-use [templates for common providers](https://github.com/Rails-Desinger/fuik/tree/main/lib/generators/fuik/provider/templates).
119
+ Fuik includes ready-to-use [templates for common providers](https://github.com/Rails-Designer/fuik/tree/main/lib/generators/fuik/provider/templates).
116
120
 
117
121
 
118
122
  ### Event type & ID lookup
@@ -148,7 +152,7 @@ event_id:
148
152
 
149
153
  ## Add your custom provider
150
154
 
151
- Have a provider template others could use? Add it to [lib/generators/fuik/provider/templates/your_provider/](https://github.com/Rails-Desinger/fuik/tree/main/lib/generators/fuik/provider/templates) and submit a PR!
155
+ Have a provider template others could use? Add it to [lib/generators/fuik/provider/templates/your_provider/](https://github.com/Rails-Designer/fuik/tree/main/lib/generators/fuik/provider/templates) and submit a PR!
152
156
 
153
157
  Include:
154
158
  - `base.rb.tt` with signature verification (if applicable);
@@ -8,18 +8,20 @@
8
8
  --color-bg-hover: oklch(97% 0.01 250);
9
9
  }
10
10
 
11
- * { box-sizing: border-box; }
11
+ * { box-sizing: border-box; margin: 0; padding: 0; }
12
12
 
13
13
  body {
14
- margin: 0;
15
- padding: 2rem;
16
- max-inline-size: 80rem;
17
- margin-inline: auto;
18
14
  font-family: system-ui, -apple-system, sans-serif;
19
15
  line-height: 1.5;
20
16
  color: var(--color-text);
21
17
  }
22
18
 
19
+ main {
20
+ padding: 2rem;
21
+ max-inline-size: 80rem;
22
+ margin-inline: auto;
23
+ }
24
+
23
25
  h1 {
24
26
  margin-block-end: 1rem;
25
27
  font-size: 1.875rem;
@@ -49,19 +51,49 @@
49
51
  background: var(--color-bg-hover);
50
52
  border-radius: .5rem;
51
53
  overflow-x: auto;
54
+ }
52
55
  }
53
56
 
54
57
  dl {
55
58
  display: grid;
56
59
  grid-template-columns: auto 1fr;
57
60
  gap: 1rem 2rem;
61
+ overflow: hidden;
58
62
 
59
63
  dt {
60
64
  font-weight: 600;
61
65
  color: var(--color-text);
62
66
  }
63
67
 
64
- dd { margin: 0; }
68
+ dd {
69
+ position: relative;
70
+ overflow-x: auto;
71
+ }
72
+ }
73
+
74
+ .copy-button {
75
+ padding: .125rem;
76
+ color: oklch(from var(--color-text) l c h / 80%);
77
+ background: var(--color-bg);
78
+ border: 0;
79
+ border-radius: .25rem;
80
+ cursor: pointer;
81
+
82
+ &:hover {
83
+ color: oklch(from var(--color-text) l c h);
84
+ transition: transform ease-in-out 300ms;
85
+ transform: scale(1.10);
86
+ }
87
+
88
+ &[position="fixed"] {
89
+ position: absolute;
90
+ top: .5rem; right: .5rem;
91
+ }
92
+
93
+ svg {
94
+ width: 1rem;
95
+ aspect-ratio: 1 / 1;
96
+ }
65
97
  }
66
98
  }
67
99
 
@@ -59,7 +59,7 @@ module Fuik
59
59
  end
60
60
 
61
61
  def event_class_for(provider, event_type)
62
- "#{provider.camelize}::#{event_type.tr("./:-", "_").camelize}".safe_constantize
62
+ "#{provider.camelize}::#{event_type.tr("./:-[]", "_").camelize}".safe_constantize
63
63
  end
64
64
 
65
65
  def should_verify? = base_class&.respond_to?(:verify!)
@@ -0,0 +1,6 @@
1
+ <%# locals: (target:, delay: 5000, position: :relative) %>
2
+ <button data-action="copy" data-target="<%= target %>" data-copy-delay="<%= delay %>" position="<%= position %>" class="copy-button">
3
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon" stroke-width="">
4
+ <path fill-rule="evenodd" d="M13.887 3.182c.396.037.79.08 1.183.128C16.194 3.45 17 4.414 17 5.517V16.75A2.25 2.25 0 0 1 14.75 19h-9.5A2.25 2.25 0 0 1 3 16.75V5.517c0-1.103.806-2.068 1.93-2.207.393-.048.787-.09 1.183-.128A3.001 3.001 0 0 1 9 1h2c1.373 0 2.531.923 2.887 2.182ZM7.5 4A1.5 1.5 0 0 1 9 2.5h2A1.5 1.5 0 0 1 12.5 4v.5h-5V4Z" clip-rule="evenodd" ></path>
5
+ </svg>
6
+ </button>
@@ -7,7 +7,7 @@
7
7
  <dd><%= @webhook_event.provider %></dd>
8
8
 
9
9
  <dt>Event ID</dt>
10
- <dd><%= @webhook_event.event_id %></dd>
10
+ <dd><%= tag.code @webhook_event.event_id, id: "event_id" %> <%= render "copy_button", target: "#event_id" %></dd>
11
11
 
12
12
  <dt>Type</dt>
13
13
  <dd><%= @webhook_event.event_type %></dd>
@@ -19,10 +19,10 @@
19
19
  <dd><%= @webhook_event.created_at.strftime("%Y-%m-%d %H:%M:%S") %></dd>
20
20
 
21
21
  <dt>Payload</dt>
22
- <dd><pre><%= JSON.pretty_generate(@webhook_event.payload) %></pre></dd>
22
+ <dd><pre id="payload"><%= JSON.pretty_generate(@webhook_event.payload) %></pre> <%= render "copy_button", target: "#payload", position: :fixed %></dd>
23
23
 
24
24
  <dt>Headers</dt>
25
- <dd><pre><%= JSON.pretty_generate(@webhook_event.headers) %></pre></dd>
25
+ <dd><pre id="headers"><%= JSON.pretty_generate(@webhook_event.headers) %></pre> <%= render "copy_button", target: "#headers", position: :fixed %></dd>
26
26
 
27
27
  <% if @webhook_event.error.present? %>
28
28
  <dt>Error</dt>
@@ -8,10 +8,11 @@
8
8
  <%= yield :head %>
9
9
 
10
10
  <%= stylesheet_link_tag "fuik/application", media: "all" %>
11
+ <script defer src="https://cdn.jsdelivr.net/npm/attractivejs@0.11.0"></script>
11
12
  </head>
12
13
  <body>
13
-
14
- <%= yield %>
15
-
14
+ <main>
15
+ <%= yield %>
16
+ </main>
16
17
  </body>
17
18
  </html>
data/lib/fuik/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Fuik
2
- VERSION = "0.5.0"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -12,10 +12,6 @@ module Fuik
12
12
  def add_route
13
13
  route 'mount Fuik::Engine => "/webhooks"'
14
14
  end
15
-
16
- def show_readme
17
- readme "README" if behavior == :invoke
18
- end
19
15
  end
20
16
  end
21
17
  end
@@ -9,7 +9,11 @@ module Fuik
9
9
  argument :event_names, type: :array, default: []
10
10
 
11
11
  def create_base_class
12
- template "base.rb.tt", "app/webhooks/#{file_name}/base.rb"
12
+ if packaged_base_exists?
13
+ template packaged_base_template_path, "app/webhooks/#{file_name}/base.rb"
14
+ else
15
+ template "base.rb.tt", "app/webhooks/#{file_name}/base.rb"
16
+ end
13
17
  end
14
18
 
15
19
  def create_event_classes
@@ -26,6 +30,14 @@ module Fuik
26
30
 
27
31
  private
28
32
 
33
+ def packaged_base_exists?
34
+ File.exist?(packaged_base_template_path)
35
+ end
36
+
37
+ def packaged_base_template_path
38
+ File.join(self.class.source_root, file_name, "base.rb.tt")
39
+ end
40
+
29
41
  def packaged_event_exists? = File.exist?(packaged_event_template_path)
30
42
 
31
43
  def copy_packaged_event
@@ -38,7 +50,7 @@ module Fuik
38
50
 
39
51
  def packaged_event_template_path = File.join(self.class.source_root, "providers", file_name, "#{event_file_name}.rb.tt")
40
52
 
41
- def event_file_path = Rails.join("app", "webhooks", file_name, "#{event_file_name}.rb")
53
+ def event_file_path = Rails.root.join("app", "webhooks", file_name, "#{event_file_name}.rb")
42
54
 
43
55
  def event_file_name = @event_name.underscore
44
56
 
@@ -1,7 +1,7 @@
1
1
  module <%= provider_module_name %>
2
2
  class Base < Fuik::Event
3
3
  def self.verify!(request)
4
- secret = Rails.application.credentials.dig(:webhooks, :github, :secret)
4
+ secret = Rails.application.credentials.dig(:github, :secret)
5
5
  signature = request.headers["X-Hub-Signature-256"]
6
6
  expected_signature = "sha256=" + OpenSSL::HMAC.hexdigest("SHA256", secret, request.raw_post)
7
7
 
@@ -1,7 +1,7 @@
1
1
  module <%= provider_module_name %>
2
2
  class Base < Fuik::Event
3
3
  def self.verify!(request)
4
- public_key_base64 = Rails.application.credentials.dig(:webhooks, :mailpace, :public_key)
4
+ public_key_base64 = Rails.application.credentials.dig(:mailpace, :public_key)
5
5
  signature_base64 = request.headers["X-MailPace-Signature"]
6
6
 
7
7
  verify_key = Ed25519::VerifyKey.new(Base64.strict_decode64(public_key_base64))
@@ -1,7 +1,7 @@
1
1
  module <%= provider_module_name %>
2
2
  class Base < Fuik::Event
3
3
  def self.verify!(request)
4
- secret = Rails.application.credentials.dig(:webhooks, :stripe, :secret)
4
+ secret = Rails.application.credentials.dig(:stripe, :signing_secret)
5
5
  signature = request.headers["Stripe-Signature"]
6
6
 
7
7
  Stripe::Webhook.construct_event(
@@ -1,12 +1,14 @@
1
- module <%= provider_module_name %>
2
- class <%= event_class_name %> < Base
1
+ module Stripe
2
+ class CheckoutSessionCompleted < Base
3
3
  def process!
4
- session_id = payload.dig("data", "object", "id")
5
-
6
4
  # TODO: Add business logic
7
5
  # session = Stripe::Checkout::Session.retrieve(session_id) # this assumes the Stripe gem is available
8
6
 
9
7
  @webhook_event.processed!
10
8
  end
9
+
10
+ private
11
+
12
+ def session_id = payload.dig("data", "object", "id")
11
13
  end
12
14
  end
@@ -1,5 +1,5 @@
1
- module <%= provider_module_name %>
2
- class <%= event_class_name %> < Base
1
+ module Stripe
2
+ class CustomerSubscriptionDeleted < Base
3
3
  def process!
4
4
  subscription_id = payload.dig("data", "object", "id")
5
5
 
@@ -1,11 +1,13 @@
1
- module <%= provider_module_name %>
2
- class <%= event_class_name %> < Base
1
+ module Stripe
2
+ class CustomerSubscriptionUpdated < Base
3
3
  def process!
4
- subscription_id = payload.dig("data", "object", "id")
5
-
6
4
  # TODO: Add business logic
7
5
 
8
6
  @webhook_event.processed!
9
7
  end
8
+
9
+ private
10
+
11
+ def subscription_id = payload.dig("data", "object", "id")
10
12
  end
11
13
  end
@@ -0,0 +1,13 @@
1
+ module Stripe
2
+ class PaymentIntentSucceeded < Base
3
+ def process!
4
+ # TODO: Add business logic
5
+
6
+ @webhook_event.processed!
7
+ end
8
+
9
+ private
10
+
11
+ def payment_intent_id = payload["data"]["object"]["id"]
12
+ end
13
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fuik
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rails Designer
@@ -23,7 +23,9 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: 7.0.0
26
- description: TBD
26
+ description: Fuik (Dutch for fish trap) is a Rails engine that catches and stores
27
+ webhooks from any provider. View all events in the admin interface, then create
28
+ event classes to add your business logic.
27
29
  email:
28
30
  - devs@railsdesigner.com
29
31
  executables: []
@@ -42,6 +44,7 @@ files:
42
44
  - app/models/fuik/application_record.rb
43
45
  - app/models/fuik/event.rb
44
46
  - app/models/fuik/webhook_event.rb
47
+ - app/views/fuik/events/_copy_button.html.erb
45
48
  - app/views/fuik/events/index.html.erb
46
49
  - app/views/fuik/events/show.html.erb
47
50
  - app/views/layouts/fuik/application.html.erb
@@ -51,7 +54,6 @@ files:
51
54
  - lib/fuik/engine.rb
52
55
  - lib/fuik/version.rb
53
56
  - lib/generators/fuik/install/install_generator.rb
54
- - lib/generators/fuik/install/templates/README
55
57
  - lib/generators/fuik/provider/provider_generator.rb
56
58
  - lib/generators/fuik/provider/templates/README
57
59
  - lib/generators/fuik/provider/templates/base.rb.tt
@@ -67,6 +69,7 @@ files:
67
69
  - lib/generators/fuik/provider/templates/stripe/checkout_session_completed.rb.tt
68
70
  - lib/generators/fuik/provider/templates/stripe/customer_subscription_deleted.rb.tt
69
71
  - lib/generators/fuik/provider/templates/stripe/customer_subscription_updated.rb.tt
72
+ - lib/generators/fuik/provider/templates/stripe/payment_intent_succeeded.rb.tt
70
73
  homepage: https://railsdesigner.com/fuik/
71
74
  licenses:
72
75
  - MIT
@@ -87,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
90
  - !ruby/object:Gem::Version
88
91
  version: '0'
89
92
  requirements: []
90
- rubygems_version: 4.0.0
93
+ rubygems_version: 4.0.4
91
94
  specification_version: 4
92
- summary: TBD
95
+ summary: A fish trap for webhooks
93
96
  test_files: []
@@ -1,24 +0,0 @@
1
- ===============================================================================
2
-
3
- Fuik has been installed! 🎣
4
-
5
- Next steps:
6
-
7
- 1. Run migrations:
8
- rails db:migrate
9
-
10
- 2. Webhooks can be sent to:
11
- POST /webhooks/:provider
12
-
13
- Example: POST /webhooks/stripe
14
-
15
- 3. (Optional) Generate webhook class for a provider:
16
- rails generate fuik:provider stripe checkout_session_completed
17
-
18
- Or start from scratch:
19
- rails generate fuik:provider custom_provider my_event
20
-
21
- 4. View received webhooks at:
22
- GET /webhooks
23
-
24
- ===============================================================================