pg_rails 7.0.8.pre.alpha.82 → 7.0.8.pre.alpha.83

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: f155f16783603b8b6acd943855ce4d4996d92722235ec8eea4fe9cf82dd6efb0
4
- data.tar.gz: 4403492bc1eaeecb807dd9bab487047b89681007100baf5e6758271a8967f163
3
+ metadata.gz: f13f3f371227ad2016ab3996077254555a2d258d2132b6c61e1dbb616cdabf48
4
+ data.tar.gz: 11206668b12f2acfc9f7878ab7049b27476f7984013a5a107a269ab8273aa8bd
5
5
  SHA512:
6
- metadata.gz: 97f5a71981109ce5a8dac87ce5db0184e5c21fc906adc0863ca916e2b8868e5dc013ea46a924e42780b49e9d658faf32a8b5c34bcdf272edd549f848a4ad9918
7
- data.tar.gz: 69dc1acfe7f80c080c4f0263f1904f9ceaff511da31a24e37ba5f77fa6e76fb4888af45313c7c41ab58b3fe3697cdaf46306c28c426bcac91e0badc84ad4aa69
6
+ metadata.gz: b274dd6247c0d49ced832c8ad44c7bfb4c2916876b87921399c88468ee4297c0008ca2fd9a1a806db8477a7d9fada576b8b02faa19c48fe69298bb8a33bd32fe
7
+ data.tar.gz: 6a4dbbff767631ed6f1ee0cf9b1eea4a8e8ef7f61c015b900b3f6d4656481f9b74aecd77704bd65931884665230194bbec53d3710c64c27c8b32cde6d77309fb
@@ -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
@@ -0,0 +1,10 @@
1
+ module Public
2
+ class WebhooksController < PublicController
3
+ def mailgun
4
+ # FIXME: verify signature
5
+ # params['signature']['timestamp']
6
+ PgEngine::Mailgun::LogSync.digest(params['event-data'])
7
+ head :ok
8
+ end
9
+ end
10
+ 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,59 @@ 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
+ )
50
+ rescue StandardError => e
51
+ pg_err e, item
42
52
  end
43
53
 
44
- def self.sync_redis
45
- json = []
46
- Dir["#{dir}/*.json"].each do |file|
47
- json.push(*JSON.parse(File.read(file)))
48
- end
54
+ def self.write_log(items)
55
+ FileUtils.mkdir_p(log_dir)
56
+ File.write("#{log_dir}/#{domain}_#{Time.zone.now.strftime('%Y-%m-%d_%H.%M.%S')}.json", items.to_json)
57
+ end
49
58
 
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
59
+ def self.domain
60
+ ENV.fetch('MAILGUN_DOMAIN')
61
+ end
62
+
63
+ def self.log_dir
64
+ @log_dir ||= if Rails.env.test?
65
+ File.expand_path 'tmp/mailgun_logs', Rails.root
66
+ else
67
+ # :nocov:
68
+ File.expand_path 'log/mailgun_logs', Rails.root
69
+ # :nocov:
70
+ end
68
71
  end
69
72
  end
70
73
  end
@@ -5,7 +5,14 @@ require 'rainbow'
5
5
  # TODO: poder pasar blocks
6
6
 
7
7
  def pg_err(*args)
8
- raise args.first if ENV.fetch('RAISE_ERRORS', false) && args.first.is_a?(Exception)
8
+ if ENV.fetch('RAISE_ERRORS', false)
9
+ # :nocov:
10
+ raise args.first if args.first.is_a?(Exception)
11
+
12
+ raise StandardError, args
13
+
14
+ # :nocov:
15
+ end
9
16
 
10
17
  byebug if ENV.fetch('BYEBUG_ERRORS', false) # rubocop:disable Lint/Debugger
