pg_rails 7.0.8.pre.alpha.82 → 7.0.8.pre.alpha.84

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/pg_engine/app/admin/email_logs.rb +37 -0
  3. data/pg_engine/app/controllers/admin/email_logs_controller.rb +50 -0
  4. data/pg_engine/app/controllers/pg_engine/base_controller.rb +3 -0
  5. data/pg_engine/app/controllers/public/webhooks_controller.rb +77 -0
  6. data/pg_engine/app/decorators/email_log_decorator.rb +16 -0
  7. data/pg_engine/app/models/email.rb +16 -2
  8. data/pg_engine/app/models/email_log.rb +59 -0
  9. data/pg_engine/app/policies/email_log_policy.rb +31 -0
  10. data/pg_engine/app/views/admin/email_logs/_email_log.html.slim +1 -0
  11. data/pg_engine/app/views/admin/email_logs/_form.html.slim +16 -0
  12. data/pg_engine/app/views/admin/email_logs/show.html.slim +18 -0
  13. data/pg_engine/app/views/admin/emails/show.html.slim +20 -4
  14. data/pg_engine/app/views/pg_engine/base/index.html.slim +2 -0
  15. data/pg_engine/config/locales/es.yml +1 -0
  16. data/pg_engine/config/routes.rb +26 -0
  17. data/pg_engine/db/migrate/20240523183651_create_email_logs.rb +19 -0
  18. data/pg_engine/lib/pg_engine/email_observer.rb +4 -2
  19. data/pg_engine/lib/pg_engine/mailgun/log_sync.rb +36 -35
  20. data/pg_engine/lib/pg_engine/utils/check_invalid_records.rb +39 -0
  21. data/pg_engine/lib/pg_engine/utils/pg_logger.rb +20 -2
  22. data/pg_engine/spec/controllers/admin/email_logs_controller_spec.rb +179 -0
  23. data/pg_engine/spec/controllers/pg_engine/base_controller_spec.rb +11 -0
  24. data/pg_engine/spec/controllers/public/webhooks_controller_spec.rb +142 -0
  25. data/pg_engine/spec/factories/email_logs.rb +20 -0
  26. data/pg_engine/spec/lib/pg_engine/mailgun/log_sync_spec.rb +81 -7
  27. data/pg_engine/spec/models/email_log_spec.rb +48 -0
  28. data/pg_engine/spec/models/email_spec.rb +35 -0
  29. data/pg_layout/app/views/layouts/pg_layout/base.html.slim +11 -0
  30. data/pg_rails/lib/pg_rails/rspec_logger_matchers.rb +62 -0
  31. data/pg_rails/lib/version.rb +1 -1
  32. metadata +18 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f155f16783603b8b6acd943855ce4d4996d92722235ec8eea4fe9cf82dd6efb0
4
- data.tar.gz: 4403492bc1eaeecb807dd9bab487047b89681007100baf5e6758271a8967f163
3
+ metadata.gz: 9c61900d2d0b3a827718b84a3cab67f4851b2eb3087e7fbc1d313f0acf163bf3
4
+ data.tar.gz: bfca92cbb58ba292877ccb61b15b08049a0d800fdc13408f82647e9ea7c66ee9
5
5
  SHA512:
