nuntius 0.1.2 → 1.0.27

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.
Files changed (169) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +199 -63
  4. data/Rakefile +62 -1
  5. data/app/controllers/nuntius/admin/campaigns_controller.rb +56 -0
  6. data/app/controllers/nuntius/admin/layouts/attachments_controller.rb +32 -0
  7. data/app/controllers/nuntius/admin/layouts_controller.rb +50 -0
  8. data/app/controllers/nuntius/admin/lists/subscribers_controller.rb +50 -0
  9. data/app/controllers/nuntius/admin/lists_controller.rb +46 -0
  10. data/app/controllers/nuntius/admin/locales_controller.rb +46 -0
  11. data/app/controllers/nuntius/admin/messages_controller.rb +24 -0
  12. data/app/controllers/nuntius/admin/templates_controller.rb +56 -0
  13. data/app/controllers/nuntius/api/events_controller.rb +16 -0
  14. data/app/controllers/nuntius/application_admin_controller.rb +11 -0
  15. data/app/controllers/nuntius/application_controller.rb +12 -0
  16. data/app/controllers/nuntius/callbacks_controller.rb +21 -0
  17. data/app/controllers/nuntius/dashboard_controller.rb +12 -0
  18. data/app/controllers/nuntius/feedback_controller.rb +17 -0
  19. data/app/controllers/nuntius/inbound_messages/twilio_inbound_smses_controller.rb +56 -0
  20. data/app/controllers/nuntius/messages_controller.rb +13 -0
  21. data/app/drops/nuntius/application_drop.rb +17 -0
  22. data/app/drops/nuntius/campaign_drop.rb +7 -0
  23. data/app/drops/nuntius/layout_drop.rb +11 -0
  24. data/app/drops/nuntius/message_drop.rb +11 -0
  25. data/app/drops/nuntius/template_drop.rb +7 -0
  26. data/app/exceptions/nuntius/base_exception.rb +4 -0
  27. data/app/exceptions/nuntius/missing_messenger_exception.rb +4 -0
  28. data/app/helpers/nuntius/application_helper.rb +78 -0
  29. data/app/jobs/nuntius/application_job.rb +9 -0
  30. data/app/jobs/nuntius/deliver_inbound_message_job.rb +10 -0
  31. data/app/jobs/nuntius/messenger_job.rb +17 -0
  32. data/app/jobs/nuntius/process_inbound_message_job.rb +10 -0
  33. data/app/jobs/nuntius/purge_message_job.rb +13 -0
  34. data/app/jobs/nuntius/retrieve_mail_job.rb +18 -0
  35. data/app/jobs/nuntius/transport_delivery_job.rb +32 -0
  36. data/app/jobs/nuntius/transport_refresh_job.rb +22 -0
  37. data/app/message_boxes/nuntius/base_message_box.rb +75 -0
  38. data/app/messengers/nuntius/base_messenger.rb +193 -0
  39. data/app/messengers/nuntius/custom_messenger.rb +6 -0
  40. data/app/models/nuntius/application_record.rb +11 -0
  41. data/app/models/nuntius/attachment.rb +13 -0
  42. data/app/models/nuntius/campaign.rb +75 -0
  43. data/app/models/nuntius/concerns/metadata_scoped.rb +31 -0
  44. data/app/models/nuntius/concerns/yamlify.rb +23 -0
  45. data/app/models/nuntius/inbound_message.rb +14 -0
  46. data/app/models/nuntius/layout.rb +13 -0
  47. data/app/models/nuntius/list.rb +10 -0
  48. data/app/models/nuntius/locale.rb +11 -0
  49. data/app/models/nuntius/message.rb +148 -0
  50. data/app/models/nuntius/subscriber.rb +12 -0
  51. data/app/models/nuntius/template.rb +102 -0
  52. data/app/presenters/application_presenter.rb +28 -0
  53. data/app/presenters/template_presenter.rb +17 -0
  54. data/app/providers/nuntius/apnotic_push_provider.rb +44 -0
  55. data/app/providers/nuntius/base_provider.rb +72 -0
  56. data/app/providers/nuntius/firebase_push_provider.rb +26 -0
  57. data/app/providers/nuntius/houston_push_provider.rb +40 -0
  58. data/app/providers/nuntius/message_bird_sms_provider.rb +39 -0
  59. data/app/providers/nuntius/slack_slack_provider.rb +36 -0
  60. data/app/providers/nuntius/smtp_mail_provider.rb +80 -0
  61. data/app/providers/nuntius/twilio_sms_provider.rb +37 -0
  62. data/app/providers/nuntius/twilio_voice_provider.rb +70 -0
  63. data/app/reportlets/nuntius/application_reportlet.rb +35 -0
  64. data/app/reportlets/nuntius/daily_messages_per_template_reportlet.rb +50 -0
  65. data/app/runners/nuntius/application_runner.rb +6 -0
  66. data/app/runners/nuntius/basic_application_runner.rb +15 -0
  67. data/app/runners/nuntius/timebased_events_runner.rb +15 -0
  68. data/app/services/nuntius/application_service.rb +7 -0
  69. data/app/services/nuntius/aws_sns_processor_service.rb +81 -0
  70. data/app/services/nuntius/deliver_inbound_message_service.rb +14 -0
  71. data/app/services/nuntius/retrieve_inbound_mail_service.rb +36 -0
  72. data/app/tables/nuntius_campaigns_table.rb +21 -0
  73. data/app/tables/nuntius_layouts_table.rb +24 -0
  74. data/app/tables/nuntius_lists_table.rb +19 -0
  75. data/app/tables/nuntius_locales_table.rb +18 -0
  76. data/app/tables/nuntius_messages_table.rb +36 -0
  77. data/app/tables/nuntius_subscribers_table.rb +19 -0
  78. data/app/tables/nuntius_templates_table.rb +30 -0
  79. data/app/transports/nuntius/base_transport.rb +36 -0
  80. data/app/transports/nuntius/mail_transport.rb +35 -0
  81. data/app/transports/nuntius/push_transport.rb +15 -0
  82. data/app/transports/nuntius/slack_transport.rb +6 -0
  83. data/app/transports/nuntius/sms_transport.rb +6 -0
  84. data/app/transports/nuntius/voice_transport.rb +6 -0
  85. data/app/validators/liquid_validator.rb +11 -0
  86. data/app/views/nuntius/admin/campaigns/edit.html.slim +49 -0
  87. data/app/views/nuntius/admin/campaigns/index.html.slim +2 -0
  88. data/app/views/nuntius/admin/layouts/attachments/_attachments.html.slim +28 -0
  89. data/app/views/nuntius/admin/layouts/attachments/_index.html.slim +2 -0
  90. data/app/views/nuntius/admin/layouts/attachments/create.json.jbuilder +5 -0
  91. data/app/views/nuntius/admin/layouts/edit.html.slim +24 -0
  92. data/app/views/nuntius/admin/layouts/index.html.slim +2 -0
  93. data/app/views/nuntius/admin/lists/edit.html.slim +14 -0
  94. data/app/views/nuntius/admin/lists/index.html.slim +2 -0
  95. data/app/views/nuntius/admin/lists/subscribers/edit.html.slim +14 -0
  96. data/app/views/nuntius/admin/locales/edit.html.slim +14 -0
  97. data/app/views/nuntius/admin/locales/index.html.slim +2 -0
  98. data/app/views/nuntius/admin/messages/index.html.slim +2 -0
  99. data/app/views/nuntius/admin/messages/show.html.slim +56 -0
  100. data/app/views/nuntius/admin/templates/edit.html.slim +81 -0
  101. data/app/views/nuntius/admin/templates/index.html.slim +2 -0
  102. data/app/views/nuntius/dashboard/show.html.slim +7 -0
  103. data/app/views/nuntius/messages/show.html.slim +7 -0
  104. data/config/locales/en.yml +22 -0
  105. data/config/locales/nl.yml +22 -0
  106. data/config/routes.rb +38 -0
  107. data/config/webpack/development.js +5 -0
  108. data/config/webpack/environment.js +4 -0
  109. data/config/webpack/production.js +5 -0
  110. data/config/webpack/test.js +5 -0
  111. data/config/webpacker.yml +119 -0
  112. data/db/migrate/20190301201541_create_nuntius_templates.rb +27 -0
  113. data/db/migrate/20190301202436_create_nuntius_messages.rb +30 -0
  114. data/db/migrate/20190322112815_create_nuntius_lists.rb +12 -0
  115. data/db/migrate/20190322114340_create_nuntius_campaigns.rb +18 -0
  116. data/db/migrate/20190322121338_create_nuntius_subscribers.rb +17 -0
  117. data/db/migrate/20190327123535_add_metadata_to_models.rb +8 -0
  118. data/db/migrate/20190327124407_create_nuntius_layouts.rb +24 -0
  119. data/db/migrate/20190327143921_add_campaign_to_message.rb +7 -0
  120. data/db/migrate/20190327155112_add_state_to_campaign.rb +7 -0
  121. data/db/migrate/20190412103335_add_enabled_to_templates.rb +7 -0
  122. data/db/migrate/20190417125153_change_message_status_default.rb +9 -0
  123. data/db/migrate/20190417144554_add_nuntiable_to_subscriber.rb +7 -0
  124. data/db/migrate/20190521135011_add_payload_to_nuntius_messages.rb +7 -0
  125. data/db/migrate/20190522122657_add_metadata_to_nuntius_message.rb +7 -0
  126. data/db/migrate/20190825080757_update_nuntius_message_sending_to_sent.rb +11 -0
  127. data/db/migrate/20200220154927_change_nuntius_templates_payload_type.rb +7 -0
  128. data/db/migrate/20200224132337_create_nuntius_locales.rb +13 -0
  129. data/db/migrate/20200318095339_create_nuntius_attachments.rb +12 -0
  130. data/db/migrate/20200407050646_add_interval_to_nuntius_template.rb +5 -0
  131. data/db/migrate/20200430131219_make_html_processing_optional.rb +6 -0
  132. data/db/migrate/20200430154032_make_html_processing_optional_revert.rb +6 -0
  133. data/db/migrate/20201121185718_create_nuntius_inbound_messages.rb +21 -0
  134. data/db/migrate/20220412114148_add_last_sent_to_message.rb +5 -0
  135. data/lib/nuntius/active_record_helpers.rb +28 -0
  136. data/lib/nuntius/active_storage_helpers.rb +8 -0
  137. data/lib/nuntius/configuration.rb +97 -0
  138. data/lib/nuntius/deprecator.rb +8 -0
  139. data/lib/nuntius/devise.rb +19 -0
  140. data/lib/nuntius/engine.rb +46 -0
  141. data/lib/nuntius/i18n_store.rb +100 -0
  142. data/lib/nuntius/liquid/tags/attach_tag.rb +44 -0
  143. data/lib/nuntius/mail_allow_list.rb +23 -0
  144. data/lib/nuntius/nuntiable.rb +24 -0
  145. data/lib/nuntius/state_machine.rb +19 -0
  146. data/lib/nuntius/transactio.rb +30 -0
  147. data/lib/nuntius/version.rb +3 -1
  148. data/lib/nuntius.rb +74 -8
  149. data/lib/preamble.rb +87 -0
  150. data/lib/tasks/nuntius_tasks.rake +27 -0
  151. metadata +532 -67
  152. data/.gitignore +0 -4
  153. data/Gemfile +0 -4
  154. data/lib/nuntius/encodings/url_safe_base64.rb +0 -26
  155. data/lib/nuntius/encodings.rb +0 -9
  156. data/lib/nuntius/envelope.rb +0 -45
  157. data/lib/nuntius/key.rb +0 -52
  158. data/lib/nuntius/messenger.rb +0 -37
  159. data/nuntius.gemspec +0 -23
  160. data/spec/keys/alice.pem +0 -27
  161. data/spec/keys/alice.pub +0 -9
  162. data/spec/keys/bob.pem +0 -27
  163. data/spec/keys/bob.pub +0 -9
  164. data/spec/nuntius/encodings/url_safe_base64_spec.rb +0 -36
  165. data/spec/nuntius/envelope_spec.rb +0 -6
  166. data/spec/nuntius/key_spec.rb +0 -22
  167. data/spec/nuntius/messenger_spec.rb +0 -26
  168. data/spec/spec_helper.rb +0 -9
  169. data/spec/support/keys.rb +0 -6
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 736ed78b3a455b90aad20c47ba9bf6c3946cb7d45dc064c33d689a622ac40f18
4
+ data.tar.gz: c2f9abeeffe69fe5f28df8af6b0ff1c72c3c73d743b9156f0a12ed6daca3d1a9
5
+ SHA512:
6
+ metadata.gz: a6fe800fc712a05dc2a35166a28a6d3c0d41f248365ca1cdb3f529f1430e77ca11553342cc0681490b1aaad952de6f87b89412f8329501e79765c556efa3428f
7
+ data.tar.gz: 4e79093e36ffeb8967aa5568a064b41828c33dcd3da32bf87ff0a5ed3504f5c3dc2794560c237254e63ed042a521442d3c51e57ca54690f209057e5bc29b73a5
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2018 Tom de Grunt
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,93 +1,229 @@
1
- # Nuntius:
1
+ # Nuntius
2
2
 