11
18
 
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ # generado con pg_rails
4
+
5
+ require 'rails_helper'
6
+
7
+ # This spec was generated by rspec-rails when you ran the scaffold generator.
8
+ # It demonstrates how one might use RSpec to specify the controller code that
9
+ # was generated by Rails when you ran the scaffold generator.
10
+ #
11
+ # It assumes that the implementation code is generated by the rails scaffold
12
+ # generator. If you are using any extension libraries to generate different
13
+ # controller code, this generated spec may or may not pass.
14
+ #
15
+ # It only uses APIs available in rails and/or rspec-rails. There are a number
16
+ # of tools you can use to make these specs even more expressive, but we're
17
+ # sticking to rails and rspec-rails APIs to keep things simple and stable.
18
+ #
19
+ # Compared to earlier versions of this generator, there is very limited use of
20
+ # stubs and message expectations in this spec. Stubs are only used when there
21
+ # is no simpler way to get a handle on the object needed for the example.
22
+ # Message expectations are only used when there is no simpler way to specify
23
+ # that an instance is receiving a specific message.
24
+ #
25
+ # Also compared to earlier versions of this generator, there are no longer any
26
+ # expectations of assigns and templates rendered. These features have been
27
+ # removed from Rails core in Rails 5, but can be added back in via the
28
+ # `rails-controller-testing` gem.
29
+
30
+ RSpec.describe Admin::EmailLogsController do
31
+ render_views
32
+ # This should return the minimal set of attributes required to create a valid
33
+ # EmailLog. As you add validations to EmailLog, be sure to
34
+ # adjust the attributes here as well.
35
+ let(:valid_attributes) do
36
+ attributes_for(:email_log)
37
+ end
38
+
39
+ let(:logged_user) { create :user, :developer }
40
+
41
+ before do
42
+ sign_in logged_user if logged_user.present?
43
+ end
44
+
45
+ describe '#mailgun_sync' do
46
+ subject do
47
+ post :mailgun_sync
48
+ end
49
+
50
+ before do
51
+ allow(PgEngine::Mailgun::LogSync).to receive(:download).and_return([])
52
+ end
53
+
54
+ it do
55
+ subject
56
+ expect(response).to have_http_status(:redirect)
57
+ end
58
+ end
59
+
60
+ describe 'routing' do
61
+ it 'routes GET index correctly' do
62
+ route = { get: '/a/email_logs' }
63
+ expect(route).to route_to(controller: 'admin/email_logs', action: 'index')
64
+ end
65
+ end
66
+
67
+ describe 'GET #index' do
68
+ subject do
69
+ get :index, params: {}
70
+ end
71
+
72
+ before { create :email_log }
73
+
74
+ it 'returns a success response' do
75
+ subject
76
+ expect(response).to be_successful
77
+ end
78
+
79
+ context 'when user is not logged in' do
80
+ let(:logged_user) { nil }
81
+
82
+ it 'redirects to login path' do
83
+ subject
84
+ expect(response).to redirect_to(new_user_session_path)
85
+ end
86
+ end
87
+
88
+ context 'when se pide el excel' do
89
+ subject do
90
+ get :index, params: {}, format: 'xlsx'
91
+ end
92
+
93
+ it 'returns a success response' do
94
+ subject
95
+ expect(response).to be_successful
96
+ end
97
+ end
98
+ end
99
+
100
+ describe 'GET #show' do
101
+ it 'returns a success response' do
102
+ email_log = create(:email_log)
103
+ get :show, params: { id: email_log.to_param }
104
+ expect(response).to be_successful
105
+ end
106
+ end
107
+
108
+ describe 'GET #new' do
109
+ it 'returns a success response' do
110
+ get :new, params: {}
111
+ expect(response).to be_successful
112
+ end
113
+ end
114
+
115
+ describe 'GET #edit' do
116
+ it 'returns a success response' do
117
+ email_log = create(:email_log)
118
+ get :edit, params: { id: email_log.to_param }
119
+ expect(response).to be_successful
120
+ end
121
+ end
122
+
123
+ describe 'POST #create' do
124
+ context 'with valid params' do
125
+ it 'creates a new EmailLog' do
126
+ expect do
127
+ post :create, params: { email_log: valid_attributes }
128
+ end.to change(EmailLog, :count).by(1)
129
+ end
130
+
131
+ it 'redirects to the created email_log' do
132
+ post :create, params: { email_log: valid_attributes }
133
+ expect(response).to redirect_to([:admin, EmailLog.last])
134
+ end
135
+ end
136
+ end
137
+
138
+ describe 'PUT #update' do
139
+ context 'with valid params' do
140
+ let(:new_attributes) do
141
+ attributes_for(:email_log)
142
+ end
143
+
144
+ it 'redirects to the email_log' do
145
+ email_log = create(:email_log)
146
+ put :update, params: { id: email_log.to_param, email_log: valid_attributes }
147
+ expect(response).to redirect_to([:admin, email_log])
148
+ end
149
+ end
150
+ end
151
+
152
+ describe 'DELETE #destroy' do
153
+ subject do
154
+ request.headers['Accept'] = 'text/vnd.turbo-stream.html,text/html'
155
+ delete :destroy, params: { id: email_log.to_param, redirect_to: redirect_url }
156
+ end
157
+
158
+ let!(:email_log) { create :email_log }
159
+ let(:redirect_url) { nil }
160
+
161
+ it 'destroys the requested email_log' do
162
+ expect { subject }.to change(EmailLog, :count).by(-1)
163
+ end
164
+
165
+ it 'quita el elemento de la lista' do
166
+ subject
167
+ expect(response.body).to include('turbo-stream action="remove"')
168
+ end
169
+
170
+ context 'si hay redirect_to' do
171
+ let(:redirect_url) { admin_email_logs_url }
172
+
173
+ it 'redirects to the email_logs list' do
174
+ subject
175
+ expect(response).to redirect_to(admin_email_logs_url)
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,42 @@
1
+ require 'rails_helper'
2
+
3
+ describe Public::WebhooksController do
4
+ describe '#mailgun' do
5
+ subject do
6
+ post :mailgun, body:, as: :json
7
+ end
8
+
9
+ let(:body) do
10
+ <<~JSON
11
+ {
12
+ "signature": {
13
+ "timestamp": "1529006854",
14
+ "token": "a8ce0edb2dd8301dee6c2405235584e45aa91d1e9f979f3de0",
15
+ "signature": "d2271d12299f6592d9d44cd9d250f0704e4674c30d79d07c47a66f95ce71cf55"
16
+ },
17
+ "event-data": {
18
+ "timestamp": 1715014542.2477064,
19
+ "ip": "66.102.8.333",
20
+ "event": "delivered",
21
+ "id": "log_2",
22
+ "severity":"temporary",
23
+ "log-level": "info",
24
+ "message": {
25
+ "headers": { "message-id": "msgid@fakeapp2024.mail" }
26
+ },
27
+ "recipient": "natprobel@fakemail.com"
28
+ }
29
+ }
30
+ JSON
31
+ end
32
+
33
+ it do
34
+ subject
35
+ expect(response).to have_http_status(:ok)
36
+ end
37
+
38
+ it do
39
+ expect { subject }.to change(EmailLog, :count).by(1)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # generado con pg_rails
4
+
5
+ FactoryBot.define do
6
+ factory :email_log do
7
+ email
8
+ log_id { Faker::Lorem.sentence }
9
+ event { %w[accepted delivered failed opened].sample }
10
+ log_level { %w[info warn error].sample }
11
+ severity { %w[permanent temporary].sample }
12
+ timestamp { '' }
13
+ message_id { Faker::Lorem.sentence }
14
+
15
+ trait :email_existente do
16
+ email { nil }
17
+ email_id { Email.pluck(:id).sample }
18
+ end
19
+ end
20
+ end
@@ -1,25 +1,99 @@
1
1
  require 'rails_helper'
