nuntius 0.1.1 → 1.0.27

Sign up to get free protection for your applications and to get access to all the features.
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 -47
  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 -12
  167. data/spec/nuntius/messenger_spec.rb +0 -26
  168. data/spec/spec_helper.rb +0 -9
  169. data/spec/support/keys.rb +0 -3
@@ -0,0 +1,21 @@
1
+ class CreateNuntiusInboundMessages < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :nuntius_inbound_messages, id: :uuid do |t|
4
+ t.string :status, default: 'pending'
5
+ t.string :transport
6
+ t.string :provider
7
+ t.string :provider_id
8
+ t.string :from
9
+ t.string :to
10
+ t.string :cc
11
+ t.string :subject
12
+ t.text :html
13
+ t.text :text
14
+ t.jsonb :payload
15
+ t.jsonb :metadata
16
+ t.string :digest
17
+
18
+ t.timestamps
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ class AddLastSentToMessage < ActiveRecord::Migration[6.0]
2
+ def change
3
+ add_column :nuntius_messages, :last_sent_at, :datetime, null: true
4
+ end
5
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'nuntiable'
4
+ require_relative 'devise'
5
+ require_relative 'state_machine'
6
+ require_relative 'transactio'
7
+
8
+ module Nuntius::ActiveRecordHelpers
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ delegate :nuntiable?, to: :class
13
+ end
14
+
15
+ class_methods do
16
+ def nuntiable(options = {})
17
+ @_nuntius_nuntiable_options = options
18
+ include Nuntius::Nuntiable
19
+ include Nuntius::StateMachine if options[:use_state_machine]
20
+ include Nuntius::Devise if options[:override_devise]
21
+ include Nuntius::Transactio
22
+ end
23
+
24
+ def nuntiable?
25
+ included_modules.include?(Nuntius::Nuntiable)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nuntius::ActiveStorageHelpers
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ has_one_attached :content, service: Nuntius.config.active_storage_service
7
+ end
8
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nuntius
4
+ class Configuration
5
+ attr_accessor :admin_authentication_module, :base_controller, :base_runner, :layout, :admin_layout, :jobs_queue_name, :visible_scope, :add_metadata, :metadata_fields, :default_template_scope, :allow_custom_events, :active_storage_service
6
+ attr_writer :logger, :host, :metadata_humanize, :default_params
7
+
8
+ attr_reader :transports, :providers
9
+
10
+ def initialize
11
+ @logger = Logger.new(STDOUT)
12
+ @logger.level = Logger::INFO
13
+ @base_controller = '::ApplicationController'
14
+ @base_runner = 'Nuntius::BasicApplicationRunner'
15
+ @nuntiable_classes = []
16
+ @nuntiable_class_names = []
17
+ @transports = []
18
+ @providers = {}
19
+ @jobs_queue_name = :message
20
+ @visible_scope = -> { all }
21
+ @add_metadata = -> {}
22
+ @metadata_fields = {}
23
+ @metadata_humanize = ->(data) { data.inspect }
24
+ @default_template_scope = ->(_object) { all }
25
+ @allow_custom_events = false
26
+ @layout = 'application'
27
+ @admin_layout = 'application'
28
+ @active_storage_service = nil
29
+ end
30
+
31
+ # logger [Object].
32
+ def logger
33
+ @logger.is_a?(Proc) ? instance_exec(&@logger) : @logger
34
+ end
35
+
36
+ def host(message)
37
+ @host.is_a?(Proc) ? instance_exec(message, &@host) : @host
38
+ end
39
+
40
+ # Make the part that is important for visible readable for humans
41
+ def metadata_humanize(metadata)
42
+ @metadata_humanize.is_a?(Proc) ? instance_exec(metadata, &@metadata_humanize) : @metadata_humanize
43
+ end
44
+
45
+ # admin_mount_point [String].
46
+ def admin_mount_point
47
+ @admin_mount_point ||= '/nuntius'
48
+ end
49
+
50
+ def add_nuntiable_class(klass)
51
+ @nuntiable_class_names = []
52
+ @nuntiable_classes << klass.to_s unless @nuntiable_classes.include?(klass.to_s)
53
+ end
54
+
55
+ def nuntiable_class_names
56
+ return @nuntiable_class_names if @nuntiable_class_names.present?
57
+
58
+ compile_nuntiable_class_names!
59
+ end
60
+
61
+ def provider(provider, transport:, priority: 1, timeout: 0, settings: {})
62
+ if @transports.include? transport
63
+ @providers[transport.to_sym] ||= []
64
+ @providers[transport.to_sym].push(provider: provider, priority: priority, timeout: timeout, settings: settings)
65
+ else
66
+ Nuntius.logger.warn "provider #{provider} not enabled as transport #{transport} is not enabled"
67
+ end
68
+ end
69
+
70
+ def transport(transport)
71
+ @transports.push(transport) if transport
72
+ end
73
+
74
+ def default_params(transaction_log_entry)
75
+ @default_params.is_a?(Proc) ? instance_exec(transaction_log_entry, &@default_params) : @default_params
76
+ end
77
+
78
+ private
79
+
80
+ def compile_nuntiable_class_names
81
+ names = []
82
+ names << 'Custom' if allow_custom_events
83
+
84
+ @nuntiable_classes.each do |klass_name|
85
+ klass = klass_name.constantize
86
+ names << klass.name
87
+ names += klass.descendants.map(&:name)
88
+ end
89
+
90
+ names.sort!
91
+ end
92
+
93
+ def compile_nuntiable_class_names!
94
+ @nuntiable_class_names = compile_nuntiable_class_names
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,8 @@
1
+ module Nuntius
2
+ class Deprecator
3
+ def deprecation_warning(deprecated_method_name, message, _caller_backtrace = nil)
4
+ message = "#{deprecated_method_name} is deprecated and will be removed from Nuntius | #{message}"
5
+ Kernel.warn message
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nuntius
4
+ module Devise
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ raise "#{name} must be nuntiable" unless nuntiable?
9
+
10
+ orchestrator = Evento::Orchestrator.new(self)
11
+ orchestrator.define_event_methods_on(messenger, devise: true) { |object, options = {}| }
12
+
13
+ orchestrator.override_devise_notification do |notification, *devise_params|
14
+ # All notifications have either a token as the first param, or nothing
15
+ Nuntius.event(notification, self, { token: devise_params.first })
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nuntius
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace Nuntius
6
+
7
+ initializer 'nuntius.config' do |_app|
8
+ path = File.expand_path(File.join(File.dirname(__FILE__), '.', 'liquid', '{tags,filters}', '*.rb'))
9
+ Dir.glob(path).each do |c|
10
+ require_dependency(c)
11
+ end
12
+ end
13
+
14
+ initializer :append_migrations do |app|
15
+ unless app.root.to_s.match? root.to_s
16
+ config.paths['db/migrate'].expanded.each do |expanded_path|
17
+ app.config.paths['db/migrate'] << expanded_path
18
+ end
19
+ end
20
+ end
21
+
22
+ initializer 'active_storage.attached' do
23
+ config.after_initialize do
24
+ ActiveSupport.on_load(:active_record) do
25
+ Nuntius::Attachment.include(Nuntius::ActiveStorageHelpers)
26
+ end
27
+ end
28
+ end
29
+
30
+ #
31
+ # initializer "webpacker.proxy" do |app|
32
+ # insert_middleware = begin
33
+ # Nuntius.webpacker.config.dev_server.present?
34
+ # rescue
35
+ # nil
36
+ # end
37
+ # next unless insert_middleware
38
+ #
39
+ # app.middleware.insert_before(
40
+ # 0, Webpacker::DevServerProxy, # "Webpacker::DevServerProxy" if Rails version < 5
41
+ # ssl_verify_none: true,
42
+ # webpacker: Nuntius.webpacker
43
+ # )
44
+ # end
45
+ end
46
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'i18n/core_ext/hash'
4
+
5
+ module Nuntius
6
+ begin
7
+ require 'oj'
8
+ class JSON
9
+ class << self
10
+ def encode(value)
11
+ Oj::Rails.encode(value)
12
+ end
13
+
14
+ def decode(value)
15
+ Oj.load(value)
16
+ end
17
+ end
18
+ end
19
+ rescue LoadError
20
+ require 'active_support/json'
21
+ JSON = ActiveSupport::JSON
22
+ end
23
+
24
+ class I18nStore
25
+ def initialize; end
26
+
27
+ def keys
28
+ return [] unless template
29
+
30
+ result = []
31
+ locales.each do |locale|
32
+ result += flat_hash(locale.data).keys
33
+ end
34
+ result
35
+ end
36
+
37
+ def [](key)
38
+ return unless template
39
+
40
+ result = {}
41
+ locales.each do |locale|
42
+ hash = flat_hash(locale.data).transform_values { |v| JSON.encode(v) }
43
+ result.merge! hash
44
+ end
45
+ result[key]
46
+ end
47
+
48
+ def []=(key, value)
49
+ # NOOP
50
+ end
51
+
52
+ def with(template)
53
+ with_custom_backend do
54
+ self.template = template
55
+ yield(template)
56
+ self.template = nil
57
+ end
58
+ end
59
+
60
+ def template
61
+ Thread.current[:nuntius_i18n_store_template]
62
+ end
63
+
64
+ def template=(template)
65
+ Thread.current[:nuntius_i18n_store_template] = template
66
+ end
67
+
68
+ private
69
+
70
+ def with_custom_backend
71
+ Thread.current[:nuntius_i18n_store_old_backend] = I18n.backend
72
+ I18n.backend = I18n::Backend::Chain.new(custom_i18n_backend, I18n.backend)
73
+
74
+ yield
75
+
76
+ I18n.backend = Thread.current[:nuntius_i18n_store_old_backend]
77
+ end
78
+
79
+ def locales
80
+ Nuntius::Locale.all
81
+ end
82
+
83
+ def flat_hash(hash = {})
84
+ (hash || {}).reduce({}) do |a, (k, v)|
85
+ tmp = v.is_a?(Hash) ? flat_hash(v).map { |k2, v2| ["#{k}.#{k2}", v2] }.to_h : { k => v }
86
+ a.merge(tmp)
87
+ end
88
+ end
89
+
90
+ # Yield our own custom backend
91
+ def custom_i18n_backend
92
+ return @custom_i18n_backend if @custom_i18n_backend
93
+
94
+ @custom_i18n_backend = I18n::Backend::KeyValue.new(Nuntius.i18n_store)
95
+ @custom_i18n_backend.class.send(:include, I18n::Backend::Cascade)
96
+
97
+ @custom_i18n_backend
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Attaches files (from URL)
4
+ #
5
+ # == Basic usage:
6
+ # {%attach 'https://www.boxture.com/assets/images/logo.png'%}
7
+ #
8
+ class AttachTag < LiquidumTag
9
+ def render(context)
10
+ super
11
+
12
+ return unless argv1
13
+
14
+ message = context.registers['message']
15
+
16
+ if argv1.is_a? String
17
+ message.add_attachment({ url: argv1 })
18
+ elsif argv1.instance_of?(ActiveStorageAttachedOneDrop) || argv1.instance_of?(ActiveStorage::AttachmentDrop)
19
+
20
+ io = StringIO.new(argv1.download)
21
+ io.rewind
22
+ content_type = argv1.content_type
23
+ filename = argv1.filename
24
+
25
+ if arg(:convert) == 'pdf' && content_type != 'application/pdf'
26
+ content_type = 'application/pdf'
27
+ pdf = Labelary::Label.render(zpl: io.read,
28
+ content_type: content_type,
29
+ dpmm: 8,
30
+ width: arg(:width).blank? ? 4 : arg(:width),
31
+ height: arg(:height).blank? ? 6 : arg(:height))
32
+
33
+ io = StringIO.new(pdf)
34
+ filename = "#{filename}.pdf"
35
+ end
36
+
37
+ message.add_attachment({ content: io, filename: filename, content_type: content_type })
38
+ end
39
+
40
+ ''
41
+ end
42
+ end
43
+
44
+ Liquid::Template.register_tag('attach', AttachTag)
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mail'
4
+
5
+ module Nuntius
6
+ class MailAllowList
7
+ def initialize(allow_list = [])
8
+ allow_list = [] if allow_list.blank?
9
+ @allow_list = allow_list.map(&:downcase)
10
+ end
11
+
12
+ def allowed?(email)
13
+ return true if @allow_list.blank?
14
+
15
+ mail_to = Mail::Address.new(email.downcase)
16
+ allow_list_match = @allow_list.detect do |allow|
17
+ allow == (allow.include?('@') ? mail_to.to_s : mail_to.domain)
18
+ end
19
+
20
+ allow_list_match.present?
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nuntius
4
+ module Nuntiable
5
+ extend ActiveSupport::Concern
6
+
7
+ class_methods do
8
+ def nuntiable_options
9
+ @_nuntius_nuntiable_options || {}
10
+ end
11
+
12
+ def messenger
13
+ Nuntius::BaseMessenger.messenger_for_class(name)
14
+ end
15
+ end
16
+
17
+ included do
18
+ raise "Nuntius Messenger has not been implemented for class #{name}" unless messenger
19
+
20
+ Nuntius.config.add_nuntiable_class(self)
21
+ has_many :messages, as: :nuntiable, class_name: 'Nuntius::Message'
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nuntius
4
+ module StateMachine
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ raise "#{name} must be nuntiable" unless nuntiable?
9
+
10
+ orchestrator = Evento::Orchestrator.new(self)
11
+ orchestrator.define_event_methods_on(messenger, state_machine: true) { |object, options = {}| }
12
+
13
+ orchestrator.after_audit_trail_commit(:nuntius) do |resource_state_transition|
14
+ resource = resource_state_transition.resource
15
+ Nuntius.event(event, resource) if resource.nuntiable? && event.present?
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nuntius
4
+ module Transactio
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ raise "#{name} must be nuntiable" unless nuntiable?
9
+
10
+ orchestrator = Evento::Orchestrator.new(self)
11
+ if nuntiable_options[:life_cycle]
12
+ orchestrator.define_event_methods_on(messenger, life_cycle: true) do |object, options = {}|
13
+ end
14
+ end
15
+
16
+ orchestrator = Evento::Orchestrator.new(self)
17
+ orchestrator.after_transaction_log_commit(:nuntius) do |transaction_log_entry|
18
+ resource = transaction_log_entry.transaction_loggable
19
+ event = transaction_log_entry.event
20
+
21
+ if resource.present? && event.present? && resource.nuntiable?
22
+ params = Nuntius.config.default_params(transaction_log_entry)
23
+
24
+ Nuntius.event(event, resource, params)
25
+ Nuntius.event('save', resource, params) if %w[create update].include?(event)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Nuntius
2
- VERSION = "0.1.1"
4
+ VERSION = "1.0.27"
3
5
  end