6
- metadata.gz: 97f5a71981109ce5a8dac87ce5db0184e5c21fc906adc0863ca916e2b8868e5dc013ea46a924e42780b49e9d658faf32a8b5c34bcdf272edd549f848a4ad9918
7
- data.tar.gz: 69dc1acfe7f80c080c4f0263f1904f9ceaff511da31a24e37ba5f77fa6e76fb4888af45313c7c41ab58b3fe3697cdaf46306c28c426bcac91e0badc84ad4aa69
6
+ metadata.gz: 2282deaa98881e20bd0b754c6496fc9da679214760ea45fd5f8c2f0b64a0903e1557cffb2f8d4c13b156d46e62b237113bf8f24bdba676436a404eb1e57e37c5
7
+ data.tar.gz: d9ece2e6b39c53169548c253afdb18fb9707d76bc762b0b86b7cc2656e563a4efea6d303f51814aac22926effd37ef1ec1d6c6a6d00bded153476864586f6b14
@@ -0,0 +1,37 @@
1
+ ActiveAdmin.register EmailLog do
2
+ permit_params :email_id, :log_id, :event, :log_level, :severity, :timestamp, :message_id
3
+
4
+ index do
5
+ selectable_column
6
+ id_column
7
+ column :email
8
+ column :log_id
9
+ column :event
10
+ column :log_level
11
+ column :severity
12
+ column :timestamp
13
+ column :message_id
14
+ actions
15
+ end
16
+
17
+ filter :email
18
+ filter :log_id
19
+ filter :event
20
+ filter :log_level
21
+ filter :severity
22
+ filter :timestamp
23
+ filter :message_id
24
+
25
+ form do |f|
26
+ f.inputs do
27
+ f.input :email
28
+ f.input :log_id
29
+ f.input :event
30
+ f.input :log_level
31
+ f.input :severity
32
+ f.input :timestamp
33
+ f.input :message_id
34
+ end
35
+ f.actions
36
+ end
37
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # generado con pg_rails
4
+
5
+ module Admin
6
+ class EmailLogsController < AdminController
7
+ include PgEngine::Resource
8
+
9
+ before_action { @clase_modelo = EmailLog }
10
+
11
+ before_action(only: :index) { authorize EmailLog }
12
+
13
+ before_action :set_instancia_modelo, only: %i[new create show edit update destroy]
14
+
15
+ add_breadcrumb EmailLog.nombre_plural, :admin_email_logs_path
16
+
17
+ before_action do
18
+ @actions = [
19
+ ["Mailgun sync: #{ENV.fetch('MAILGUN_DOMAIN', nil)}", mailgun_sync_admin_email_logs_path, {
20
+ 'data-turbo-method': :post, class: 'me-2 btn btn-primary btn-sm'
21
+ }]
22
+ ]
23
+ end
24
+
25
+ def mailgun_sync
26
+ @new_items = PgEngine::Mailgun::LogSync.download
27
+ flash[:success] = "#{@new_items.length} nuevos items"
28
+
29
+ redirect_to admin_email_logs_path
30
+ end
31
+
32
+ private
33
+
34
+ def atributos_permitidos
35
+ %i[email_id log_id event log_level severity timestamp message_id]
36
+ end
37
+
38
+ def atributos_para_buscar
39
+ %i[email log_id event log_level severity timestamp message_id]
40
+ end
41
+
42
+ def atributos_para_listar
43
+ %i[email log_id event log_level severity timestamp message_id]
44
+ end
45
+
46
+ def atributos_para_mostrar
47
+ %i[email log_id event log_level severity timestamp message_id]
48
+ end
49
+ end
50
+ end
@@ -40,6 +40,9 @@ module PgEngine
40
40
  render turbo_stream: (turbo_stream.remove_all('.modal') + render_turbo_stream_flash_messages),
41
41
  status: :internal_server_error
42
42
  end
43
+ format.any do
44
+ head :internal_server_error
45
+ end
43
46
  end
44
47
  end
45
48
 