3
- > A messenger, reporter, courier, bearer of news or tidings
3
+ Nuntius offers messaging and notifications for ActiveRecord models in Ruby on Rails applications.
4
4
 
5
- Nuntius is a simple scheme to send and receive messages in a cryptographicaly secure and compatible way.
5
+ ## Setup
6
+
7
+ Add Nuntius to your Gemfile and run bundle install to install it.
8
+
9
+ Create an initializer (config/initializers/messaging.rb) and configure as desired:
10
+
11
+ ```ruby
12
+ Nuntius.setup do
13
+ # Have Nuntius log to the Rails.logger
14
+ config.logger = Rails.logger
15
+
16
+ # Allow custom events (default = false)
17
+ # Enable this option to allow use of Nuntius with a Hash
18
+ config.allow_custom_events = true
19
+
20
+ # Configure the transport you want to use
21
+
22
+ # Enable e-mail
23
+ config.transport :mail
24
+ # Enable push notifications
25
+ config.transport :push
26
+ # Enable SMS
27
+ config.transport :sms
28
+ # Enable voice
29
+ config.transport :voice
30
+ # Enable Slack
31
+ config.transport :slack
32
+
33
+ # Configure providers for each of the transports you enabled above.
34
+ # Advised is to either do this using credentials, environment variables, or somewhere in a model (securely stored away).
35
+ config.provider :slack, transport: :slack, settings: lambda { |_message|
36
+ Rails.application.credentials[:slack]
37
+ }
38
+ end
39
+ ```
40
+
41
+ Mount the Rails engine in your routes.rb to enable Nuntius' maintenance pages:
42
+
43
+ ```ruby
44
+ Rails.application.routes.draw do
45
+ # your own routes ...
46
+ mount Nuntius::Engine, at: '/messaging', as: 'nuntius' # change the path and aliases at your own discretion
47
+ end
48
+ ```
49
+
50
+ To enable you to send messages with Nuntius you need to make one or more ActiveRecord models nuntiable:
51
+
52
+ ```ruby
53
+ class Car < ApplicationRecord
54
+ nuntiable
55
+ end
56
+ ```
57
+
58
+ Additionally you need to define an extension of the Nuntius::BaseMessenger for the same model with a matching name (in app/messengers):
59
+
60
+ ```ruby
61
+ class CarMessenger < Nuntius::BaseMessenger
62
+ def your_event(car, params)
63
+ # your optional logic here
64
+ end
65
+ end
66
+ ```
67
+
68
+ If you are using the state_machines-activemodel gem you can pass use_state_machine: true to the
69
+ nuntiable call, this will automatically define empty methods for these events on the model's
70
+ messenger class if they are not defined already.
71
+
72
+ Additionally the use_state_machine option will add an after_commit hook to the state machine
73
+ to automatically trigger the event for the state transition.
6
74
 