2
2
  require 'fileutils'
3
3
 
4
- describe PgEngine::Mailgun::LogSync do
4
+ describe PgEngine::Mailgun::LogSync, vcr: { cassette_name: 'mailgun/log_sync_download',
5
+ match_requests_on: %i[method host] } do
5
6
  let(:instancia) { described_class }
6
7
 
7
- describe '#download',
8
- vcr: { cassette_name: 'mailgun/log_sync_download',
9
- match_requests_on: %i[method host] } do
8
+ describe '#download' do
10
9
  subject do
11
10
  instancia.download
12
- instancia.sync_redis
13
11
  end
14
12
 
15
13
  after do
16
- Dir["#{instancia.dir}/*.json"].each { |file| File.delete(file) }
14
+ FileUtils.rm_r(instancia.log_dir)
17
15
  end
18
16
 
19
17
  let!(:email) { create :email, message_id: '66393f1bc7d4_47a5108ec1628f@notebook.mail' }
20
18
 
21
19
  it do
22
- expect { subject }.to change { email.logs.to_a.length }.from(0).to(3)
20
+ expect { subject }.to change { email.email_logs.count }.from(0).to(3)
21
+ .and(change(EmailLog, :count).to(8))
22
+ end
23
+ end
24
+
25
+ describe '#digest' do
26
+ subject do
27
+ instancia.digest(JSON.parse(log_data))
28
+ end
29
+
30
+ let(:log_data) do
31
+ <<~JSON
32
+ {
33
+ "timestamp": 1715014542.2477064,
34
+ "ip": "66.102.8.333",
35
+ "event": "delivered",
36
+ "id": "log_2",
37
+ "severity":"temporary",
38
+ "log-level": "info",
39
+ "message": {
40
+ "headers": { "message-id": "msgid@fakeapp2024.mail" }
41
+ },
42
+ "recipient": "natprobel@fakemail.com"
43
+ }
44
+ JSON
45
+ end
46
+
47
+ let(:expected_attributes) do
48
+ {
49
+ log_id: 'log_2',
50
+ event: 'delivered',
51
+ log_level: 'info',
52
+ severity: 'temporary',
53
+ timestamp: 1_715_014_542,
54
+ message_id: 'msgid@fakeapp2024.mail'
55
+ }
56
+ end
57
+
58
+ it do
59
+ expect { subject }.to change(EmailLog, :count).by(1)
60
+ end
61
+
62
+ it do
63
+ expect(subject).to have_attributes(expected_attributes)
64
+ end
65
+
66
+ context 'ya existe el log' do
67
+ subject do
68
+ instancia.digest(JSON.parse(log_data))
69
+ instancia.digest(JSON.parse(log_data))
70
+ end
71
+
72
+ it 'solo lo crea una vez' do
73
+ expect { subject }.to change(EmailLog, :count).by(1)
74
+ end
75
+ end
76
+
77
+ context 'cuando se asocia a un email' do
78
+ let!(:email) { create :email, message_id: 'msgid@fakeapp2024.mail' }
79
+
80
+ it do
81
+ expect(subject.email).to eq email
82
+ end
83
+
84
+ it 'changes email status' do
85
+ expect { subject }.to change { email.reload.status }.to 'delivered'
86
+ end
87
+ end
88
+
89
+ context 'cuando hay errores' do
90
+ subject do
91
+ instancia.digest({})
92
+ end
93
+
94
+ it do
95
+ expect { subject }.not_to change(EmailLog, :count)
96
+ end
23
97
  end