@@ -0,0 +1,77 @@
1
+ module Public
2
+ class WebhooksController < PublicController
3
+ skip_before_action :verify_authenticity_token
4
+
5
+ before_action :verify_signature, only: :mailgun
6
+
7
+ rescue_from StandardError do
8
+ pg_err 'webhook internal server error', request.body.read
9
+ head :internal_server_error
10
+ end
11
+
12
+ rescue_from ActionDispatch::Http::Parameters::ParseError do
13
+ pg_warn 'webhook parser error', request.body.read
14
+ head :bad_request
15
+ end
16
+
17
+ def mailgun
18
+ if PgEngine::Mailgun::LogSync.digest(params['event-data'])
19
+ head :ok
20
+ else
21
+ # Si no se guardó el log es porque ya existía un log con ese ID
22
+ # Mando :not_acceptable (406) para que Mailgun no vuelva a intentar
23
+ # https://documentation.mailgun.com/docs/mailgun/user-manual/tracking-messages
24
+ pg_warn 'ya existía un log con ese id, raaaaro', params
25
+ head :not_acceptable
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def used_tokens
32
+ Kredis.unique_list 'mailgun_webhook_used_tokens'
33
+ end
34
+
35
+ def not_used_token(token)
36
+ if used_tokens.elements.include?(token)
37
+ pg_warn 'Mailgun Webhook: refusing used token'
38
+ head :ok
39
+
40
+ false
41
+ else
42
+ used_tokens << token
43
+ true
44
+ end
45
+ end
46
+
47
+ def timestamp_not_too_far(timestamp)
48
+ if (Time.zone.at(timestamp.to_i) - Time.zone.now).abs > 1.hour
49
+ pg_warn 'Mailgun Webhook: refusing due to timestamp too far'
50
+ head :ok
51
+
52
+ false
53
+ else
54
+ true
55
+ end
56
+ end
57
+
58
+ def verify_signature
59
+ timestamp = params['signature']['timestamp']
60
+ token = params['signature']['token']
61
+ signature = params['signature']['signature']
62
+ hexdigest = encode(timestamp + token)
63
+
64
+ return unless not_used_token(token)
65
+ return unless timestamp_not_too_far(timestamp)
66
+ return unless hexdigest != signature
67
+
68
+ pg_warn 'Mailgun Webhook: refusing invalid signature'
69
+ head :ok
70
+ end
71
+
72
+ def encode(data)
73
+ webhook_secret_key = Rails.application.credentials.dig(:mailgun, :webhook_secret_key)
74
+ OpenSSL::HMAC.hexdigest('sha256', webhook_secret_key, data)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # generado con pg_rails
4
+
5
+ class EmailLogDecorator < PgEngine::BaseRecordDecorator
6
+ delegate_all
7
+
8
+ # Define presentation-specific methods here. Helpers are accessed through
9
+ # `helpers` (aka `h`). You can override attributes, for example:
10
+ #
11
+ # def created_at
12
+ # helpers.content_tag :span, class: 'time' do
13
+ # object.created_at.strftime("%a %m/%d/%y")
14
+ # end
15
+ # end
16
+ end
@@ -45,10 +45,10 @@ class Email < ApplicationRecord
45
45
  belongs_to :creado_por, optional: true, class_name: 'User'
46
46
  belongs_to :actualizado_por, optional: true, class_name: 'User'
47
47
 
48
- kredis_unique_list :logs
48
+ has_many :email_logs, dependent: :destroy
49
49
 
50
50
  # TODO: y el fallido temporario?
51
- enumerize :status, in: { pending: 0, failed: 1, sent: 2, accepted: 3, delivered: 4, rejected: 5 }
51
+ enumerize :status, in: { pending: 0, failed: 1, sent: 2, accepted: 3, delivered: 4, rejected: 5 }, scope: true
52
52
 
53
53
  validates :from_address, :to, :status, presence: true
54
54
 
@@ -74,4 +74,18 @@ class Email < ApplicationRecord
74
74
  end
75
75
 
76
76
  # validates_format_of :subject, with: /\A[[[:alpha:]]\(\)\w\s.,;!¡?¿-]+\z/
