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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a165b29c06bb5d9a9aab0b65de25bd913ef7926909773485e97f0778bda4299d
4
- data.tar.gz: c3f9727392a4049e27ac6bf83718749d5110cd290fa37718ee5b988d2c9c16e3
3
+ metadata.gz: 0ce88ebd076b697f1933784607d0e7d743e66c0fe2a3522b2d91fbf8f7d674b4
4
+ data.tar.gz: b8eede6dba32f1933ab8ea706dd27dcc7d54fcc2a1bafb6c63249accc2e335f5
5
5
  SHA512:
6
- metadata.gz: ca5db1201aa140ed1abe235d217183270b8b171d8b368ea7b5392c9cb04a2bf923c1c0e468788e1c2846dbd5c38bc32af53d427dbf307193ccaa00efbf6dd7d6
7
- data.tar.gz: 8f179fd84cc0bd0f9e4899353d95af62e9e716552ae0bec86cdc7be2782056fcfb08b06a7efd3297e7468f1bb72ab6f5b16a29e31fc5ed0eb615117e790b8885
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
@@ -1,10 +1,2 @@
1
- /.bundle/
2
- /.yardoc
3
1
  /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- .idea/
2
+ /coverage
data/README.md CHANGED
@@ -1,45 +1,35 @@
1
1
  # WebPush
2
2
 