24
98
  end
25
99
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ # generado con pg_rails
4
+
5
+ require 'rails_helper'
6
+
7
+ RSpec.describe EmailLog do
8
+ let(:email_log) { create(:email_log) }
9
+
10
+ it 'se persiste' do
11
+ expect(email_log).to be_persisted
12
+ end
13
+
14
+ describe 'status_for_email' do
15
+ subject do
16
+ email_log.status_for_email
17
+ end
18
+
19
+ let(:email_log) { create(:email_log, event:, severity:) }
20
+ let(:severity) { nil }
21
+
22
+ context 'cuando es accepted' do
23
+ let(:event) { 'accepted' }
24
+
25
+ it { is_expected.to eq 'accepted' }
26
+ end
27
+
28
+ context 'cuando es delivered' do
29
+ let(:event) { 'delivered' }
30
+
31
+ it { is_expected.to eq 'delivered' }
32
+ end
33
+
34
+ context 'cuando hay un fallo temporario' do
35
+ let(:event) { 'failed' }
36
+ let(:severity) { 'temporary' }
37
+
38
+ it { is_expected.to eq 'accepted' }
39
+ end
40
+
41
+ context 'cuando hay un fallo permanente' do
42
+ let(:event) { 'failed' }
43
+ let(:severity) { 'permanent' }
44
+
45
+ it { is_expected.to eq 'rejected' }
46
+ end
47
+ end
48
+ end
@@ -10,4 +10,39 @@ RSpec.describe Email do
10
10
  it 'se persiste' do
