pg_rails 7.5.1 → 7.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/pg_associable/app/helpers/pg_associable/helpers.rb +19 -2
  3. data/pg_associable/app/javascript/asociable_controller.tsx +1 -1
  4. data/pg_associable/app/javascript/modal_controller.js +8 -3
  5. data/pg_associable/spec/pg_associable/helpers_spec.rb +40 -2
  6. data/pg_engine/app/controllers/admin/user_accounts_controller.rb +5 -1
  7. data/pg_engine/app/controllers/admin/users_controller.rb +0 -17
  8. data/pg_engine/app/controllers/concerns/pg_engine/resource.rb +1 -3
  9. data/pg_engine/app/controllers/pg_engine/base_admin_controller.rb +19 -0
  10. data/pg_engine/app/controllers/pg_engine/base_controller.rb +4 -4
  11. data/pg_engine/app/controllers/pg_engine/base_public_controller.rb +17 -0
  12. data/pg_engine/app/controllers/pg_engine/base_users_controller.rb +17 -0
  13. data/pg_engine/app/controllers/users/account_switcher_controller.rb +3 -0
  14. data/pg_engine/app/controllers/users/accounts_controller.rb +35 -0
  15. data/pg_engine/app/helpers/pg_engine/flash_helper.rb +1 -2
  16. data/pg_engine/app/models/account.rb +5 -0
  17. data/pg_engine/app/models/current.rb +2 -0
  18. data/pg_engine/app/models/email.rb +4 -1
  19. data/pg_engine/app/models/email_log.rb +2 -1
  20. data/pg_engine/app/models/pg_engine/base_record.rb +3 -1
  21. data/pg_engine/app/models/user.rb +16 -4
  22. data/pg_engine/app/models/user_account.rb +2 -2
  23. data/pg_engine/app/overrides/audited_audit.rb +15 -0
  24. data/pg_engine/app/policies/account_policy.rb +4 -0
  25. data/pg_engine/app/views/admin/user_accounts/_form.html.slim +2 -2
  26. data/pg_engine/app/views/admin/users/show.html.slim +1 -1
  27. data/pg_engine/app/views/users/account_switcher/list.html.slim +18 -4
  28. data/pg_engine/app/views/users/accounts/show.html.slim +13 -0
  29. data/pg_engine/config/routes.rb +9 -1
  30. data/pg_engine/db/seeds.rb +13 -11
  31. data/pg_engine/lib/pg_engine/configuracion.rb +0 -2
  32. data/pg_engine/spec/controllers/admin/email_logs_controller_spec.rb +3 -1
  33. data/pg_engine/spec/models/user_spec.rb +7 -0
  34. data/pg_engine/spec/overrides/audited_audit_spec.rb +16 -0
  35. data/pg_engine/spec/requests/users/accounts_spec.rb +22 -0
  36. data/pg_engine/spec/requests/users/switcher_spec.rb +9 -1
  37. data/pg_engine/spec/system/breadcrumbs_spec.rb +0 -1
  38. data/pg_engine/spec/system/date_selector_spec.rb +0 -1
  39. data/pg_engine/spec/system/login_spec.rb +1 -1
  40. data/pg_engine/spec/system/modal_windows_spec.rb +0 -1
  41. data/pg_engine/spec/system/tenants_spec.rb +2 -1
  42. data/pg_layout/app/javascript/controllers/popover_toggler_controller.js +5 -1
  43. data/pg_layout/app/javascript/controllers/tooltip_controller.js +5 -1
  44. data/pg_layout/app/views/devise/sessions/new.html.erb +1 -1
  45. data/pg_layout/app/views/pg_layout/_sidebar.html.erb +13 -7
  46. data/pg_rails/lib/version.rb +1 -1
  47. data/pg_scaffold/lib/generators/pg_rspec/scaffold/templates/controller_spec.rb +1 -0
  48. data/pg_scaffold/spec/generators_spec.rb +4 -4
  49. metadata +10 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 99e5df3ed137be9ec63699ccfd381f75f63cf1a7a272c36e49177147be1ad958
4
- data.tar.gz: f95e10f28d40ab3c513e0a9e680baf268fe500f3a740cbde18fe3754b4f6941e
3
+ metadata.gz: b312261e863e04fcc457b8b773531325d1c69f9b4ef0ca1269b39853f737844a
4
+ data.tar.gz: 641bbe1b7b128e67ec7ffb874765dfeae35aac6dadf917fcbe4367b3c98939cb
5
5
  SHA512:
6
- metadata.gz: 69842b1daf20fce9bfb7a62196d44a83e5b16d6f18198fdf7afcaa229e7ce86f51383106e8d4158259af3eebc9190bc26724cd39cb00afb837902c34e45fe7ae
7
- data.tar.gz: d27a734ecdd58f0d552b76a2fbc4225341572b24ba467b398be5e93f489eac4d60a116333a828b3382be9791f830aea715e506f4fda01a923f6d5c00ee41a16f
6
+ metadata.gz: 66f4093830e6a889cf66cfc39e6b0bfb015e93ad8e48c0e33a2c3292363f7511dbc1062b7b9993d0e0e2277ae49986c9eb0390572d63a2100a6057fb6b20e213
7
+ data.tar.gz: dc1b35305080b8bd01dbafeea7453bcf8f7bd85fe4609ee7657f18985402b86f755c170b39ce28b55e5c3939a2f5659f57e9ba3ee8336877ef8c18712fcf01be
@@ -3,7 +3,7 @@ module PgAssociable
3
3
  MAX_RESULTS = 8