3
- [![Code Climate](https://codeclimate.com/github/zaru/webpush/badges/gpa.svg)](https://codeclimate.com/github/zaru/webpush)
4
- [![Test Coverage](https://codeclimate.com/github/zaru/webpush/badges/coverage.svg)](https://codeclimate.com/github/zaru/webpush/coverage)
5
- [![Build Status](https://travis-ci.org/zaru/webpush.svg?branch=master)](https://travis-ci.org/zaru/webpush)
6
- [![Gem Version](https://badge.fury.io/rb/webpush.svg)](https://badge.fury.io/rb/webpush)
3
+ [![Gem Version](https://badge.fury.io/rb/web-push.svg)](https://badge.fury.io/rb/web-push)
4
+ ![Build Status](https://github.com/pushpad/web-push/workflows/CI/badge.svg)
7
5
 
8
- This gem makes it possible to send push messages to web browsers from Ruby backends using the [Web Push Protocol](https://tools.ietf.org/html/draft-ietf-webpush-protocol-10). It supports [Message Encryption for Web Push](https://tools.ietf.org/html/draft-ietf-webpush-encryption) to send messages securely from server to user agent.
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 your application's Gemfile:
10
+ Add this line to the Gemfile:
17
11
 
18
12
  ```ruby
19
13
  gem 'web-push'
20
14
  ```
21
15
 
22
- And then execute:
23
-
24
- $ bundle
16
+ Or install the gem:
25
17
 
26
- Or install it yourself as:
27
-
28
- $ gem install web-push
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. Your server has (optionally) generated (one-time) a set of [Voluntary Application server Identification (VAPID)](https://tools.ietf.org/html/draft-ietf-webpush-vapid-01) keys. Otherwise, to send messages through Chrome, you have registered your site through the [Google Developer Console](https://console.developers.google.com/) and have obtained a GCM sender id and GCM API key from your app settings.
35
- 2. A `manifest.json` file, linked from your user's page, identifies your app settings.
36
- 3. Also 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, with creates a `subscription` JSON object on the client side.
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` attribute to be saved on the server side.
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 javascript must register a service worker script at an appropriate scope (we're sticking with the root).
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
- // application.js
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
- #### With VAPID
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 application javascript uses the `navigator.serviceWorker.pushManager` to subscribe to push notifications, passing the VAPID public key to the subscription settings.
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
- Hook into an client-side or backend event in your app to deliver a push message. The server must be made aware of the `subscription`. In the example below, we send the JSON generated subscription object to our backend at the "/push" endpoint with a message.
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
- Imagine a Ruby app endpoint that responds to the request by triggering notification through the `web-push` gem.
80
+ Then you can use this gem to send web push messages:
161
81
 
162
82
  ```ruby
163
- # app.rb
164
- # Use the web-push gem API to deliver a push notiifcation merging
165
- # the message, subscription values, and vapid options
166
- post "/push" do
167
- WebPush.payload_send(
168
- message: params[:message],
169
- endpoint: params[:subscription][:endpoint],
170
- p256dh: params[:subscription][:keys][:p256dh],
171
- auth: params[:subscription][:keys][:auth],
172
- vapid: {
173
- subject: "mailto:sender@example.com",
174
- public_key: ENV['VAPID_PUBLIC_KEY'],
175
- private_key: ENV['VAPID_PRIVATE_KEY']
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 `/serviceworker.js` script may respond to `'push'` events. One action it can take is to trigger desktop notifications by calling `showNotification` on the `registration` property.
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
- // serviceworker.js
195
- // The serviceworker context can respond to 'push' events and trigger
196
- // notifications on the registration property
197
- self.addEventListener("push", (event) => {
198
- let title = (event.data && event.data.text()) || "Yay a message";
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, using something like the example below.
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
- // application.js
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: "title",
247
- body: "body",
248
- icon: "http://example.com/icon.pn"
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
- ### With GCM api key
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
- payloads received sample code.
189
+ Bug reports and pull requests are welcome on GitHub at https://github.com/pushpad/web-push.
343
190
 
344
- ```javascript
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
- Bug reports and pull requests are welcome on GitHub at https://github.com/zaru/webpush.
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.
@@ -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).next_bytes(32)
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).next_bytes(16)
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).next_bytes(12)
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
 
@@ -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.gsub(GCM_URL, TEMP_GCM_URL)
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 api_key?
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, 24 * 60 * 60)
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
@@ -78,10 +78,15 @@ module WebPush
78
78
  alias to_hash to_h
79
79
 
80
80
  def to_pem
81
- public_key = OpenSSL::PKey::EC.new curve
82
- public_key.private_key = nil
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
- curve.to_pem + public_key.to_pem
88
+ def public_key_to_pem
89
+ curve.public_to_pem
85
90
  end
86
91
 
87
92
  def inspect
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebPush
4
- VERSION = '1.0.0'.freeze
4
+ VERSION = '2.0.0'.freeze
5
5
  end
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
@@ -1,8 +1,7 @@
1
- $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
2
- require 'pry'
3
1
  require 'web_push'
4
2
  require 'webmock/rspec'
5
3
  require 'simplecov'
4
+
6
5
  WebMock.disable_net_connect!(allow_localhost: true)
7
6
  SimpleCov.start
8
7
 
@@ -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).next_bytes(32)
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).next_bytes(16)
73
- nonce = HKDF.new(prk, salt: salt, info: nonce_info).next_bytes(12)
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 + 24 * 60 * 60,
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
@@ -194,8 +194,8 @@ describe WebPush do
194
194
  include_examples 'request headers with VAPID'
195
195
  end
196
196
 
197
- context 'chrome GCM endpoint: request headers with GCM api key' do
198
- let(:endpoint) { 'https://android.googleapis.com/gcm/send/subscription-id' }
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, api_key: 'GCM_API_KEY') }
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, api_key: 'GCM_API_KEY')
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 = '>= 2.2'
15
+ spec.required_ruby_version = '>= 3.0'
15
16
 
16
- spec.add_dependency 'hkdf', '~> 0.2'
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: 1.0.0
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-26 00:00:00.000000000 Z
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.2'
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.2'
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: bundler
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: '10.0'
77
- type: :development
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: '10.0'
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: '2.2'
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.0.3.1
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
@@ -1,2 +0,0 @@
1
- --format documentation
2
- --color
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
@@ -1,8 +0,0 @@
1
- require 'bundler/gem_tasks'
2
- require 'rspec/core/rake_task'
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
- task default: :spec
7
-
8
- import './lib/tasks/web_push.rake'
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
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -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
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WebPush
4
- class Railtie < Rails::Railtie
5
- rake_tasks do
6
- load 'tasks/web_push.rake'
7
- end
8
- end
9
- end