77
+
78
+ def update_status!
79
+ statuses = email_logs.map(&:status_for_email).compact
80
+
81
+ # Aprovechando que los values de status están dispuestos de manera "cronologica"
82
+ new_status = statuses.map { |st| Email.status.find_value(st).value }.max
83
+ return unless new_status
84
+
85
+ self.status = new_status
86
+ return unless changed?
87
+
88
+ self.audit_comment = 'Actualizando status desde logs'
89
+ save!
90
+ end
77
91
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ # == Schema Information
4
+ #
5
+ # Table name: email_logs
6
+ #
7
+ # id :bigint not null, primary key
8
+ # event :string
9
+ # log_level :string
10
+ # severity :string
11
+ # timestamp :bigint
12
+ # created_at :datetime not null
13
+ # updated_at :datetime not null
14
+ # email_id :bigint indexed
15
+ # log_id :string
16
+ # message_id :string
17
+ #
18
+ # Foreign Keys
19
+ #
20
+ # fk_rails_... (email_id => emails.id)
21
+ #
22
+ # generado con pg_rails
23
+
24
+ class EmailLog < ApplicationRecord
25
+ audited
26
+
27
+ belongs_to :email, optional: true
28
+
29
+ after_create_commit do
30
+ email.update_status! if email.present?
31
+ end
32
+
33
+ def status_for_email
34
+ case event
35
+ when 'accepted'
36
+ 'accepted'
37
+ when 'delivered'
38
+ 'delivered'
39
+ when 'failed'
40
+ if severity == 'permanent'
41
+ 'rejected'
42
+ elsif severity == 'temporary'
43
+ 'accepted'
44
+ else
45
+ # :nocov:
46
+ pg_warn 'No se pudo detectar el status de email', self
47
+ nil
48
+ # :nocov:
49
+ end
50
+ when 'opened'
51
+ # No cambia el status
52
+ else
53
+ # :nocov:
54
+ pg_warn 'No se pudo detectar el status de email', self
55
+ nil
56
+ # :nocov:
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # generado con pg_rails
4
+
5
+ class EmailLogPolicy < ApplicationPolicy
6
+ class Scope < ApplicationPolicy::Scope
7
+ # def resolve
8
+ # if policy.acceso_total?
9
+ # scope.all
10
+ # else
11
+ # scope.none
12
+ # end
13
+ # end
14
+ end
15
+
16
+ # def puede_editar?
17
+ # acceso_total? && !record.readonly?
18
+ # end
19
+
20
+ # def puede_crear?
21
+ # acceso_total? || user.asesor?
22
+ # end
23
+
24
+ # def puede_borrar?
25
+ # acceso_total? && !record.readonly?
26
+ # end
27
+
28
+ # def acceso_total?
29
+ # user.developer?
30
+ # end
31
+ end
@@ -0,0 +1 @@
1
+ h1 el partiaaal
@@ -0,0 +1,16 @@
1
+ / # locals: (object: nil, asociable: false)
2
+
3
+ div style="max-width: 22em" data-controller="pg_form"
4
+ = pg_form_for(@email_log || object, asociable:) do |f|
5
+ = f.mensajes_de_error
6
+
7
+ = hidden_field_tag :asociable, true if asociable
8
+ = f.pg_associable :email
9
+ = f.input :log_id
10
+ = f.input :event
11
+ = f.input :log_level
12
+ = f.input :severity
13
+ = f.input :timestamp
14
+ = f.input :message_id
15
+ .mt-2
16
+ = f.button :submit
@@ -0,0 +1,18 @@
1
+ - content_for :title do
2
+ = @email_log.to_s
3
+ - content_for :actions do
4
+ = @email_log.destroy_link_redirect
5
+ .ms-1
6
+ = @email_log.edit_link
7
+
8
+ table.table.table-borderless.table-sm.w-auto.mb-0.m-3
9
+ - atributos_para_mostrar.each do |att|
10
+ tr
11
+ th = @clase_modelo.human_attribute_name(att)
12
+ td = @email_log.send(att)
13
+ tr
14
+ th = t('attributes.created_at')
15
+ td = @email_log.created_at
16
+ tr
17
+ th = t('attributes.updated_at')
18
+ td = @email_log.updated_at
@@ -23,7 +23,23 @@ table.table.table-borderless.table-sm.w-auto.mb-0.m-3
23
23
  th = t('attributes.updated_at')
24
24
  td = @email.updated_at
25
25
 
