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.
@@ -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
@@ -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,9 @@
1
+ require "base64"
2
+
3
+ module Notifications
4
+ def self.prepare_upload(file)
5
+ raise ArgumentError.new("Document is larger than 2MB") if file.size > Client::MAX_FILE_UPLOAD_SIZE
6
+
7
+ { file: Base64.strict_encode64(file.read) }
8
+ end
9
+ 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