4
4
 
5
5
  def pg_respond_abrir_modal
6
- src = @clase_modelo.new.decorate.new_object_url
6
+ src = clase_modelo.new.decorate.new_object_url
7
7
  content = ModalContentComponent.new(src:).render_in(view_context)
8
8
  modal = AsociableModalComponent.new(modal_id: params[:id]).with_content(content)
9
9
  render turbo_stream: turbo_stream.append_all('body', modal)
@@ -14,10 +14,27 @@ module PgAssociable
14
14
  resultados_prefix = 'resultados-inline'
15
15
  query = params[:query]
16
16
  timeout_id = params[:timeout_id]
17
- @collection = policy_scope(@clase_modelo).kept.query(query).limit(MAX_RESULTS)
17
+ @collection = search_in_scope(query)
18
18
  render turbo_stream:
19
19
  turbo_stream.update("#{resultados_prefix}-#{params[:id]}",
20
20
  partial:, locals: { collection: @collection, query:, timeout_id: })
21
21
  end
22
+
23
+ def search_in_scope(query)
24
+ scope = policy_scope(clase_modelo).kept
25
+
26
+ if clase_modelo.ransackable_attributes.include?('search')
27
+ scope.ransack(search_cont: query).result
28
+ else
29
+ Rails.logger.warn("WARNING: #{clase_modelo} should implement a 'search' ransacker")
30
+
31
+ if scope.respond_to?(:query)
32
+ Rails.logger.warn("DEPRECATED WARNING: #{clase_modelo}#query is deprecated in favor of 'search' ransacker")
33
+ scope.query(query)
34
+ else
35
+ scope.where(id: query)
36
+ end
37
+ end
38
+ end
22
39
  end
23
40
  end
@@ -66,7 +66,7 @@ export default class extends Controller {
66
66
  }
67
67
  const doSearchBounce = debounce((force) => {
68
68
  this.doSearch(force)
69
- }, 900)
69
+ }, 200)
70
70
 
