notifications-ruby-client 1.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 +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +159 -0
- data/Rakefile +12 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/test_client.rb +182 -0
- data/lib/notifications/client/notification.rb +57 -0
- data/lib/notifications/client/notifications_collection.rb +23 -0
- data/lib/notifications/client/request_error.rb +22 -0
- data/lib/notifications/client/response_notification.rb +11 -0
- data/lib/notifications/client/speaker.rb +97 -0
- data/lib/notifications/client/version.rb +5 -0
- data/lib/notifications/client.rb +70 -0
- data/notifications-ruby-client.gemspec +32 -0
- metadata +161 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cfd87a0ae55ca5a8d843a19bd9ffc99959ca646f
|
4
|
+
data.tar.gz: 48c8ed194a9364549035cdfe410103c22aa3988f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 048a94ca3bd1fe8d9c16fe91a24f8fe509e23119d4f4a86fd9fca38293cc5a829f5c40cef58d3c3630084984b7274f997cc416db0a0056e79d2a50f414493058
|
7
|
+
data.tar.gz: 04c883580688bd5a6e66ccb14d4abfb266e72f77880776c8ea1c435ae61e873c90b6228e2a9b0ec7b4e0a6f542a4e894156b31c4bba7b7d816928a2218155e3a
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Government Digital Service
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
# GOV.UK Notify Ruby client
|
2
|
+
|
3
|
+
API client for GOV.UK Notify written in Ruby.
|
4
|
+
|
5
|
+
[](https://travis-ci.org/alphagov/notifications-ruby-client)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Prior to usage an account must be created through the Notify admin console. This will allow access to the API credentials you application.
|
10
|
+
|
11
|
+
You can then install the gem or require it in your application.
|
12
|
+
|
13
|
+
```
|
14
|
+
gem install 'notifications-ruby-client'
|
15
|
+
```
|
16
|
+
|
17
|
+
## Getting started
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'notifications-ruby-client'
|
21
|
+
client = Notifications::Client.new(service_id, secret_id)
|
22
|
+
```
|
23
|
+
|
24
|
+
you can also override api endpoint
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
client = Notifications::Client.new(service_id, secret_id, base_url)
|
28
|
+
client.base_url # => Notifications::Client::PRODUCTION_BASE_URL
|
29
|
+
```
|
30
|
+
|
31
|
+
Generate an API key by logging in to GOV.UK Notify [GOV.UK Notify](https://www.notifications.service.gov.uk) and going to the API integration page.
|
32
|
+
|
33
|
+
You will find your service ID on the API integration page.
|
34
|
+
|
35
|
+
### Send a message
|
36
|
+
|
37
|
+
Text message:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
sms = client.send_sms(to: number,
|
41
|
+
template: template_id,
|
42
|
+
personalisation: {
|
43
|
+
name: "name",
|
44
|
+
year: "2016"
|
45
|
+
}
|
46
|
+
)
|
47
|
+
|
48
|
+
```
|
49
|
+
|
50
|
+
Email:
|
51
|
+
```ruby
|
52
|
+
email = client.send_email(to: number, template: template_id)
|
53
|
+
|
54
|
+
sms = client.send_sms(
|
55
|
+
to: number,
|
56
|
+
template: template_id,
|
57
|
+
personalisation: {
|
58
|
+
name: "name",
|
59
|
+
year: "2016"
|
60
|
+
}
|
61
|
+
) # => Notifications::Client::ResponseNotification
|
62
|
+
```
|
63
|
+
|
64
|
+
Find `template_id` by clicking **API info** for the template you want to send.
|
65
|
+
|
66
|
+
If a template has placeholders, you need to provide their values in `personalisation`. Otherwise do not pass in `personalisation`
|
67
|
+
|
68
|
+
If successful the response is a `Notifications::Client::ResponseNotification`, which has the notification id.
|
69
|
+
Otherwise a Notifications::Client::RequestError is returned.
|
70
|
+
|
71
|
+
|
72
|
+
### Get the status of one message
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
notification = client.get_notification(id) # => Notifications::Client::Notification
|
76
|
+
notification.id # => uuid for the notification
|
77
|
+
notification.to # => recipient email address or mobile number
|
78
|
+
notification.status # => status of the message "created|pending|sent|delivered|permanent-failure|temporary-failure"
|
79
|
+
notification.created_at # => Date time the message was created
|
80
|
+
notification.api_key # => uuid for the api key (not the actual api key)
|
81
|
+
notification.billable_units # => units billable or nil for email
|
82
|
+
notification.subject # => Subject of email or nil for sms
|
83
|
+
notification.body # => Body of message
|
84
|
+
notification.job # => job id if created by a csv or nil if message sent via api
|
85
|
+
notification.notification_type # => sms | email
|
86
|
+
notification.service # => uuid for service
|
87
|
+
notification.sent_at # => Date time the message is sent to the provider or nil if status = "created"
|
88
|
+
notification.sent_by # => Name of the provider that sent the message or nil if status = "created"
|
89
|
+
notification.template # => Hash containing template id, name, version, template type sms|email
|
90
|
+
notification.template_version # Template version number
|
91
|
+
notification.reference # => reference of the email or nil for sms
|
92
|
+
notification.updated_at # => Date time that the notification was last updated
|
93
|
+
```
|
94
|
+
|
95
|
+
### Get the status of all messages
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
notifications = client.get_notifications
|
99
|
+
notifications.links # => {"last"=>"/notifications?page=4", "next"=>"/notifications?page=2"}
|
100
|
+
notifications.total # => 202
|
101
|
+
notifications.page_size # => 50
|
102
|
+
notifications.collection # => [] (array of notification objects)
|
103
|
+
|
104
|
+
```
|
105
|
+
|
106
|
+
Query parameters are also supported
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
client.get_notifications(
|
110
|
+
page: 2,
|
111
|
+
limit_days: 3,
|
112
|
+
page_size: 20,
|
113
|
+
status: "delivered",
|
114
|
+
template_type: "sms"
|
115
|
+
)
|
116
|
+
```
|
117
|
+
|
118
|
+
### Exceptions
|
119
|
+
|
120
|
+
Raised exceptions will contain error message and response status code
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
client = Notifications::Client.new(base_url, invalid, invalid)
|
124
|
+
rescue Notifications::Client::RequestError => e
|
125
|
+
e.code # => 403
|
126
|
+
e.message # => Invalid credentials
|
127
|
+
```
|
128
|
+
<table>
|
129
|
+
<thead>
|
130
|
+
<tr>
|
131
|
+
<td> Code </td>
|
132
|
+
<td> Message </td>
|
133
|
+
</tr>
|
134
|
+
</thead>
|
135
|
+
<tbdoy>
|
136
|
+
<tr>
|
137
|
+
<td> 403 </td>
|
138
|
+
<td> {"token"=>["Invalid token: signature"]} </td>
|
139
|
+
</tr>
|
140
|
+
<tr>
|
141
|
+
<td> 403 </td>
|
142
|
+
<td> {"token"=>["Invalid token: expired"]} </td>
|
143
|
+
</tr>
|
144
|
+
<tr>
|
145
|
+
<td> 429 </td>
|
146
|
+
<td> Exceeded send limits (50) for today </td>
|
147
|
+
</tr>
|
148
|
+
<tr>
|
149
|
+
<td> 400 </td>
|
150
|
+
<td> Can’t send to this recipient using a team-only API key </td>
|
151
|
+
</tr>
|
152
|
+
<tr>
|
153
|
+
<td> 400 </td>
|
154
|
+
<td> Can’t send to this recipient when service is in trial
|
155
|
+
mode - see https://www.notifications.service.gov.uk/trial-mode
|
156
|
+
</td>
|
157
|
+
</tr>
|
158
|
+
</tbody>
|
159
|
+
</table>
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
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
|
+
|
9
|
+
desc "Run govuk-lint with similar params to CI"
|
10
|
+
task "lint" do
|
11
|
+
sh "bundle exec govuk-lint-ruby --format clang spec lib"
|
12
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "notifications/client"
|
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/setup
ADDED
data/bin/test_client.rb
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'notifications/client'
|
3
|
+
require 'notifications/client/notification'
|
4
|
+
require 'notifications/client/response_notification'
|
5
|
+
require 'notifications/client/notification'
|
6
|
+
|
7
|
+
def main
|
8
|
+
client = Notifications::Client.new(ENV['SERVICE_ID'], ENV['API_KEY'], ENV['NOTIFY_API_URL'])
|
9
|
+
email_notification = test_send_email_endpoint(client)
|
10
|
+
sms_notification = test_send_sms_endpoint(client)
|
11
|
+
test_get_notification_by_id_endpoint(client, email_notification.id, 'email')
|
12
|
+
test_get_notification_by_id_endpoint(client, sms_notification.id, 'sms')
|
13
|
+
test_get_all_notifications(client, sms_notification.id, email_notification.id)
|
14
|
+
p 'ruby client functional tests pass'
|
15
|
+
exit 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_send_email_endpoint(client)
|
19
|
+
email_resp = client.send_email(to: ENV['FUNCTIONAL_TEST_EMAIL'], template: ENV['EMAIL_TEMPLATE_ID'])
|
20
|
+
test_notification_response_data_type(email_resp, 'email')
|
21
|
+
email_resp
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_send_sms_endpoint(client)
|
25
|
+
sms_resp = client.send_sms(to: ENV['FUNCTIONAL_TEST_NUMBER'], template: ENV['SMS_TEMPLATE_ID'])
|
26
|
+
test_notification_response_data_type(sms_resp, 'sms')
|
27
|
+
sms_resp
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_notification_response_data_type(notification, message_type)
|
31
|
+
unless notification.is_a?(Notifications::Client::ResponseNotification) then
|
32
|
+
p 'failed ' + message_type +' response is not a Notifications::Client::ResponseNotification'
|
33
|
+
exit 1
|
34
|
+
end
|
35
|
+
unless notification.id.is_a?(String) then
|
36
|
+
p 'failed '+ message_type + 'id is not a String'
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_get_notification_by_id_endpoint(client, id, message_type)
|
42
|
+
get_notification_response = get_notification_for_id(client, id, message_type)
|
43
|
+
unless get_notification_response.is_a?(Notifications::Client::Notification) then
|
44
|
+
p 'get notification is not a Notifications::Client::Notification for id ' + id
|
45
|
+
exit 1
|
46
|
+
end
|
47
|
+
if message_type == 'email' then
|
48
|
+
field_should_not_be_nil(expected_fields_in_email_resp, get_notification_response, 'send_email')
|
49
|
+
field_should_be_nil(expected_fields_in_email_resp_that_are_nil, get_notification_response, 'send_email')
|
50
|
+
end
|
51
|
+
if message_type == 'sms' then
|
52
|
+
field_should_not_be_nil(expected_fields_in_sms_resp, get_notification_response, 'send_sms')
|
53
|
+
field_should_be_nil(expected_fields_in_sms_resp_that_are_nil, get_notification_response, 'send_sms')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def get_notification_for_id(client, id, message_type)
|
59
|
+
max_attempts = 0
|
60
|
+
wait_for_sent_message = true
|
61
|
+
while max_attempts < 3 && wait_for_sent_message
|
62
|
+
begin
|
63
|
+
get_notification_response = client.get_notification(id)
|
64
|
+
wait_for_sent_message = false
|
65
|
+
rescue Notifications::Client::RequestError => no_result
|
66
|
+
if no_result.message == "No result found"
|
67
|
+
max_attempts = max_attempts + 1
|
68
|
+
sleep 3
|
69
|
+
else
|
70
|
+
p 'get_notification threw an exception for the ' + message_type + ' notification'
|
71
|
+
p no_result.to_s
|
72
|
+
exit 1
|
73
|
+
end
|
74
|
+
end
|
75
|
+
if get_notification_response != nil && get_notification_response.send(:'status') == 'created'
|
76
|
+
# we want to test the sent response?
|
77
|
+
wait_for_sent_message = true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
if max_attempts == 3 then
|
81
|
+
p 'get_notification failed because the ' + message_type + ' notification was not found'
|
82
|
+
exit 1
|
83
|
+
end
|
84
|
+
get_notification_response
|
85
|
+
end
|
86
|
+
|
87
|
+
def field_should_not_be_nil(fields, obj, method_name)
|
88
|
+
fields.each do |field|
|
89
|
+
if obj.send(:"#{field}") == nil then
|
90
|
+
p 'contract test failed because ' + field + ' should not be nil for ' + method_name + ' response'
|
91
|
+
exit 1
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def field_should_be_nil(fields, obj, method_name)
|
97
|
+
fields.each do |field|
|
98
|
+
if obj.send(:"#{field}") != nil then
|
99
|
+
p 'contract test failed because ' + field + ' should be nil for ' + method_name + ' response'
|
100
|
+
exit 1
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def expected_fields_in_email_resp
|
106
|
+
%w(id
|
107
|
+
api_key
|
108
|
+
billable_units
|
109
|
+
to
|
110
|
+
subject
|
111
|
+
body
|
112
|
+
notification_type
|
113
|
+
status
|
114
|
+
service
|
115
|
+
sent_at
|
116
|
+
sent_by
|
117
|
+
template
|
118
|
+
template_version
|
119
|
+
created_at
|
120
|
+
updated_at
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
def expected_fields_in_email_resp_that_are_nil
|
125
|
+
%w(job)
|
126
|
+
end
|
127
|
+
|
128
|
+
def expected_fields_in_sms_resp
|
129
|
+
%w(id
|
130
|
+
api_key
|
131
|
+
billable_units
|
132
|
+
to
|
133
|
+
body
|
134
|
+
notification_type
|
135
|
+
status
|
136
|
+
service
|
137
|
+
sent_at
|
138
|
+
sent_by
|
139
|
+
template
|
140
|
+
template_version
|
141
|
+
created_at
|
142
|
+
updated_at
|
143
|
+
)
|
144
|
+
end
|
145
|
+
|
146
|
+
def expected_fields_in_sms_resp_that_are_nil
|
147
|
+
%w(job
|
148
|
+
subject
|
149
|
+
reference)
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_get_all_notifications(client, first_id, second_id)
|
153
|
+
notifications = client.get_notifications()
|
154
|
+
unless notifications.is_a?(Notifications::Client::NotificationsCollection) then
|
155
|
+
p 'get all notifications is not Notifications::Client::NotificationsCollection'
|
156
|
+
exit 1
|
157
|
+
end
|
158
|
+
|
159
|
+
field_should_not_be_nil(expected_fields_for_get_all_notifications, notifications, 'get_notifications')
|
160
|
+
|
161
|
+
notification_collection = notifications.send(:'collection')
|
162
|
+
unless notification_collection[0].id == first_id then
|
163
|
+
p 'first item in notification_collection is not the expected notification, last message sent'
|
164
|
+
exit 0
|
165
|
+
end
|
166
|
+
unless notification_collection[1].id == second_id then
|
167
|
+
p 'second item in notification_collection is not the expected notification, second last message sent'
|
168
|
+
exit 0
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def expected_fields_for_get_all_notifications
|
173
|
+
%W(links
|
174
|
+
total
|
175
|
+
page_size
|
176
|
+
collection
|
177
|
+
)
|
178
|
+
end
|
179
|
+
|
180
|
+
if __FILE__ == $PROGRAM_NAME
|
181
|
+
main
|
182
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Notifications
|
2
|
+
class Client
|
3
|
+
class Notification
|
4
|
+
FIELDS = [
|
5
|
+
:id,
|
6
|
+
:api_key,
|
7
|
+
:billable_units,
|
8
|
+
:to,
|
9
|
+
:subject,
|
10
|
+
:body,
|
11
|
+
:job,
|
12
|
+
:notification_type,
|
13
|
+
:status,
|
14
|
+
:service,
|
15
|
+
:sent_at,
|
16
|
+
:sent_by,
|
17
|
+
:template,
|
18
|
+
:template_version,
|
19
|
+
:reference,
|
20
|
+
:created_at,
|
21
|
+
:updated_at
|
22
|
+
].freeze
|
23
|
+
|
24
|
+
attr_reader(*FIELDS)
|
25
|
+
|
26
|
+
def initialize(notification)
|
27
|
+
notification = normalize(notification)
|
28
|
+
|
29
|
+
FIELDS.each do |field|
|
30
|
+
instance_variable_set(:"@#{field}", notification.fetch(field.to_s, nil)
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
[
|
36
|
+
:sent_at,
|
37
|
+
:created_at,
|
38
|
+
:updated_at
|
39
|
+
].each do |field|
|
40
|
+
define_method field do
|
41
|
+
begin
|
42
|
+
value = instance_variable_get(:"@#{field}")
|
43
|
+
Time.parse value
|
44
|
+
rescue
|
45
|
+
value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def normalize(notification)
|
53
|
+
notification.key?('data') ? notification['data']['notification'] : notification
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Notifications
|
2
|
+
class Client
|
3
|
+
class NotificationsCollection
|
4
|
+
attr_reader :links,
|
5
|
+
:total,
|
6
|
+
:page_size,
|
7
|
+
:collection
|
8
|
+
|
9
|
+
def initialize(response)
|
10
|
+
@links = response["links"]
|
11
|
+
@total = response["total"]
|
12
|
+
@page_size = response["page_size"]
|
13
|
+
@collection = collection_from(response["notifications"])
|
14
|
+
end
|
15
|
+
|
16
|
+
def collection_from(notifications)
|
17
|
+
notifications.map do |notification|
|
18
|
+
Notification.new(notification)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Notifications
|
2
|
+
class Client
|
3
|
+
class RequestError < StandardError
|
4
|
+
attr_reader :code, :message
|
5
|
+
|
6
|
+
def initialize(response)
|
7
|
+
@code = response.code
|
8
|
+
@message = message_from(response.body)
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"#{code} #{message}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def message_from(body)
|
16
|
+
JSON.parse(body).fetch("message")
|
17
|
+
rescue JSON::ParserError
|
18
|
+
body
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require "net/https"
|
2
|
+
require "uri"
|
3
|
+
require "jwt"
|
4
|
+
require "notifications/client/request_error"
|
5
|
+
|
6
|
+
module Notifications
|
7
|
+
class Client
|
8
|
+
class Speaker
|
9
|
+
attr_reader :base_url
|
10
|
+
|
11
|
+
BASE_PATH = "/notifications".freeze
|
12
|
+
USER_AGENT = "NOTIFY-API-RUBY-CLIENT/#{Notifications::Client::VERSION}".freeze
|
13
|
+
|
14
|
+
##
|
15
|
+
# @param service_id [String] your service
|
16
|
+
# API identifier
|
17
|
+
# @param secret [String] your service API
|
18
|
+
# secret
|
19
|
+
# @param base_url [String] host URL. This is
|
20
|
+
# the address to perform the requests
|
21
|
+
def initialize(service_id, secret_token, base_url = nil)
|
22
|
+
@service_id = service_id
|
23
|
+
@secret_token = secret_token
|
24
|
+
@base_url = base_url || PRODUCTION_BASE_URL
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# @param kind [String] 'email' or 'sms'
|
29
|
+
# @param form_data [Hash]
|
30
|
+
# @option form_data [String] :to recipient
|
31
|
+
# to notify (sms or email)
|
32
|
+
# @option form_data [String] :template
|
33
|
+
# template to render in notification
|
34
|
+
# @option form_data [Hash] :personalisation
|
35
|
+
# fields to use in the template
|
36
|
+
# @see #perform_request!
|
37
|
+
def post(kind, form_data)
|
38
|
+
request = Net::HTTP::Post.new(
|
39
|
+
"#{BASE_PATH}/#{kind}",
|
40
|
+
headers
|
41
|
+
)
|
42
|
+
request.body = form_data.is_a?(Hash) ? form_data.to_json : form_data
|
43
|
+
perform_request!(request)
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# @param id [String]
|
48
|
+
# @param options [Hash] query
|
49
|
+
# @see #perform_request!
|
50
|
+
def get(id = nil, options = {})
|
51
|
+
path = BASE_PATH.dup
|
52
|
+
path << "/" << id if id
|
53
|
+
path << "?" << URI.encode_www_form(options) if options.any?
|
54
|
+
request = Net::HTTP::Get.new(path, headers)
|
55
|
+
perform_request!(request)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
##
|
61
|
+
# @return [Hash] JSON parsed response
|
62
|
+
# @raise [RequestError] if request is
|
63
|
+
# not successful
|
64
|
+
def perform_request!(request)
|
65
|
+
response = open(request)
|
66
|
+
if response.is_a?(Net::HTTPClientError)
|
67
|
+
raise RequestError.new(response)
|
68
|
+
else
|
69
|
+
JSON.parse(response.body)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def open(request)
|
74
|
+
uri = URI.parse(@base_url)
|
75
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
76
|
+
http.request(request)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def headers
|
81
|
+
{
|
82
|
+
"User-agent" => USER_AGENT,
|
83
|
+
"Content-Type" => "application/json",
|
84
|
+
"Authorization" => "Bearer " + jwt_token
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
def jwt_token
|
89
|
+
payload = {
|
90
|
+
iss: @service_id,
|
91
|
+
iat: Time.now.to_i
|
92
|
+
}
|
93
|
+
JWT.encode payload, @secret_token, "HS256"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "notifications/client/version"
|
2
|
+
require "notifications/client/speaker"
|
3
|
+
require "notifications/client/notification"
|
4
|
+
require "notifications/client/response_notification"
|
5
|
+
require "notifications/client/notifications_collection"
|
6
|
+
require 'active_support/core_ext/module/delegation'
|
7
|
+
|
8
|
+
module Notifications
|
9
|
+
class Client
|
10
|
+
attr_reader :speaker
|
11
|
+
|
12
|
+
PRODUCTION_BASE_URL = "https://api.notifications.service.gov.uk".freeze
|
13
|
+
|
14
|
+
delegate :base_url,
|
15
|
+
:base_url=,
|
16
|
+
to: :speaker
|
17
|
+
|
18
|
+
##
|
19
|
+
# @see Notifications::Client::Speaker#initialize
|
20
|
+
def initialize(*args)
|
21
|
+
@speaker = Speaker.new(*args)
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# @see Notifications::Client::Speaker#post
|
26
|
+
# @return [ResponseNotification]
|
27
|
+
def send_email(args)
|
28
|
+
ResponseNotification.new(
|
29
|
+
speaker.post("email", args)
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# @see Notifications::Client::Speaker#post
|
35
|
+
# @return [ResponseNotification]
|
36
|
+
def send_sms(args)
|
37
|
+
ResponseNotification.new(
|
38
|
+
speaker.post("sms", args)
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# @param id [String]
|
44
|
+
# @see Notifications::Client::Speaker#get
|
45
|
+
# @return [Notification]
|
46
|
+
def get_notification(id)
|
47
|
+
Notification.new(
|
48
|
+
speaker.get(id)
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# @param options [Hash]
|
54
|
+
# @option options [String] :template_type
|
55
|
+
# sms or email
|
56
|
+
# @option options [String] :status
|
57
|
+
# sending, delivered, permanently failed,
|
58
|
+
# temporarily failed, or technical failure
|
59
|
+
# @option options [String] :page
|
60
|
+
# @option options [String] :page_size
|
61
|
+
# @option options [String] :limit_days
|
62
|
+
# @see Notifications::Client::Speaker#get
|
63
|
+
# @return [NotificationsCollection]
|
64
|
+
def get_notifications(options = {})
|
65
|
+
NotificationsCollection.new(
|
66
|
+
speaker.get(nil, options)
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'notifications/client/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "notifications-ruby-client"
|
8
|
+
spec.version = Notifications::Client::VERSION
|
9
|
+
spec.authors = [
|
10
|
+
"bitzesty",
|
11
|
+
"dazahern"
|
12
|
+
]
|
13
|
+
|
14
|
+
spec.email = ["info@bitzesty.com", "daz.ahern@digital.cabinet-office.gov.uk"]
|
15
|
+
|
16
|
+
spec.summary = "Ruby client for GOV.UK Notifications API"
|
17
|
+
spec.homepage = "https://github.com/alphagov/notifications-ruby-client"
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_runtime_dependency "jwt", "~> 1.5"
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
29
|
+
spec.add_development_dependency "webmock", "~> 2.0"
|
30
|
+
spec.add_development_dependency "factory_girl", "~> 4.7"
|
31
|
+
spec.add_development_dependency "govuk-lint", "~> 1.1.0"
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: notifications-ruby-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- bitzesty
|
8
|
+
- dazahern
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2016-08-31 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: jwt
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.5'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.5'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: bundler
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1.7'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.7'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rake
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '10.0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '10.0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rspec
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '3.0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '3.0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: webmock
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '2.0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '2.0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: factory_girl
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '4.7'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '4.7'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: govuk-lint
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 1.1.0
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: 1.1.0
|
112
|
+
description:
|
113
|
+
email:
|
114
|
+
- info@bitzesty.com
|
115
|
+
- daz.ahern@digital.cabinet-office.gov.uk
|
116
|
+
executables: []
|
117
|
+
extensions: []
|
118
|
+
extra_rdoc_files: []
|
119
|
+
files:
|
120
|
+
- ".gitignore"
|
121
|
+
- ".rspec"
|
122
|
+
- ".travis.yml"
|
123
|
+
- Gemfile
|
124
|
+
- LICENSE
|
125
|
+
- README.md
|
126
|
+
- Rakefile
|
127
|
+
- bin/console
|
128
|
+
- bin/setup
|
129
|
+
- bin/test_client.rb
|
130
|
+
- lib/notifications/client.rb
|
131
|
+
- lib/notifications/client/notification.rb
|
132
|
+
- lib/notifications/client/notifications_collection.rb
|
133
|
+
- lib/notifications/client/request_error.rb
|
134
|
+
- lib/notifications/client/response_notification.rb
|
135
|
+
- lib/notifications/client/speaker.rb
|
136
|
+
- lib/notifications/client/version.rb
|
137
|
+
- notifications-ruby-client.gemspec
|
138
|
+
homepage: https://github.com/alphagov/notifications-ruby-client
|
139
|
+
licenses: []
|
140
|
+
metadata: {}
|
141
|
+
post_install_message:
|
142
|
+
rdoc_options: []
|
143
|
+
require_paths:
|
144
|
+
- lib
|
145
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
requirements: []
|
156
|
+
rubyforge_project:
|
157
|
+
rubygems_version: 2.5.1
|
158
|
+
signing_key:
|
159
|
+
specification_version: 4
|
160
|
+
summary: Ruby client for GOV.UK Notifications API
|
161
|
+
test_files: []
|