pezza_action_push_web 0.1.2 → 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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/app/controllers/action_push_web/subscriptions_controller.rb +2 -5
- data/app/models/action_push_web/subscription.rb +46 -0
- data/db/migrate/20251209235643_add_unique_index.rb +6 -0
- data/db/migrate/20260517003340_add_unique_index_for_null_owner.rb +6 -0
- data/lib/action_push_web/notification.rb +1 -1
- data/lib/action_push_web/pusher.rb +13 -2
- data/lib/action_push_web/subscription_notification.rb +1 -1
- data/lib/action_push_web/version.rb +1 -1
- data/lib/action_push_web.rb +1 -0
- data/lib/generators/action_push_web/install/templates/config/push.yml.tt +2 -2
- metadata +18 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 93d488729aae040d4f85f2251e45aefb608835869b9c5d568f8e538c02b0e41d
|
|
4
|
+
data.tar.gz: f6984298ffdcf0b4722bf7eb4a7efdd860befe66ac602add26061596a2bef0c2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eb237077e3d17e665abe9213a2a1aac9dbb53458b78ffef87ae3533c7239b2695927f3d94f3c0d01c0ed97e0c568fe12c4a6432a0bdcbac2f326ce2eb0469fdc
|
|
7
|
+
data.tar.gz: 0d72b0362ea10d90bd530e89eaf4efb083f8e00dff5cf287f966106782bc3ca33f014e45e7498a183844fd2b6e5c3db2441e2c36aa214e29ef3486acc010c717
|
data/README.md
CHANGED
|
@@ -93,8 +93,8 @@ shared:
|
|
|
93
93
|
# Change the subject (default: mailto:sender@example.com).
|
|
94
94
|
# expiration: mailto:support@my-domain.com
|
|
95
95
|
|
|
96
|
-
# Change the urgency (default:
|
|
97
|
-
# urgency:
|
|
96
|
+
# Change the urgency (default: high). You also choose to set this at the notification level.
|
|
97
|
+
# urgency: normal
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
This file contains the configuration for the push notification services you want to use.
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
module ActionPushWeb
|
|
2
2
|
class SubscriptionsController < ApplicationController
|
|
3
3
|
def create
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
else
|
|
7
|
-
ApplicationPushSubscription.create! push_subscription_params.merge(user_agent: request.user_agent)
|
|
8
|
-
end
|
|
4
|
+
ApplicationPushSubscription.create_with(user_agent: request.user_agent).
|
|
5
|
+
create_or_find_by!(push_subscription_params)
|
|
9
6
|
|
|
10
7
|
head :ok
|
|
11
8
|
end
|
|
@@ -2,12 +2,58 @@ module ActionPushWeb
|
|
|
2
2
|
class Subscription < ApplicationRecord
|
|
3
3
|
include ActiveSupport::Rescuable
|
|
4
4
|
|
|
5
|
+
PERMITTED_ENDPOINT_HOSTS = %w[
|
|
6
|
+
jmt17.google.com
|
|
7
|
+
fcm.googleapis.com
|
|
8
|
+
updates.push.services.mozilla.com
|
|
9
|
+
web.push.apple.com
|
|
10
|
+
notify.windows.com
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
5
13
|
rescue_from(TokenError) { destroy! }
|
|
6
14
|
|
|
7
15
|
belongs_to :owner, polymorphic: true, optional: true
|
|
8
16
|
|
|
17
|
+
validates :endpoint, presence: true
|
|
18
|
+
validate :validate_endpoint_url
|
|
19
|
+
|
|
9
20
|
def push(notification)
|
|
10
21
|
ActionPushWeb.push(SubscriptionNotification.new(notification:, subscription: self))
|
|
11
22
|
end
|
|
23
|
+
|
|
24
|
+
def resolved_endpoint_ip
|
|
25
|
+
return @resolved_endpoint_ip if defined?(@resolved_endpoint_ip)
|
|
26
|
+
@resolved_endpoint_ip = Surfguard.resolve_public_ips(endpoint_uri&.host).first
|
|
27
|
+
rescue Surfguard::Unresolvable
|
|
28
|
+
# A host that resolves to nothing has no usable public IP, same outcome as
|
|
29
|
+
# one whose only addresses are blocked: no endpoint IP to pin, which fails
|
|
30
|
+
# endpoint validation. Push has no lookup-failed surface to distinguish.
|
|
31
|
+
@resolved_endpoint_ip = nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def endpoint_uri
|
|
37
|
+
@endpoint_uri ||= URI.parse(endpoint) if endpoint.present?
|
|
38
|
+
rescue URI::InvalidURIError
|
|
39
|
+
nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def validate_endpoint_url
|
|
43
|
+
if endpoint_uri.nil?
|
|
44
|
+
errors.add(:endpoint, "is not a valid URL")
|
|
45
|
+
elsif endpoint_uri.scheme != "https"
|
|
46
|
+
errors.add(:endpoint, "must use HTTPS")
|
|
47
|
+
elsif !permitted_endpoint_host?
|
|
48
|
+
errors.add(:endpoint, "is not a permitted push service")
|
|
49
|
+
elsif resolved_endpoint_ip.nil?
|
|
50
|
+
errors.add(:endpoint, "resolves to a private or invalid IP address")
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def permitted_endpoint_host?
|
|
55
|
+
host = endpoint_uri&.host&.downcase
|
|
56
|
+
PERMITTED_ENDPOINT_HOSTS.any? { |permitted| host&.end_with?(permitted) }
|
|
57
|
+
end
|
|
12
58
|
end
|
|
13
59
|
end
|
|
@@ -10,7 +10,11 @@ module ActionPushWeb
|
|
|
10
10
|
it.body = payload
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
if resolved_endpoint_ip
|
|
14
|
+
pinned_connection.request(request)
|
|
15
|
+
else
|
|
16
|
+
connection.request(uri, request)
|
|
17
|
+
end.tap { handle_response(it) }
|
|
14
18
|
rescue OpenSSL::OpenSSLError
|
|
15
19
|
raise TokenError.new
|
|
16
20
|
end
|
|
@@ -20,7 +24,7 @@ module ActionPushWeb
|
|
|
20
24
|
attr_reader :config, :notification
|
|
21
25
|
|
|
22
26
|
delegate :title, :body, :icon_path, :path, :silent, :badge, :endpoint, :p256dh_key,
|
|
23
|
-
:auth_key, to: :notification
|
|
27
|
+
:auth_key, :resolved_endpoint_ip, to: :notification
|
|
24
28
|
|
|
25
29
|
def message
|
|
26
30
|
JSON.generate title:, options: { body:, icon: icon_path, silent:, badge:, data: { path: } }
|
|
@@ -38,6 +42,13 @@ module ActionPushWeb
|
|
|
38
42
|
@uri ||= URI.parse(endpoint)
|
|
39
43
|
end
|
|
40
44
|
|
|
45
|
+
def pinned_connection
|
|
46
|
+
Net::HTTP.new(uri.host, uri.port).tap do |http|
|
|
47
|
+
http.ipaddr = resolved_endpoint_ip
|
|
48
|
+
http.use_ssl = true
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
41
52
|
def headers
|
|
42
53
|
headers = {}
|
|
43
54
|
headers["Content-Type"] = "application/octet-stream"
|
|
@@ -8,6 +8,6 @@ module ActionPushWeb
|
|
|
8
8
|
attr_reader :notification, :subscription
|
|
9
9
|
|
|
10
10
|
delegate_missing_to :notification
|
|
11
|
-
delegate :endpoint, :p256dh_key, :auth_key, to: :subscription
|
|
11
|
+
delegate :endpoint, :p256dh_key, :auth_key, :resolved_endpoint_ip, to: :subscription
|
|
12
12
|
end
|
|
13
13
|
end
|
data/lib/action_push_web.rb
CHANGED
|
@@ -15,8 +15,8 @@ shared:
|
|
|
15
15
|
# Change the subject (default: mailto:sender@example.com).
|
|
16
16
|
# subject: mailto:support@my-domain.com
|
|
17
17
|
|
|
18
|
-
# Change the urgency (default:
|
|
19
|
-
# urgency:
|
|
18
|
+
# Change the urgency (default: high). You also choose to set this at the notification level.
|
|
19
|
+
# urgency: normal
|
|
20
20
|
|
|
21
21
|
# Change the icon path (default: nil). You also choose to set this at the notification level.
|
|
22
22
|
# icon_path: https://example.com/icon.png
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pezza_action_push_web
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nick Pezza
|
|
@@ -93,6 +93,20 @@ dependencies:
|
|
|
93
93
|
- - ">="
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
95
|
version: '0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: surfguard
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
type: :runtime
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
96
110
|
description: Send push notifications to web apps
|
|
97
111
|
email:
|
|
98
112
|
- pezza@hey.com
|
|
@@ -116,6 +130,8 @@ files:
|
|
|
116
130
|
- config/importmap.rb
|
|
117
131
|
- config/routes.rb
|
|
118
132
|
- db/migrate/20250907213606_create_action_push_web_subscriptions.rb
|
|
133
|
+
- db/migrate/20251209235643_add_unique_index.rb
|
|
134
|
+
- db/migrate/20260517003340_add_unique_index_for_null_owner.rb
|
|
119
135
|
- lib/action_push_web.rb
|
|
120
136
|
- lib/action_push_web/engine.rb
|
|
121
137
|
- lib/action_push_web/errors.rb
|
|
@@ -156,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
156
172
|
- !ruby/object:Gem::Version
|
|
157
173
|
version: '0'
|
|
158
174
|
requirements: []
|
|
159
|
-
rubygems_version:
|
|
175
|
+
rubygems_version: 4.0.18
|
|
160
176
|
specification_version: 4
|
|
161
177
|
summary: Send push notifications to web apps
|
|
162
178
|
test_files: []
|