26
- h4 Logs
27
- - @email.logs.to_a.each do |log|
28
- - json = JSON.parse(log)
29
- p = json['event']
26
+ .m-4
27
+ h4 Logs
28
+ table.table
29
+ tr
30
+ th log_id
31
+ th event
32
+ th log_level
33
+ th severity
34
+ th timestamp
35
+ th created_at
36
+ th updated_at
37
+ - @email.email_logs.order(timestamp: :desc).each do |log|
38
+ tr
39
+ td = log.log_id
40
+ td = log.event
41
+ td = log.log_level
42
+ td = log.severity
43
+ td = log.timestamp
44
+ td = log.created_at
45
+ td = log.updated_at
@@ -1,5 +1,7 @@
1
1
  - content_for(:title, @clase_modelo.nombre_plural)
2
2
  - content_for :actions do
3
+ - @actions&.each do |link_args|
4
+ = link_to(*link_args)
3
5
  - if @filtros.present?
4
6
  button.btn.btn-sm.btn-outline-primary[
5
7
  type="button" data-bs-toggle="collapse"
@@ -69,6 +69,7 @@ es:
69
69
  new:
70
70
  sign_up: Crear una cuenta
71
71
  passwords:
72
+ send_instructions: Vas a recibir un correo con instrucciones sobre cómo resetear tu contraseña en unos pocos minutos.
72
73
  new:
73
74
  send_me_reset_password_instructions: Enviar instrucciones para restablecer contraseña
74
75
  forgot_your_password: ¿Olvidaste tu contraseña?
@@ -3,6 +3,7 @@ include PgEngine::RouteHelpers
3
3
  Rails.application.routes.draw do
4
4
  namespace :public, path: '' do
5
5
  pg_resource(:mensaje_contactos, only: [:new, :create], path: 'contacto')
6
+ post 'webhook/mailgun', to: 'webhooks#mailgun'
6
7
  end
7
8
  devise_for :users, controllers: {
8
9
  confirmations: 'users/confirmations',
@@ -10,6 +11,11 @@ Rails.application.routes.draw do
10
11
  }, failure_app: PgEngine::DeviseFailureApp
11
12
  namespace :admin, path: 'a' do
12
13
  pg_resource(:emails)
14
+ pg_resource(:email_logs) do
15
+ collection do
16
+ post :mailgun_sync
17
+ end
18
+ end
13
19
  pg_resource(:users)
14
20
  pg_resource(:accounts)
15
21
  pg_resource(:user_accounts)
@@ -102,6 +108,17 @@ end
102
108
  # PATCH /a/emails/:id(.:format) admin/emails#update
103
109
  # PUT /a/emails/:id(.:format) admin/emails#update
104
110
  # DELETE /a/emails/:id(.:format) admin/emails#destroy
111
+ # abrir_modal_admin_email_logs GET /a/email_logs/abrir_modal(.:format) admin/email_logs#abrir_modal
112
+ # buscar_admin_email_logs POST /a/email_logs/buscar(.:format) admin/email_logs#buscar
113
+ # mailgun_sync_admin_email_logs POST /a/email_logs/mailgun_sync(.:format) admin/email_logs#mailgun_sync
114
+ # admin_email_logs GET /a/email_logs(.:format) admin/email_logs#index
115
+ # POST /a/email_logs(.:format) admin/email_logs#create
116
+ # new_admin_email_log GET /a/email_logs/new(.:format) admin/email_logs#new
117
+ # edit_admin_email_log GET /a/email_logs/:id/edit(.:format) admin/email_logs#edit
118
+ # admin_email_log GET /a/email_logs/:id(.:format) admin/email_logs#show
119
+ # PATCH /a/email_logs/:id(.:format) admin/email_logs#update
120
+ # PUT /a/email_logs/:id(.:format) admin/email_logs#update
121
+ # DELETE /a/email_logs/:id(.:format) admin/email_logs#destroy
105
122
  # abrir_modal_admin_users GET /a/users/abrir_modal(.:format) admin/users#abrir_modal
106
123
  # buscar_admin_users POST /a/users/buscar(.:format) admin/users#buscar
107
124
  # admin_users GET /a/users(.:format) admin/users#index
@@ -165,6 +182,15 @@ end
165
182
  # active_admin_audited_audits GET /active_admin/audited_audits(.:format) active_admin/audited_audits#index
166
183
  # active_admin_audited_audit GET /active_admin/audited_audits/:id(.:format) active_admin/audited_audits#show
167
184
  # active_admin_dashboard GET /active_admin/dashboard(.:format) active_admin/dashboard#index
185
+ # batch_action_active_admin_email_logs POST /active_admin/email_logs/batch_action(.:format) active_admin/email_logs#batch_action
186
+ # active_admin_email_logs GET /active_admin/email_logs(.:format) active_admin/email_logs#index
187
+ # POST /active_admin/email_logs(.:format) active_admin/email_logs#create
188
+ # new_active_admin_email_log GET /active_admin/email_logs/new(.:format) active_admin/email_logs#new
189
+ # edit_active_admin_email_log GET /active_admin/email_logs/:id/edit(.:format) active_admin/email_logs#edit
190
+ # active_admin_email_log GET /active_admin/email_logs/:id(.:format) active_admin/email_logs#show
191
+ # PATCH /active_admin/email_logs/:id(.:format) active_admin/email_logs#update
192
+ # PUT /active_admin/email_logs/:id(.:format) active_admin/email_logs#update
193
+ # DELETE /active_admin/email_logs/:id(.:format) active_admin/email_logs#destroy
168
194
  # batch_action_active_admin_emails POST /active_admin/emails/batch_action(.:format) active_admin/emails#batch_action
169
195
  # active_admin_emails GET /active_admin/emails(.:format) active_admin/emails#index
170
196
  # active_admin_email GET /active_admin/emails/:id(.:format) active_admin/emails#show
@@ -0,0 +1,19 @@
1
+ # generado con pg_rails
2
+
3
+ class CreateEmailLogs < ActiveRecord::Migration[7.1]
4
+ def change
5
+ create_table :email_logs do |t|
6
+ t.references :email, foreign_key: true
7
+ t.string :log_id
8
+ t.string :event
9
+ t.string :log_level
10
+ t.string :severity
11
+ t.bigint :timestamp
12
+ t.string :message_id
13
+
14
+
15
+ t.timestamps
16
+ end
17
+
18
+ end
19
+ end
@@ -20,8 +20,10 @@ module PgEngine
20
20
  pg_err e
21
21
  end
22
22
 
23
- def self.get_status(message)
24
- message.perform_deliveries ? :sent : :blocked
23
+ def self.get_status(_message)
24
+ # TODO: falta implementar el interceptor y habría que dar algún detalle de por uqé se bloqueó
25
+ # message.perform_deliveries ? :sent : :failed
26
+ :sent
25
27
  end
26
28
  end
27
29
  end
@@ -8,8 +8,6 @@ module PgEngine
8
8
  module Mailgun
9
9
  class LogSync
10
10
  def self.download # rubocop:disable Metrics/AbcSize
11
- domain = ENV.fetch('MAILGUN_DOMAIN')
12
-
13
11
  key = Rails.application.credentials.dig(:mailgun, :api_key)
14
12
  mg_client = ::Mailgun::Client.new(key)
15
13
  items = []
@@ -17,54 +15,57 @@ module PgEngine
17
15
  start_time = DateTime.now - 3.days
18
16
  range = 1.day
19
17
  current = end_time - range
18
+
20
19
  loop do
21
20
  get = "#{domain}/events?begin=#{current.to_i}&end=#{(current + range).to_i}&limit=300"
22
21
  result = mg_client.get(get)
23
22
  result.to_h!
24
- items.push(result.body['items'])
25
- # puts "Current: #{current}. Items count: #{result.body['items'].length}"
23
+ items.push(*result.body['items'])
26
24
  current -= range
27
25
 
28
26
  break if current < start_time
29
27
  end
30
28
 
31
- FileUtils.mkdir_p(dir)
29
+ write_log(items)
32
30
 
33
- File.write("#{dir}/#{domain}-#{Time.zone.now.strftime('%Y-%m-%d_%H.%M.%S')}.json", items.flatten.to_json)
31
+ items.map do |item|
32
+ digest(item)
33
+ end.compact
34
34
  end
35
35
 
36
- def self.dir
37
- @dir ||= if Rails.env.test?
38
- File.expand_path 'tmp/mailgun_logs', Rails.root
39
- else
40
- File.expand_path 'log/mailgun_logs', Rails.root
41
- end
36
+ def self.digest(item)
37
+ message_id = item['message']['headers']['message-id']
38
+
39
+ return if EmailLog.exists?(log_id: item['id'])
40
+
41
+ EmailLog.create!(
42
+ email: Email.where(message_id:).first,
43
+ log_id: item['id'],
44
+ event: item['event'],
45
+ log_level: item['log-level'],
46
+ severity: item['severity'],
47
+ timestamp: item['timestamp'],
48
+ message_id:
49
+ )
42
50
  end
43
51
 
44
- def self.sync_redis
45
- json = []
46
- Dir["#{dir}/*.json"].each do |file|
47
- json.push(*JSON.parse(File.read(file)))
48
- end
52
+ def self.write_log(items)
53
+ FileUtils.mkdir_p(log_dir)
54
+ File.write("#{log_dir}/#{domain}_#{Time.zone.now.strftime('%Y-%m-%d_%H.%M.%S')}.json", items.to_json)
55
+ end
49
56
 
50
- json.each do |i|
51
- # [
52
- # Time.at(i["timestamp"]).strftime('%y-%m-%d %H:%M %z'),
53
- # i["message"]["headers"]["message-id"],
54
- # # i["message"]["headers"]["message-id"][3..15],
55
- # i["event"],
56
- # i["recipient"],
57
- # i["message"]["headers"]["from"],
58
- # i["message"]["headers"]["subject"],
59
- # ]
60
- message_id = i['message']['headers']['message-id']
61
- email = Email.where(message_id:).first
62
- if email
63
- email.logs << i.to_json
64
- else
65
- pg_warn "No existe el mail con message_id = #{message_id}", :warn
66
- end
67
- end
57
+ def self.domain
58
+ ENV.fetch('MAILGUN_DOMAIN')
59
+ end
60
+
61
+ def self.log_dir
62
+ @log_dir ||= if Rails.env.test?
63
+ File.expand_path 'tmp/mailgun_logs', Rails.root
64
+ else
65
+ # :nocov:
66
+ File.expand_path 'log/mailgun_logs', Rails.root
67
+ # :nocov:
68
+ end
68
69
  end
69
70
  end
70
71
  end
@@ -0,0 +1,39 @@
1
+ # :nocov:
2
+ module PgEngine
3
+ module Utils
4
+ class CheckInvalidRecords
5
+ def run
6
+ invalids = []
7
+ classes.each do |klass|
8
+ klass.find_each do |record|
9
+ invalids << record unless record.valid?
10
+ end
11
+ end
12
+ invalids.map do |r|
13
+ [
14
+ (r.account.to_s if r.respond_to?(:account)),
15
+ r.class.to_s,
16
+ r.id,
17
+ r.errors.full_messages
18
+ ]
19
+ end
20
+ end
21
+
22
+ def classes
23
+ ActiveRecord::Base.descendants - ignored_classes
24
+ end
25
+
26
+ def ignored_classes
27
+ [
28
+ ActiveStorage::Record,
29
+ PgEngine::BaseRecord,
30
+ ActiveAdmin::Comment,
31
+ Audited::Audit,
32
+ ActiveStorage::Blob,
33
+ ApplicationRecord
34
+ ]
35
+ end
36
+ end
37
+ end
38
+ end
39
+ # :nocov: