notifications-ruby-client 4.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/.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
data/docker/Dockerfile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
FROM ruby:2.3.1-slim
|
2
|
+
|
3
|
+
ARG HTTP_PROXY
|
4
|
+
ARG HTTPS_PROXY
|
5
|
+
ARG NO_PROXY
|
6
|
+
|
7
|
+
RUN \
|
8
|
+
echo "Install Debian packages" \
|
9
|
+
&& ([ -z "$HTTP_PROXY" ] || echo "Acquire::http::Proxy \"${HTTP_PROXY}\";" > /etc/apt/apt.conf.d/99HttpProxy) \
|
10
|
+
&& apt-get update \
|
11
|
+
&& apt-get install -y --no-install-recommends \
|
12
|
+
gcc \
|
13
|
+
make \
|
14
|
+
curl \
|
15
|
+
git \
|
16
|
+
|
17
|
+
&& echo "Clean up" \
|
18
|
+
&& rm -rf /var/lib/apt/lists/* /tmp/*
|
19
|
+
|
20
|
+
ENV PATH=/var/project/vendor/bin:$PATH \
|
21
|
+
BUNDLE_PATH="/var/project/vendor/bundle" \
|
22
|
+
BUNDLE_BIN="/var/project/vendor/bin" \
|
23
|
+
BUNDLE_APP_CONFIG="/var/project/.bundle"
|
24
|
+
|
25
|
+
|
26
|
+
WORKDIR /var/project
|
data/docker/Makefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
.DEFAULT_GOAL := help
|
2
|
+
SHELL := /bin/bash
|
3
|
+
|
4
|
+
.PHONY: help
|
5
|
+
help:
|
6
|
+
@cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
7
|
+
|
8
|
+
.PHONY: build
|
9
|
+
build:
|
10
|
+
docker pull `grep "FROM " Dockerfile | cut -d ' ' -f 2` || true
|
11
|
+
docker build \
|
12
|
+
--build-arg HTTP_PROXY="${HTTP_PROXY}" \
|
13
|
+
--build-arg HTTPS_PROXY="${HTTP_PROXY}" \
|
14
|
+
--build-arg NO_PROXY="${NO_PROXY}" \
|
15
|
+
-t govuk/notify-ruby-client-builder \
|
16
|
+
.
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require_relative "client/version"
|
2
|
+
require_relative "client/speaker"
|
3
|
+
require_relative "client/notification"
|
4
|
+
require_relative "client/response_notification"
|
5
|
+
require_relative "client/response_precompiled_letter"
|
6
|
+
require_relative "client/notifications_collection"
|
7
|
+
require_relative "client/received_text"
|
8
|
+
require_relative "client/received_text_collection"
|
9
|
+
require_relative "client/response_template"
|
10
|
+
require_relative "client/template_collection"
|
11
|
+
require_relative "client/template_preview"
|
12
|
+
require_relative "client/uuid_validator"
|
13
|
+
require_relative "client/helper_methods"
|
14
|
+
require "forwardable"
|
15
|
+
|
16
|
+
module Notifications
|
17
|
+
class Client
|
18
|
+
attr_reader :speaker
|
19
|
+
|
20
|
+
PRODUCTION_BASE_URL = "https://api.notifications.service.gov.uk".freeze
|
21
|
+
MAX_FILE_UPLOAD_SIZE = 2 * 1024 * 1024 # 2MB limit on uploaded documents
|
22
|
+
|
23
|
+
extend Forwardable
|
24
|
+
def_delegators :speaker, :service_id, :secret_token, :base_url, :base_url=
|
25
|
+
|
26
|
+
##
|
27
|
+
# @see Notifications::Client::Speaker#initialize
|
28
|
+
def initialize(*args)
|
29
|
+
@speaker = Speaker.new(*args)
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# @see Notifications::Client::Speaker#post
|
34
|
+
# @return [ResponseNotification]
|
35
|
+
def send_email(args)
|
36
|
+
ResponseNotification.new(
|
37
|
+
speaker.post("email", args)
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# @see Notifications::Client::Speaker#post
|
43
|
+
# @return [ResponseNotification]
|
44
|
+
def send_sms(args)
|
45
|
+
ResponseNotification.new(
|
46
|
+
speaker.post("sms", args)
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# @see Notifications::Client::Speaker#post
|
52
|
+
# @return [ResponseNotification]
|
53
|
+
def send_letter(args)
|
54
|
+
ResponseNotification.new(
|
55
|
+
speaker.post("letter", args)
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# @param reference [String]
|
61
|
+
# @param pdf_file [File]
|
62
|
+
# @see Notifications::Client::Speaker#post_precompiled_letter
|
63
|
+
# @return [ResponsePrecompiledLetter]
|
64
|
+
def send_precompiled_letter(reference, pdf_file, postage = nil)
|
65
|
+
ResponsePrecompiledLetter.new(
|
66
|
+
speaker.post_precompiled_letter(reference, pdf_file, postage)
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# @param id [String]
|
72
|
+
# @see Notifications::Client::Speaker#get
|
73
|
+
# @return [Notification]
|
74
|
+
def get_notification(id)
|
75
|
+
Notification.new(
|
76
|
+
speaker.get(id)
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# @param options [Hash]
|
82
|
+
# @option options [String] :template_type
|
83
|
+
# sms or email
|
84
|
+
# @option options [String] :status
|
85
|
+
# sending, delivered, permanently failed,
|
86
|
+
# temporarily failed, or technical failure
|
87
|
+
# @option options [String] :reference
|
88
|
+
# your reference for the notification
|
89
|
+
# @option options [String] :older_than
|
90
|
+
# notification id to return notificaitons that are older than this id.
|
91
|
+
# @see Notifications::Client::Speaker#get
|
92
|
+
# @return [NotificationsCollection]
|
93
|
+
def get_notifications(options = {})
|
94
|
+
NotificationsCollection.new(
|
95
|
+
speaker.get(nil, options)
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# @param id [String]
|
101
|
+
# @return [Template]
|
102
|
+
def get_template_by_id(id, options = {})
|
103
|
+
path = "/v2/template/" << id
|
104
|
+
Template.new(
|
105
|
+
speaker.get_with_url(path, options)
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# @param id [String]
|
111
|
+
# @param version [int]
|
112
|
+
# @return [Template]
|
113
|
+
def get_template_version(id, version, options = {})
|
114
|
+
path = "/v2/template/" << id << "/version/" << version.to_s
|
115
|
+
Template.new(
|
116
|
+
speaker.get_with_url(path, options)
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
##
|
121
|
+
# @option options [String] :type
|
122
|
+
# email, sms, letter
|
123
|
+
# @return [TemplateCollection]
|
124
|
+
def get_all_templates(options = {})
|
125
|
+
path = "/v2/templates"
|
126
|
+
TemplateCollection.new(
|
127
|
+
speaker.get_with_url(path, options)
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
##
|
132
|
+
# @param options [String]
|
133
|
+
# @option personalisation [Hash]
|
134
|
+
# @return [TemplatePreview]
|
135
|
+
def generate_template_preview(id, options = {})
|
136
|
+
path = "/v2/template/" << id << "/preview"
|
137
|
+
TemplatePreview.new(
|
138
|
+
speaker.post_with_url(path, options)
|
139
|
+
)
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# @option options [String] :older_than
|
144
|
+
# received text id to return received texts that are older than this id.
|
145
|
+
# @return [ReceivedTextCollection]
|
146
|
+
def get_received_texts(options = {})
|
147
|
+
path = "/v2/received-text-messages"
|
148
|
+
ReceivedTextCollection.new(
|
149
|
+
speaker.get_with_url(path, options)
|
150
|
+
)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
module Notifications
|
4
|
+
class Client
|
5
|
+
class Notification
|
6
|
+
FIELDS = %i(
|
7
|
+
id
|
8
|
+
reference
|
9
|
+
email_address
|
10
|
+
phone_number
|
11
|
+
line_1
|
12
|
+
line_2
|
13
|
+
line_3
|
14
|
+
line_4
|
15
|
+
line_5
|
16
|
+
line_6
|
17
|
+
postcode
|
18
|
+
postage
|
19
|
+
type
|
20
|
+
status
|
21
|
+
template
|
22
|
+
body
|
23
|
+
subject
|
24
|
+
sent_at
|
25
|
+
created_at
|
26
|
+
completed_at
|
27
|
+
created_by_name
|
28
|
+
).freeze
|
29
|
+
|
30
|
+
attr_reader(*FIELDS)
|
31
|
+
|
32
|
+
def initialize(notification)
|
33
|
+
FIELDS.each do |field|
|
34
|
+
instance_variable_set(:"@#{field}", notification.fetch(field.to_s, nil))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
%i(
|
39
|
+
sent_at
|
40
|
+
created_at
|
41
|
+
completed_at
|
42
|
+
).each do |field|
|
43
|
+
define_method field do
|
44
|
+
begin
|
45
|
+
value = instance_variable_get(:"@#{field}")
|
46
|
+
Time.parse value
|
47
|
+
rescue StandardError
|
48
|
+
value
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Notifications
|
2
|
+
class Client
|
3
|
+
class NotificationsCollection
|
4
|
+
attr_reader :links,
|
5
|
+
:collection
|
6
|
+
|
7
|
+
def initialize(response)
|
8
|
+
@links = response["links"]
|
9
|
+
@collection = collection_from(response["notifications"])
|
10
|
+
end
|
11
|
+
|
12
|
+
def collection_from(notifications)
|
13
|
+
notifications.map do |notification|
|
14
|
+
Notification.new(notification)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
module Notifications
|
4
|
+
class Client
|
5
|
+
class ReceivedText
|
6
|
+
FIELDS = %i(
|
7
|
+
id
|
8
|
+
created_at
|
9
|
+
content
|
10
|
+
notify_number
|
11
|
+
service_id
|
12
|
+
user_number
|
13
|
+
).freeze
|
14
|
+
|
15
|
+
attr_reader(*FIELDS)
|
16
|
+
|
17
|
+
def initialize(received_text)
|
18
|
+
FIELDS.each do |field|
|
19
|
+
instance_variable_set(:"@#{field}", received_text.fetch(field.to_s, nil))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def created_at
|
24
|
+
value = instance_variable_get(:@created_at)
|
25
|
+
Time.parse(value)
|
26
|
+
rescue StandardError
|
27
|
+
value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Notifications
|
2
|
+
class Client
|
3
|
+
class ReceivedTextCollection
|
4
|
+
attr_reader :links, :collection
|
5
|
+
|
6
|
+
def initialize(response)
|
7
|
+
@links = response["links"]
|
8
|
+
@collection = collection_from(response["received_text_messages"])
|
9
|
+
end
|
10
|
+
|
11
|
+
def collection_from(received_texts)
|
12
|
+
received_texts.map do |received_text|
|
13
|
+
ReceivedText.new(received_text)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Notifications
|
2
|
+
class Client
|
3
|
+
class RequestError < StandardError
|
4
|
+
attr_reader :code, :body
|
5
|
+
|
6
|
+
def initialize(response)
|
7
|
+
@code = response.code
|
8
|
+
@body = parse_body(response.body)
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse_body(body)
|
12
|
+
JSON.parse(body)
|
13
|
+
rescue JSON::ParserError
|
14
|
+
body
|
15
|
+
end
|
16
|
+
|
17
|
+
def message
|
18
|
+
return body if body.is_a?(String)
|
19
|
+
|
20
|
+
error_messages = body.fetch('errors')
|
21
|
+
.map { |e| "#{e.fetch('error')}: #{e.fetch('message')}" }
|
22
|
+
error_messages.join(", ")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class ClientError < RequestError; end
|
27
|
+
class BadRequestError < ClientError; end
|
28
|
+
class AuthError < ClientError; end
|
29
|
+
class NotFoundError < ClientError; end
|
30
|
+
class RateLimitError < ClientError; end
|
31
|
+
|
32
|
+
class ServerError < RequestError; end
|
33
|
+
|
34
|
+
module ErrorHandling
|
35
|
+
def build_error(response)
|
36
|
+
error_class_for_code(response.code.to_i).new(response)
|
37
|
+
end
|
38
|
+
|
39
|
+
def error_class_for_code(code)
|
40
|
+
case code
|
41
|
+
when 400
|
42
|
+
BadRequestError
|
43
|
+
when 403
|
44
|
+
AuthError
|
45
|
+
when 404
|
46
|
+
NotFoundError
|
47
|
+
when 429
|
48
|
+
RateLimitError
|
49
|
+
when (400..499)
|
50
|
+
ClientError
|
51
|
+
when (500..599)
|
52
|
+
ServerError
|
53
|
+
else
|
54
|
+
RequestError
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Notifications
|
2
|
+
class Client
|
3
|
+
class ResponseNotification
|
4
|
+
FIELDS = %i(
|
5
|
+
id
|
6
|
+
reference
|
7
|
+
content
|
8
|
+
template
|
9
|
+
uri
|
10
|
+
).freeze
|
11
|
+
|
12
|
+
attr_reader(*FIELDS)
|
13
|
+
|
14
|
+
def initialize(notification)
|
15
|
+
FIELDS.each do |field|
|
16
|
+
instance_variable_set(:"@#{field}", notification.fetch(field.to_s, nil))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Notifications
|
2
|
+
class Client
|
3
|
+
class ResponsePrecompiledLetter
|
4
|
+
FIELDS = %i(
|
5
|
+
id
|
6
|
+
reference
|
7
|
+
postage
|
8
|
+
).freeze
|
9
|
+
|
10
|
+
attr_reader(*FIELDS)
|
11
|
+
|
12
|
+
def initialize(notification)
|
13
|
+
FIELDS.each do |field|
|
14
|
+
instance_variable_set(:"@#{field}", notification.fetch(field.to_s, nil))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
module Notifications
|
4
|
+
class Client
|
5
|
+
class Template
|
6
|
+
FIELDS = %i(
|
7
|
+
id
|
8
|
+
type
|
9
|
+
name
|
10
|
+
created_at
|
11
|
+
updated_at
|
12
|
+
created_by
|
13
|
+
version
|
14
|
+
body
|
15
|
+
subject
|
16
|
+
).freeze
|
17
|
+
|
18
|
+
attr_reader(*FIELDS)
|
19
|
+
|
20
|
+
def initialize(notification)
|
21
|
+
FIELDS.each do |field|
|
22
|
+
instance_variable_set(:"@#{field}", notification.fetch(field.to_s, nil))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
%i(
|
27
|
+
created_at
|
28
|
+
updated_at
|
29
|
+
).each do |field|
|
30
|
+
define_method field do
|
31
|
+
begin
|
32
|
+
value = instance_variable_get(:"@#{field}")
|
33
|
+
Time.parse value
|
34
|
+
rescue StandardError
|
35
|
+
value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|