pushpad 1.1.0 → 1.2.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: dccdac2f6334014fc3b1a7fa42b5cc0644135df02b3e58f9c44f17e7fe00a27e
4
- data.tar.gz: 69c4ea4985bdd6c120445e36c58e8adf0f572874dd7fd3ef929ad90176c84b18
3
+ metadata.gz: 6ca523c6dd48111c5a369889092c80690401158c3f0a14142eb3aee236848062
4
+ data.tar.gz: 637c8461863686d6c3c1f9f666a7df74b2053aed5017318f360054f908b83fbe
5
5
  SHA512:
6
- metadata.gz: b9ab88edcae1bcb44f8e6e1b388d25ee47459c81b6f2c72c9b450a1bf64b08dd874b019d518733a1cb4cf53c7f4f3c8feec7ffc418a144c81cc6b0864c1b67d2
7
- data.tar.gz: 6540c56bb6cbaa46e496098669d081c7c66f35c20e1cc82bb4602510a696179c9fa71ba381dd1693c181fe32adf8a05ef5224ca9a2ea22f16648e35b2eca138b
6
+ metadata.gz: 7aaed7d9218f698803bf1adda9ba1459365b49eaba897903b1cab109aeb9bb825ab40b25119a52cc620d515dd7cce36ad8509d34baacb7b74d58028c26327207
7
+ data.tar.gz: 0e89ea2619f3c6f39c4a073c95d56faa451e672b86ad3d898e681b53c7ecef59af7e2b7b5fd22b3be957ab02cb7fcc98b6c7e4a84b5a328e853f6c5abc8905ac
data/README.md CHANGED
@@ -237,6 +237,29 @@ Pushpad::Subscription.count(project_id: 5, uids: ['user1'], tags: 'sports && tra
237
237
  If `Pushpad.project_id` is defined, the `project_id` option can be
238
238
  omitted.
239
239
 
240
+ ## Getting push subscription data
241
+
242
+ You can retrieve the subscriptions for a given project,
243
+ optionally filtered by `tags` or `uids`:
244
+
245
+ ```ruby
246
+ Pushpad::Subscription.find_all(project_id: 5)
247
+ Pushpad::Subscription.find_all(project_id: 5, uids: ['user1'])
248
+ Pushpad::Subscription.find_all(project_id: 5, tags: ['sports'])
249
+ Pushpad::Subscription.find_all(project_id: 5, tags: 'sports && travel')
250
+ Pushpad::Subscription.find_all(project_id: 5, uids: ['user1'], tags: 'sports && travel')
251
+ ```
252
+
253
+ If `Pushpad.project_id` is defined, the `project_id` option can be
254
+ omitted.
255
+
256
+ The REST API paginates the result set. You can pass a `page` parameter
257
+ to get the full list in multiple requests.
258
+
259
+ ```ruby
260
+ subscriptions = Pushpad::Subscription.find_all(project_id: 5, page: 2)
261
+ ```
262
+
240
263
  ## License
241
264
 
242
265
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -2,51 +2,67 @@ module Pushpad
2
2
  class Subscription
3
3
  class CountError < RuntimeError
4
4
  end
5
-
6
- def self.count(options = {})
7
- CountQuery.new(options).perform
5
+
6
+ class FindError < RuntimeError
8
7
  end
8
+
9
+ attr_reader :id, :endpoint, :p256dh, :auth, :uid, :tags, :last_click_at, :created_at
9
10
 
10
- class CountQuery
11
- attr_reader :options
11
+ def initialize(options)
12
+ @id = options[:id]
13
+ @endpoint = options[:endpoint]
14
+ @p256dh = options[:p256dh]
15
+ @auth = options[:auth]
16
+ @uid = options[:uid]
17
+ @tags = options[:tags]
18
+ @last_click_at = options[:last_click_at] && Time.parse(options[:last_click_at])
19
+ @created_at = options[:created_at] && Time.parse(options[:created_at])
20
+ end
12
21
 
13
- def initialize(options)
14
- @options = options
15
- end
22
+ def self.count(options = {})
23
+ project_id = options[:project_id] || Pushpad.project_id
24
+ raise "You must set project_id" unless project_id
16
25
 
17
- def perform
18
- project_id = options[:project_id] || Pushpad.project_id
19
- raise "You must set project_id" unless project_id
26
+ endpoint = "https://pushpad.xyz/api/v1/projects/#{project_id}/subscriptions"
27
+ response = Request.head(endpoint, query_parameters: query_parameters(options))
20
28
 
21
- endpoint = "https://pushpad.xyz/api/v1/projects/#{project_id}/subscriptions"
22
- response = Request.head(endpoint, query_parameters: query_parameters)
29
+ unless response.code == "200"
30
+ raise CountError, "Response #{response.code} #{response.message}: #{response.body}"
31
+ end
23
32
 
24
- unless response.code == "200"
25
- raise CountError, "Response #{response.code} #{response.message}: #{response.body}"
26
- end
33
+ response["X-Total-Count"].to_i
34
+ end
35
+
36
+ def self.find_all(options = {})
37
+ project_id = options[:project_id] || Pushpad.project_id
38
+ raise "You must set project_id" unless project_id
27
39
 
28
- response["X-Total-Count"].to_i
29
- end
40
+ query_parameters_with_pagination = query_parameters(options)
41
+ query_parameters_with_pagination << ["page", options[:page]] if options.key?(:page)
30
42
 
31
- private
43
+ response = Request.get("https://pushpad.xyz/api/v1/projects/#{project_id}/subscriptions",
44
+ query_parameters: query_parameters_with_pagination)
32
45
 
33
- def query_parameters
34
- [uid_query_parameters, tag_query_parameters].flatten(1)
46
+ unless response.code == "200"
47
+ raise FindError, "Response #{response.code} #{response.message}: #{response.body}"
35
48
  end
36
49
 
37
- def uid_query_parameters
38
- options.fetch(:uids, []).map { |uid| ["uids[]", uid] }
50
+ JSON.parse(response.body, symbolize_names: true).map do |attributes|
51
+ new(attributes)
39
52
  end
53
+ end
40
54
 
41
- def tag_query_parameters
42
- tags = options.fetch(:tags, [])
55
+ private
43
56
 
44
- if tags.is_a?(String)
45
- [["tags", tags]]
46
- else
47
- tags.map { |tag| ["tags[]", tag] }
48
- end
49
- end
57
+ def self.query_parameters(options)
58
+ uids = options.fetch(:uids, [])
59
+ uids_query = uids.map { |uid| ["uids[]", uid] }
60
+
61
+ tags = options.fetch(:tags, [])
62
+ tags_query = tags.is_a?(String) ? [["tags", tags]] : tags.map { |tag| ["tags[]", tag] }
63
+
64
+ [uids_query, tags_query].flatten(1)
50
65
  end
66
+
51
67
  end
52
68
  end
data/pushpad.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "pushpad"
3
- spec.version = '1.1.0'
3
+ spec.version = '1.2.0'
4
4
  spec.authors = ["Pushpad"]
5
5
  spec.email = ["support@pushpad.xyz"]
6
6
  spec.summary = "Web push notifications for Chrome, Firefox, Opera, Edge and Safari using Pushpad."
@@ -13,6 +13,17 @@ module Pushpad
13
13
  stub_request(:head, "https://pushpad.xyz/api/v1/projects/#{options[:project_id]}/subscriptions").
14
14
  to_return(status: 503)
15
15
  end
16
+
17
+ def stub_subscriptions_get(options)
18
+ stub_request(:get, "https://pushpad.xyz/api/v1/projects/#{options[:project_id]}/subscriptions").
19
+ with(query: hash_including(options.fetch(:query, {}))).
20
+ to_return(status: 200, body: options[:list].to_json)
21
+ end
22
+
23
+ def stub_failing_subscriptions_get(options)
24
+ stub_request(:get, "https://pushpad.xyz/api/v1/projects/#{options[:project_id]}/subscriptions").
25
+ to_return(status: 403)
26
+ end
16
27
 
17
28
  describe ".count" do
18
29
  it "returns value from X-Total-Count header" do
@@ -81,5 +92,110 @@ module Pushpad
81
92
  }.to raise_error(Subscription::CountError)
82
93
  end
83
94
  end
95
+
96
+ describe ".find_all" do
97
+ it "returns subscriptions of project with attributes from json response" do
98
+ attributes = {
99
+ id: 1169,
100
+ endpoint: "https://example.com/push/f7Q1Eyf7EyfAb1",
101
+ p256dh: "BCQVDTlYWdl05lal3lG5SKr3VxTrEWpZErbkxWrzknHrIKFwihDoZpc_2sH6Sh08h-CacUYI-H8gW4jH-uMYZQ4=",
102
+ auth: "cdKMlhgVeSPzCXZ3V7FtgQ==",
103
+ uid: "exampleUid",
104
+ tags: ["exampleTag1", "exampleTag2"],
105
+ last_click_at: "2023-11-03T10:30:00.000Z",
106
+ created_at: "2016-09-06T10:47:05.494Z"
107
+ }
108
+ stub_subscriptions_get(project_id: 10, list: [attributes])
109
+
110
+ subscriptions = Subscription.find_all(project_id: 10)
111
+
112
+ attributes.delete(:last_click_at)
113
+ attributes.delete(:created_at)
114
+ expect(subscriptions[0]).to have_attributes(attributes)
115
+ expect(subscriptions[0].last_click_at.utc.to_s).to eq(Time.utc(2023, 11, 3, 10, 30, 0.0).to_s)
116
+ expect(subscriptions[0].created_at.utc.to_s).to eq(Time.utc(2016, 9, 6, 10, 47, 5.494).to_s)
117
+ end
118
+
119
+ it "falls back to global project id" do
120
+ attributes = { id: 5 }
121
+ stub_subscriptions_get(project_id: 10, list: [attributes])
122
+
123
+ Pushpad.project_id = 10
124
+ subscriptions = Subscription.find_all
125
+
126
+ expect(subscriptions[0]).to have_attributes(attributes)
127
+ end
128
+
129
+ it "fails with helpful error message when project_id is missing" do
130
+ Pushpad.project_id = nil
131
+
132
+ expect {
133
+ Subscription.find_all
134
+ }.to raise_error(/must set project_id/)
135
+ end
136
+
137
+ it "allows passing page parameter for pagination" do
138
+ attributes = { id: 5 }
139
+ stub_subscriptions_get(project_id: 10, list: [attributes], query: { page: "3" })
140
+
141
+ subscriptions = Subscription.find_all(project_id: 10, page: 3)
142
+
143
+ expect(subscriptions[0]).to have_attributes(attributes)
144
+ end
145
+
146
+ it "fails with FindError if response status code is not 200" do
147
+ stub_failing_subscriptions_get(project_id: 10)
148
+
149
+ expect {
150
+ Subscription.find_all(project_id: 10)
151
+ }.to raise_error(Subscription::FindError)
152
+ end
153
+
154
+ it "allows passing uids" do
155
+ attributes = { id: 5 }
156
+ request = stub_subscriptions_get(project_id: 5, list: [attributes], query: { uids: ["uid0", "uid1"] })
157
+
158
+ Subscription.find_all(project_id: 5, uids: ["uid0", "uid1"])
159
+
160
+ expect(request).to have_been_made.once
161
+ end
162
+
163
+ it "allows passing tags" do
164
+ attributes = { id: 5 }
165
+ request = stub_subscriptions_get(project_id: 5, list: [attributes], query: { tags: ["sports", "travel"] })
166
+
167
+ Subscription.find_all(project_id: 5, tags: ["sports", "travel"])
168
+
169
+ expect(request).to have_been_made.once
170
+ end
171
+
172
+ it "allows passing tags as boolean expression" do
173
+ attributes = { id: 5 }
174
+ request = stub_subscriptions_get(project_id: 5, list: [attributes], query: { tags: "sports || travel" })
175
+
176
+ Subscription.find_all(project_id: 5, tags: "sports || travel")
177
+
178
+ expect(request).to have_been_made.once
179
+ end
180
+
181
+ it "allows passing tags and uids" do
182
+ attributes = { id: 5 }
183
+ request = stub_subscriptions_get(project_id: 5, list: [attributes],
184
+ query: { tags: ["sports", "travel"], uids: ["uid0"] })
185
+
186
+ Subscription.find_all(project_id: 5, tags: ["sports", "travel"], uids: ["uid0"])
187
+
188
+ expect(request).to have_been_made.once
189
+ end
190
+
191
+ it "works properly when there are no results" do
192
+ stub_subscriptions_get(project_id: 5, list: [])
193
+
194
+ subscriptions = Subscription.find_all(project_id: 5)
195
+
196
+ expect(subscriptions).to eq([])
197
+ end
198
+ end
199
+
84
200
  end
85
201
  end
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pushpad
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pushpad
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2024-09-18 00:00:00.000000000 Z
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- description:
41
+ description:
42
42
  email:
43
43
  - support@pushpad.xyz
44
44
  executables: []
@@ -66,7 +66,7 @@ homepage: https://pushpad.xyz
66
66
  licenses:
67
67
  - MIT
68
68
  metadata: {}
69
- post_install_message:
69
+ post_install_message:
70
70
  rdoc_options: []
71
71
  require_paths:
72
72
  - lib
@@ -81,8 +81,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  requirements: []
84
- rubygems_version: 3.5.16
85
- signing_key:
84
+ rubygems_version: 3.0.3.1
85
+ signing_key:
86
86
  specification_version: 4
87
87
  summary: Web push notifications for Chrome, Firefox, Opera, Edge and Safari using
88
88
  Pushpad.