7
75
  ## Usage
8
76
 
9
- ### Encript a Message
77
+ ### With templates
78
+
79
+ Usually you would call Nuntius programatically with code by using Templates. In this case you would use for example:
10
80
 
11
81
  ```ruby
12
- require 'nuntius'
13
-
14
- sender = Nuntius::Key.new( File.read('private_key_path') )
15
- messenger = Nuntius::Mesenger.new({
16
- :key => sender
17
- })
18
-
19
- receiver = Nuntius::Key.new( File.read('public_key_path') )
20
-
21
- envelope = messenger.wrap({
22
- :message => "Message Content",
23
- :to => receiver
24
- })
25
-
26
- envelope.data
27
- # => The encripted message
28
- envelope.key
29
- # => The encripted message key
30
- envelope.signature
31
- # => The encripted message signature
82
+ Nuntius.event(:your_event, car)
32
83
  ```
33
84
 
34
- ### Decript a message
85
+ When custom events are enabled you can also do the following:
35
86
 
36
87
  ```ruby
37
- require 'nuntius'
88
+ Nuntius.event('shipped', { shipped: { to: 'test@example.com', ref: 'Test-123'} }, attachments: [ { url: 'http://example.com' } ])
89
+ ```
38
90
 
39
- receiver = Nuntius::Key.new( File.read('private_key_path') )
40
- messenger = Nuntius::Mesenger.new({
41
- :key => receiver
42
- })
91
+ For the above cases you need to define templates, this is done with the maintenace pages under
92
+ /messaging/admin/templates (/messaging is whatever you have defined in your routes file).
43
93
 
