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
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
|