web47core 2.2.20 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f9305a37f231981bf61fa093709aa13bfda35fde37df2cdee660f6ba219ca46
4
- data.tar.gz: 48757e73cfdc337e0c5bf3480401161bf2983e56270a1fd31341ee33000f653b
3
+ metadata.gz: 7147715aefdef70511603bf5ddb8afa017da40ef51c54d4c14e10edd7c15d21d
4
+ data.tar.gz: 0fca6d931d158a0900121ed7f22983fc13322375fc1e3acccd18fd2062a2cdfe
5
5
  SHA512:
6
- metadata.gz: 1a03cfb814a6ad378787599aeace957ebf0b8c35777e156e157a3ad4a6e6d86149dca91d24b1efa4cf380007d3fb953d55df202f490490240c7ab51bfab53a66
7
- data.tar.gz: 307bb6fbc9d022e56cf06e0dd3fa2ace89403c281107c3aa1f0f294896f799f8ca59974dc2aecc8641eecd0fa5872f53893a5f23f48491244675db578e132288
6
+ metadata.gz: 05d7ded51da1a605dadd22666a988a2cd77dea9c320a187fa57ab7259d345a1f9910fdf31d674b8b0dac511895f721313e3ef068e0be9b7ae745b37b426fb122
7
+ data.tar.gz: ffc6a842ae0142f3cd4c0ba63813e4fb685a21208a84aba45a79dd5fe9b65507f6318ffdb6b74a81d28fdca8b06cccde584df7fea7fa1cd647b776e4a84654a8
@@ -17,12 +17,12 @@
17
17
  data: {confirm: t('confirm_destroy_all')}}
18
18
  %i.material-icons
19
19
  delete
