web-push 1.0.0 → 2.0.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/.github/workflows/ci.yml +22 -0
- data/.gitignore +1 -9
- data/README.md +48 -211
- data/lib/web_push/encryption.rb +3 -5
- data/lib/web_push/request.rb +5 -33
- data/lib/web_push/vapid_key.rb +8 -3
- data/lib/web_push/version.rb +1 -1
- data/lib/web_push.rb +2 -3
- data/spec/spec_helper.rb +1 -2
- data/spec/web_push/encryption_spec.rb +3 -3
- data/spec/web_push/request_spec.rb +1 -46
- data/spec/web_push/vapid_key_spec.rb +29 -0
- data/spec/web_push_spec.rb +4 -4
- data/web-push.gemspec +5 -6
- metadata +19 -56
- data/.rspec +0 -2
- data/.rubocop.yml +0 -30
- data/.travis.yml +0 -24
- data/CHANGELOG.md +0 -183
- data/Rakefile +0 -8
- data/bin/console +0 -14
- data/bin/rake +0 -16
- data/bin/rspec +0 -16
- data/bin/setup +0 -8
- data/lib/tasks/web_push.rake +0 -14
- data/lib/web_push/railtie.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ce88ebd076b697f1933784607d0e7d743e66c0fe2a3522b2d91fbf8f7d674b4
|
4
|
+
data.tar.gz: b8eede6dba32f1933ab8ea706dd27dcc7d54fcc2a1bafb6c63249accc2e335f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8cfedadf6aa0335ac451df3b47358b801802aed8e81f49ab869826eef67ff64bb06950095fd8764c259b37165dd5cdd7537521f23957cde359bb41e14661f53d
|
7
|
+
data.tar.gz: 8cb1d4e8711c0356dd22b10befaf535cbe9fbc3878bb18414f708dfa378472f2728d576641831822c63928320c10b79ded83cc888542280a9161eb83b194df86
|
@@ -0,0 +1,22 @@
|
|
1
|
+
name: CI
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches: [ master ]
|
5
|
+
pull_request:
|
6
|
+
branches: [ master ]
|
7
|
+
jobs:
|
8
|
+
test:
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
strategy:
|
11
|
+
fail-fast: false
|
12
|
+
matrix:
|
13
|
+
ruby-version: ['3.0', '3.1']
|
14
|
+
steps:
|
15
|
+
- uses: actions/checkout@v3
|
16
|
+
- name: Set up Ruby
|
17
|
+
uses: ruby/setup-ruby@v1
|
18
|
+
with:
|
19
|
+
ruby-version: ${{ matrix.ruby-version }}
|
20
|
+
bundler-cache: true
|
21
|
+
- name: Run tests
|
22
|
+
run: bundle exec rspec
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,45 +1,35 @@
|
|
1
1
|
# WebPush
|
2
2
|
|
3
|
-
[](https://travis-ci.org/zaru/webpush)
|
6
|
-
[](https://badge.fury.io/rb/webpush)
|
3
|
+
[](https://badge.fury.io/rb/web-push)
|
4
|
+

|
7
5
|
|
8
|
-
This gem makes it possible to send push messages to web browsers from Ruby backends using the [Web Push Protocol](https://
|
9
|
-
|
10
|
-
Payload is supported by Chrome 50+, Firefox 48+, Edge 79+.
|
11
|
-
|
12
|
-
[webpush Demo app here (building by Sinatra app).](https://github.com/zaru/webpush_demo_ruby)
|
6
|
+
This gem makes it possible to send push messages to web browsers from Ruby backends using the [Web Push Protocol](https://datatracker.ietf.org/doc/html/rfc8030). It supports [Message Encryption for Web Push](https://datatracker.ietf.org/doc/html/rfc8291) and [VAPID](https://datatracker.ietf.org/doc/html/rfc8292).
|
13
7
|
|
14
8
|
## Installation
|
15
9
|
|
16
|
-
Add this line to
|
10
|
+
Add this line to the Gemfile:
|
17
11
|
|
18
12
|
```ruby
|
19
13
|
gem 'web-push'
|
20
14
|
```
|
21
15
|
|
22
|
-
|
23
|
-
|
24
|
-
$ bundle
|
16
|
+
Or install the gem:
|
25
17
|
|
26
|
-
|
27
|
-
|
28
|
-
|
18
|
+
```console
|
19
|
+
$ gem install web-push
|
20
|
+
```
|
29
21
|
|
30
22
|
## Usage
|
31
23
|
|
32
24
|
Sending a web push message to a visitor of your website requires a number of steps:
|
33
25
|
|
34
|
-
1.
|
35
|
-
2.
|
36
|
-
3.
|
37
|
-
4. Your server uses the `web-push` gem to send a notification with the `subscription` obtained from the client and an optional payload (the message).
|
38
|
-
5. Your service worker is set up to receive `'push'` events. To trigger a desktop notification, the user has accepted the prompt to receive notifications from your site.
|
26
|
+
1. In the user's web browser, a `serviceWorker` is installed and activated and its `pushManager` property is subscribed to push events with your VAPID public key, which creates a `subscription` JSON object on the client side.
|
27
|
+
2. Your server uses the `web-push` gem to send a notification with the `subscription` obtained from the client and an optional payload (the message).
|
28
|
+
3. Your service worker is set up to receive `'push'` events. To trigger a desktop notification, the user has accepted the prompt to receive notifications from your site.
|
39
29
|
|
40
30
|
### Generating VAPID keys
|
41
31
|
|
42
|
-
Use `web-push` to generate a VAPID key that has both a `public_key` and `private_key`
|
32
|
+
Use `web-push` to generate a VAPID key pair (that has both a `public_key` and `private_key`) and save it on the server side.
|
43
33
|
|
44
34
|
```ruby
|
45
35
|
# One-time, on the server
|
@@ -53,64 +43,25 @@ vapid_key.private_key
|
|
53
43
|
vapid_key.to_pem
|
54
44
|
```
|
55
45
|
|
56
|
-
### Declaring manifest.json
|
57
|
-
|
58
|
-
Check out the [Web Manifest docs](https://developer.mozilla.org/en-US/docs/Web/Manifest) for details on what to include in your `manifest.json` file. If using VAPID, no app credentials are needed.
|
59
|
-
|
60
|
-
```javascript
|
61
|
-
{
|
62
|
-
"name": "My Website"
|
63
|
-
}
|
64
|
-
```
|
65
|
-
For Chrome web push, add the GCM sender id to a `manifest.json`.
|
66
|
-
|
67
|
-
```javascript
|
68
|
-
{
|
69
|
-
"name": "My Website",
|
70
|
-
"gcm_sender_id": "1006629465533"
|
71
|
-
}
|
72
|
-
```
|
73
|
-
|
74
|
-
The file is served within the scope of your service worker script, like at the root, and link to it somewhere in the `<head>` tag:
|
75
|
-
|
76
|
-
```html
|
77
|
-
<!-- index.html -->
|
78
|
-
<link rel="manifest" href="/manifest.json" />
|
79
|
-
```
|
80
|
-
|
81
46
|
### Installing a service worker
|
82
47
|
|
83
|
-
Your application
|
48
|
+
Your application must use JavaScript to register a service worker script at an appropriate scope (root is recommended).
|
84
49
|
|
85
50
|
```javascript
|
86
|
-
|
87
|
-
// Register the serviceWorker script at /serviceworker.js from your server if supported
|
88
|
-
if (navigator.serviceWorker) {
|
89
|
-
navigator.serviceWorker.register('/serviceworker.js')
|
90
|
-
.then(function(reg) {
|
91
|
-
console.log('Service worker change, registered the service worker');
|
92
|
-
});
|
93
|
-
}
|
94
|
-
// Otherwise, no push notifications :(
|
95
|
-
else {
|
96
|
-
console.error('Service worker is not supported in this browser');
|
97
|
-
}
|
51
|
+
navigator.serviceWorker.register('/service-worker.js')
|
98
52
|
```
|
99
53
|
|
100
54
|
### Subscribing to push notifications
|
101
55
|
|
102
|
-
|
103
|
-
|
104
|
-
The VAPID public key you generated earlier is made available to the client as a `UInt8Array`. To do this, one way would be to expose the urlsafe-decoded bytes from Ruby to JavaScript when rendering the HTML template. (Global variables used here for simplicity).
|
56
|
+
The VAPID public key you generated earlier is made available to the client as a `UInt8Array`. To do this, one way would be to expose the urlsafe-decoded bytes from Ruby to JavaScript when rendering the HTML template.
|
105
57
|
|
106
58
|
```javascript
|
107
59
|
window.vapidPublicKey = new Uint8Array(<%= Base64.urlsafe_decode64(ENV['VAPID_PUBLIC_KEY']).bytes %>);
|
108
60
|
```
|
109
61
|
|
110
|
-
Your
|
62
|
+
Your JavaScript code uses the `pushManager` interface to subscribe to push notifications, passing the VAPID public key to the subscription settings.
|
111
63
|
|
112
64
|
```javascript
|
113
|
-
// application.js
|
114
65
|
// When serviceWorker is supported, installed, and activated,
|
115
66
|
// subscribe the pushManager property with the vapidPublicKey
|
116
67
|
navigator.serviceWorker.ready.then((serviceWorkerRegistration) => {
|
@@ -122,120 +73,49 @@ navigator.serviceWorker.ready.then((serviceWorkerRegistration) => {
|
|
122
73
|
});
|
123
74
|
```
|
124
75
|
|
125
|
-
#### Without VAPID
|
126
|
-
|
127
|
-
If you will not be sending VAPID details, then there is no need generate VAPID keys, and the `applicationServerKey` parameter may be omitted from the `pushManager.subscribe` call.
|
128
|
-
|
129
|
-
```javascript
|
130
|
-
// application.js
|
131
|
-
// When serviceWorker is supported, installed, and activated,
|
132
|
-
// subscribe the pushManager property with the vapidPublicKey
|
133
|
-
navigator.serviceWorker.ready.then((serviceWorkerRegistration) => {
|
134
|
-
serviceWorkerRegistration.pushManager
|
135
|
-
.subscribe({
|
136
|
-
userVisibleOnly: true
|
137
|
-
});
|
138
|
-
});
|
139
|
-
```
|
140
|
-
|
141
76
|
### Triggering a web push notification
|
142
77
|
|
143
|
-
|
144
|
-
|
145
|
-
```javascript
|
146
|
-
// application.js
|
147
|
-
// Send the subscription and message from the client for the backend
|
148
|
-
// to set up a push notification
|
149
|
-
$(".web-push-button").on("click", (e) => {
|
150
|
-
navigator.serviceWorker.ready
|
151
|
-
.then((serviceWorkerRegistration) => {
|
152
|
-
serviceWorkerRegistration.pushManager.getSubscription()
|
153
|
-
.then((subscription) => {
|
154
|
-
$.post("/push", { subscription: subscription.toJSON(), message: "You clicked a button!" });
|
155
|
-
});
|
156
|
-
});
|
157
|
-
});
|
158
|
-
```
|
78
|
+
In order to send web push notifications, the push subscription must be stored in the backend. Get the subscription with `pushManager.getSubscription()` and store it in your database.
|
159
79
|
|
160
|
-
|
80
|
+
Then you can use this gem to send web push messages:
|
161
81
|
|
162
82
|
```ruby
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
ssl_timeout: 5, # value for Net::HTTP#ssl_timeout=, optional
|
178
|
-
open_timeout: 5, # value for Net::HTTP#open_timeout=, optional
|
179
|
-
read_timeout: 5 # value for Net::HTTP#read_timeout=, optional
|
180
|
-
)
|
181
|
-
end
|
83
|
+
WebPush.payload_send(
|
84
|
+
message: message,
|
85
|
+
endpoint: subscription['endpoint'],
|
86
|
+
p256dh: subscription['keys']['p256dh'],
|
87
|
+
auth: subscription['keys']['auth'],
|
88
|
+
vapid: {
|
89
|
+
subject: "mailto:sender@example.com",
|
90
|
+
public_key: ENV['VAPID_PUBLIC_KEY'],
|
91
|
+
private_key: ENV['VAPID_PRIVATE_KEY']
|
92
|
+
},
|
93
|
+
ssl_timeout: 5, # optional value for Net::HTTP#ssl_timeout=
|
94
|
+
open_timeout: 5, # optional value for Net::HTTP#open_timeout=
|
95
|
+
read_timeout: 5 # optional value for Net::HTTP#read_timeout=
|
96
|
+
)
|
182
97
|
```
|
183
98
|
|
184
|
-
Note: the VAPID options should be omitted if the client-side subscription was
|
185
|
-
generated without the `applicationServerKey` parameter described earlier. You
|
186
|
-
would instead pass the GCM api key along with the api request as shown in the
|
187
|
-
Usage section below.
|
188
|
-
|
189
99
|
### Receiving the push event
|
190
100
|
|
191
|
-
Your
|
101
|
+
Your `service-worker.js` script should respond to `'push'` events. One action it can take is to trigger desktop notifications by calling `showNotification` on the `registration` property.
|
192
102
|
|
193
103
|
```javascript
|
194
|
-
|
195
|
-
//
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
let body = "We have received a push message";
|
200
|
-
let tag = "push-simple-demo-notification-tag";
|
201
|
-
let icon = '/assets/my-logo-120x120.png';
|
202
|
-
|
203
|
-
event.waitUntil(
|
204
|
-
self.registration.showNotification(title, { body, icon, tag })
|
205
|
-
)
|
104
|
+
self.addEventListener('push', (event) => {
|
105
|
+
// Get the push message
|
106
|
+
var message = event.data;
|
107
|
+
// Display a notification
|
108
|
+
event.waitUntil(self.registration.showNotification('Example'));
|
206
109
|
});
|
207
110
|
```
|
208
111
|
|
209
|
-
Before the notifications can be displayed, the user must grant permission for [notifications](https://developer.mozilla.org/en-US/docs/Web/API/notification) in a browser prompt
|
112
|
+
Before the notifications can be displayed, the user must grant permission for [notifications](https://developer.mozilla.org/en-US/docs/Web/API/notification) in a browser prompt. Use something like this in your JavaScript code:
|
210
113
|
|
211
114
|
```javascript
|
212
|
-
|
213
|
-
|
214
|
-
// Let's check if the browser supports notifications
|
215
|
-
if (!("Notification" in window)) {
|
216
|
-
console.error("This browser does not support desktop notification");
|
217
|
-
}
|
218
|
-
|
219
|
-
// Let's check whether notification permissions have already been granted
|
220
|
-
else if (Notification.permission === "granted") {
|
221
|
-
console.log("Permission to receive notifications has been granted");
|
222
|
-
}
|
223
|
-
|
224
|
-
// Otherwise, we need to ask the user for permission
|
225
|
-
else if (Notification.permission !== 'denied') {
|
226
|
-
Notification.requestPermission(function (permission) {
|
227
|
-
// If the user accepts, let's create a notification
|
228
|
-
if (permission === "granted") {
|
229
|
-
console.log("Permission to receive notifications has been granted");
|
230
|
-
}
|
231
|
-
});
|
232
|
-
}
|
115
|
+
Notification.requestPermission();
|
233
116
|
```
|
234
117
|
|
235
|
-
If everything worked, you should see a desktop notification triggered via web
|
236
|
-
push. Yay!
|
237
|
-
|
238
|
-
Note: if you're using Rails, check out [serviceworker-rails](https://github.com/rossta/serviceworker-rails), a gem that makes it easier to host serviceworker scripts and manifest.json files at canonical endpoints (i.e., non-digested URLs) while taking advantage of the asset pipeline.
|
118
|
+
If everything worked, you should see a desktop notification triggered via web push. Yay!
|
239
119
|
|
240
120
|
## API
|
241
121
|
|
@@ -243,9 +123,9 @@ Note: if you're using Rails, check out [serviceworker-rails](https://github.com/
|
|
243
123
|
|
244
124
|
```ruby
|
245
125
|
message = {
|
246
|
-
title: "
|
247
|
-
body: "
|
248
|
-
icon: "
|
126
|
+
title: "Example",
|
127
|
+
body: "Hello, world!",
|
128
|
+
icon: "https://example.com/icon.png"
|
249
129
|
}
|
250
130
|
|
251
131
|
WebPush.payload_send(
|
@@ -304,53 +184,10 @@ WebPush.payload_send(
|
|
304
184
|
)
|
305
185
|
```
|
306
186
|
|
307
|
-
|
308
|
-
|
309
|
-
```ruby
|
310
|
-
WebPush.payload_send(
|
311
|
-
endpoint: "https://fcm.googleapis.com/gcm/send/eah7hak....",
|
312
|
-
message: "A message",
|
313
|
-
p256dh: "BO/aG9nYXNkZmFkc2ZmZHNmYWRzZmFl...",
|
314
|
-
auth: "aW1hcmthcmFpa3V6ZQ==",
|
315
|
-
api_key: "<GCM API KEY>"
|
316
|
-
)
|
317
|
-
```
|
318
|
-
|
319
|
-
### ServiceWorker sample
|
320
|
-
|
321
|
-
see. https://github.com/zaru/web-push-sample
|
322
|
-
|
323
|
-
p256dh and auth generate sample code.
|
324
|
-
|
325
|
-
```javascript
|
326
|
-
navigator.serviceWorker.ready.then(function(sw) {
|
327
|
-
Notification.requestPermission(function(permission) {
|
328
|
-
if(permission !== 'denied') {
|
329
|
-
sw.pushManager.subscribe({userVisibleOnly: true}).then(function(s) {
|
330
|
-
var data = {
|
331
|
-
endpoint: s.endpoint,
|
332
|
-
p256dh: btoa(String.fromCharCode.apply(null, new Uint8Array(s.getKey('p256dh')))).replace(/\+/g, '-').replace(/\//g, '_'),
|
333
|
-
auth: btoa(String.fromCharCode.apply(null, new Uint8Array(s.getKey('auth')))).replace(/\+/g, '-').replace(/\//g, '_')
|
334
|
-
}
|
335
|
-
console.log(data);
|
336
|
-
});
|
337
|
-
}
|
338
|
-
});
|
339
|
-
});
|
340
|
-
```
|
187
|
+
## Contributing
|
341
188
|
|
342
|
-
|
189
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/pushpad/web-push.
|
343
190
|
|
344
|
-
|
345
|
-
self.addEventListener("push", function(event) {
|
346
|
-
var json = event.data.json();
|
347
|
-
self.registration.showNotification(json.title, {
|
348
|
-
body: json.body,
|
349
|
-
icon: json.icon
|
350
|
-
});
|
351
|
-
});
|
352
|
-
```
|
353
|
-
|
354
|
-
## Contributing
|
191
|
+
## Credits
|
355
192
|
|
356
|
-
|
193
|
+
This library is a fork of [zaru/webpush](https://github.com/zaru/webpush) actively maintained by [Pushpad](https://pushpad.xyz) with many improvements, bug fixes and frequent updates.
|
data/lib/web_push/encryption.rb
CHANGED
@@ -4,7 +4,6 @@ module WebPush
|
|
4
4
|
module Encryption
|
5
5
|
extend self
|
6
6
|
|
7
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
8
7
|
def encrypt(message, p256dh, auth)
|
9
8
|
assert_arguments(message, p256dh, auth)
|
10
9
|
|
@@ -27,11 +26,11 @@ module WebPush
|
|
27
26
|
content_encryption_key_info = "Content-Encoding: aes128gcm\0"
|
28
27
|
nonce_info = "Content-Encoding: nonce\0"
|
29
28
|
|
30
|
-
prk = HKDF.new(shared_secret, salt: client_auth_token, algorithm: 'SHA256', info: info).
|
29
|
+
prk = HKDF.new(shared_secret, salt: client_auth_token, algorithm: 'SHA256', info: info).read(32)
|
31
30
|
|
32
|
-
content_encryption_key = HKDF.new(prk, salt: salt, info: content_encryption_key_info).
|
31
|
+
content_encryption_key = HKDF.new(prk, salt: salt, info: content_encryption_key_info).read(16)
|
33
32
|
|
34
|
-
nonce = HKDF.new(prk, salt: salt, info: nonce_info).
|
33
|
+
nonce = HKDF.new(prk, salt: salt, info: nonce_info).read(12)
|
35
34
|
|
36
35
|
ciphertext = encrypt_payload(message, content_encryption_key, nonce)
|
37
36
|
|
@@ -43,7 +42,6 @@ module WebPush
|
|
43
42
|
|
44
43
|
aes128gcmheader + ciphertext
|
45
44
|
end
|
46
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
47
45
|
|
48
46
|
private
|
49
47
|
|
data/lib/web_push/request.rb
CHANGED
@@ -1,25 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'uri'
|
4
|
-
require 'jwt'
|
5
|
-
require 'base64'
|
6
|
-
|
7
3
|
module WebPush
|
8
|
-
# It is temporary URL until supported by the GCM server.
|
9
|
-
GCM_URL = 'https://android.googleapis.com/gcm/send'.freeze
|
10
|
-
TEMP_GCM_URL = 'https://fcm.googleapis.com/fcm'.freeze
|
11
4
|
|
12
|
-
# rubocop:disable Metrics/ClassLength
|
13
5
|
class Request
|
14
6
|
def initialize(message: '', subscription:, vapid:, **options)
|
15
7
|
endpoint = subscription.fetch(:endpoint)
|
16
|
-
@endpoint = endpoint
|
8
|
+
@endpoint = endpoint
|
17
9
|
@payload = build_payload(message, subscription)
|
18
10
|
@vapid_options = vapid
|
19
11
|
@options = default_options.merge(options)
|
20
12
|
end
|
21
13
|
|
22
|
-
# rubocop:disable Metrics/AbcSize
|
23
14
|
def perform
|
24
15
|
http = Net::HTTP.new(uri.host, uri.port, *proxy_options)
|
25
16
|
http.use_ssl = true
|
@@ -35,7 +26,6 @@ module WebPush
|
|
35
26
|
|
36
27
|
resp
|
37
28
|
end
|
38
|
-
# rubocop:enable Metrics/AbcSize
|
39
29
|
|
40
30
|
def proxy_options
|
41
31
|
return [] unless @options[:proxy]
|
@@ -45,7 +35,6 @@ module WebPush
|
|
45
35
|
[proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password]
|
46
36
|
end
|
47
37
|
|
48
|
-
# rubocop:disable Metrics/MethodLength
|
49
38
|
def headers
|
50
39
|
headers = {}
|
51
40
|
headers['Content-Type'] = 'application/octet-stream'
|
@@ -57,24 +46,18 @@ module WebPush
|
|
57
46
|
headers["Content-Length"] = @payload.length.to_s
|
58
47
|
end
|
59
48
|
|
60
|
-
if
|
61
|
-
headers['Authorization'] = "key=#{api_key}"
|
62
|
-
elsif vapid?
|
49
|
+
if vapid?
|
63
50
|
headers["Authorization"] = build_vapid_header
|
64
51
|
end
|
65
52
|
|
66
53
|
headers
|
67
54
|
end
|
68
|
-
# rubocop:enable Metrics/MethodLength
|
69
55
|
|
70
56
|
def build_vapid_header
|
71
|
-
# https://tools.ietf.org/id/draft-ietf-webpush-vapid-03.html
|
72
|
-
|
73
57
|
vapid_key = vapid_pem ? VapidKey.from_pem(vapid_pem) : VapidKey.from_keys(vapid_public_key, vapid_private_key)
|
74
58
|
jwt = JWT.encode(jwt_payload, vapid_key.curve, 'ES256', jwt_header_fields)
|
75
59
|
p256ecdsa = vapid_key.public_key_for_push_header
|
76
|
-
|
77
|
-
"vapid t=#{jwt},k=#{p256ecdsa}"
|
60
|
+
"vapid t=#{jwt},k=#{p256ecdsa}"
|
78
61
|
end
|
79
62
|
|
80
63
|
def body
|
@@ -112,11 +95,11 @@ module WebPush
|
|
112
95
|
end
|
113
96
|
|
114
97
|
def expiration
|
115
|
-
@vapid_options.fetch(:expiration,
|
98
|
+
@vapid_options.fetch(:expiration, 12 * 60 * 60)
|
116
99
|
end
|
117
100
|
|
118
101
|
def subject
|
119
|
-
@vapid_options.fetch(:subject, 'sender@example.com')
|
102
|
+
@vapid_options.fetch(:subject, 'mailto:sender@example.com')
|
120
103
|
end
|
121
104
|
|
122
105
|
def vapid_public_key
|
@@ -148,14 +131,6 @@ module WebPush
|
|
148
131
|
Encryption.encrypt(message, p256dh, auth)
|
149
132
|
end
|
150
133
|
|
151
|
-
def api_key
|
152
|
-
@options.fetch(:api_key, nil)
|
153
|
-
end
|
154
|
-
|
155
|
-
def api_key?
|
156
|
-
!(api_key.nil? || api_key.empty?) && @endpoint =~ %r{\Ahttps://(android|gcm-http|fcm)\.googleapis\.com}
|
157
|
-
end
|
158
|
-
|
159
134
|
def vapid?
|
160
135
|
@vapid_options.any?
|
161
136
|
end
|
@@ -164,7 +139,6 @@ module WebPush
|
|
164
139
|
WebPush.encode64(bin).delete('=')
|
165
140
|
end
|
166
141
|
|
167
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Style/GuardClause
|
168
142
|
def verify_response(resp)
|
169
143
|
if resp.is_a?(Net::HTTPGone) # 410
|
170
144
|
raise ExpiredSubscription.new(resp, uri.host)
|
@@ -183,7 +157,5 @@ module WebPush
|
|
183
157
|
raise ResponseError.new(resp, uri.host)
|
184
158
|
end
|
185
159
|
end
|
186
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Style/GuardClause
|
187
160
|
end
|
188
|
-
# rubocop:enable Metrics/ClassLength
|
189
161
|
end
|
data/lib/web_push/vapid_key.rb
CHANGED
@@ -78,10 +78,15 @@ module WebPush
|
|
78
78
|
alias to_hash to_h
|
79
79
|
|
80
80
|
def to_pem
|
81
|
-
|
82
|
-
|
81
|
+
private_key_to_pem + public_key_to_pem
|
82
|
+
end
|
83
|
+
|
84
|
+
def private_key_to_pem
|
85
|
+
curve.to_pem
|
86
|
+
end
|
83
87
|
|
84
|
-
|
88
|
+
def public_key_to_pem
|
89
|
+
curve.public_to_pem
|
85
90
|
end
|
86
91
|
|
87
92
|
def inspect
|
data/lib/web_push/version.rb
CHANGED
data/lib/web_push.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
require 'openssl'
|
4
4
|
require 'base64'
|
5
5
|
require 'hkdf'
|
6
|
+
require 'jwt'
|
7
|
+
require 'uri'
|
6
8
|
require 'net/http'
|
7
9
|
require 'json'
|
8
10
|
|
@@ -11,7 +13,6 @@ require 'web_push/errors'
|
|
11
13
|
require 'web_push/vapid_key'
|
12
14
|
require 'web_push/encryption'
|
13
15
|
require 'web_push/request'
|
14
|
-
require 'web_push/railtie' if defined?(Rails)
|
15
16
|
|
16
17
|
# Push API implementation
|
17
18
|
#
|
@@ -34,7 +35,6 @@ module WebPush
|
|
34
35
|
# @param options [Hash<Symbol,String>] additional options for the notification
|
35
36
|
# @option options [#to_s] :ttl Time-to-live in seconds
|
36
37
|
# @option options [#to_s] :urgency Urgency can be very-low, low, normal, high
|
37
|
-
# rubocop:disable Metrics/ParameterLists
|
38
38
|
def payload_send(message: '', endpoint:, p256dh: '', auth: '', vapid: {}, **options)
|
39
39
|
WebPush::Request.new(
|
40
40
|
message: message,
|
@@ -43,7 +43,6 @@ module WebPush
|
|
43
43
|
**options
|
44
44
|
).perform
|
45
45
|
end
|
46
|
-
# rubocop:enable Metrics/ParameterLists
|
47
46
|
|
48
47
|
# Generate a VapidKey instance to obtain base64 encoded public and private keys
|
49
48
|
# suitable for VAPID protocol JSON web token signing
|
data/spec/spec_helper.rb
CHANGED
@@ -67,10 +67,10 @@ describe WebPush::Encryption do
|
|
67
67
|
content_encryption_key_info = "Content-Encoding: aes128gcm\0"
|
68
68
|
nonce_info = "Content-Encoding: nonce\0"
|
69
69
|
|
70
|
-
prk = HKDF.new(shared_secret, salt: client_auth_token, algorithm: 'SHA256', info: info).
|
70
|
+
prk = HKDF.new(shared_secret, salt: client_auth_token, algorithm: 'SHA256', info: info).read(32)
|
71
71
|
|
72
|
-
content_encryption_key = HKDF.new(prk, salt: salt, info: content_encryption_key_info).
|
73
|
-
nonce = HKDF.new(prk, salt: salt, info: nonce_info).
|
72
|
+
content_encryption_key = HKDF.new(prk, salt: salt, info: content_encryption_key_info).read(16)
|
73
|
+
nonce = HKDF.new(prk, salt: salt, info: nonce_info).read(12)
|
74
74
|
|
75
75
|
decrypt_ciphertext(ciphertext, content_encryption_key, nonce)
|
76
76
|
end
|
@@ -18,51 +18,6 @@ describe WebPush::Request do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
describe 'from :api_key' do
|
22
|
-
def build_request_with_api_key(endpoint, options = {})
|
23
|
-
subscription = {
|
24
|
-
endpoint: endpoint,
|
25
|
-
keys: {
|
26
|
-
p256dh: 'p256dh',
|
27
|
-
auth: 'auth'
|
28
|
-
}
|
29
|
-
}
|
30
|
-
WebPush::Request.new(message: '', subscription: subscription, vapid: {}, **options)
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'inserts Authorization header when api_key present, and endpoint is for Chrome\'s non-standards-compliant GCM endpoints' do
|
34
|
-
request = build_request_with_api_key('https://gcm-http.googleapis.com/gcm/xyz', api_key: 'api_key')
|
35
|
-
|
36
|
-
expect(request.headers['Authorization']).to eq('key=api_key')
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'insert Authorization header for Chrome\'s new standards-compliant endpoints, even if api_key is present' do
|
40
|
-
request = build_request_with_api_key('https://fcm.googleapis.com/fcm/send/ABCD1234', api_key: 'api_key')
|
41
|
-
|
42
|
-
expect(request.headers['Authorization']).to eq('key=api_key')
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'does not insert Authorization header when endpoint is not for Chrome, even if api_key is present' do
|
46
|
-
request = build_request_with_api_key('https://some.random.endpoint.com/xyz', api_key: 'api_key')
|
47
|
-
|
48
|
-
expect(request.headers['Authorization']).to be_nil
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'does not insert Authorization header when api_key blank' do
|
52
|
-
request = build_request_with_api_key('endpoint', api_key: nil)
|
53
|
-
|
54
|
-
expect(request.headers['Authorization']).to be_nil
|
55
|
-
|
56
|
-
request = build_request_with_api_key('endpoint', api_key: '')
|
57
|
-
|
58
|
-
expect(request.headers['Authorization']).to be_nil
|
59
|
-
|
60
|
-
request = build_request_with_api_key('endpoint')
|
61
|
-
|
62
|
-
expect(request.headers['Authorization']).to be_nil
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
21
|
describe 'from :ttl' do
|
67
22
|
it 'can override Ttl with :ttl option with string' do
|
68
23
|
request = build_request(ttl: '300')
|
@@ -91,7 +46,7 @@ describe WebPush::Request do
|
|
91
46
|
time = Time.at(1_476_150_897)
|
92
47
|
jwt_payload = {
|
93
48
|
aud: 'https://fcm.googleapis.com',
|
94
|
-
exp: time.to_i +
|
49
|
+
exp: time.to_i + 12 * 60 * 60,
|
95
50
|
sub: 'mailto:sender@example.com'
|
96
51
|
}
|
97
52
|
jwt_header_fields = { "typ": "JWT", "alg": "ES256" }
|
@@ -43,6 +43,35 @@ describe WebPush::VapidKey do
|
|
43
43
|
expect(pem).to include('-----BEGIN PUBLIC KEY-----')
|
44
44
|
end
|
45
45
|
|
46
|
+
it 'returns the correct public and private keys in pem format' do
|
47
|
+
public_key_base64 = 'BMA-wciFTkEq2waVGB2hg8cSyiRiMcsIvIYQb3LkLOmBheh3YC6NB2GtE9t6YgaXt428rp7bC9JjuPtAY9AQaR8='
|
48
|
+
private_key_base64 = '4MwLvN1Cpxe43AV9fa4BiS-SPp51gWlhv9c6bb_XSJ4='
|
49
|
+
key = WebPush::VapidKey.from_keys(public_key_base64, private_key_base64)
|
50
|
+
pem = key.to_pem
|
51
|
+
expected_pem = <<~PEM
|
52
|
+
-----BEGIN EC PRIVATE KEY-----
|
53
|
+
MHcCAQEEIODMC7zdQqcXuNwFfX2uAYkvkj6edYFpYb/XOm2/10ieoAoGCCqGSM49
|
54
|
+
AwEHoUQDQgAEwD7ByIVOQSrbBpUYHaGDxxLKJGIxywi8hhBvcuQs6YGF6HdgLo0H
|
55
|
+
Ya0T23piBpe3jbyuntsL0mO4+0Bj0BBpHw==
|
56
|
+
-----END EC PRIVATE KEY-----
|
57
|
+
-----BEGIN PUBLIC KEY-----
|
58
|
+
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwD7ByIVOQSrbBpUYHaGDxxLKJGIx
|
59
|
+
ywi8hhBvcuQs6YGF6HdgLo0HYa0T23piBpe3jbyuntsL0mO4+0Bj0BBpHw==
|
60
|
+
-----END PUBLIC KEY-----
|
61
|
+
PEM
|
62
|
+
expect(pem).to eq(expected_pem)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'can return the private key in pem format' do
|
66
|
+
pem = WebPush::VapidKey.new.private_key_to_pem
|
67
|
+
expect(pem).to include('-----BEGIN EC PRIVATE KEY-----')
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'can return the public key in pem format' do
|
71
|
+
pem = WebPush::VapidKey.new.public_key_to_pem
|
72
|
+
expect(pem).to include('-----BEGIN PUBLIC KEY-----')
|
73
|
+
end
|
74
|
+
|
46
75
|
it 'imports pem of public and private keys' do
|
47
76
|
pem = WebPush::VapidKey.new.to_pem
|
48
77
|
key = WebPush::VapidKey.from_pem pem
|
data/spec/web_push_spec.rb
CHANGED
@@ -194,8 +194,8 @@ describe WebPush do
|
|
194
194
|
include_examples 'request headers with VAPID'
|
195
195
|
end
|
196
196
|
|
197
|
-
context 'chrome
|
198
|
-
let(:endpoint) { 'https://
|
197
|
+
context 'chrome endpoint: request headers without VAPID' do
|
198
|
+
let(:endpoint) { 'https://fcm.googleapis.com/fcm/subscription-id' }
|
199
199
|
let(:expected_endpoint) { 'https://fcm.googleapis.com/fcm/subscription-id' }
|
200
200
|
|
201
201
|
let(:message) { JSON.generate(body: 'body') }
|
@@ -221,7 +221,7 @@ describe WebPush do
|
|
221
221
|
allow(WebPush::Encryption).to receive(:encrypt).and_return(payload)
|
222
222
|
end
|
223
223
|
|
224
|
-
subject { WebPush.payload_send(message: message, endpoint: endpoint, p256dh: p256dh, auth: auth
|
224
|
+
subject { WebPush.payload_send(message: message, endpoint: endpoint, p256dh: p256dh, auth: auth) }
|
225
225
|
|
226
226
|
it 'calls the relevant service with the correct headers' do
|
227
227
|
expect(WebPush::Encryption).to receive(:encrypt).and_return(payload)
|
@@ -247,7 +247,7 @@ describe WebPush do
|
|
247
247
|
.with(body: nil, headers: expected_headers)
|
248
248
|
.to_return(status: 201, body: '', headers: {})
|
249
249
|
|
250
|
-
WebPush.payload_send(endpoint: endpoint
|
250
|
+
WebPush.payload_send(endpoint: endpoint)
|
251
251
|
end
|
252
252
|
end
|
253
253
|
end
|
data/web-push.gemspec
CHANGED
@@ -3,6 +3,7 @@ require_relative 'lib/web_push/version'
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = 'web-push'
|
5
5
|
spec.version = WebPush::VERSION
|
6
|
+
spec.license = 'MIT'
|
6
7
|
spec.authors = ['zaru', 'collimarco']
|
7
8
|
spec.email = ['support@pushpad.xyz']
|
8
9
|
|
@@ -11,15 +12,13 @@ Gem::Specification.new do |spec|
|
|
11
12
|
|
12
13
|
spec.files = `git ls-files`.split("\n")
|
13
14
|
|
14
|
-
spec.required_ruby_version = '>=
|
15
|
+
spec.required_ruby_version = '>= 3.0'
|
15
16
|
|
16
|
-
spec.add_dependency 'hkdf', '~> 0
|
17
|
+
spec.add_dependency 'hkdf', '~> 1.0'
|
17
18
|
spec.add_dependency 'jwt', '~> 2.0'
|
19
|
+
spec.add_dependency 'openssl', '~> 2.2'
|
18
20
|
|
19
|
-
spec.add_development_dependency 'bundler', '>= 1.17.3'
|
20
|
-
spec.add_development_dependency 'pry'
|
21
|
-
spec.add_development_dependency 'rake', '>= 10.0'
|
22
21
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
23
|
-
spec.add_development_dependency 'simplecov'
|
22
|
+
spec.add_development_dependency 'simplecov', '~> 0.0'
|
24
23
|
spec.add_development_dependency 'webmock', '~> 3.0'
|
25
24
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: web-push
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zaru
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-11-
|
12
|
+
date: 2022-11-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: hkdf
|
@@ -17,14 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '0
|
20
|
+
version: '1.0'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '0
|
27
|
+
version: '1.0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: jwt
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -40,47 +40,19 @@ dependencies:
|
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '2.0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
43
|
+
name: openssl
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - "
|
47
|
-
- !ruby/object:Gem::Version
|
48
|
-
version: 1.17.3
|
49
|
-
type: :development
|
50
|
-
prerelease: false
|
51
|
-
version_requirements: !ruby/object:Gem::Requirement
|
52
|
-
requirements:
|
53
|
-
- - ">="
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version: 1.17.3
|
56
|
-
- !ruby/object:Gem::Dependency
|
57
|
-
name: pry
|
58
|
-
requirement: !ruby/object:Gem::Requirement
|
59
|
-
requirements:
|
60
|
-
- - ">="
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
version: '0'
|
63
|
-
type: :development
|
64
|
-
prerelease: false
|
65
|
-
version_requirements: !ruby/object:Gem::Requirement
|
66
|
-
requirements:
|
67
|
-
- - ">="
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '0'
|
70
|
-
- !ruby/object:Gem::Dependency
|
71
|
-
name: rake
|
72
|
-
requirement: !ruby/object:Gem::Requirement
|
73
|
-
requirements:
|
74
|
-
- - ">="
|
46
|
+
- - "~>"
|
75
47
|
- !ruby/object:Gem::Version
|
76
|
-
version: '
|
77
|
-
type: :
|
48
|
+
version: '2.2'
|
49
|
+
type: :runtime
|
78
50
|
prerelease: false
|
79
51
|
version_requirements: !ruby/object:Gem::Requirement
|
80
52
|
requirements:
|
81
|
-
- - "
|
53
|
+
- - "~>"
|
82
54
|
- !ruby/object:Gem::Version
|
83
|
-
version: '
|
55
|
+
version: '2.2'
|
84
56
|
- !ruby/object:Gem::Dependency
|
85
57
|
name: rspec
|
86
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -99,16 +71,16 @@ dependencies:
|
|
99
71
|
name: simplecov
|
100
72
|
requirement: !ruby/object:Gem::Requirement
|
101
73
|
requirements:
|
102
|
-
- - "
|
74
|
+
- - "~>"
|
103
75
|
- !ruby/object:Gem::Version
|
104
|
-
version: '0'
|
76
|
+
version: '0.0'
|
105
77
|
type: :development
|
106
78
|
prerelease: false
|
107
79
|
version_requirements: !ruby/object:Gem::Requirement
|
108
80
|
requirements:
|
109
|
-
- - "
|
81
|
+
- - "~>"
|
110
82
|
- !ruby/object:Gem::Version
|
111
|
-
version: '0'
|
83
|
+
version: '0.0'
|
112
84
|
- !ruby/object:Gem::Dependency
|
113
85
|
name: webmock
|
114
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,25 +102,15 @@ executables: []
|
|
130
102
|
extensions: []
|
131
103
|
extra_rdoc_files: []
|
132
104
|
files:
|
105
|
+
- ".github/workflows/ci.yml"
|
133
106
|
- ".gitignore"
|
134
|
-
- ".rspec"
|
135
|
-
- ".rubocop.yml"
|
136
|
-
- ".travis.yml"
|
137
|
-
- CHANGELOG.md
|
138
107
|
- Gemfile
|
139
108
|
- LICENSE
|
140
109
|
- README.md
|
141
|
-
- Rakefile
|
142
|
-
- bin/console
|
143
|
-
- bin/rake
|
144
|
-
- bin/rspec
|
145
|
-
- bin/setup
|
146
|
-
- lib/tasks/web_push.rake
|
147
110
|
- lib/web-push.rb
|
148
111
|
- lib/web_push.rb
|
149
112
|
- lib/web_push/encryption.rb
|
150
113
|
- lib/web_push/errors.rb
|
151
|
-
- lib/web_push/railtie.rb
|
152
114
|
- lib/web_push/request.rb
|
153
115
|
- lib/web_push/vapid_key.rb
|
154
116
|
- lib/web_push/version.rb
|
@@ -159,7 +121,8 @@ files:
|
|
159
121
|
- spec/web_push_spec.rb
|
160
122
|
- web-push.gemspec
|
161
123
|
homepage: https://github.com/pushpad/web-push
|
162
|
-
licenses:
|
124
|
+
licenses:
|
125
|
+
- MIT
|
163
126
|
metadata: {}
|
164
127
|
post_install_message:
|
165
128
|
rdoc_options: []
|
@@ -169,14 +132,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
169
132
|
requirements:
|
170
133
|
- - ">="
|
171
134
|
- !ruby/object:Gem::Version
|
172
|
-
version: '
|
135
|
+
version: '3.0'
|
173
136
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
174
137
|
requirements:
|
175
138
|
- - ">="
|
176
139
|
- !ruby/object:Gem::Version
|
177
140
|
version: '0'
|
178
141
|
requirements: []
|
179
|
-
rubygems_version: 3.
|
142
|
+
rubygems_version: 3.3.26
|
180
143
|
signing_key:
|
181
144
|
specification_version: 4
|
182
145
|
summary: Web Push library for Ruby (RFC8030)
|
data/.rspec
DELETED
data/.rubocop.yml
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require: rubocop-performance
|
2
|
-
|
3
|
-
AllCops:
|
4
|
-
Exclude:
|
5
|
-
- 'bin/**/*'
|
6
|
-
|
7
|
-
Metrics/AbcSize:
|
8
|
-
Max: 20
|
9
|
-
|
10
|
-
Metrics/ClassLength:
|
11
|
-
Max: 100
|
12
|
-
|
13
|
-
Metrics/ModuleLength:
|
14
|
-
Max: 100
|
15
|
-
|
16
|
-
Metrics/LineLength:
|
17
|
-
Enabled: false
|
18
|
-
|
19
|
-
Metrics/BlockLength:
|
20
|
-
Exclude:
|
21
|
-
- spec/**/*_spec.rb
|
22
|
-
|
23
|
-
Lint/AmbiguousBlockAssociation:
|
24
|
-
Enabled: false
|
25
|
-
|
26
|
-
Style/Documentation:
|
27
|
-
Enabled: false
|
28
|
-
|
29
|
-
Style/IndentHeredoc:
|
30
|
-
Enabled: false
|
data/.travis.yml
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
env:
|
2
|
-
global:
|
3
|
-
- CC_TEST_REPORTER_ID=155202524386dfebe0c3267a5c868b5417ff4cc2cde8ed301fb36b177d46a458
|
4
|
-
language: ruby
|
5
|
-
rvm:
|
6
|
-
- 2.2
|
7
|
-
- 2.3
|
8
|
-
- 2.4
|
9
|
-
- 2.5
|
10
|
-
- 2.6
|
11
|
-
- 2.7
|
12
|
-
before_install:
|
13
|
-
- gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
|
14
|
-
- gem install bundler -v 1.17.3
|
15
|
-
before_script:
|
16
|
-
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
17
|
-
- chmod +x ./cc-test-reporter
|
18
|
-
- ./cc-test-reporter before-build
|
19
|
-
script: "bundle exec rake spec"
|
20
|
-
after_script:
|
21
|
-
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
22
|
-
addons:
|
23
|
-
code_climate:
|
24
|
-
repo_token: 155202524386dfebe0c3267a5c868b5417ff4cc2cde8ed301fb36b177d46a458
|
data/CHANGELOG.md
DELETED
@@ -1,183 +0,0 @@
|
|
1
|
-
# Changelog
|
2
|
-
|
3
|
-
## [v1.1.0](https://github.com/zaru/webpush/tree/v1.1.0) (2020-11-16)
|
4
|
-
|
5
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v1.0.0...v1.1.0)
|
6
|
-
|
7
|
-
**Merged pull requests:**
|
8
|
-
|
9
|
-
- Eliminate Ruby 2.7 warnings. [\#95](https://github.com/zaru/webpush/pull/95) ([morgoth](https://github.com/morgoth))
|
10
|
-
- set minimum ruby version is 2.2 [\#94](https://github.com/zaru/webpush/pull/94) ([Wolfer](https://github.com/Wolfer))
|
11
|
-
- Add proxy support [\#93](https://github.com/zaru/webpush/pull/93) ([Bugagazavr](https://github.com/Bugagazavr))
|
12
|
-
- fix syntax error [\#91](https://github.com/zaru/webpush/pull/91) ([tonytonyjan](https://github.com/tonytonyjan))
|
13
|
-
- change dependency gem versions [\#88](https://github.com/zaru/webpush/pull/88) ([zaru](https://github.com/zaru))
|
14
|
-
|
15
|
-
## [v1.0.0](https://github.com/zaru/webpush/tree/v1.0.0) (2019-08-15)
|
16
|
-
|
17
|
-
A stable version 1.0.0 has been released.
|
18
|
-
|
19
|
-
Thanks @mohamedhafez, @mplatov and @MedetaiAkaru for everything!
|
20
|
-
|
21
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.8...v1.0.0)
|
22
|
-
|
23
|
-
**Merged pull requests:**
|
24
|
-
|
25
|
-
- switch to aes128gcm encoding [\#84](https://github.com/zaru/webpush/pull/84) ([mohamedhafez](https://github.com/mohamedhafez))
|
26
|
-
- Fixed fcm spec [\#77](https://github.com/zaru/webpush/pull/77) ([zaru](https://github.com/zaru))
|
27
|
-
- add fcm endpoints [\#76](https://github.com/zaru/webpush/pull/76) ([MedetaiAkaru](https://github.com/MedetaiAkaru))
|
28
|
-
- Add Rubocop and fix [\#74](https://github.com/zaru/webpush/pull/74) ([zaru](https://github.com/zaru))
|
29
|
-
- Fix TravisCI bundler version [\#73](https://github.com/zaru/webpush/pull/73) ([zaru](https://github.com/zaru))
|
30
|
-
|
31
|
-
## [v0.3.8](https://github.com/zaru/webpush/tree/v0.3.8) (2019-04-16)
|
32
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.7...v0.3.8)
|
33
|
-
|
34
|
-
**Merged pull requests:**
|
35
|
-
|
36
|
-
- Fix authorization header [\#72](https://github.com/zaru/webpush/pull/72) ([xronos-i-am](https://github.com/xronos-i-am))
|
37
|
-
|
38
|
-
## [v0.3.7](https://github.com/zaru/webpush/tree/v0.3.7) (2019-03-06)
|
39
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.6...v0.3.7)
|
40
|
-
|
41
|
-
**Merged pull requests:**
|
42
|
-
|
43
|
-
- Add PEM support to import / export keys [\#65](https://github.com/zaru/webpush/pull/65) ([collimarco](https://github.com/collimarco))
|
44
|
-
|
45
|
-
## [v0.3.6](https://github.com/zaru/webpush/tree/v0.3.6) (2019-01-09)
|
46
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.5...v0.3.6)
|
47
|
-
|
48
|
-
**Merged pull requests:**
|
49
|
-
|
50
|
-
- Added a error class to arguments of raise\_error [\#62](https://github.com/zaru/webpush/pull/62) ([zaru](https://github.com/zaru))
|
51
|
-
- Fix TravisCI bundler version [\#61](https://github.com/zaru/webpush/pull/61) ([zaru](https://github.com/zaru))
|
52
|
-
- Raise Webpush::Unauthorized on HTTP 403 [\#59](https://github.com/zaru/webpush/pull/59) ([collimarco](https://github.com/collimarco))
|
53
|
-
|
54
|
-
## [v0.3.5](https://github.com/zaru/webpush/tree/v0.3.5) (2019-01-02)
|
55
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.4...v0.3.5)
|
56
|
-
|
57
|
-
**Merged pull requests:**
|
58
|
-
|
59
|
-
- Fix \#55 and \#51: raise the proper error based on the HTTP status code [\#58](https://github.com/zaru/webpush/pull/58) ([collimarco](https://github.com/collimarco))
|
60
|
-
- Add urgency option [\#57](https://github.com/zaru/webpush/pull/57) ([collimarco](https://github.com/collimarco))
|
61
|
-
- Add Rake task to generate VAPID keys [\#54](https://github.com/zaru/webpush/pull/54) ([stevenharman](https://github.com/stevenharman))
|
62
|
-
|
63
|
-
## [v0.3.4](https://github.com/zaru/webpush/tree/v0.3.4) (2018-05-25)
|
64
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.3...v0.3.4)
|
65
|
-
|
66
|
-
**Merged pull requests:**
|
67
|
-
|
68
|
-
- add http timeout options [\#50](https://github.com/zaru/webpush/pull/50) ([aishek](https://github.com/aishek))
|
69
|
-
|
70
|
-
## [v0.3.3](https://github.com/zaru/webpush/tree/v0.3.3) (2017-11-06)
|
71
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.2...v0.3.3)
|
72
|
-
|
73
|
-
**Merged pull requests:**
|
74
|
-
|
75
|
-
- Add typ to JWT header fields [\#46](https://github.com/zaru/webpush/pull/46) ([ykzts](https://github.com/ykzts))
|
76
|
-
- Specify the version of JWT strictly [\#45](https://github.com/zaru/webpush/pull/45) ([ykzts](https://github.com/ykzts))
|
77
|
-
|
78
|
-
## [v0.3.2](https://github.com/zaru/webpush/tree/v0.3.2) (2017-07-01)
|
79
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.1...v0.3.2)
|
80
|
-
|
81
|
-
**Merged pull requests:**
|
82
|
-
|
83
|
-
- feat: improve response error codes [\#39](https://github.com/zaru/webpush/pull/39) ([glennr](https://github.com/glennr))
|
84
|
-
- Update README.md [\#38](https://github.com/zaru/webpush/pull/38) ([kitaindia](https://github.com/kitaindia))
|
85
|
-
- Fix code example: Add close bracket [\#37](https://github.com/zaru/webpush/pull/37) ([kuranari](https://github.com/kuranari))
|
86
|
-
- fix code in README [\#36](https://github.com/zaru/webpush/pull/36) ([kuranari](https://github.com/kuranari))
|
87
|
-
- Minor fix in README: Close code blocks [\#32](https://github.com/zaru/webpush/pull/32) ([nicolas-fricke](https://github.com/nicolas-fricke))
|
88
|
-
- Copy edits for README clarifying GCM requirements [\#30](https://github.com/zaru/webpush/pull/30) ([rossta](https://github.com/rossta))
|
89
|
-
- Adding VAPID documentation [\#28](https://github.com/zaru/webpush/pull/28) ([rossta](https://github.com/rossta))
|
90
|
-
|
91
|
-
## [v0.3.1](https://github.com/zaru/webpush/tree/v0.3.1) (2016-10-24)
|
92
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.3.0...v0.3.1)
|
93
|
-
|
94
|
-
**Merged pull requests:**
|
95
|
-
|
96
|
-
- Bug fix invalid base64 [\#29](https://github.com/zaru/webpush/pull/29) ([rossta](https://github.com/rossta))
|
97
|
-
- Clarify VAPID usage further in README [\#27](https://github.com/zaru/webpush/pull/27) ([rossta](https://github.com/rossta))
|
98
|
-
|
99
|
-
## [v0.3.0](https://github.com/zaru/webpush/tree/v0.3.0) (2016-10-14)
|
100
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.2.5...v0.3.0)
|
101
|
-
|
102
|
-
**Merged pull requests:**
|
103
|
-
|
104
|
-
- Implement VAPID authorization [\#26](https://github.com/zaru/webpush/pull/26) ([rossta](https://github.com/rossta))
|
105
|
-
|
106
|
-
## [v0.2.5](https://github.com/zaru/webpush/tree/v0.2.5) (2016-09-14)
|
107
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.2.4...v0.2.5)
|
108
|
-
|
109
|
-
**Merged pull requests:**
|
110
|
-
|
111
|
-
- api key only needed for old google apis [\#24](https://github.com/zaru/webpush/pull/24) ([mohamedhafez](https://github.com/mohamedhafez))
|
112
|
-
|
113
|
-
## [v0.2.4](https://github.com/zaru/webpush/tree/v0.2.4) (2016-08-29)
|
114
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.2.3...v0.2.4)
|
115
|
-
|
116
|
-
**Merged pull requests:**
|
117
|
-
|
118
|
-
- VERIFY\_PEER by default - no need for a cert\_store option [\#20](https://github.com/zaru/webpush/pull/20) ([mohamedhafez](https://github.com/mohamedhafez))
|
119
|
-
|
120
|
-
## [v0.2.3](https://github.com/zaru/webpush/tree/v0.2.3) (2016-06-19)
|
121
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.2.2...v0.2.3)
|
122
|
-
|
123
|
-
**Merged pull requests:**
|
124
|
-
|
125
|
-
- detect and handle response errors [\#18](https://github.com/zaru/webpush/pull/18) ([mohamedhafez](https://github.com/mohamedhafez))
|
126
|
-
|
127
|
-
## [v0.2.2](https://github.com/zaru/webpush/tree/v0.2.2) (2016-06-13)
|
128
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.2.1...v0.2.2)
|
129
|
-
|
130
|
-
**Merged pull requests:**
|
131
|
-
|
132
|
-
- Don't include API key for firefox or other browsers [\#16](https://github.com/zaru/webpush/pull/16) ([mohamedhafez](https://github.com/mohamedhafez))
|
133
|
-
- Option to specify a cert store [\#15](https://github.com/zaru/webpush/pull/15) ([mohamedhafez](https://github.com/mohamedhafez))
|
134
|
-
- show ttl option in README [\#14](https://github.com/zaru/webpush/pull/14) ([mohamedhafez](https://github.com/mohamedhafez))
|
135
|
-
|
136
|
-
## [v0.2.1](https://github.com/zaru/webpush/tree/v0.2.1) (2016-05-23)
|
137
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.2.0...v0.2.1)
|
138
|
-
|
139
|
-
**Merged pull requests:**
|
140
|
-
|
141
|
-
- Make the response more detailed. [\#10](https://github.com/zaru/webpush/pull/10) ([kevinjom](https://github.com/kevinjom))
|
142
|
-
|
143
|
-
## [v0.2.0](https://github.com/zaru/webpush/tree/v0.2.0) (2016-05-16)
|
144
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.6...v0.2.0)
|
145
|
-
|
146
|
-
**Merged pull requests:**
|
147
|
-
|
148
|
-
- Make message payload optional [\#8](https://github.com/zaru/webpush/pull/8) ([rossta](https://github.com/rossta))
|
149
|
-
- Add specs [\#7](https://github.com/zaru/webpush/pull/7) ([rossta](https://github.com/rossta))
|
150
|
-
|
151
|
-
## [v0.1.6](https://github.com/zaru/webpush/tree/v0.1.6) (2016-05-12)
|
152
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.5...v0.1.6)
|
153
|
-
|
154
|
-
**Merged pull requests:**
|
155
|
-
|
156
|
-
- Add rake binstub [\#6](https://github.com/zaru/webpush/pull/6) ([rossta](https://github.com/rossta))
|
157
|
-
- Add syntax highlighting to README snippets [\#5](https://github.com/zaru/webpush/pull/5) ([rossta](https://github.com/rossta))
|
158
|
-
- Extract encryption module [\#4](https://github.com/zaru/webpush/pull/4) ([rossta](https://github.com/rossta))
|
159
|
-
- Add some happy case specs [\#3](https://github.com/zaru/webpush/pull/3) ([waheedel](https://github.com/waheedel))
|
160
|
-
|
161
|
-
## [v0.1.5](https://github.com/zaru/webpush/tree/v0.1.5) (2016-04-29)
|
162
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.4...v0.1.5)
|
163
|
-
|
164
|
-
**Merged pull requests:**
|
165
|
-
|
166
|
-
- add Ttl header parameter [\#1](https://github.com/zaru/webpush/pull/1) ([shouta-dev](https://github.com/shouta-dev))
|
167
|
-
|
168
|
-
## [v0.1.4](https://github.com/zaru/webpush/tree/v0.1.4) (2016-04-27)
|
169
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.3...v0.1.4)
|
170
|
-
|
171
|
-
## [v0.1.3](https://github.com/zaru/webpush/tree/v0.1.3) (2016-04-13)
|
172
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.2...v0.1.3)
|
173
|
-
|
174
|
-
## [v0.1.2](https://github.com/zaru/webpush/tree/v0.1.2) (2016-04-12)
|
175
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.1...v0.1.2)
|
176
|
-
|
177
|
-
## [v0.1.1](https://github.com/zaru/webpush/tree/v0.1.1) (2016-03-31)
|
178
|
-
[Full Changelog](https://github.com/zaru/webpush/compare/v0.1.0...v0.1.1)
|
179
|
-
|
180
|
-
## [v0.1.0](https://github.com/zaru/webpush/tree/v0.1.0) (2016-03-31)
|
181
|
-
|
182
|
-
|
183
|
-
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
data/Rakefile
DELETED
data/bin/console
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "web_push"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start
|
data/bin/rake
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This file was generated by Bundler.
|
4
|
-
#
|
5
|
-
# The application 'rake' is installed as part of a gem, and
|
6
|
-
# this file is here to facilitate running it.
|
7
|
-
#
|
8
|
-
|
9
|
-
require "pathname"
|
10
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
11
|
-
Pathname.new(__FILE__).realpath)
|
12
|
-
|
13
|
-
require "rubygems"
|
14
|
-
require "bundler/setup"
|
15
|
-
|
16
|
-
load Gem.bin_path("rake", "rake")
|
data/bin/rspec
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This file was generated by Bundler.
|
4
|
-
#
|
5
|
-
# The application 'rspec' is installed as part of a gem, and
|
6
|
-
# this file is here to facilitate running it.
|
7
|
-
#
|
8
|
-
|
9
|
-
require "pathname"
|
10
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
11
|
-
Pathname.new(__FILE__).realpath)
|
12
|
-
|
13
|
-
require "rubygems"
|
14
|
-
require "bundler/setup"
|
15
|
-
|
16
|
-
load Gem.bin_path("rspec-core", "rspec")
|
data/bin/setup
DELETED
data/lib/tasks/web_push.rake
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
namespace :web_push do
|
2
|
-
desc 'Generate VAPID public/private key pair'
|
3
|
-
task :generate_keys do
|
4
|
-
require 'web_push'
|
5
|
-
|
6
|
-
WebPush.generate_key.tap do |keypair|
|
7
|
-
puts <<-KEYS
|
8
|
-
Generated VAPID keypair:
|
9
|
-
Public -> #{keypair.public_key}
|
10
|
-
Private -> #{keypair.private_key}
|
11
|
-
KEYS
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|