notifications-ruby-client 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +12 -0
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +100 -0
- data/CONTRIBUTING.md +39 -0
- data/DOCUMENTATION.md +949 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/Makefile +87 -0
- data/README.md +10 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/generate_docker_env.sh +29 -0
- data/bin/setup +8 -0
- data/bin/test_client.rb +454 -0
- data/docker/Dockerfile +26 -0
- data/docker/Makefile +16 -0
- data/lib/notifications/client.rb +153 -0
- data/lib/notifications/client/helper_methods.rb +9 -0
- data/lib/notifications/client/notification.rb +54 -0
- data/lib/notifications/client/notifications_collection.rb +19 -0
- data/lib/notifications/client/received_text.rb +31 -0
- data/lib/notifications/client/received_text_collection.rb +18 -0
- data/lib/notifications/client/request_error.rb +59 -0
- data/lib/notifications/client/response_notification.rb +21 -0
- data/lib/notifications/client/response_precompiled_letter.rb +19 -0
- data/lib/notifications/client/response_template.rb +41 -0
- data/lib/notifications/client/speaker.rb +171 -0
- data/lib/notifications/client/template_collection.rb +16 -0
- data/lib/notifications/client/template_preview.rb +22 -0
- data/lib/notifications/client/uuid_validator.rb +25 -0
- data/lib/notifications/client/version.rb +14 -0
- data/notifications-ruby-client.gemspec +31 -0
- metadata +181 -0
@@ -0,0 +1,171 @@
|
|
1
|
+
require "base64"
|
2
|
+
require "net/https"
|
3
|
+
require "uri"
|
4
|
+
require "jwt"
|
5
|
+
require_relative "request_error"
|
6
|
+
|
7
|
+
module Notifications
|
8
|
+
class Client
|
9
|
+
class Speaker
|
10
|
+
include ErrorHandling
|
11
|
+
|
12
|
+
attr_reader :base_url
|
13
|
+
attr_reader :service_id
|
14
|
+
attr_reader :secret_token
|
15
|
+
|
16
|
+
BASE_PATH = "/v2/notifications".freeze
|
17
|
+
USER_AGENT = "NOTIFY-API-RUBY-CLIENT/#{Notifications::Client::VERSION}".freeze
|
18
|
+
|
19
|
+
##
|
20
|
+
# @param secret [String] your service API secret
|
21
|
+
# @param base_url [String] host URL. This is the address to perform the requests.
|
22
|
+
# If left nil the production url is used.
|
23
|
+
def initialize(secret_token = nil, base_url = nil)
|
24
|
+
@service_id = secret_token[secret_token.length - 73..secret_token.length - 38]
|
25
|
+
@secret_token = secret_token[secret_token.length - 36..secret_token.length]
|
26
|
+
@base_url = base_url || PRODUCTION_BASE_URL
|
27
|
+
|
28
|
+
validate_uuids!
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# @param kind [String] 'email', 'sms' or 'letter'
|
33
|
+
# @param form_data [Hash]
|
34
|
+
# @option form_data [String] :phone_number
|
35
|
+
# phone number of the sms recipient
|
36
|
+
# @option form_data [String] :email_address
|
37
|
+
# email address of the email recipent
|
38
|
+
# @option form_data [String] :template
|
39
|
+
# template to render in notification
|
40
|
+
# @option form_data [Hash] :personalisation
|
41
|
+
# fields to use in the template
|
42
|
+
# @option form_data [String] :reference
|
43
|
+
# A reference specified by the service for the notification. Get all notifications can be filtered by this reference.
|
44
|
+
# This reference can be unique or used used to refer to a batch of notifications.
|
45
|
+
# Can be an empty string or nil, when you do not require a reference for the notifications.
|
46
|
+
# @option form_data [String] :email_reply_to_id
|
47
|
+
# id of the email address that replies to email notifications will be sent to
|
48
|
+
# @option form_data [String] :sms_sender_id
|
49
|
+
# id of the sender to be used for an sms notification
|
50
|
+
# @see #perform_request!
|
51
|
+
def post(kind, form_data)
|
52
|
+
request = Net::HTTP::Post.new(
|
53
|
+
"#{BASE_PATH}/#{kind}",
|
54
|
+
headers
|
55
|
+
)
|
56
|
+
request.body = form_data.is_a?(Hash) ? form_data.to_json : form_data
|
57
|
+
perform_request!(request)
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# @param id [String]
|
62
|
+
# @param options [Hash] query
|
63
|
+
# @see #perform_request!
|
64
|
+
def get(id = nil, options = {})
|
65
|
+
path = BASE_PATH.dup
|
66
|
+
path << "/" << id if id
|
67
|
+
path << "?" << URI.encode_www_form(options) if options.any?
|
68
|
+
request = Net::HTTP::Get.new(path, headers)
|
69
|
+
perform_request!(request)
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# @param url path of endpoint
|
74
|
+
# @param id [String]
|
75
|
+
# @param options [Hash] query
|
76
|
+
# @see #perform_request!
|
77
|
+
def get_with_url(url, options = {})
|
78
|
+
path = url
|
79
|
+
path << "?" << URI.encode_www_form(options) if options.any?
|
80
|
+
request = Net::HTTP::Get.new(path, headers)
|
81
|
+
perform_request!(request)
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# @param url [String] path of the endpoint
|
86
|
+
# @param form_data [Hash]
|
87
|
+
# @option form_data [String] :template_id
|
88
|
+
# id of the template to render
|
89
|
+
# @option form_data [Hash] :personalisation
|
90
|
+
# fields to use in the template
|
91
|
+
# @see #perform_request!
|
92
|
+
def post_with_url(url, form_data)
|
93
|
+
request = Net::HTTP::Post.new(
|
94
|
+
url,
|
95
|
+
headers
|
96
|
+
)
|
97
|
+
request.body = form_data.is_a?(Hash) ? form_data.to_json : form_data
|
98
|
+
perform_request!(request)
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# @param reference [String] reference of the notification
|
103
|
+
# @param pdf_file [File] PDF file opened for reading
|
104
|
+
# @see #perform_request!
|
105
|
+
def post_precompiled_letter(reference, pdf_file, postage = nil)
|
106
|
+
content = Base64.strict_encode64(pdf_file.read)
|
107
|
+
form_data = { reference: reference, content: content }
|
108
|
+
|
109
|
+
if postage != nil
|
110
|
+
form_data[:postage] = postage
|
111
|
+
end
|
112
|
+
|
113
|
+
request = Net::HTTP::Post.new(
|
114
|
+
"#{BASE_PATH}/letter",
|
115
|
+
headers
|
116
|
+
)
|
117
|
+
request.body = form_data.to_json
|
118
|
+
perform_request!(request)
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
##
|
124
|
+
# @return [Hash] JSON parsed response
|
125
|
+
# @raise [RequestError] if request is
|
126
|
+
# not successful
|
127
|
+
def perform_request!(request)
|
128
|
+
response = open(request)
|
129
|
+
if response.is_a?(Net::HTTPClientError) || response.is_a?(Net::HTTPServerError)
|
130
|
+
raise build_error(response)
|
131
|
+
else
|
132
|
+
JSON.parse(response.body)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def open(request)
|
137
|
+
uri = URI.parse(@base_url)
|
138
|
+
Net::HTTP.start(uri.host, uri.port, :ENV, use_ssl: uri.scheme == 'https') do |http|
|
139
|
+
http.request(request)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def headers
|
144
|
+
{
|
145
|
+
"User-agent" => USER_AGENT,
|
146
|
+
"Content-Type" => "application/json",
|
147
|
+
"Authorization" => "Bearer " + jwt_token
|
148
|
+
}
|
149
|
+
end
|
150
|
+
|
151
|
+
def jwt_token
|
152
|
+
payload = {
|
153
|
+
iss: @service_id,
|
154
|
+
iat: Time.now.to_i
|
155
|
+
}
|
156
|
+
JWT.encode payload, @secret_token, "HS256"
|
157
|
+
end
|
158
|
+
|
159
|
+
def validate_uuids!
|
160
|
+
contextual_message = [
|
161
|
+
"This error is probably caused by initializing the Notifications client with an invalid API key.",
|
162
|
+
"You can generate a new API key by logging into Notify and visiting the 'API integration' page:",
|
163
|
+
"https://www.notifications.service.gov.uk",
|
164
|
+
].join("\n")
|
165
|
+
|
166
|
+
UuidValidator.validate!(@service_id, contextual_message)
|
167
|
+
UuidValidator.validate!(@secret_token, contextual_message)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Notifications
|
2
|
+
class Client
|
3
|
+
class TemplateCollection
|
4
|
+
attr_reader :collection
|
5
|
+
def initialize(response)
|
6
|
+
@collection = collection_from(response["templates"])
|
7
|
+
end
|
8
|
+
|
9
|
+
def collection_from(templates)
|
10
|
+
templates.map do |template|
|
11
|
+
Template.new(template)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Notifications
|
2
|
+
class Client
|
3
|
+
class TemplatePreview
|
4
|
+
FIELDS = %i(
|
5
|
+
id
|
6
|
+
version
|
7
|
+
body
|
8
|
+
subject
|
9
|
+
type
|
10
|
+
html
|
11
|
+
).freeze
|
12
|
+
|
13
|
+
attr_reader(*FIELDS)
|
14
|
+
|
15
|
+
def initialize(notification)
|
16
|
+
FIELDS.each do |field|
|
17
|
+
instance_variable_set(:"@#{field}", notification.fetch(field.to_s, nil))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Notifications
|
2
|
+
class UuidValidator
|
3
|
+
HEX = /[0-9a-f]/
|
4
|
+
REGEX = /^#{HEX}{8}-#{HEX}{4}-#{HEX}{4}-#{HEX}{4}-#{HEX}{12}$/
|
5
|
+
|
6
|
+
attr_accessor :uuid
|
7
|
+
|
8
|
+
def initialize(uuid)
|
9
|
+
self.uuid = uuid
|
10
|
+
end
|
11
|
+
|
12
|
+
def valid?
|
13
|
+
!!(uuid && uuid.match(REGEX))
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.validate!(uuid, contextual_message = nil)
|
17
|
+
return if new(uuid).valid?
|
18
|
+
|
19
|
+
message = "#{uuid.inspect} is not a valid uuid"
|
20
|
+
message += "\n#{contextual_message}" if contextual_message
|
21
|
+
|
22
|
+
raise ArgumentError, message
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Version numbering follows Semantic Versionning:
|
2
|
+
#
|
3
|
+
# Given a version number MAJOR.MINOR.PATCH, increment the:
|
4
|
+
# - MAJOR version when you make incompatible API changes,
|
5
|
+
# - MINOR version when you add functionality in a backwards-compatible manner, and
|
6
|
+
# - PATCH version when you make backwards-compatible bug fixes.
|
7
|
+
#
|
8
|
+
# -- http://semver.org/
|
9
|
+
|
10
|
+
module Notifications
|
11
|
+
class Client
|
12
|
+
VERSION = "4.0.0".freeze
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,31 @@
|
|
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
|
+
"Government Digital Service"
|
11
|
+
]
|
12
|
+
|
13
|
+
spec.email = ["notify@digital.cabinet-office.gov.uk"]
|
14
|
+
|
15
|
+
spec.summary = "Ruby client for GOV.UK Notifications API"
|
16
|
+
spec.homepage = "https://github.com/alphagov/notifications-ruby-client"
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_runtime_dependency "jwt", ">= 1.5", "< 3"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
26
|
+
spec.add_development_dependency "rake", "~> 12.3"
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.7"
|
28
|
+
spec.add_development_dependency "webmock", "~> 3.4"
|
29
|
+
spec.add_development_dependency "factory_bot", "~> 4.10"
|
30
|
+
spec.add_development_dependency "govuk-lint", "~> 3.8"
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: notifications-ruby-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 4.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Government Digital Service
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-07-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: jwt
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '3'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.5'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: bundler
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.13'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.13'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '12.3'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '12.3'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rspec
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.7'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '3.7'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: webmock
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '3.4'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '3.4'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: factory_bot
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '4.10'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '4.10'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: govuk-lint
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '3.8'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '3.8'
|
117
|
+
description:
|
118
|
+
email:
|
119
|
+
- notify@digital.cabinet-office.gov.uk
|
120
|
+
executables: []
|
121
|
+
extensions: []
|
122
|
+
extra_rdoc_files: []
|
123
|
+
files:
|
124
|
+
- ".github/PULL_REQUEST_TEMPLATE.md"
|
125
|
+
- ".gitignore"
|
126
|
+
- ".rspec"
|
127
|
+
- ".rubocop.yml"
|
128
|
+
- CHANGELOG.md
|
129
|
+
- CONTRIBUTING.md
|
130
|
+
- DOCUMENTATION.md
|
131
|
+
- Gemfile
|
132
|
+
- LICENSE
|
133
|
+
- Makefile
|
134
|
+
- README.md
|
135
|
+
- Rakefile
|
136
|
+
- bin/console
|
137
|
+
- bin/generate_docker_env.sh
|
138
|
+
- bin/setup
|
139
|
+
- bin/test_client.rb
|
140
|
+
- docker/Dockerfile
|
141
|
+
- docker/Makefile
|
142
|
+
- lib/notifications/client.rb
|
143
|
+
- lib/notifications/client/helper_methods.rb
|
144
|
+
- lib/notifications/client/notification.rb
|
145
|
+
- lib/notifications/client/notifications_collection.rb
|
146
|
+
- lib/notifications/client/received_text.rb
|
147
|
+
- lib/notifications/client/received_text_collection.rb
|
148
|
+
- lib/notifications/client/request_error.rb
|
149
|
+
- lib/notifications/client/response_notification.rb
|
150
|
+
- lib/notifications/client/response_precompiled_letter.rb
|
151
|
+
- lib/notifications/client/response_template.rb
|
152
|
+
- lib/notifications/client/speaker.rb
|
153
|
+
- lib/notifications/client/template_collection.rb
|
154
|
+
- lib/notifications/client/template_preview.rb
|
155
|
+
- lib/notifications/client/uuid_validator.rb
|
156
|
+
- lib/notifications/client/version.rb
|
157
|
+
- notifications-ruby-client.gemspec
|
158
|
+
homepage: https://github.com/alphagov/notifications-ruby-client
|
159
|
+
licenses: []
|
160
|
+
metadata: {}
|
161
|
+
post_install_message:
|
162
|
+
rdoc_options: []
|
163
|
+
require_paths:
|
164
|
+
- lib
|
165
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - ">="
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '0'
|
175
|
+
requirements: []
|
176
|
+
rubyforge_project:
|
177
|
+
rubygems_version: 2.7.6
|
178
|
+
signing_key:
|
179
|
+
specification_version: 4
|
180
|
+
summary: Ruby client for GOV.UK Notifications API
|
181
|
+
test_files: []
|