44
- sender = Nuntius::Key.new( File.read('public_key_path') )
94
+ When Nuntius#message is called a message will be sent for every matching template. To allow you to
95
+ send different messages under different circumstances you can specify a template_scope on the messenger
96
+ class that uses the template's metadata in combination with the nuntiable object to determine whether
97
+ or not the template should be used.
45
98
 
46
- envelope = Nuntius::Envelope.new({
47
- :data => 'The encripted message'
48
- :key => 'The encripted message key'
49
- :signature => 'The encripted message signature'
50
- })
99
+ ### Timebased events
51
100
 
52
- message = messenger.unwrap({
53
- :envelope => envelope,
54
- :from => sender
55
- })
101
+ If you want to send messages based on time intervals you can add such events to your messenger with the
102
+ timebased_scope class method like so:
56
103
 
57
- message
58
- # => The verified and decripted raw message
104
+ ```ruby
105
+ class CarMessenger < Nuntius::BaseMessenger
106
+ # time_range is a range, for a before scope the time_range the interval is added to the current
107
+ # time, the end of the range is 1 hour from the start.
108
+ timebased_scope :before_tuneup do |time_range, metadata|
109
+ cars = Car.where(tuneup_at: time_range)
110
+ cars = cars.where(color: metadata['color']) if metadata['color'].present?
111
+ cars
112
+ end
113
+
114
+ # For an after scope the time_range the interval is taken from the current time, the end of the
115
+ # range is 1 hour from its start.
116
+ timebased_scope :after_tuneup do |time_range, metadata|
117
+ cars = Car.where(tuneup_at: time_range)
118
+ cars = cars.where(color: metadata['color']) if metadata['color'].present?
119
+ cars
120
+ end
121
+ end
59
122
  ```