71
71
  this.input.addEventListener('blur', () => {
72
72
  this.input.placeholder = this.originalPlaceholder
@@ -105,9 +105,14 @@ export default class extends Controller {
105
105
  // this.modalPuntero.hide()
106
106
  // pero tiraba a veces error:
107
107
  // TypeError: can't convert null to object, _isWithActiveTrigger
108
- document.querySelectorAll('.modal-backdrop').forEach((el) => {
109
- el.remove()
110
- })
108
+ // document.querySelectorAll('.modal-backdrop').forEach((el) => {
109
+ // el.remove()
110
+ // })
111
+ // UPDATE: 11-09-2024, vuelvo a poner el hide, porque en parece que
112
+ // el problema de _isWithActiveTrigger viene por el lado de los
113
+ // tooltips:
114
+ // https://github.com/twbs/bootstrap/issues/37474
115
+ this.modalPuntero.hide()
111
116
  document.dispatchEvent(new Event('hidden.bs.modal'))
112
117
  this.modalPuntero.dispose()
113
118
  }
@@ -1,7 +1,27 @@
1
1
  require 'rails_helper'
2
2
 
3
3
  describe PgAssociable::Helpers do
4
- describe '#pg_respond_buscar' do
4
+ # DEPRECATED
5
+ describe '#pg_respond_buscar with query scope' do
6
+ let(:ctrl) do
7
+ Admin::CategoriaDeCosasController.new
8
+ end
9
+ let!(:categoria_de_cosa) { create :categoria_de_cosa }
10
+
11
+ before do
12
+ Current.user = create :user, :developer
13
+ allow(ctrl).to receive_messages(params: { id: 123, query: categoria_de_cosa.nombre })
14
+ allow(ctrl).to receive(:render)
15
+ end
16
+
17
+ it do
18
+ ctrl.pg_respond_buscar
19
+ categoria_de_cosas = ctrl.instance_variable_get(:@collection)
20
+ expect(categoria_de_cosas).to eq [categoria_de_cosa]
21
+ end
22
+ end
23
+
24
+ describe '#pg_respond_buscar with id' do
5
25
  let(:ctrl) do
6
26
  Admin::CosasController.new
7
27
  end
@@ -11,7 +31,6 @@ describe PgAssociable::Helpers do
11
31
  Current.user = create :user, :developer
12
32
  allow(ctrl).to receive_messages(params: { id: 123, query: cosa.id })
13
33
  allow(ctrl).to receive(:render)
14
- ctrl.instance_variable_set(:@clase_modelo, Cosa)
15
34
  end
16
35
 
17
36
  it do
@@ -20,4 +39,23 @@ describe PgAssociable::Helpers do
20
39
  expect(cosas).to eq [cosa]
21
40
  end
22
41
  end
42
+
43
+ describe '#pg_respond_buscar with ransack' do
44
+ let(:ctrl) do
45
+ Admin::AccountsController.new
46
+ end
47
+ let!(:account) { create :account }
48
+
49
+ before do
50
+ Current.user = create :user, :developer
51
+ allow(ctrl).to receive_messages(params: { id: 123, query: account.nombre })
52
+ allow(ctrl).to receive(:render)
53
+ end
54
+
55
+ it do
56
+ ctrl.pg_respond_buscar
57
+ accounts = ctrl.instance_variable_get(:@collection)
58
+ expect(accounts).to eq [account]
59
+ end
60
+ end
23
61
  end
@@ -15,7 +15,11 @@ module Admin
15
15
  private
16
16
 
17
17
  def atributos_permitidos
18
- %i[user_id account_id profiles]
18
+ [
19
+ :user_id,
20
+ :account_id,
21
+ { profiles: [] }
22
+ ]
19
23
  end
20
24
 
21
25
  def atributos_para_buscar
@@ -28,23 +28,6 @@ module Admin
28
28
  pg_respond_update
29
29
  end
30
30
 
31
- # TODO: sacar este método a otro lado, que no sea AdminController
32
- skip_before_action :authenticate_user!, only: [:login_as]
33
-
34
- # :nocov:
35
- def login_as
36
- return unless dev_user_or_env?
37
-
38
- usuario = User.find(params[:id])
39
- if usuario.confirmed_at.present?
40
- sign_in(:user, usuario)
41
- redirect_to after_sign_in_path_for(usuario)
42
- else
43
- go_back('No está confirmado')
44
- end
45
- end
46
- # :nocov:
47
-
48
31
  private
49
32
 
50
33
  def atributos_permitidos
@@ -418,9 +418,7 @@ module PgEngine
418
418
  instancia_modelo.assign_attributes(modelo_params) if action_name.in? %w[update]
419
419
  end
420
420
 
421
- # FIXME: estaría bueno delegar directamente a pundit, pero habría que
422
- # arreglar tema policies
423
- Current.user&.developer? || authorize(instancia_modelo)
421
+ authorize(instancia_modelo)
424
422
 
425
423
  # TODO: problema en create y update cuando falla la validacion
426
424
  # Reproducir el error antes de arreglarlo
@@ -0,0 +1,19 @@
1
+ module PgEngine
2
+ class BaseAdminController < ApplicationController
3
+ include PgEngine::RequireSignIn
4
+
5
+ before_action do
6
+ raise Pundit::NotAuthorizedError unless Current.user&.developer?
7
+
8
+ Current.namespace = :admin
9
+
10
+ add_breadcrumb 'Admin'
11
+ end
12
+
13
+ around_action :set_without_tenant
14
+
15
+ def set_without_tenant(&)
16
+ ActsAsTenant.without_tenant(&)
17
+ end
18
+ end
19
+ end
@@ -25,15 +25,15 @@ module PgEngine
25
25
  throw :warden, scope: :user, message: :invalid
26
26
  end
27
27
 
28
+ @current_tenant_set_by_domain_or_subdomain = true
28
29
  else
29
- account = if session['current_user_account'].present?
30
- UserAccount.where(id: session['current_user_account']).first&.account
31
- elsif Current.user.user_accounts.count == 1
30
+ account = if Current.user.user_accounts.count == 1
32
31
  Current.user.user_accounts.first.account
32
+ elsif session['current_user_account'].present?
33
+ UserAccount.where(id: session['current_user_account']).first&.account
33
34
  end
34
35
  set_current_tenant(account)
35
36
  end
36
- Current.account = ActsAsTenant.current_tenant
37
37
  end
38
38
  end
39
39
  # rubocop:enable Rails/ApplicationController
@@ -0,0 +1,17 @@
1
+ module PgEngine
2
+ class BasePublicController < ApplicationController
3
+ # :nocov:
4
+ def login_as
5
+ return head :bad_request unless dev_user_or_env?
6
+
7
+ usuario = User.find(params[:id])
8
+ if usuario.confirmed_at.present?
9
+ sign_in(:user, usuario)
10
+ redirect_to after_sign_in_path_for(usuario)
11
+ else
12
+ go_back('No está confirmado')
13
+ end
14
+ end
15
+ # :nocov:
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module PgEngine
2
+ class BaseUsersController < ApplicationController
3
+ include PgEngine::RequireSignIn
4
+ include PgEngine::RequireTenantSet
5
+
6
+ before_action do
7
+ # FIXME: requisito que esto esté seteado
8
+ Current.namespace = :users
9
+
10
+ add_breadcrumb 'Inicio', :users_root_path unless using_modal2? || frame_embedded?
11
+ end
12
+
13
+ def home
14
+ render html: '<h1>Inicio</h1>'.html_safe, layout: 'pg_layout/centered'
15
+ end
16
+ end
17
+ end
@@ -1,11 +1,14 @@
1
1
  module Users
2
2
  class AccountSwitcherController < PgEngine.config.users_controller
3
3
  rescue_from ActsAsTenant::Errors::NoTenantSet, with: :internal_error
4
+ skip_before_action :require_tenant_set
4
5
 
5
6
  before_action do
6
7
  @no_main_frame = true
7
8
  end
8
9
 
10
+ layout 'pg_layout/centered'
11
+
9
12
  def list
10
13
  @user_accounts = Current.user.user_accounts
11
14
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # generado con pg_rails
4
+
5
+ module Users
6
+ class AccountsController < UsersController
7
+ include PgEngine::Resource
8
+
9
+ self.clase_modelo = Account
10
+ add_breadcrumb 'Cuentas'
11
+ self.skip_default_breadcrumb = true
12
+
13
+ before_action(only: :index) { authorize Account }
14
+
15
+ before_action :set_instancia_modelo, only: %i[new create show edit update destroy]
16
+
17
+ # private
18
+
19
+ # def atributos_permitidos
20
+ # %i[plan nombre domain subdomain]
21
+ # end
22
+
23
+ # def atributos_para_buscar
24
+ # atributos_permitidos
25
+ # end
26
+
27
+ # def atributos_para_listar
28
+ # atributos_permitidos
29
+ # end
30
+
31
+ # def atributos_para_mostrar
32
+ # atributos_permitidos
33
+ # end
34
+ end
35
+ end
@@ -9,9 +9,8 @@ module PgEngine
9
9
  end
10
10
 
11
11
  def render_turbo_stream_title
12
- title = [breadcrumbs.last&.name, I18n.t('app_name')].compact.join(' - ')
12
+ title = [breadcrumbs.last&.name, ActsAsTenant.current_tenant, I18n.t('app_name')].compact.join(' - ')
13
13
  turbo_stream.update_all 'title', title
14
- # rubocop:enable Rails/SkipsModelValidations
15
14
  end
16
15
  end
17
16
  end
@@ -22,6 +22,7 @@
22
22
  class Account < ApplicationRecord
23
23
  audited
24
24
  include Discard::Model
25
+ include Hashid::Rails
25
26
 
26
27
  has_many :user_accounts
27
28
  has_many :users, through: :user_accounts
@@ -33,6 +34,10 @@ class Account < ApplicationRecord
33
34
 
34
35
  validates :plan, :nombre, presence: true
35
36
 
37
+ ransacker :search do |parent|
38
+ parent.table[:nombre]
39
+ end
40
+
36
41
  def to_s
37
42
  nombre
38
43
  end
@@ -9,4 +9,6 @@ class Current < ActiveSupport::CurrentAttributes
9
9
  #
10
10
  # Time.zone = user.time_zone
11
11
  # end
12
+
13
+ deprecate :account, deprecator: PgEngine.deprecator
12
14
  end
@@ -46,7 +46,10 @@ class Email < ApplicationRecord
46
46
 
47
47
  has_one_attached :encoded_eml
48
48
 
49
- belongs_to :associated, polymorphic: true, optional: true
49
+ acts_as_tenant :account, optional: true
50
+
51
+ tenantable_belongs_to :associated, polymorphic: true, optional: true,
52
+ assign_tenant_from_associated: true
50
53
 
51
54
  belongs_to :creado_por, optional: true, class_name: 'User'
52
55
  belongs_to :actualizado_por, optional: true, class_name: 'User'
@@ -23,7 +23,8 @@
23
23
  class EmailLog < ApplicationRecord
24
24
  audited
25
25
 
26
- belongs_to :email, optional: true
26
+ acts_as_tenant :account, optional: true
27
+ tenantable_belongs_to :email, optional: true, assign_tenant_from_associated: true
27
28
 
28
29
  after_create_commit do
29
30
  email.update_status! if email.present?
@@ -19,7 +19,9 @@ module PgEngine
19
19
  attr_accessor :default_modal
20
20
  end
21
21
 
22
- scope :query, ->(param) { param.present? ? where(id: param) : all }
22
+ # ransacker :search do |parent|
23
+ # parent.table[:nombre]
24
+ # end
23
25
 
24
26
  def self.ransackable_associations(_auth_object = nil)
25
27
  authorizable_ransackable_associations
@@ -76,16 +76,16 @@ class User < ApplicationRecord
76
76
  end
77
77
 
78
78
  def create_account
79
- # rubocop:disable Rails/Presence
80
79
  account =
81
80
  if ActsAsTenant.current_tenant.present?
82
- # FIXME!: raise PgEngine::Error unless invited
81
+ # :nocov:
82
+ raise PgEngine::Error, 'user not invited' unless Rails.env.test?
83
+ # :nocov:
84
+
83
85
  ActsAsTenant.current_tenant
84
86
  else
85
87
  Account.create(nombre: email, plan: 0)
86
88
  end
87
- # rubocop:enable Rails/Presence
88
-
89
89
  ua = user_accounts.create(account:)
90
90
 
91
91
  raise(Error, 'no se pudo crear la cuenta') unless ua.persisted?
@@ -99,8 +99,20 @@ class User < ApplicationRecord
99
99
  # true
100
100
  # end
101
101
 
102
+ # DEPRECATED
102
103
  scope :query, ->(param) { where('email ILIKE ?', "%#{param}%") }
103
104
 
105
+ ransacker :search do |parent|
106
+ Arel::Nodes::InfixOperation.new(
107
+ '||',
108
+ Arel::Nodes::InfixOperation.new(
109
+ '||',
110
+ parent.table[:nombre], parent.table[:apellido]
111
+ ),
112
+ parent.table[:email]
113
+ )
114
+ end
115
+
104
116
  def to_s
105
117
  nombre_completo
106
118
  end
@@ -21,6 +21,7 @@
21
21
  # fk_rails_... (user_id => users.id)
22
22
  #
23
23
 
24
+ # FIXME: add column active?
24
25
  class UserAccount < ApplicationRecord
25
26
  audited
26
27
  include Hashid::Rails
@@ -33,7 +34,6 @@ class UserAccount < ApplicationRecord
33
34
 
34
35
  enumerize :profiles, in: {
35
36
  admin: 1,
36
- dueño: 2,
37
- invitado: 3
37
+ editor: 2
38
38
  }, multiple: true
39
39
  end
@@ -0,0 +1,15 @@
1
+ Audited::Audit.class_eval do
2
+ before_validation do
3
+ if account_id.nil?
4
+ if auditable.respond_to?(:account_id)
5
+ self.account_id = auditable.account_id
6
+ elsif auditable_type == 'Account'
7
+ self.account_id = auditable.id
8
+ elsif ActsAsTenant.current_tenant.present?
9
+ self.account = ActsAsTenant.current_tenant
10
+ end
11
+ end
12
+ end
13
+
14
+ belongs_to :account, optional: true
15
+ end
@@ -28,4 +28,8 @@ class AccountPolicy < ApplicationPolicy
28
28
  # def acceso_total?
29
29
  # user.developer?
30
30
  # end
31
+ def base_access_to_record?
32
+ ActsAsTenant.unscoped? ||
33
+ record.user_accounts.pluck(:user_id).include?(user.id)
34
+ end
31
35
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  div style="max-width: 22em"
4
4
  = pg_form_for(@user_account || object) do |f|
5
- = f.pg_associable :user
6
- = f.pg_associable :account
5
+ = f.pg_associable :user, preload: 10
6
+ = f.pg_associable :account, preload: 5
7
7
  = f.input :profiles
8
8
  .mt-2
9
9
  = f.button :submit
@@ -5,7 +5,7 @@
5
5
  .ms-1
6
6
  = @user.edit_link
7
7
  .ms-1
8
- = link_to admin_login_as_path(id: @user.id), class: 'btn btn-light btn-sm' do
8
+ = link_to login_as_path(id: @user.id), class: 'btn btn-light btn-sm' do
9
9
  span.bi.bi-arrow-right
10
10
  | Login as
11
11
 
@@ -1,6 +1,20 @@
1
- h1 Switcher
1
+ h1 Cambiar a otra cuenta
2
2
 
3
- ul
3
+ - if @current_tenant_set_by_domain_or_subdomain
4
+ p Estás en el dominio de #{ActsAsTenant.current_tenant} (#{request.host})
5
+ p
6
+ | Para cambiar de cuenta vas a tener que iniciar sesión en el dominio
7
+ |< de Bien o de la cuenta específica a la que quieras cambiar
8
+
9
+ ul.m-auto.list-group style="max-width: 20em"
4
10
  - @user_accounts.each do |user_account|
5
- li = link_to user_account.account, users_account_switch_path(user_account),
6
- 'data-turbo-method': :post
11
+ li.list-group-item
12
+ - if @current_tenant_set_by_domain_or_subdomain
13
+ = user_account.account
14
+ - elsif user_account.account == ActsAsTenant.current_tenant
15
+ b
16
+ = user_account.account
17
+ | (Actual)
18
+ - else
19
+ = link_to user_account.account, users_account_switch_path(user_account),
20
+ 'data-turbo-method': :post
@@ -0,0 +1,13 @@
1
+ h1
2
+ |> Usuarios de la cuenta:
3
+ = @account
4
+
5
+ div style="max-width: 30em"
6
+ table.table.table-sm
7
+ tr
8
+ th Nombre
9
+ th Roles
10
+ - @account.user_accounts.each do |user_account|
11
+ tr
12
+ td = user_account.user
13
+ td = user_account.profiles.texts.join(', ')
@@ -13,6 +13,9 @@ Rails.application.routes.draw do
13
13
  pg_resource(:mensaje_contactos, only: [:new, :create], path: 'contacto')
14
14
  post 'webhook/mailgun', to: 'webhooks#mailgun'
15
15
  end
16
+
17
+ get 'login_as', to: 'public#login_as'
18
+
16
19
  devise_for :users, controllers: {
17
20
  confirmations: 'users/confirmations',
18
21
  registrations: 'users/registrations'
@@ -25,7 +28,13 @@ Rails.application.routes.draw do
25
28
  get '', action: 'list', as: 'account_switcher'
26
29
  post ':user_account_id', action: 'switch', as: 'account_switch'
27
30
  end
31
+
32
+ pg_resource(:accounts, path: 'cuentas', only: [:show])
33
+ # get 'account', to: 'accounts#show'
28
34
  end
35
+
36
+ get '/u', to: 'users#home', as: :users_root
37
+
29
38
  namespace :admin, path: 'a' do
30
39
  pg_resource(:emails)
31
40
  pg_resource(:eventos)
@@ -37,7 +46,6 @@ Rails.application.routes.draw do
37
46
  pg_resource(:users)
38
47
  pg_resource(:accounts)
39
48
  pg_resource(:user_accounts)
40
- get 'login_as', to: 'users#login_as'
41
49
  end
42
50
  if defined? ActiveAdmin
43
51
  ActiveAdmin.routes(self)
@@ -1,15 +1,17 @@
1
- ActsAsTenant.without_tenant do
2
- DatabaseCleaner.clean_with(:truncation, except: %w(ar_internal_metadata))
1
+ DatabaseCleaner.clean_with(:truncation, except: %w(ar_internal_metadata))
3
2
 
4
3
 
5
- bien = FactoryBot.create :account, nombre: 'Bien', subdomain: 'bien'
6
- uno = FactoryBot.create :user, email: 'mrosso10@gmail.com', nombre: 'Martín', apellido: 'Rosso', password: 'admin123',
7
- confirmed_at: Time.now, developer: true, orphan: true
8
- bien.users << uno
4
+ bien = FactoryBot.create(:account, nombre: 'Bien', subdomain: 'bien')
5
+ rosso = FactoryBot.create(:user, email: 'mrosso10@gmail.com', nombre: 'Martín', apellido: 'Rosso', password: 'admin123',
6
+ confirmed_at: Time.now, developer: true, orphan: true)
9
7
 
10
- mal = FactoryBot.create :account, nombre: 'Mal', subdomain: 'mal'
11
- otro = FactoryBot.create :user, email: 'mal@gmail.com', nombre: 'Mal', apellido: 'Mal', password: 'admin123',
12
- confirmed_at: Time.now, developer: true, orphan: true
8
+ bien.user_accounts.create(user: rosso, profiles: [:admin])
13
9
 
14
- mal.users << otro
15
- end
10
+ racionalismo = FactoryBot.create(:account, nombre: 'Racionalismo', subdomain: 'racionalismo')
11
+ baruch = FactoryBot.create(:user, email: 'baruch@bien.com', nombre: 'Baruch', apellido: 'Spinoza', password: 'admin123',
12
+ confirmed_at: Time.now, orphan: true)
13
+ rené = FactoryBot.create(:user, email: 'rene@bien.com', nombre: 'René', apellido: 'Descartes', password: 'admin123',
14
+ confirmed_at: Time.now, orphan: true)
15
+
16
+ racionalismo.user_accounts.create(user: baruch, profiles: [:admin])
17
+ racionalismo.user_accounts.create(user: rené, profiles: [:editor])
@@ -9,8 +9,6 @@ module PgEngine
9
9
  def initialize
10
10
  if defined? UsersController
11
11
  @users_controller = UsersController
12
- elsif defined? FrontendController
13
- @users_controller = FrontendController
14
12
  end
15
13
 
16
14
  @global_domains = ['app.localhost.com', 'test.host', 'localhost']
@@ -33,9 +33,11 @@ RSpec.describe Admin::EmailLogsController do
33
33
  # EmailLog. As you add validations to EmailLog, be sure to
34
34
  # adjust the attributes here as well.
35
35
  let(:valid_attributes) do
36
- attributes_for(:email_log)
36
+ attributes_for(:email_log).merge(email_id: email.id)
37
37
  end
38
38
 
39
+ let(:email) { create :email }
40
+
39
41
  let(:logged_user) { create :user, :developer }
40
42
 
41
43
  before do
@@ -56,4 +56,11 @@ RSpec.describe User do
56
56
  expect(user).not_to be_persisted
57
57
  end
58
58
  end
59
+
60
+ describe 'search ransacker' do
61
+ it 'searchs' do
62
+ results = described_class.ransack(search_cont: user.nombre).result.to_a
63
+ expect(results).to eq [user]
64
+ end
65
+ end
59
66
  end
@@ -0,0 +1,16 @@
1
+ require 'rails_helper'
2
+
3
+ describe 'Audited::Audit' do
4
+ subject do
5
+ create :categoria_de_cosa
6
+ end
7
+
8
+ it 'creates the audits' do
9
+ expect { subject }.to change(Audited::Audit, :count).by(1)
10
+ end
11
+
12
+ it 'assigns the tenant to audits' do
13
+ subject
14
+ expect(Audited::Audit.last.account).to eq ActsAsTenant.current_tenant
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ require 'rails_helper'
2
+
3
+ describe 'Users::AccountsController' do
4
+ let(:account) { ActsAsTenant.current_tenant }
5
+ let(:user) { create :user }
6
+
7
+ before do
8
+ sign_in user
9
+ end
10
+
11
+ it 'shows the owned account' do
12
+ get "/u/cuentas/#{account.to_param}"
13
+ expect(response).to have_http_status(:ok)
14
+ end
15
+
16
+ it 'denies foreign account' do
17
+ other_account = create :account
18
+ get "/u/cuentas/#{other_account.to_param}"
19
+ expect(response).to have_http_status(:redirect)
20
+ expect(flash[:alert]).to eq 'Acceso no autorizado'
21
+ end
22
+ end
@@ -30,15 +30,23 @@ describe 'redirection' do
30
30
  let!(:other_account) { create :account }
31
31
  let!(:other_user_account) { logged_user.user_accounts.create(account: other_account) }
32
32
 
33
+ before do
34
+ third_account = create :account
35
+ logged_user.user_accounts.create(account: third_account)
36
+ end
37
+
33
38
  it 'redirects to switcher' do
34
39
  get '/u/cosas'
35
40
  expect(response).to redirect_to users_account_switcher_path
36
41
  follow_redirect!
37
- expect(response.body).to include 'Switcher'
42
+ expect(response.body).to include 'Cambiar a otra cuenta'
38
43
  post "/u/switcher/#{other_user_account.to_param}"
39
44
  expect(response).to redirect_to(root_path)
40
45
  follow_redirect!
46
+ get '/u/cosas'
47
+ expect(response).to have_http_status(:ok)
41
48
  expect(response.body).to include other_account.to_s
49
+ expect(response.body).to include 'No hay cosos que mostrar'
42
50
  other_user_account.destroy!
43
51
  get '/'
44
52
  expect(response).to redirect_to users_account_switcher_path
@@ -15,7 +15,6 @@ describe 'Breadcrumbs' do
15
15
  let(:path) { "/a/cosas/#{cosa.id}" }
16
16
  let(:cosa) { create :cosa }
17
17
  let(:logged_user) { create :user, :developer }
18
- let(:account) { logged_user.current_account }
19
18
 
20
19
  before do
21
20
  login_as logged_user
@@ -13,7 +13,6 @@ describe 'Date selector' do
13
13
  end
14
14
 
15
15
  let(:logged_user) { create :user, :developer }
16
- let(:account) { logged_user.current_account }
17
16
  let(:categoria_de_cosa) { create :categoria_de_cosa, fecha: }
18
17
  let(:fecha) { Date.new(2024, 8, 12) }
19
18
 
@@ -5,7 +5,7 @@ require 'rails_helper'
5
5
  describe 'Sign in' do
6
6
  shared_examples 'sign_in' do
7
7
  subject do
8
- visit '/users/sign_in'
8
+ visit '/u/categoria_de_cosas'
9
9
  fill_in 'user_email', with: user.email
10
10
  fill_in 'user_password', with: password
11
11
  find('input[type=submit]').click
@@ -13,7 +13,6 @@ describe 'Modal windows' do
13
13
  end
14
14
 
15
15
  let(:logged_user) { create :user, :developer }
16
- let(:account) { logged_user.current_account }
17
16
  let!(:categoria_de_cosa) { create :categoria_de_cosa }
18
17
 
19
18
  before do
@@ -35,13 +35,14 @@ describe 'Tenants' do
35
35
  it 'shows the switcher' do
36
36
  visitar
37
37
 
38
- expect(page).to have_text 'Switcher'
38
+ expect(page).to have_text 'Cambiar a otra cuenta'
39
39
  end
40
40
 
41
41
  it 'switches to account' do
42
42
  visitar
43
43
 
44
44
  click_on other_account.to_s
45
+ visit '/u/categoria_de_cosas'
45
46
  expect(page).to have_text 'No hay categorías de cosas que mostrar'
46
47
  end
47
48
 
@@ -24,7 +24,11 @@ export default class extends Controller {
24
24
 
25
25
  disconnect () {
26
26
  if (this.popover) {
27
- this.popover.dispose()
27
+ // setTimeout because of:
28
+ // https://github.com/twbs/bootstrap/issues/37474
29
+ setTimeout(() => {
30
+ this.popover.dispose()
31
+ }, 300)
28
32
  }
29
33
  }
30
34
  }
@@ -30,7 +30,11 @@ export default class extends Controller {
30
30
 
31
31
  disconnect () {
32
32
  if (this.tooltip) {
33
- this.tooltip.dispose()
33
+ // setTimeout because of:
34
+ // https://github.com/twbs/bootstrap/issues/37474
35
+ setTimeout(() => {
36
+ this.tooltip.dispose()
37
+ }, 300)
34
38
  }
35
39
  }
36
40
  }
@@ -33,7 +33,7 @@
33
33
  <br>
34
34
  <ul style="max-width: 500px">
35
35
  <% User.order(:id).each do |user| %>
36
- <li><%= link_to user, admin_login_as_path(id: user.id) %></li>
36
+ <li><%= link_to user, login_as_path(id: user.id) %></li>
37
37
  <% end %>
38
38
  </ul>
39
39
  </div>
@@ -5,14 +5,20 @@
5
5
  </div>
6
6
  <% if user_signed_in? %>
7
7
  <span class="d-inline-block px-3 text-end text-light"><%= Current.user %></span>
8
- <%= link_to users_account_switcher_path do %>
9
- <% if Rails.env.development? %>
10
- <span class="d-block px-3 text-secondary">Tenant: <%= ActsAsTenant.current_tenant || 'Global' %></span>
11
- <span class="d-block px-3 text-secondary">Cuenta: <%= Current.account || 'Global' %></span>
12
- <% elsif Current.account.present? %>
13
- <span class="d-block px-3 text-secondary"><%= Current.account %></span>
8
+ <span class="d-block px-3 text-secondary">
9
+ <% if Current.user.user_accounts.count > 1 %>
10
+ <%= link_to ActsAsTenant.current_tenant, [:users, ActsAsTenant.current_tenant] if ActsAsTenant.current_tenant.present? %>
11
+ <%= link_to users_account_switcher_path do %>
12
+ <% if ActsAsTenant.current_tenant.present? %>
13
+ (Cambiar)
14
+ <% else %>
15
+ Elegir cuenta
16
+ <% end %>
17
+ <% end %>
18
+ <% else %>
19
+ <%= link_to ActsAsTenant.current_tenant, [:users, ActsAsTenant.current_tenant] if ActsAsTenant.current_tenant.present? %>
14
20
  <% end %>
15
- <% end %>
21
+ </span>
16
22
  <hr>
17
23
  <% end %>
18
24
  <ul class="list-unstyled ps-0">
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgRails
4
- VERSION = '7.5.1'
4
+ VERSION = '7.5.3'
5
5
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # FIXME: reemplazar por requests spec
3
4
  # generado con pg_rails
4
5
 
5
6
  require 'rails_helper'
@@ -17,7 +17,7 @@ describe 'Generators', type: :generator do
17
17
  before { prepare_destination }
18
18
 
19
19
  it do
20
- run_generator(['Frontend/Modelo', 'bla:integer'])
20
+ run_generator(['users/modelo', 'bla:integer'])
21
21
 
22
22
  my_assert_file 'app/decorators/modelo_decorator.rb' do |content|
23
23
  expect(content).to match(/delegate_all/)
@@ -31,9 +31,9 @@ describe 'Generators', type: :generator do
31
31
  before { prepare_destination }
32
32
 
33
33
  it do
34
- run_generator(['Frontend/Modelo', 'bla:integer'])
34
+ run_generator(['users/modelo', 'bla:integer'])
35
35
 
36
- my_assert_file 'spec/controllers/frontend/modelos_controller_spec.rb' do |content|
36
+ my_assert_file 'spec/controllers/users/modelos_controller_spec.rb' do |content|
37
37
  expect(content).to match(/routing/)
38
38
  expect(content).to match(/sign_in/)
39
39
  end
@@ -46,7 +46,7 @@ describe 'Generators', type: :generator do
46
46
  before { prepare_destination }
47
47
 
48
48
  it do
49
- run_generator(['Frontend/Modelo', 'bla:integer', 'cosa:references', '--activeadmin'])
49
+ run_generator(['users/modelo', 'bla:integer', 'cosa:references', '--activeadmin'])
50
50
 
51
51
  my_assert_file 'app/admin/modelos.rb' do |content|
52
52
  expect(content).to match(/permit_params.*cosa_id/)
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.5.1
4
+ version: 7.5.3
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-09-10 00:00:00.000000000 Z
11
+ date: 2024-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -679,13 +679,17 @@ files:
679
679
  - pg_engine/app/controllers/admin/users_controller.rb
680
680
  - pg_engine/app/controllers/concerns/pg_engine/require_tenant_set.rb
681
681
  - pg_engine/app/controllers/concerns/pg_engine/resource.rb
682
+ - pg_engine/app/controllers/pg_engine/base_admin_controller.rb
682
683
  - pg_engine/app/controllers/pg_engine/base_controller.rb
684
+ - pg_engine/app/controllers/pg_engine/base_public_controller.rb
685
+ - pg_engine/app/controllers/pg_engine/base_users_controller.rb
683
686
  - pg_engine/app/controllers/pg_engine/devise_controller.rb
684
687
  - pg_engine/app/controllers/pg_engine/health_controller.rb
685
688
  - pg_engine/app/controllers/pg_engine/require_sign_in.rb
686
689
  - pg_engine/app/controllers/public/mensaje_contactos_controller.rb
687
690
  - pg_engine/app/controllers/public/webhooks_controller.rb
688
691
  - pg_engine/app/controllers/users/account_switcher_controller.rb
692
+ - pg_engine/app/controllers/users/accounts_controller.rb
689
693
  - pg_engine/app/controllers/users/confirmations_controller.rb
690
694
  - pg_engine/app/controllers/users/date_jumper_controller.rb
691
695
  - pg_engine/app/controllers/users/notifications_controller.rb
@@ -730,6 +734,7 @@ files:
730
734
  - pg_engine/app/notifiers/email_user_notifier.rb
731
735
  - pg_engine/app/notifiers/simple_user_notifier.rb
732
736
  - pg_engine/app/overrides/activestorage_direct_uploads.rb
737
+ - pg_engine/app/overrides/audited_audit.rb
733
738
  - pg_engine/app/policies/account_policy.rb
734
739
  - pg_engine/app/policies/email_log_policy.rb
735
740
  - pg_engine/app/policies/email_policy.rb
@@ -773,6 +778,7 @@ files:
773
778
  - pg_engine/app/views/public/mensaje_contactos/_gracias.html.slim
774
779
  - pg_engine/app/views/public/mensaje_contactos/new.html.slim
775
780
  - pg_engine/app/views/users/account_switcher/list.html.slim
781
+ - pg_engine/app/views/users/accounts/show.html.slim
776
782
  - pg_engine/config/initializers/action_mailer.rb
777
783
  - pg_engine/config/initializers/active_admin.rb
778
784
  - pg_engine/config/initializers/acts_as_tenant.rb
@@ -868,9 +874,11 @@ files:
868
874
  - pg_engine/spec/models/pg_engine/base_record_spec.rb
869
875
  - pg_engine/spec/models/user_account_spec.rb
870
876
  - pg_engine/spec/models/user_spec.rb
877
+ - pg_engine/spec/overrides/audited_audit_spec.rb
871
878
  - pg_engine/spec/pg_engine/pdf_preview_generator_spec.rb
872
879
  - pg_engine/spec/requests/admin/eventos_spec.rb
873
880
  - pg_engine/spec/requests/base_controller_requests_spec.rb
881
+ - pg_engine/spec/requests/users/accounts_spec.rb
874
882
  - pg_engine/spec/requests/users/base_controller_spec.rb
875
883
  - pg_engine/spec/requests/users/date_jumper_spec.rb
876
884
  - pg_engine/spec/requests/users/switcher_spec.rb