20
- %a.btn.yellow.darken-3{href: class_action_path(:resubmit_all, failed_only:true),
20
+ %a.btn.yellow.darken-3{href: class_action_path(:resbumit_all, failed_only:true),
21
21
  title: t('.resubmit_failed'),
22
22
  data: {confirm: t('.confirm_resubmit_failed')}}
23
23
  %i.material-icons
24
24
  restore
25
- %a.btn.red{href: class_action_path(:resubmit_all, failed_only:false),
25
+ %a.btn.red{href: class_action_path(:resbumit_all, failed_only:false),
26
26
  title: t('.resubmit_all'),
27
27
  data: {confirm: t('.confirm_resubmit_all')}}
28
28
  %i.material-icons
@@ -40,7 +40,7 @@
40
40
  %tbody
41
41
  - @delayed_jobs.each do |delayed_job|
42
42
  %tr
43
- %td=current_user.local_time(delayed_job.run_at)
43
+ %td=current_user.local_time(delayed_job.created_at)
44
44
  %td.name=link_to(delayed_job.display_name, model_path(delayed_job))
45
45
  %td=delayed_job.priority
46
46
  %td=delayed_job.status_description
@@ -57,4 +57,4 @@
57
57
  .card-action
58
58
  .row
59
59
  .col.s6.center-align= delete_button_tag(@delayed_job, model_path(@delayed_job))
60
- .col.s6.center-align= replay_button_tag(@delayed_job, model_action_path(@delayed_job, :resubmit))
60
+ .col.s6.center-align= replay_button_tag(@delayed_job, model_path(@delayed_job))
@@ -46,7 +46,7 @@ module CoreDelayedJobsController
46
46
 
47
47
  job.resubmit
48
48
  end
49
- flash.now[:info] = 'All Delayed Jobs has been resubmitted'
49
+ flash.now[:info] = 'All DelayJobs has been resubmitted'
50
50
  redirect_to index_path
51
51
  rescue StandardError => error
52
52
  log_controller_error error, true
@@ -40,15 +40,18 @@ module AwsConfiguration
40
40
  aws_configured? && aws_auto_scaling_group_name.present?
41
41
  end
42
42
 
43
+ def aws_credentials
44
+ @aws_credentials ||= Aws::Credentials.new(aws_access_key_id,
45
+ aws_secret_access_key)
46
+ end
47
+
43
48
  #
44
49
  # AWS client.
45
50
  #
46
51
  def aws_ec2_client
47
52
  return nil unless aws_configured?
48
53
 
49
- @aws_ec2_client ||= Aws::EC2::Client.new(region: aws_region,
50
- credentials: Aws::Credentials.new(aws_access_key_id,
51
- aws_secret_access_key))
54
+ @aws_ec2_client ||= Aws::EC2::Client.new(region: aws_region, credentials: aws_credentials);
52
55
  end
53
56
 
54
57
  #
@@ -14,6 +14,11 @@
14
14
  #
15
15
  module CoreSystemConfiguration
16
16
  extend ActiveSupport::Concern
17
+ EMAIL_PROVIDER_SMTP_TYPE = 'smtp'.freeze unless defined? EMAIL_PROVIDER_SMTP_TYPE
18
+ EMAIL_PROVIDER_SES_TYPE = 'ses'.freeze unless defined? EMAIL_PROVIDER_SES_TYPE
19
+ unless defined? ALL_EMAIL_PROVIDER_TYPES
20
+ ALL_EMAIL_PROVIDER_TYPES = [EMAIL_PROVIDER_SMTP_TYPE, EMAIL_PROVIDER_SES_TYPE].freeze
21
+ end
17
22
 
18
23
  def self.included(base)
19
24
  base.class_eval do
@@ -30,6 +35,7 @@ module CoreSystemConfiguration
30
35
  field :short_cache, { type: Integer, default: 1 }
31
36
  field :medium_cache, { type: Integer, default: 5 }
32
37
  field :long_cache, { type: Integer, default: 15 }
38
+ field :stack_email_provider, type: String, default: EMAIL_PROVIDER_SMTP_TYPE
33
39
  # URLs
34
40
  field :base_url, type: String
35
41
  field :cdn_url, type: String
@@ -43,6 +49,7 @@ module CoreSystemConfiguration
43
49
  #
44
50
  validates :environment, presence: true, uniqueness: true
45
51
  validates :default_time_zone, presence: true
52
+ validates :stack_email_provider, inclusion: { in: ALL_EMAIL_PROVIDER_TYPES }
46
53
  end
47
54
  base.extend ClassMethods
48
55
  end
@@ -75,6 +82,14 @@ module CoreSystemConfiguration
75
82
  end
76
83
  end
77
84
 
85
+ def stack_ses_provider?
86
+ EMAIL_PROVIDER_SES_TYPE.eql?(stack_email_provider)
87
+ end
88
+
89
+ def stack_smtp_provider?
90
+ EMAIL_PROVIDER_SMTP_TYPE.eql?(stack_email_provider)
91
+ end
92
+
78
93
  #
79
94
  # Cache times in minutes
80
95
  #
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # AWS SES SSO Configuration
5
+ #
6
+ module SesConfiguration
7
+ extend ActiveSupport::Concern
8
+
9
+ def self.included(base)
10
+ base.class_eval do
11
+ #
12
+ # Fields
13
+ #
14
+ field :ses_source, type: String
15
+ field :ses_source_arn_prefix, type: String
16
+ field :ses_bounce_queue_name, type: String
17
+ field :ses_region, type: String
18
+ end
19
+ end
20
+
21
+ #
22
+ # Determine if AWS is configured
23
+ #
24
+ def ses_configured?
25
+ aws_configured? &&
26
+ ses_source.present? &&
27
+ ses_source_arn_prefix.present? &&
28
+ (ses_region.present? || aws_region.present?)
29
+ end
30
+
31
+ def ses_source_arn(source = ses_source)
32
+ [ses_source_arn_prefix, source].compact.join('/')
33
+ end
34
+
35
+ #
36
+ # SES Client
37
+ #
38
+ def aws_ses_client
39
+ return nil unless ses_configured?
40
+
41
+ # We want this to remake itself each time because it is possible that the
42
+ # => user would change the access keys in between actions. Huh?
43
+ @aws_ses_client ||= Aws::SES::Client.new(region: ses_region.presence || aws_region, credentials: aws_credentials)
44
+ end
45
+ end
@@ -36,60 +36,63 @@ class EmailNotification < Notification
36
36
  field :cc, type: String
37
37
  # The subject
38
38
  field :subject, type: String
39
+ field :message_id, type: String
39
40
  #
40
41
  # Validations
41
42
  #
42
43
  validates :subject, presence: true
43
44
  validates :to, presence: true
44
-
45
- # has_many :attachments, class_name: 'EmailNotificationAttachment', dependent: :destroy
45
+ # Callbacks
46
+ before_save :ensure_headers
46
47
 
47
48
  def from_template(template_name, locals = {})
48
49
  super
49
50
  self.subject = subject_from_template(template_name, locals)
50
51
  end
51
52
 
52
- #
53
- # Add a file as an attachment to this email notification.
54
- #
55
- # Expecting a path to the file, not the file or data itself.
56
- # TODO consider how to handle a file object or data object.
57
- #
58
- # Once you have called this method, the file is stored via PaperClip and
59
- # does not need to stay persistant through email delivery.
60
- # You can delete it after telling the EmailNotification to send
61
- # the notification.
62
- #
63
- # def add_file(file)
64
- # # Make sure we are saved
65
- # save! unless persisted?
66
- # attachment = EmailNotificationAttachment.new email_notification: self
67
- # attachment.file = open(file)
68
- # attachment.save!
69
- # end
70
53
  def deliver_message!
54
+ if account.present? && account.fetch_smtp_configuration.use?
55
+ deliver_smtp_message!
56
+ elsif SystemConfiguration.stack_smtp_provider?
57
+ deliver_smtp_message!
58
+ elsif SystemConfiguration.ses_configured?
59
+ deliver_ses_message!
60
+ else
61
+ fail "Invalid configuration in stack for sending emails"
62
+ end
63
+ end
64
+
65
+ def deliver_ses_message!
66
+ config = SystemConfiguration.configuration
67
+ client = config.aws_ses_client
68
+ payload = { destination: { to_addresses: [to] },
69
+ message: {
70
+ body: { html: { data: build_message } },
71
+ subject: { data: subject } },
72
+ source: from,
73
+ source_arn: config.ses_source_arn(from) }
74
+ payload[:reply_to_addresses] = [reply_to] if reply_to.present?
75
+ resp = client.send_email(payload)
76
+ self.message_id = resp[:message_id]
77
+ end
78
+
79
+ def deliver_smtp_message!
71
80
  mail = Mail.new
72
81
  # Set the from line
73
- address = from_address
74
- mail.from = address
75
- self.from = address
82
+ mail.from = from
76
83
  # Set the sender line
77
- address = sender_address
78
- mail.sender = address
79
- self.sender = address
84
+ mail.sender = sender
80
85
  # Set the reply to
81
- address = reply_to_address
82
- if address.present?
83
- self.reply_to = address
84
- mail.reply_to = address
85
- mail.sender = address
86
+ if reply_to_address.present?
87
+ mail.reply_to = reply_to_address
88
+ mail.sender = reply_to_address
86
89
  end
87
90
 
88
91
  # Set the to address
89
92
  mail.to = to
90
93
 
91
94
  # Set the cc line
92
- mail.cc = cc unless cc.nil?
95
+ mail.cc = cc if cc.present?
93
96
 
94
97
  # Set the subject line
95
98
  mail.subject = subject
@@ -101,9 +104,6 @@ class EmailNotification < Notification
101
104
  body html_message
102
105
  end
103
106
 
104
- # Add the attachments, if there are any. If not, none are added.
105
- add_attachments(attachments) if defined?(attachments)
106
-
107
107
  # Setup the delivery method for this message only.
108
108
  if 'test'.eql?(ENV['RAILS_ENV'])
109
109
  mail.delivery_method :test
@@ -121,19 +121,12 @@ class EmailNotification < Notification
121
121
  FileUtils.remove_entry_secure(tmp_dir) if defined?(tmp_dir) && tmp_dir.present?
122
122
  end
123
123
 
124
- def add_attachments(attachments = nil)
125
- tmp_dir = Dir.mktmpdir
126
- attachments.each do |attachment|
127
- # Create a temp directory, it'll get cleaned up in the rescue.
128
- tmp_file_path = "#{tmp_dir}/#{attachment.file_file_name}"
129
- File.open(tmp_file_path, 'w') do |f|
130
- f.write(URI.parse(attachment.file_url).open.read.force_encoding('utf-16').encode)
131
- end
132
- mail.attachments[attachment.file_file_name] = {
133
- mime_type: attachment.file_content_type,
134
- content: File.open(tmp_file_path).read.force_encoding('utf-16').encode
135
- }
136
- end
124
+ # @abstract Ensure the headers of the message are set regardless if we are using
125
+ # ses or smtp
126
+ def ensure_headers
127
+ self.from = from_address
128
+ self.sender = sender_address
129
+ self.reply_to = reply_to_address
137
130
  end
138
131
 
139
132
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Web47core
4
- VERSION = '2.2.20'
4
+ VERSION = '2.3.0'
5
5
  end
data/lib/web47core.rb CHANGED
@@ -10,6 +10,7 @@ require 'app/models/concerns/delayed_job_configuration'
10
10
  require 'app/models/concerns/email_able'
11
11
  require 'app/models/concerns/encrypted_password'
12
12
  require 'app/models/concerns/google_sso_configuration'
13
+ require 'app/models/concerns/ses_configuration'
13
14
  require 'app/models/concerns/search_able'
14
15
  require 'app/models/concerns/role_able'
15
16
  require 'app/models/concerns/time_zone_able'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: web47core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.20
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Schroeder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-28 00:00:00.000000000 Z
11
+ date: 2023-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -58,6 +58,26 @@ dependencies:
58
58
  - - "<"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '2'
61
+ - !ruby/object:Gem::Dependency
62
+ name: aws-sdk-ses
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '1.55'
68
+ - - "<"
69
+ - !ruby/object:Gem::Version
70
+ version: '2'
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '1.55'
78
+ - - "<"
79
+ - !ruby/object:Gem::Version
80
+ version: '2'
61
81
  - !ruby/object:Gem::Dependency
62
82
  name: cancancan
63
83
  requirement: !ruby/object:Gem::Requirement
@@ -767,6 +787,7 @@ files:
767
787
  - lib/app/models/concerns/search_able.rb
768
788
  - lib/app/models/concerns/secure_fields.rb
769
789
  - lib/app/models/concerns/server_process_able.rb
790
+ - lib/app/models/concerns/ses_configuration.rb
770
791
  - lib/app/models/concerns/slack_configuration.rb
771
792
  - lib/app/models/concerns/standard_model.rb
772
793
  - lib/app/models/concerns/switchboard_able.rb