60
123
 
61
- ## Encription Scheme
124
+ This method also requires you to configure a template using the maintenance pages. When you choose
125
+ a timebased scope as an event you will be prompted to enter an interval, you can enter anything in the
126
+ following formats:
62
127
 
63
- Under the hood Nuntius is just a wrapper around OpenSSL and by default uses [RSA]( http://en.wikipedia.org/wiki/RSA_%28algorithm%29 ), [AES](http://en.wikipedia.org/wiki/Advanced_Encryption_Standard) in [CBC mode](http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29) and [SHA512](http://en.wikipedia.org/wiki/SHA512) to encript/decript and sign/verify the messages and [URL Safe Base64](http://en.wikipedia.org/wiki/Base64#RFC_4648) to encode/decode the results.
128
+ - N minute(s)
129
+ - N hour(s)
130
+ - N day(s)
131
+ - N week(s)
132
+ - N month(s)
64
133
 
65
- The whole scheme can be sumarized in 4 steps:
134
+ To send timebased messages you need to execute Nuntius::TimestampBasedMessagesRunner.call, you could do this
135
+ in a cronjob every 5 minutes with "bundle exec rails runner Nuntius::TimestampBasedMessagesRunner.call"
66
136
 
67
- * The message is encripted using AES-256-CBC with a randomly generated key.
68
- * The key is then encrypted using the receiver's public RSA key.
69
- * The encripted message's digest is calculated using SHA512 and then signed using the sender's private RSA key.
70
- * Finally the encripted message, the encripted key and the signed digest are encoded using the RFC4648 URL Safe Base 64 encoding
137
+ ### Direct
71
138
 
72
- In other terms, encrypting a message with nuntius is the same as doing
139
+ Another more direct way of using Nuntius is by just instantiating a message:
73
140
 
74
141
  ```ruby
75
- require 'openssl'
142
+ Nuntius::Message.new(to: 'tom@boxture.com', subject: 'Test', text: 'Test text', nuntiable: channel).deliver_as(:mail)
143
+ ```
76
144
 
77
- sender = OpenSSL::PKey::RSA.new( File.read('sender_private_key') )
78
- receiver = OpenSSL::PKey::RSA.new( File.read('receiver_public_key') )
145
+ or
79
146
 
80
- cipher = OpenSSL::Cipher.new("AES-256-CBC").encrypt
81
-
82
- key = receiver.public_encrypt( cipher.random_key )
147
+ ```ruby
148
+ user = User.find(1)
149
+ user.messages.new(to: 'test@example.com', subject: 'Test', text: 'Test text').deliver_as(:mail)
150
+ ```
83
151
 
84
- data = cipher.update("message") + cipher.final
152
+ Here we still need a nuntiable object, in case provider settings can differ from object to object.
85
153
 
86
- signature = receiver.private_encrypt( OpenSSL::Digest::SHA512.new(data).digest )
154
+ You can also define custom events, which take a scope and an event name:
87
155
 
88
- result = {
89
- :data => [data].pack("m0").tr("+/","-_").gsub("=","")
90
- :key => [key].pack("m0").tr("+/","-_").gsub("=","")
91
- :signature => [signature].pack("m0").tr("+/","-_").gsub("=","")
92
- }
156
+ ```ruby
157
+ Nuntius.event('packed', packing: {smurrefluts: 'hatseflats'})
158
+ ```
159
+
160
+ The main key of the hash passed will also be the liquid variable.
161
+
162
+ ### Inbound
163
+
164
+ Inbound messages are also possible, currently mail/IMAP and Twilio inbound SMS are supported.
165
+
166
+ ## Transports
167
+
168
+ ### Mail
169
+
170
+ #### AWS SES
171
+
172
+ In case you use AWS SES, you can use the SNS Feedback Notifications to automatically mark messages as read, or deal with complaints and bounces. Create a AWS SNS topic, with a HTTPS subscription with the following URL (pattern):
173
+
174
+ Use the following URL: https://<host>/messaging/feedback/awssns
175
+
176
+ The actual URL may be different depending on your routing setup.
177
+
178
+ The subscription will automatically be confirmed.
179
+
180
+ Next in AWS SES, configure the SNS topic to receive feedback notifications for Bounce, Complaint and Delivery and include original headers.
181
+
182
+ ### SMS
183
+
184
+ ### Push
185
+
186
+ ### Voice
187
+
188
+ #### Twilio
189
+
190
+ Information on voice TWIML is here: https://www.twilio.com/docs/voice/twiml/gather
191
+ You can try voices here: https://www.twilio.com/console/voice/twiml/text-to-speech
192
+
193
+ ```
194
+ <?xml version="1.0" encoding="UTF-8"?>
195
+ <Response>
196
+ <Say language="nl-NL">
197
+ Hallo, dit is een bericht van Boxture!
198
+ <break strength="x-weak" time="100ms"/>
199
+ <p>We geven je zo je wachtwoord-herstel-code, dus pak een pen en schrijf mee.</p>
200
+ </Say>
201
+ <Gather input="dtmf" numDigits="1" action="{%raw%}{{url}}{%endraw%}/code">
202
+ <Say language="nl-NL">Druk een toets om verder te gaan.</Say>
203
+ </Gather>
204
+ <Redirect>{%raw%}{{url}}{%endraw%}/code</Redirect>
205
+ </Response>
206
+
207
+ ---
208
+ path: /code
209
+ ---
210
+ <?xml version="1.0" encoding="UTF-8"?>
211
+ <Response>
212
+ <Gather input="dtmf" numDigits="1">
213
+ <Say language="nl-NL">
214
+ <s>Je code is:</s>
215
+ <break strength="x-weak" time="100ms"/>
216
+ <prosody rate="x-slow"><say-as interpret-as="character">1 n a x d 8 b</say-as></prosody>
217
+ <break strength="x-weak" time="1s"/>
218
+ Druk een toets om te herhalen, of hang op.
219
+ </Say>
220
+ </Gather>
221
+ <Redirect>{%raw%}{{url}}{%endraw%}/code</Redirect>
222
+ </Response>
223
+ ```
224
+
225
+ ## Testing
226
+
227
+ ```
228
+ bundle exec sidekiq -C test/dummy/config/sidekiq.yml -r test/dummy
93
229
  ```
data/Rakefile CHANGED
@@ -1 +1,62 @@
1
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rdoc/task'
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = 'rdoc'
13
+ rdoc.title = 'Nuntius'
14
+ rdoc.options << '--line-numbers'
15
+ rdoc.rdoc_files.include('README.md')
16
+ rdoc.rdoc_files.include('lib/**/*.rb')
17
+ end
18
+
19
+ APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
20
+ load 'rails/tasks/engine.rake'
21
+
22
+ load 'rails/tasks/statistics.rake'
23
+
24
+ require 'bundler/gem_tasks'
25
+
26
+ require 'rake/testtask'
27
+
28
+ Rake::TestTask.new(:test) do |t|
29
+ t.libs << 'test'
30
+ t.pattern = 'test/**/*_test.rb'
31
+ t.verbose = false
32
+ t.warning = false
33
+ end
34
+
35
+ task default: :test
36
+
37
+ # Adds the Auxilium semver task
38
+ spec = Gem::Specification.find_by_name 'auxilium'
39
+ load "#{spec.gem_dir}/lib/tasks/semver.rake"
40
+
41
+ namespace :nuntius do
42
+ namespace :webpacker do
43
+ desc 'Install deps with yarn'
44
+ task :yarn_install do
45
+ Dir.chdir(File.join(__dir__, '../..')) do
46
+ system 'yarn install --no-progress --production'
47
+ end
48
+ end
49
+
50
+ desc 'Compile JavaScript packs using webpack for production with digests'
51
+ task compile: %i[yarn_install environment] do
52
+ Webpacker.with_node_env('production') do
53
+ if Nuntius.webpacker.commands.compile
54
+ # Successful compilation!
55
+ else
56
+ # Failed compilation
57
+ exit!
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency 'nuntius/application_admin_controller'
4
+
5
+ module Nuntius
6
+ module Admin
7
+ class CampaignsController < ApplicationAdminController
8
+ before_action :set_objects, except: [:index]
9
+
10
+ def index
11
+ @campaigns = Nuntius::Campaign.visible.order(created_at: :desc)
12
+ end
13
+
14
+ def new
15
+ render :edit
16
+ end
17
+
18
+ def create
19
+ @campaign.save
20
+ respond_with :admin, @campaign, action: :edit
21
+ end
22
+
23
+ def show
24
+ redirect_to :edit_admin_campaign, status: :see_other
25
+ end
26
+
27
+ def edit; end
28
+
29
+ def update
30
+ saved = @campaign.update(campaign_params)
31
+
32
+ if saved && params[:commit] == 'send'
33
+ @campaign.publish! if @campaign.can_publish?
34
+ redirect_to :edit_admin_campaign, status: :see_other
35
+ else
36
+ respond_with :admin, @campaign
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def set_objects
43
+ @campaign = params[:id] ? Nuntius::Campaign.visible.find(params[:id]) : Nuntius::Campaign.new(campaign_params)
44
+ @lists = Nuntius::List.visible
45
+ @layouts = Nuntius::Layout.visible
46
+ @messages = Nuntius::Message.where(campaign: @campaign)
47
+ end
48
+
49
+ def campaign_params
50
+ return unless params[:campaign]
51
+
52
+ params.require(:campaign).permit(:name, :transport, :layout_id, :list_id, :from, :subject, :text, :html)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nuntius
4
+ module Admin
5
+ module Layouts
6
+ class AttachmentsController < ApplicationController
7
+ before_action :set_objects
8
+
9
+ def index; end
10
+
11
+ def create
12
+ params[:attachments].each do |file|
13
+ @layout.attachments.attach(file)
14
+ end
15
+ end
16
+
17
+ def destroy
18
+ attachment = @layout.attachments.find_by(id: params[:id])
19
+ attachment&.purge
20
+
21
+ render :create
22
+ end
23
+
24
+ private
25
+
26
+ def set_objects
27
+ @layout = Nuntius::Layout.visible.find(params[:layout_id]) if params[:layout_id]
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency 'nuntius/application_admin_controller'
4
+
5
+ module Nuntius
6
+ module Admin
7
+ class LayoutsController < ApplicationAdminController
8
+ def index
9
+ @layouts = Nuntius::Layout.visible.order(:name)
10
+ end
11
+
12
+ def new
13
+ @layout = Nuntius::Layout.new
14
+ render :edit
15
+ end
16
+
17
+ def create
18
+ @layout = Nuntius::Layout.new(layout_params)
19
+ @layout.save
20
+ respond_with :admin, @layout
21
+ end
22
+
23
+ def edit
24
+ @layout = Nuntius::Layout.visible.find(params[:id])
25
+ end
26
+
27
+ def show
28
+ redirect_to :edit_admin_layout, status: :see_other
29
+ end
30
+
31
+ def update
32
+ @layout = Nuntius::Layout.visible.find(params[:id])
33
+ @layout.update(layout_params)
34
+ respond_with :admin, @layout
35
+ end
36
+
37
+ def destroy
38
+ @layout = Nuntius::Layout.visible.find(params[:id])
39
+ @layout.destroy
40
+ respond_with @layout
41
+ end
42
+
43
+ private
44
+
45
+ def layout_params
46
+ params.require(:layout).permit(:name, :data, :metadata_yaml)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency 'nuntius/application_admin_controller'
4
+
5
+ module Nuntius
6
+ module Admin
7
+ module Lists
8
+ class SubscribersController < ApplicationAdminController
9
+ before_action :set_objects
10
+
11
+ def index
12
+ @subscribers = @list.subscribers.all
13
+ end
14
+
15
+ def new
16
+ @subscriber = @list.subscribers.new
17
+ render :edit
18
+ end
19
+
20
+ def create
21
+ @subscriber = @list.subscribers.new(subscriber_params)
22
+ @subscriber.save
23
+ # FIXME: This should redirect to list
24
+ respond_with :admin, :list, @subscriber, collection_location: -> { nuntius.admin_list_url(@list) }, location: -> { nuntius.admin_list_url(@list) }, status: :see_other
25
+ end
26
+
27
+ def edit
28
+ @subscriber = @list.subscribers.find(params[:id])
29
+ end
30
+
31
+ def update
32
+ @subscriber = @list.subscribers.find(params[:id])
33
+ @subscriber.update(subscriber_params)
34
+ # FIXME: This should redirect to list
35
+ respond_with :admin, :list, @subscriber, collection_location: -> { nuntius.admin_list_url(@list) }, location: -> { nuntius.admin_list_url(@list) }, status: :see_other
36
+ end
37
+
38
+ private
39
+
40
+ def subscriber_params
41
+ params.require(:subscriber).permit(:first_name, :last_name, :email, :phone_number, tags: [])
42
+ end
43
+
44
+ def set_objects
45
+ @list = List.find(params[:list_id])
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency 'nuntius/application_admin_controller'
4
+
5
+ module Nuntius
6
+ module Admin
7
+ class ListsController < ApplicationAdminController
8
+
9
+ def index
10
+ @lists = Nuntius::List.visible.order(:name)
11
+ end
12
+
13
+ def new
14
+ @list = Nuntius::List.new
15
+ render :edit
16
+ end
17
+
18
+ def create
19
+ @list = Nuntius::List.create(list_params)
20
+ respond_with :admin, @list
21
+ end
22
+
23
+ def show
24
+ redirect_to :edit_admin_list, status: :see_other
25
+ end
26
+
27
+ def edit
28
+ @list = Nuntius::List.visible.find(params[:id])
29
+ end
30
+
31
+ def update
32
+ @list = Nuntius::List.visible.find(params[:id])
33
+ @list.update(list_params)
34
+ respond_with :admin, @list
35
+ end
36
+
37
+ private
38
+
39
+ def set_objects; end
40
+
41
+ def list_params
42
+ params.require(:list).permit(:name)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency 'nuntius/application_admin_controller'
4
+
5
+ module Nuntius
6
+ module Admin
7
+ class LocalesController < ApplicationAdminController
8
+ def index
9
+ @locales = Nuntius::Locale.visible.order(:key)
10
+ end
11
+
12
+ def new
13
+ @locale = Nuntius::Locale.new
14
+ render :edit
15
+ end
16
+
17
+ def create
18
+ @locale = Nuntius::Locale.new(locale_params)
19
+ @locale.save
20
+ respond_with :admin, @locale
21
+ end
22
+
23
+ def show
24
+ redirect_to :edit_admin_locales, status: :see_other
25
+ end
26
+
27
+ def edit
28
+ @locale = Nuntius::Locale.visible.find(params[:id])
29
+ end
30
+
31
+ def update
32
+ @locale = Nuntius::Locale.visible.find(params[:id])
33
+ @locale.update(locale_params)
34
+ respond_with :admin, @locale
35
+ end
36
+
37
+ private
38
+
39
+ def set_objects; end
40
+
41
+ def locale_params
42
+ params.require(:locale).permit(:key, :data, :metadata_yaml, :data_yaml)
43
+ end
44
+ end
45
+ end
46
+ end