11
11
  expect(email).to be_persisted
12
12
  end
13
+
14
+ describe 'update_status!' do
15
+ context 'cuando hay accepted y delivered' do
16
+ subject do
17
+ create :email_log, email: email.reload, event: 'accepted'
18
+ create :email_log, email: email.reload, event: 'delivered'
19
+ end
20
+
21
+ it do
22
+ expect { subject }.to change { email.reload.status }.to 'delivered'
23
+ end
24
+ end
25
+
26
+ context 'cuando hay accepted y fallo temporario' do
27
+ subject do
28
+ create :email_log, email: email.reload, event: 'failed', severity: 'temporary'
29
+ create :email_log, email: email.reload, event: 'accepted'
30
+ end
31
+
32
+ it do
33
+ expect { subject }.to change { email.reload.status }.to 'accepted'
34
+ end
35
+ end
36
+
37
+ context 'cuando hay accepted y fallo permanente' do
38
+ subject do
39
+ create :email_log, email: email.reload, event: 'accepted'
40
+ create :email_log, email: email.reload, event: 'failed', severity: 'permanent'
41
+ end
42
+
43
+ it do
44
+ expect { subject }.to change { email.reload.status }.to 'rejected'
45
+ end
46
+ end
47
+ end
13
48
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgRails
4
- VERSION = '7.0.8-alpha.82'
4
+ VERSION = '7.0.8-alpha.83'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.8.pre.alpha.82
4
+ version: 7.0.8.pre.alpha.83
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martín Rosso
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-22 00:00:00.000000000 Z
11
+ date: 2024-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -944,6 +944,7 @@ files:
944
944
  - pg_engine/app/admin/accounts.rb
945
945
  - pg_engine/app/admin/audits.rb
946
946
  - pg_engine/app/admin/dashboard.rb
947
+ - pg_engine/app/admin/email_logs.rb
947
948
  - pg_engine/app/admin/emails.rb
948
949
  - pg_engine/app/admin/mensaje_contactos.rb
949
950
  - pg_engine/app/admin/user_accounts.rb
@@ -955,6 +956,7 @@ files:
955
956
  - pg_engine/app/assets/stylesheets/active_admin.scss
956
957
  - pg_engine/app/assets/stylesheets/pg_rails_b5.scss
957
958
  - pg_engine/app/controllers/admin/accounts_controller.rb
959
+ - pg_engine/app/controllers/admin/email_logs_controller.rb
958
960
  - pg_engine/app/controllers/admin/emails_controller.rb
959
961
  - pg_engine/app/controllers/admin/user_accounts_controller.rb
960
962
  - pg_engine/app/controllers/admin/users_controller.rb
@@ -963,10 +965,12 @@ files:
963
965
  - pg_engine/app/controllers/pg_engine/devise_controller.rb
964
966
  - pg_engine/app/controllers/pg_engine/require_sign_in.rb
965
967
  - pg_engine/app/controllers/public/mensaje_contactos_controller.rb
968
+ - pg_engine/app/controllers/public/webhooks_controller.rb
966
969
  - pg_engine/app/controllers/users/confirmations_controller.rb
967
970
  - pg_engine/app/controllers/users/registrations_controller.rb
968
971
  - pg_engine/app/decorators/account_decorator.rb
969
972
  - pg_engine/app/decorators/email_decorator.rb
973
+ - pg_engine/app/decorators/email_log_decorator.rb
970
974
  - pg_engine/app/decorators/mensaje_contacto_decorator.rb
971
975
  - pg_engine/app/decorators/pg_engine/base_decorator.rb
972
976
  - pg_engine/app/decorators/pg_engine/base_record_decorator.rb
@@ -989,11 +993,13 @@ files:
989
993
  - pg_engine/app/models/account.rb
990
994
  - pg_engine/app/models/current.rb
991
995
  - pg_engine/app/models/email.rb
996
+ - pg_engine/app/models/email_log.rb
992
997
  - pg_engine/app/models/mensaje_contacto.rb
993
998
  - pg_engine/app/models/pg_engine/base_record.rb