data/lib/nuntius.rb CHANGED
@@ -1,11 +1,77 @@
1
- require 'openssl'
1
+ # frozen_string_literal: true
2
+
3
+ require 'auxilium'
4
+ require 'inky'
5
+ require 'httpclient'
6
+ require 'liquidum'
7
+ require 'premailer'
8
+ require 'state_machines-activerecord'
9
+ require 'servitium'
10
+
11
+ require 'nuntius/deprecator'
12
+ require 'nuntius/engine'
13
+ require 'nuntius/configuration'
14
+ require 'nuntius/active_record_helpers'
15
+ require 'nuntius/active_storage_helpers'
16
+ require 'nuntius/i18n_store'
17
+ require 'nuntius/mail_allow_list'
2
18
 
3
19
  module Nuntius
4
- class Error < RuntimeError; end
5
- end
20
+ ROOT_PATH = Pathname.new(File.join(__dir__, '..'))
21
+
22
+ class Error < StandardError; end
23
+
24
+ class << self
25
+ attr_reader :config
26
+
27
+ def setup
28
+ @config = Configuration.new
29
+ yield config
30
+ end
31
+
32
+ def i18n_store
33
+ @i18n_store ||= Nuntius::I18nStore.new
34
+ end
6
35
 
7
- require "nuntius/version"
8
- require "nuntius/encodings"
9
- require "nuntius/key"
10
- require "nuntius/envelope"
11
- require "nuntius/messenger"
36
+ #
37
+ # Fires an event for use with templates with the object
38
+ #
39
+ # Nuntius.event(:your_event, car)
40
+ #
41
+ # When custom events are enabled you can also do the following:
42
+ #
43
+ # Nuntius.event('shipped', { shipped: { to: 'test@example.com', ref: 'Test-123'} }, attachments: [ { url: 'http://example.com' } ])
44
+ #
45
+ def event(event, obj, params = {})
46
+ return unless event
47
+ return unless obj.is_a?(Hash) || obj.nuntiable?
48
+ return unless templates?(obj, event)
49
+
50
+ options = params[:options] || {}
51
+
52
+ if options[:perform_now] == true
53
+ Nuntius::MessengerJob.perform_now(obj, event.to_s, params)
54
+ else
55
+ job = Nuntius::MessengerJob
56
+ job.set(wait: options[:wait]) if options[:wait]
57
+ job.perform_later(obj, event.to_s, params)
58
+ end
59
+ end
60
+
61
+ def active_storage_enabled?
62
+ ActiveRecord::Base.connection.table_exists? 'active_storage_attachments'
63
+ end
64
+
65
+ def templates?(obj, event)
66
+ Nuntius::Template.where(klass: Nuntius::BaseMessenger.class_names_for(obj),
67
+ event: Nuntius::BaseMessenger.event_name_for(
68
+ obj, event
69
+ )).where(enabled: true).count.positive?
70
+ end
71
+ end
72
+
73
+ # Include helpers
74
+ ActiveSupport.on_load(:active_record) do
75
+ include Nuntius::ActiveRecordHelpers
76
+ end
77
+ end
data/lib/preamble.rb ADDED
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Preamble
4
+ DEFAULTS = {
5
+ external_encoding: Encoding.default_external
6
+ }.freeze
7
+
8
+ attr_accessor :metadata, :content
9
+
10
+ def initialize(metadata, content)
11
+ @metadata = metadata
12
+ @content = content
13
+ end
14
+
15
+ def metadata_with_content
16
+ @metadata.to_yaml + "---\n" + @content
17
+ end
18
+
19
+ def dump
20
+ metadata_with_content
21
+ end
22
+
23
+ def save(path, options = {})
24
+ options = DEFAULTS.merge(options)
25
+
26
+ open(path, "w:#{options[:external_encoding]}") do |f|
27
+ f.write metadata_with_content
28
+ end
29
+ end
30
+
31
+ def self.parse(data)
32
+ preamble_lines = +''
33
+ content_lines = +''
34
+
35
+ state = :before_preamble
36
+
37
+ f = StringIO.new(data)
38
+ f.each do |line|
39
+ stripped = line.strip
40
+
41
+ case state
42
+ when :before_preamble
43
+
44
+ new_state = case stripped
45
+ when '---'
46
+ :preamble
47
+ when ''
48
+ :before_preamble
49
+ else
50
+ content_lines << line
51
+ :after_preamble
52
+ end
53
+
54
+ when :preamble
55
+
56
+ new_state = case stripped
57
+ when '---'
58
+ :after_preamble
59
+ else
60
+ preamble_lines << line
61
+ :preamble
62
+ end
63
+
64
+ when :after_preamble
65
+ new_state = :after_preamble
66
+ content_lines << line
67
+
68
+ else
69
+ raise "Invalid State: #{state}"
70
+ end
71
+
72
+ state = new_state
73
+ end
74
+
75
+ new(YAML.safe_load(preamble_lines), content_lines)
76
+ end
77
+
78
+ def self.load(path, options = {})
79
+ f = open(path, "r:#{options[:external_encoding]}")
80
+ parse(f.read)
81
+ end
82
+
83
+ def self.load_multiple(*paths)
84
+ options = paths.last.is_a?(Hash) ? paths.pop : {}
85
+ paths.map { |path| Preamble.load(path, options) }
86
+ end
87
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ desc 'Release a new version'
4
+ namespace :nuntius do
5
+ task :release do
6
+ version_file = './lib/nuntius/version.rb'
7
+ File.open(version_file, 'w') do |file|
8
+ file.puts <<~EOVERSION
9
+ # frozen_string_literal: true
10
+
11
+ module Nuntius
12
+ VERSION = '#{Nuntius::VERSION.split('.').map(&:to_i).tap { |parts| parts[2] += 1 }.join('.')}'
13
+ end
14
+ EOVERSION
15
+ end
16
+ module Nuntius
17
+ remove_const :VERSION
18
+ end
19
+ load version_file
20
+ puts "Updated version to #{Nuntius::VERSION}"
21
+
22
+ `git commit lib/nuntius/version.rb -m "Version #{Nuntius::VERSION}"`
23
+ `git push`
24
+ `git tag #{Nuntius::VERSION}`
25
+ `git push --tags`
26
+ end
27
+ end