web-push 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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