994
999
  - pg_engine/app/models/user.rb
995
1000
  - pg_engine/app/models/user_account.rb
996
1001
  - pg_engine/app/policies/account_policy.rb
1002
+ - pg_engine/app/policies/email_log_policy.rb
997
1003
  - pg_engine/app/policies/email_policy.rb
998
1004
  - pg_engine/app/policies/mensaje_contacto_policy.rb
999
1005
  - pg_engine/app/policies/pg_engine/application_policy.rb
@@ -1005,6 +1011,9 @@ files:
1005
1011
  - pg_engine/app/views/admin/accounts/edit.html.slim
1006
1012
  - pg_engine/app/views/admin/accounts/new.html.slim
1007
1013
  - pg_engine/app/views/admin/accounts/show.html.slim
1014
+ - pg_engine/app/views/admin/email_logs/_email_log.html.slim
1015
+ - pg_engine/app/views/admin/email_logs/_form.html.slim
1016
+ - pg_engine/app/views/admin/email_logs/show.html.slim
1008
1017
  - pg_engine/app/views/admin/emails/_form.html.slim
1009
1018
  - pg_engine/app/views/admin/emails/show.html.slim
1010
1019
  - pg_engine/app/views/admin/user_accounts/_form.html.slim
@@ -1047,6 +1056,7 @@ files:
1047
1056
  - pg_engine/db/migrate/20240428152916_create_mensaje_contactos.rb
1048
1057
  - pg_engine/db/migrate/20240506194106_create_emails.rb
1049
1058
  - pg_engine/db/migrate/20240517174821_pg_trgm.rb
1059
+ - pg_engine/db/migrate/20240523183651_create_email_logs.rb
1050
1060
  - pg_engine/db/seeds.rb
1051
1061
  - pg_engine/lib/pg_engine.rb
1052
1062
  - pg_engine/lib/pg_engine/configuracion.rb
@@ -1060,6 +1070,7 @@ files:
1060
1070
  - pg_engine/lib/pg_engine/utils/pg_logger.rb
1061
1071
  - pg_engine/lib/tasks/auto_anotar_modelos.rake
1062
1072
  - pg_engine/spec/controllers/admin/accounts_controller_spec.rb
1073
+ - pg_engine/spec/controllers/admin/email_logs_controller_spec.rb
1063
1074
  - pg_engine/spec/controllers/admin/emails_controller_spec.rb
1064
1075
  - pg_engine/spec/controllers/admin/user_accounts_controller_spec.rb
1065
1076
  - pg_engine/spec/controllers/admin/users_controller_spec.rb
@@ -1067,9 +1078,11 @@ files:
1067
1078
  - pg_engine/spec/controllers/devise/sessions_controller_spec.rb
1068
1079
  - pg_engine/spec/controllers/pg_engine/base_controller_spec.rb
1069
1080
  - pg_engine/spec/controllers/public/mensaje_contactos_controller_spec.rb
1081
+ - pg_engine/spec/controllers/public/webhooks_controller_spec.rb
1070
1082
  - pg_engine/spec/controllers/users/confirmations_controller_spec.rb
1071
1083
  - pg_engine/spec/controllers/users/registrations_controller_spec.rb
1072
1084
  - pg_engine/spec/factories/accounts.rb
1085
+ - pg_engine/spec/factories/email_logs.rb
1073
1086
  - pg_engine/spec/factories/emails.rb
1074
1087
  - pg_engine/spec/factories/mensaje_contactos.rb
1075
1088
  - pg_engine/spec/factories/user_accounts.rb
@@ -1086,6 +1099,7 @@ files:
1086
1099
  - pg_engine/spec/lib/pg_form_builder_spec.rb
1087
1100
  - pg_engine/spec/mailers/previews/devise_preview.rb
1088
1101
  - pg_engine/spec/models/account_spec.rb
1102
+ - pg_engine/spec/models/email_log_spec.rb
1089
1103
  - pg_engine/spec/models/email_spec.rb
1090
1104
  - pg_engine/spec/models/mensaje_contacto_spec.rb
1091
1105
  - pg_engine/spec/models/pg_engine/base_record_spec.rb