pg_rails 7.4.3 → 7.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/pg_associable/spec/system/associable_spec.rb +5 -4
- data/pg_engine/app/controllers/admin/accounts_controller.rb +4 -6
- data/pg_engine/app/controllers/admin/email_logs_controller.rb +0 -2
- data/pg_engine/app/controllers/admin/emails_controller.rb +0 -2
- data/pg_engine/app/controllers/admin/user_accounts_controller.rb +0 -2
- data/pg_engine/app/controllers/admin/users_controller.rb +2 -3
- data/pg_engine/app/controllers/concerns/pg_engine/resource.rb +3 -0
- data/pg_engine/app/controllers/pg_engine/base_controller.rb +50 -7
- data/pg_engine/app/controllers/pg_engine/require_sign_in.rb +1 -1
- data/pg_engine/app/controllers/users/account_switcher_controller.rb +19 -0
- data/pg_engine/app/helpers/pg_engine/form_helper.rb +0 -1
- data/pg_engine/app/helpers/pg_engine/route_helper.rb +11 -5
- data/pg_engine/app/lib/pg_engine/filtros_builder.rb +2 -1
- data/pg_engine/app/models/account.rb +4 -0
- data/pg_engine/app/models/current.rb +5 -5
- data/pg_engine/app/models/user.rb +36 -5
- data/pg_engine/app/models/user_account.rb +1 -0
- data/pg_engine/app/policies/user_account_policy.rb +1 -0
- data/pg_engine/app/policies/user_policy.rb +6 -13
- data/pg_engine/app/views/admin/accounts/_form.html.slim +2 -0
- data/pg_engine/app/views/users/account_switcher/list.html.slim +6 -0
- data/pg_engine/config/initializers/acts_as_tenant.rb +38 -0
- data/pg_engine/config/routes.rb +4 -0
- data/pg_engine/db/migrate/20240905154330_account_tenant_columns.rb +10 -0
- data/pg_engine/db/seeds.rb +13 -4
- data/pg_engine/lib/pg_engine/configuracion.rb +3 -17
- data/pg_engine/lib/pg_engine/engine.rb +0 -1
- data/pg_engine/lib/pg_engine/utils/pg_logger.rb +2 -1
- data/pg_engine/lib/pg_engine.rb +5 -0
- data/pg_engine/spec/controllers/admin/accounts_controller_spec.rb +2 -2
- data/pg_engine/spec/controllers/admin/user_accounts_controller_spec.rb +4 -3
- data/pg_engine/spec/controllers/admin/users_controller_spec.rb +9 -3
- data/pg_engine/spec/models/user_spec.rb +11 -4
- data/pg_engine/spec/requests/base_controller_requests_spec.rb +1 -1
- data/pg_engine/spec/requests/users/base_controller_spec.rb +15 -0
- data/pg_engine/spec/requests/users/switcher_spec.rb +60 -0
- data/pg_engine/spec/system/breadcrumbs_spec.rb +6 -6
- data/pg_engine/spec/system/date_selector_spec.rb +1 -1
- data/pg_engine/spec/system/destroy_spec.rb +3 -3
- data/pg_engine/spec/system/modal_windows_spec.rb +5 -5
- data/pg_engine/spec/system/page_sizes_spec.rb +2 -2
- data/pg_engine/spec/system/signup_spec.rb +4 -4
- data/pg_engine/spec/system/tenants_spec.rb +55 -0
- data/pg_engine/spec/system/tooltips_spec.rb +0 -1
- data/pg_layout/app/views/devise/sessions/new.html.erb +4 -0
- data/pg_layout/app/views/pg_layout/_sidebar.html.erb +8 -0
- data/pg_rails/lib/version.rb +1 -1
- data/pg_scaffold/lib/generators/pg_pundit/templates/policy.rb +1 -1
- data/pg_scaffold/lib/generators/pg_rails/system_spec/templates/system_spec.rb +1 -1
- data/pg_scaffold/lib/generators/pg_rspec/scaffold/templates/controller_spec.rb +0 -2
- metadata +23 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: c9044a5f343884a27bcfdb2be81907fcaaa743b4c1419c4dd1646214a50c5f7e
         | 
| 4 | 
            +
              data.tar.gz: 2542d054eb7ec2ae29e95fdff5a7a0d8cccdef4d57e5a7073b4c0fe945f91fff
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 19ebd2bc479aab28961ba3280a2c0bf276e202501eecfc0474863a00e89882c79bef6c369e9d1ae7a533ad9118716389af0964ae66395a34ff0572011fb5e4ac
         | 
| 7 | 
            +
              data.tar.gz: 5a37d34ab77355940e8c8988af1a9c4d839069b9b37bf645088ea5325c18f8e4829c99ae31877c53195d08caf22bae6ba01efa0d55cf8d95872056a481d51473
         | 
| @@ -3,7 +3,7 @@ require 'rails_helper' | |
| 3 3 | 
             
            describe 'Associable' do
         | 
| 4 4 | 
             
              let(:user) { create :user, :developer }
         | 
| 5 5 |  | 
| 6 | 
            -
              let(:path) { '/ | 
| 6 | 
            +
              let(:path) { '/a/cosas/new' }
         | 
| 7 7 |  | 
| 8 8 | 
             
              before do
         | 
| 9 9 | 
             
                login_as user
         | 
| @@ -16,16 +16,17 @@ describe 'Associable' do | |
| 16 16 | 
             
                find('.cosa_categoria_de_cosa input[type=text]').click
         | 
| 17 17 | 
             
                expect(page).to have_text :all, 'Nuevo'
         | 
| 18 18 | 
             
                find('.cosa_categoria_de_cosa .list-group-item').click
         | 
| 19 | 
            +
                select Account.first.to_s
         | 
| 19 20 | 
             
                fill_in 'categoria_de_cosa_nombre', with: 'la categoría'
         | 
| 20 21 | 
             
                select 'Completar', from: 'categoria_de_cosa_tipo'
         | 
| 21 22 | 
             
                click_on 'Agregar Categoría de cosa'
         | 
| 22 23 | 
             
                click_on 'Cargar Coso'
         | 
| 23 | 
            -
                expect(page).to have_text ' | 
| 24 | 
            +
                expect(page).to have_text 'La cosa'
         | 
| 24 25 | 
             
              end
         | 
| 25 26 |  | 
| 26 27 | 
             
              context 'cuando crea desde el nested' do
         | 
| 27 28 | 
             
                let!(:categ) { create :categoria_de_cosa }
         | 
| 28 | 
            -
                let(:path) { "/ | 
| 29 | 
            +
                let(:path) { "/a/categoria_de_cosas/#{categ.hashid}/cosas/new" }
         | 
| 29 30 |  | 
| 30 31 | 
             
                it do
         | 
| 31 32 | 
             
                  input = find_by_id('cosa_categoria_de_cosa')
         | 
| @@ -36,7 +37,7 @@ describe 'Associable' do | |
| 36 37 | 
             
              context 'cuando edita desde el nested' do
         | 
| 37 38 | 
             
                let!(:categ) { create :categoria_de_cosa }
         | 
| 38 39 | 
             
                let!(:cosa) { create :cosa, categoria_de_cosa: categ }
         | 
| 39 | 
            -
                let(:path) { "/ | 
| 40 | 
            +
                let(:path) { "/a/categoria_de_cosas/#{categ.hashid}/cosas/#{cosa.id}/edit" }
         | 
| 40 41 |  | 
| 41 42 | 
             
                it do
         | 
| 42 43 | 
             
                  ele = find_by_id('cosa_categoria_de_cosa_id', visible: :all)
         | 
| @@ -12,24 +12,22 @@ module Admin | |
| 12 12 |  | 
| 13 13 | 
             
                before_action :set_instancia_modelo, only: %i[new create show edit update destroy]
         | 
| 14 14 |  | 
| 15 | 
            -
                add_breadcrumb Account.nombre_plural, :admin_accounts_path
         | 
| 16 | 
            -
             | 
| 17 15 | 
             
                private
         | 
| 18 16 |  | 
| 19 17 | 
             
                def atributos_permitidos
         | 
| 20 | 
            -
                  %i[plan nombre]
         | 
| 18 | 
            +
                  %i[plan nombre domain subdomain]
         | 
| 21 19 | 
             
                end
         | 
| 22 20 |  | 
| 23 21 | 
             
                def atributos_para_buscar
         | 
| 24 | 
            -
                   | 
| 22 | 
            +
                  atributos_permitidos
         | 
| 25 23 | 
             
                end
         | 
| 26 24 |  | 
| 27 25 | 
             
                def atributos_para_listar
         | 
| 28 | 
            -
                   | 
| 26 | 
            +
                  atributos_permitidos
         | 
| 29 27 | 
             
                end
         | 
| 30 28 |  | 
| 31 29 | 
             
                def atributos_para_mostrar
         | 
| 32 | 
            -
                   | 
| 30 | 
            +
                  atributos_permitidos
         | 
| 33 31 | 
             
                end
         | 
| 34 32 | 
             
              end
         | 
| 35 33 | 
             
            end
         | 
| @@ -12,8 +12,6 @@ module Admin | |
| 12 12 |  | 
| 13 13 | 
             
                before_action :set_instancia_modelo, only: %i[new create show edit update destroy]
         | 
| 14 14 |  | 
| 15 | 
            -
                add_breadcrumb EmailLog.nombre_plural, :admin_email_logs_path
         | 
| 16 | 
            -
             | 
| 17 15 | 
             
                before_action do
         | 
| 18 16 | 
             
                  @actions = [
         | 
| 19 17 | 
             
                    ["Mailgun sync: #{ENV.fetch('MAILGUN_DOMAIN', nil)}", mailgun_sync_admin_email_logs_path, {
         | 
| @@ -12,8 +12,6 @@ module Admin | |
| 12 12 |  | 
| 13 13 | 
             
                before_action :set_instancia_modelo, only: %i[new create show edit update destroy]
         | 
| 14 14 |  | 
| 15 | 
            -
                add_breadcrumb Email.nombre_plural, :admin_emails_path
         | 
| 16 | 
            -
             | 
| 17 15 | 
             
                after_action only: :create do
         | 
| 18 16 | 
             
                  if @saved
         | 
| 19 17 | 
             
                    PgEngine::AdminMailer.with(email_object: @email).admin_mail.deliver_later
         | 
| @@ -16,11 +16,10 @@ module Admin | |
| 16 16 |  | 
| 17 17 | 
             
                before_action :set_instancia_modelo, only: %i[new create show edit update destroy]
         | 
| 18 18 |  | 
| 19 | 
            -
                add_breadcrumb User.nombre_plural, :admin_users_path
         | 
| 20 | 
            -
             | 
| 21 19 | 
             
                def create
         | 
| 22 20 | 
             
                  @user.skip_confirmation!
         | 
| 23 | 
            -
                  @user. | 
| 21 | 
            +
                  @user.orphan = true
         | 
| 22 | 
            +
             | 
| 24 23 | 
             
                  pg_respond_create
         | 
| 25 24 | 
             
                end
         | 
| 26 25 |  | 
| @@ -2,12 +2,51 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module PgEngine
         | 
| 4 4 | 
             
              # rubocop:disable Rails/ApplicationController
         | 
| 5 | 
            +
              # rubocop:disable Metrics/ClassLength
         | 
| 5 6 | 
             
              class BaseController < ActionController::Base
         | 
| 7 | 
            +
                # Importante que esta línea esté al principio
         | 
| 8 | 
            +
                protect_from_forgery with: :exception
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                set_current_tenant_by_subdomain_or_domain(:account, :subdomain, :domain)
         | 
| 11 | 
            +
                set_current_tenant_through_filter
         | 
| 12 | 
            +
             | 
| 6 13 | 
             
                before_action do
         | 
| 14 | 
            +
                  Current.user = current_user
         | 
| 7 15 | 
             
                  Current.controller = self
         | 
| 8 | 
            -
                end
         | 
| 9 16 |  | 
| 17 | 
            +
                  # if ActsAsTenant.current_tenant.blank? && !global_domain?
         | 
| 18 | 
            +
                  #   raise ActsAsTenant::Errors::NoTenantSet
         | 
| 19 | 
            +
                  # end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  if Current.user.present?
         | 
| 22 | 
            +
                    if ActsAsTenant.current_tenant.present?
         | 
| 23 | 
            +
                      unless Current.user.user_accounts.exists?(account: ActsAsTenant.current_tenant)
         | 
| 24 | 
            +
                        sign_out(Current.user)
         | 
| 25 | 
            +
                        throw :warden, scope: :user, message: :invalid
         | 
| 26 | 
            +
                      end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    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
         | 
| 32 | 
            +
                                  Current.user.user_accounts.first
         | 
| 33 | 
            +
                                end
         | 
| 34 | 
            +
                      set_current_tenant(account)
         | 
| 35 | 
            +
                      # FIXME: un concern que redirija al switcher si no hay current tenant
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
                    Current.account = ActsAsTenant.current_tenant
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 10 40 | 
             
                # rubocop:enable Rails/ApplicationController
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                # :nocov:
         | 
| 43 | 
            +
                def global_domain?
         | 
| 44 | 
            +
                  return true if Rails.env.test?
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  request.host.in? PgEngine.config.global_domains
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
                # :nocov:
         | 
| 49 | 
            +
             | 
| 11 50 | 
             
                include Pundit::Authorization
         | 
| 12 51 | 
             
                include PrintHelper
         | 
| 13 52 | 
             
                include PostgresHelper
         | 
| @@ -25,10 +64,11 @@ module PgEngine | |
| 25 64 | 
             
                  end
         | 
| 26 65 | 
             
                end
         | 
| 27 66 |  | 
| 28 | 
            -
                protect_from_forgery with: :exception
         | 
| 29 | 
            -
             | 
| 30 67 | 
             
                rescue_from StandardError, with: :internal_error
         | 
| 68 | 
            +
                rescue_from ActsAsTenant::Errors::NoTenantSet, with: :no_tenant_set
         | 
| 69 | 
            +
             | 
| 31 70 | 
             
                rescue_from PgEngine::BadUserInput, with: :bad_user_input
         | 
| 71 | 
            +
             | 
| 32 72 | 
             
                rescue_from ActionController::InvalidAuthenticityToken,
         | 
| 33 73 | 
             
                            with: :invalid_authenticity_token
         | 
| 34 74 |  | 
| @@ -38,6 +78,12 @@ module PgEngine | |
| 38 78 | 
             
                  redirect_to e.url
         | 
| 39 79 | 
             
                end
         | 
| 40 80 |  | 
| 81 | 
            +
                def no_tenant_set(error)
         | 
| 82 | 
            +
                  return internal_error(error) if Current.user.blank?
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                  redirect_to users_account_switcher_path
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 41 87 | 
             
                def bad_user_input(error)
         | 
| 42 88 | 
             
                  render_my_component(BadUserInputComponent.new(error_msg: error.message), :bad_request)
         | 
| 43 89 | 
             
                end
         | 
| @@ -63,10 +109,6 @@ module PgEngine | |
| 63 109 | 
             
                  render_my_component(InternalErrorComponent.new, :ok)
         | 
| 64 110 | 
             
                end
         | 
| 65 111 |  | 
| 66 | 
            -
                before_action do
         | 
| 67 | 
            -
                  Current.user = current_user
         | 
| 68 | 
            -
                end
         | 
| 69 | 
            -
             | 
| 70 112 | 
             
                helper_method :dev_user_or_env?
         | 
| 71 113 | 
             
                def dev_user_or_env?
         | 
| 72 114 | 
             
                  Rails.env.development? || dev_user?
         | 
| @@ -181,4 +223,5 @@ module PgEngine | |
| 181 223 | 
             
                  redirect_back fallback_location: root_path
         | 
| 182 224 | 
             
                end
         | 
| 183 225 | 
             
              end
         | 
| 226 | 
            +
              # rubocop:enable Metrics/ClassLength
         | 
| 184 227 | 
             
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            module Users
         | 
| 2 | 
            +
              class AccountSwitcherController < PgEngine.config.users_controller
         | 
| 3 | 
            +
                rescue_from ActsAsTenant::Errors::NoTenantSet, with: :internal_error
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                before_action do
         | 
| 6 | 
            +
                  @no_main_frame = true
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def list
         | 
| 10 | 
            +
                  @user_accounts = Current.user.user_accounts
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def switch
         | 
| 14 | 
            +
                  user_account = UserAccount.find(params[:user_account_id])
         | 
| 15 | 
            +
                  session['current_user_account'] = user_account.id
         | 
| 16 | 
            +
                  redirect_to root_path
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| @@ -3,21 +3,25 @@ | |
| 3 3 | 
             
            module PgEngine
         | 
| 4 4 | 
             
              module RouteHelper
         | 
| 5 5 | 
             
                class NamespaceDeductor
         | 
| 6 | 
            -
                  def self. | 
| 6 | 
            +
                  def self.controller(context)
         | 
| 7 7 | 
             
                    if context.respond_to?(:request) && context.request
         | 
| 8 8 | 
             
                      # Controllers
         | 
| 9 | 
            -
                      context | 
| 9 | 
            +
                      context
         | 
| 10 10 | 
             
                    elsif context.respond_to?(:helpers) && context.helpers
         | 
| 11 11 | 
             
                      # Decorators
         | 
| 12 | 
            -
                      context.helpers. | 
| 12 | 
            +
                      context.helpers.controller
         | 
| 13 13 | 
             
                    elsif context.respond_to?(:template) && context.template
         | 
| 14 14 | 
             
                      # FormBuilders
         | 
| 15 | 
            -
                      context.template. | 
| 15 | 
            +
                      context.template.controller
         | 
| 16 16 | 
             
                    end
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 |  | 
| 19 19 | 
             
                  def self.current_route(context)
         | 
| 20 | 
            -
                     | 
| 20 | 
            +
                    controller = controller(context)
         | 
| 21 | 
            +
                    # Sólo si hay un controller de verdá
         | 
| 22 | 
            +
                    return if controller.instance_of? ApplicationController
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    req = controller.request
         | 
| 21 25 | 
             
                    Rails.application.routes.recognize_path(req.path, method: req.env['REQUEST_METHOD'])
         | 
| 22 26 | 
             
                  end
         | 
| 23 27 |  | 
| @@ -25,6 +29,8 @@ module PgEngine | |
| 25 29 | 
             
                    return Current.namespace if Current.namespace.present?
         | 
| 26 30 |  | 
| 27 31 | 
             
                    route = current_route(context)
         | 
| 32 | 
            +
                    return if route.blank?
         | 
| 33 | 
            +
             | 
| 28 34 | 
             
                    parts = route[:controller].split('/')
         | 
| 29 35 | 
             
                    return unless parts.length > 1
         | 
| 30 36 |  | 
| @@ -4,9 +4,9 @@ class Current < ActiveSupport::CurrentAttributes | |
| 4 4 |  | 
| 5 5 | 
             
              # resets { Time.zone = nil }
         | 
| 6 6 |  | 
| 7 | 
            -
              def user=(user)
         | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
              end
         | 
| 7 | 
            +
              # def user=(user)
         | 
| 8 | 
            +
              #   super
         | 
| 9 | 
            +
              #
         | 
| 10 | 
            +
              #   Time.zone    = user.time_zone
         | 
| 11 | 
            +
              # end
         | 
| 12 12 | 
             
            end
         | 
| @@ -37,7 +37,22 @@ class User < ApplicationRecord | |
| 37 37 | 
             
              include Discard::Model
         | 
| 38 38 |  | 
| 39 39 | 
             
              has_many :user_accounts
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              # Hace falta?
         | 
| 40 42 | 
             
              has_many :accounts, through: :user_accounts
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              # default_scope lambda {
         | 
| 45 | 
            +
              #   if ActsAsTenant.current_tenant.present?
         | 
| 46 | 
            +
              #     joins(:user_accounts).where('user_accounts.account_id': ActsAsTenant.current_tenant.id)
         | 
| 47 | 
            +
              #   else
         | 
| 48 | 
            +
              #     raise ActsAsTenant::Errors::NoTenantSet unless Current.user.blank? || ActsAsTenant.unscoped?
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              #     # Aún no autenticó devise o es el admin
         | 
| 51 | 
            +
              #     all
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              #   end
         | 
| 54 | 
            +
              # }
         | 
| 55 | 
            +
             | 
| 41 56 | 
             
              has_many :notifications, as: :recipient, class_name: 'Noticed::Notification'
         | 
| 42 57 |  | 
| 43 58 | 
             
              validates :nombre, :apellido, presence: true
         | 
| @@ -57,14 +72,23 @@ class User < ApplicationRecord | |
| 57 72 | 
             
              attr_accessor :orphan
         | 
| 58 73 |  | 
| 59 74 | 
             
              after_create do
         | 
| 60 | 
            -
                # TODO: si fue invitado, sumar a la account del invitador
         | 
| 61 75 | 
             
                create_account unless orphan
         | 
| 62 76 | 
             
              end
         | 
| 63 77 |  | 
| 64 78 | 
             
              def create_account
         | 
| 65 | 
            -
                 | 
| 79 | 
            +
                # rubocop:disable Rails/Presence
         | 
| 80 | 
            +
                account =
         | 
| 81 | 
            +
                  if ActsAsTenant.current_tenant.present?
         | 
| 82 | 
            +
                    # FIXME!: raise PgEngine::Error unless invited
         | 
| 83 | 
            +
                    ActsAsTenant.current_tenant
         | 
| 84 | 
            +
                  else
         | 
| 85 | 
            +
                    Account.create(nombre: email, plan: 0)
         | 
| 86 | 
            +
                  end
         | 
| 87 | 
            +
                # rubocop:enable Rails/Presence
         | 
| 88 | 
            +
             | 
| 66 89 | 
             
                ua = user_accounts.create(account:)
         | 
| 67 | 
            -
             | 
| 90 | 
            +
             | 
| 91 | 
            +
                raise(Error, 'no se pudo crear la cuenta') unless ua.persisted?
         | 
| 68 92 | 
             
              end
         | 
| 69 93 |  | 
| 70 94 | 
             
              def password_required?
         | 
| @@ -87,9 +111,16 @@ class User < ApplicationRecord | |
| 87 111 |  | 
| 88 112 | 
             
              class Error < PgEngine::Error; end
         | 
| 89 113 |  | 
| 90 | 
            -
              def  | 
| 114 | 
            +
              def default_account
         | 
| 91 115 | 
             
                raise Error, 'El usuario debe tener cuenta' if accounts.empty?
         | 
| 92 116 |  | 
| 93 | 
            -
                 | 
| 117 | 
            +
                user_accounts.first.account
         | 
| 118 | 
            +
                # throw :warden, scope: :user, message: :user_not_belongs_to_account
         | 
| 119 | 
            +
              end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
              deprecate :current_account, deprecator: PgEngine.deprecator
         | 
| 122 | 
            +
             | 
| 123 | 
            +
              def current_account
         | 
| 124 | 
            +
                ActsAsTenant.current_tenant
         | 
| 94 125 | 
             
              end
         | 
| 95 126 | 
             
            end
         | 
| @@ -4,17 +4,6 @@ | |
| 4 4 |  | 
| 5 5 | 
             
            class UserPolicy < ApplicationPolicy
         | 
| 6 6 | 
             
              class Scope < ApplicationPolicy::Scope
         | 
| 7 | 
            -
                def resolve
         | 
| 8 | 
            -
                  if policy.acceso_total?
         | 
| 9 | 
            -
                    if Current.account.present?
         | 
| 10 | 
            -
                      scope.joins(:user_accounts).where('user_accounts.account_id': Current.account.id)
         | 
| 11 | 
            -
                    else
         | 
| 12 | 
            -
                      scope.none
         | 
| 13 | 
            -
                    end
         | 
| 14 | 
            -
                  else
         | 
| 15 | 
            -
                    scope.none
         | 
| 16 | 
            -
                  end
         | 
| 17 | 
            -
                end
         | 
| 18 7 | 
             
              end
         | 
| 19 8 |  | 
| 20 9 | 
             
              # def puede_editar?
         | 
| @@ -29,7 +18,11 @@ class UserPolicy < ApplicationPolicy | |
| 29 18 | 
             
              #   acceso_total? && !record.readonly?
         | 
| 30 19 | 
             
              # end
         | 
| 31 20 |  | 
| 32 | 
            -
              def  | 
| 33 | 
            -
                user. | 
| 21 | 
            +
              def base_access_to_record?
         | 
| 22 | 
            +
                user.developer? || user == record
         | 
| 34 23 | 
             
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              # def base_access_to_collection?
         | 
| 26 | 
            +
              #   user&.present?
         | 
| 27 | 
            +
              # end
         | 
| 35 28 | 
             
            end
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            ActsAsTenant.configure do |config|
         | 
| 2 | 
            +
              config.require_tenant = true
         | 
| 3 | 
            +
              # config.require_tenant = lambda do |options|
         | 
| 4 | 
            +
              #   # if options[:scope] == User && true # global_domain?
         | 
| 5 | 
            +
              #   #   # tal vez en algunos casos de devise sí requeriría el tenant?
         | 
| 6 | 
            +
              #   #   #   creería que no, el único lugar en donde se debería queriar
         | 
| 7 | 
            +
              #   #   #   User es en devise y es para obtener el current_user
         | 
| 8 | 
            +
              #   #   #   hay que ver luego qué pasa con invitable
         | 
| 9 | 
            +
              #   #   false
         | 
| 10 | 
            +
              #   # else
         | 
| 11 | 
            +
              #   #   true
         | 
| 12 | 
            +
              #   # end
         | 
| 13 | 
            +
              # end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              # Customize the query for loading the tenant in background jobs
         | 
| 16 | 
            +
              # config.job_scope = ->{ all }
         | 
| 17 | 
            +
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            SET_TENANT_PROC = lambda do
         | 
| 20 | 
            +
              if defined?(Rails::Console)
         | 
| 21 | 
            +
                puts "> ActsAsTenant.current_tenant = Account.first"
         | 
| 22 | 
            +
                ActsAsTenant.current_tenant = Account.first
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
            end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            Rails.application.configure do
         | 
| 27 | 
            +
              if Rails.env.development?
         | 
| 28 | 
            +
                # Set the tenant to the first account in development on load
         | 
| 29 | 
            +
                config.after_initialize do
         | 
| 30 | 
            +
                  SET_TENANT_PROC.call
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                # Reset the tenant after calling 'reload!' in the console
         | 
| 34 | 
            +
                ActiveSupport::Reloader.to_complete do
         | 
| 35 | 
            +
                  SET_TENANT_PROC.call
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
    
        data/pg_engine/config/routes.rb
    CHANGED
    
    | @@ -21,6 +21,10 @@ Rails.application.routes.draw do | |
| 21 21 | 
             
                post 'notifications/mark_as_seen', to: 'notifications#mark_as_seen'
         | 
| 22 22 | 
             
                post 'notifications/mark_as_unseen', to: 'notifications#mark_as_unseen'
         | 
| 23 23 | 
             
                get 'date_jumper/jump'
         | 
| 24 | 
            +
                scope controller: 'account_switcher', path: 'switcher' do
         | 
| 25 | 
            +
                  get '', action: 'list', as: 'account_switcher'
         | 
| 26 | 
            +
                  post ':user_account_id', action: 'switch', as: 'account_switch'
         | 
| 27 | 
            +
                end
         | 
| 24 28 | 
             
              end
         | 
| 25 29 | 
             
              namespace :admin, path: 'a' do
         | 
| 26 30 | 
             
                pg_resource(:emails)
         | 
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            class AccountTenantColumns < ActiveRecord::Migration[7.2]
         | 
| 2 | 
            +
              def change
         | 
| 3 | 
            +
                add_column :accounts, :domain, :string
         | 
| 4 | 
            +
                add_column :accounts, :subdomain, :string
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                add_reference :audits, :account, index: true, foreign_key: true
         | 
| 7 | 
            +
                add_reference :emails, :account, index: true, foreign_key: true
         | 
| 8 | 
            +
                add_reference :email_logs, :account, index: true, foreign_key: true
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
            end
         | 
    
        data/pg_engine/db/seeds.rb
    CHANGED
    
    | @@ -1,6 +1,15 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            ActsAsTenant.without_tenant do
         | 
| 2 | 
            +
              DatabaseCleaner.clean_with(:truncation, except: %w(ar_internal_metadata))
         | 
| 2 3 |  | 
| 3 | 
            -
            FactoryBot.create :user, email: 'mrosso10@gmail.com', nombre: 'Martín', apellido: 'Rosso', password: 'admin123',
         | 
| 4 | 
            -
                                     confirmed_at: Time.now, developer: true
         | 
| 5 4 |  | 
| 6 | 
            -
             | 
| 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
         | 
| 9 | 
            +
             | 
| 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
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              mal.users << otro
         | 
| 15 | 
            +
            end
         | 
| @@ -4,30 +4,16 @@ | |
| 4 4 |  | 
| 5 5 | 
             
            module PgEngine
         | 
| 6 6 | 
             
              class Configuracion
         | 
| 7 | 
            -
                attr_accessor : | 
| 8 | 
            -
                              :boton_destroy, :boton_edit, :boton_show,
         | 
| 9 | 
            -
                              :boton_light, :icono_destroy, :icono_edit,
         | 
| 10 | 
            -
                              :icono_show, :boton_export, :bootstrap_version,
         | 
| 11 | 
            -
                              :users_controller
         | 
| 7 | 
            +
                attr_accessor :users_controller, :global_domains
         | 
| 12 8 |  | 
| 13 9 | 
             
                def initialize
         | 
| 14 | 
            -
                  @sistema_iconos = 'bi'
         | 
| 15 | 
            -
                  @clase_botones_chicos = 'btn-sm'
         | 
| 16 | 
            -
                  @boton_destroy = 'light'
         | 
| 17 | 
            -
                  @boton_export = 'warning'
         | 
| 18 | 
            -
                  @boton_edit = 'light'
         | 
| 19 | 
            -
                  @boton_show = 'light'
         | 
| 20 | 
            -
                  @boton_light = 'light'
         | 
| 21 | 
            -
                  @icono_destroy = 'trash-fill'
         | 
| 22 | 
            -
                  @icono_edit = 'pencil'
         | 
| 23 | 
            -
                  @icono_show = 'eye-fill'
         | 
| 24 | 
            -
                  @bootstrap_version = 5
         | 
| 25 | 
            -
             | 
| 26 10 | 
             
                  if defined? UsersController
         | 
| 27 11 | 
             
                    @users_controller = UsersController
         | 
| 28 12 | 
             
                  elsif defined? FrontendController
         | 
| 29 13 | 
             
                    @users_controller = FrontendController
         | 
| 30 14 | 
             
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  @global_domains = ['app.localhost.com', 'test.host', 'localhost']
         | 
| 31 17 | 
             
                end
         | 
| 32 18 | 
             
              end
         | 
| 33 19 | 
             
            end
         | 
| @@ -3,9 +3,10 @@ | |
| 3 3 | 
             
            require 'rainbow'
         | 
| 4 4 |  | 
| 5 5 | 
             
            # TODO: poder pasar blocks
         | 
| 6 | 
            +
            # TODO: loguear paralelamente a otro file
         | 
| 6 7 |  | 
| 7 8 | 
             
            def pg_err(*args)
         | 
| 8 | 
            -
              if ENV.fetch('RAISE_ERRORS', false)
         | 
| 9 | 
            +
              if ENV.fetch('RAISE_ERRORS', false) == '1'
         | 
| 9 10 | 
             
                # :nocov:
         | 
| 10 11 | 
             
                raise args.first if args.first.is_a?(Exception)
         | 
| 11 12 |  | 
    
        data/pg_engine/lib/pg_engine.rb
    CHANGED
    
    | @@ -16,6 +16,7 @@ require 'rails' | |
| 16 16 | 
             
            require 'anycable'
         | 
| 17 17 | 
             
            require 'anycable-rails'
         | 
| 18 18 | 
             
            require 'anycable-rails-jwt'
         | 
| 19 | 
            +
            require 'acts_as_tenant'
         | 
| 19 20 | 
             
            require 'cable_ready'
         | 
| 20 21 | 
             
            require 'caxlsx_rails'
         | 
| 21 22 | 
             
            require 'draper'
         | 
| @@ -105,4 +106,8 @@ module PgEngine | |
| 105 106 | 
             
                  https://fonts.googleapis.com/css2?family=Ubuntu:ital,wght@0,300;0,400;\
         | 
| 106 107 | 
             
                  0,500;0,700;1,300;1,400;1,500;1,700&display=swap
         | 
| 107 108 | 
             
                URL
         | 
| 109 | 
            +
             | 
| 110 | 
            +
              def self.deprecator
         | 
| 111 | 
            +
                @deprecator ||= ActiveSupport::Deprecation.new('7.5', 'PgEngine')
         | 
| 112 | 
            +
              end
         | 
| 108 113 | 
             
            end
         | 
| @@ -130,7 +130,7 @@ RSpec.describe Admin::AccountsController do | |
| 130 130 |  | 
| 131 131 | 
             
                  it 'redirects to the created account' do
         | 
| 132 132 | 
             
                    post :create, params: { account: valid_attributes }
         | 
| 133 | 
            -
                    expect(response).to redirect_to(Account.last | 
| 133 | 
            +
                    expect(response).to redirect_to([:admin, Account.last])
         | 
| 134 134 | 
             
                  end
         | 
| 135 135 | 
             
                end
         | 
| 136 136 |  | 
| @@ -163,7 +163,7 @@ RSpec.describe Admin::AccountsController do | |
| 163 163 | 
             
                  it 'redirects to the account' do
         | 
| 164 164 | 
             
                    account = create(:account)
         | 
| 165 165 | 
             
                    put :update, params: { id: account.to_param, account: valid_attributes }
         | 
| 166 | 
            -
                    expect(response).to redirect_to( | 
| 166 | 
            +
                    expect(response).to redirect_to([:admin, Account.last])
         | 
| 167 167 | 
             
                  end
         | 
| 168 168 | 
             
                end
         | 
| 169 169 |  | 
| @@ -31,7 +31,7 @@ RSpec.describe Admin::UserAccountsController do | |
| 31 31 | 
             
              render_views
         | 
| 32 32 | 
             
              let!(:user) { create :user }
         | 
| 33 33 |  | 
| 34 | 
            -
              let!(:account) {  | 
| 34 | 
            +
              let!(:account) { ActsAsTenant.current_tenant }
         | 
| 35 35 |  | 
| 36 36 | 
             
              # This should return the minimal set of attributes required to create a valid
         | 
| 37 37 | 
             
              # UserAccount. As you add validations to UserAccount, be sure to
         | 
| @@ -125,7 +125,7 @@ RSpec.describe Admin::UserAccountsController do | |
| 125 125 |  | 
| 126 126 | 
             
                  it 'redirects to the created user_account' do
         | 
| 127 127 | 
             
                    post :create, params: { user_account: valid_attributes }
         | 
| 128 | 
            -
                    expect(response).to redirect_to(UserAccount.last | 
| 128 | 
            +
                    expect(response).to redirect_to([:admin, UserAccount.last])
         | 
| 129 129 | 
             
                  end
         | 
| 130 130 | 
             
                end
         | 
| 131 131 |  | 
| @@ -151,7 +151,8 @@ RSpec.describe Admin::UserAccountsController do | |
| 151 151 | 
             
                  it 'redirects to the user_account' do
         | 
| 152 152 | 
             
                    user_account = create(:user_account)
         | 
| 153 153 | 
             
                    put :update, params: { id: user_account.to_param, user_account: valid_attributes }
         | 
| 154 | 
            -
             | 
| 154 | 
            +
             | 
| 155 | 
            +
                    expect(response).to redirect_to([:admin, UserAccount.last])
         | 
| 155 156 | 
             
                  end
         | 
| 156 157 | 
             
                end
         | 
| 157 158 |  | 
| @@ -99,12 +99,18 @@ RSpec.describe Admin::UsersController do | |
| 99 99 | 
             
                  it 'creates a new User' do
         | 
| 100 100 | 
             
                    expect do
         | 
| 101 101 | 
             
                      post :create, params: { user: valid_attributes }
         | 
| 102 | 
            -
                    end.to change(User, :count).by(1)
         | 
| 102 | 
            +
                    end.to change(User.unscoped, :count).by(1)
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  it 'dont creates a new account' do
         | 
| 106 | 
            +
                    expect do
         | 
| 107 | 
            +
                      post :create, params: { user: valid_attributes }
         | 
| 108 | 
            +
                    end.not_to change(Account.unscoped, :count)
         | 
| 103 109 | 
             
                  end
         | 
| 104 110 |  | 
| 105 111 | 
             
                  it 'redirects to the created user' do
         | 
| 106 112 | 
             
                    post :create, params: { user: valid_attributes }
         | 
| 107 | 
            -
                    expect(response).to redirect_to(User.last | 
| 113 | 
            +
                    expect(response).to redirect_to([:admin, User.unscoped.last])
         | 
| 108 114 | 
             
                  end
         | 
| 109 115 | 
             
                end
         | 
| 110 116 |  | 
| @@ -137,7 +143,7 @@ RSpec.describe Admin::UsersController do | |
| 137 143 | 
             
                  it 'redirects to the user' do
         | 
| 138 144 | 
             
                    user = create(:user)
         | 
| 139 145 | 
             
                    put :update, params: { id: user.to_param, user: valid_attributes }
         | 
| 140 | 
            -
                    expect(response).to redirect_to(user.decorate | 
| 146 | 
            +
                    expect(response).to redirect_to([:admin, user.decorate])
         | 
| 141 147 | 
             
                  end
         | 
| 142 148 | 
             
                end
         | 
| 143 149 |  | 
| @@ -12,7 +12,7 @@ RSpec.describe User do | |
| 12 12 | 
             
              end
         | 
| 13 13 |  | 
| 14 14 | 
             
              it do
         | 
| 15 | 
            -
                expect(user. | 
| 15 | 
            +
                expect(user.default_account).to be_present
         | 
| 16 16 | 
             
              end
         | 
| 17 17 |  | 
| 18 18 | 
             
              context 'si es orphan' do
         | 
| @@ -23,11 +23,18 @@ RSpec.describe User do | |
| 23 23 | 
             
                end
         | 
| 24 24 |  | 
| 25 25 | 
             
                it do
         | 
| 26 | 
            -
                  expect { user. | 
| 26 | 
            +
                  expect { user.default_account }.to raise_error(User::Error)
         | 
| 27 27 | 
             
                end
         | 
| 28 28 | 
             
              end
         | 
| 29 29 |  | 
| 30 30 | 
             
              context 'Si falla la creación de cuenta, que rollbackee la transaction de create user' do
         | 
| 31 | 
            +
                # rubocop:disable Lint/SuppressedException
         | 
| 32 | 
            +
                subject do
         | 
| 33 | 
            +
                  user.save
         | 
| 34 | 
            +
                rescue User::Error
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
                # rubocop:enable Lint/SuppressedException
         | 
| 37 | 
            +
             | 
| 31 38 | 
             
                let(:user) do
         | 
| 32 39 | 
             
                  build(:user)
         | 
| 33 40 | 
             
                end
         | 
| @@ -41,11 +48,11 @@ RSpec.describe User do | |
| 41 48 | 
             
                end
         | 
| 42 49 |  | 
| 43 50 | 
             
                it do
         | 
| 44 | 
            -
                  expect {  | 
| 51 | 
            +
                  expect { subject }.not_to change(described_class, :count)
         | 
| 45 52 | 
             
                end
         | 
| 46 53 |  | 
| 47 54 | 
             
                it do
         | 
| 48 | 
            -
                   | 
| 55 | 
            +
                  subject
         | 
| 49 56 | 
             
                  expect(user).not_to be_persisted
         | 
| 50 57 | 
             
                end
         | 
| 51 58 | 
             
              end
         | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            require 'rails_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe 'redirection' do
         | 
| 4 | 
            +
              context 'when public controller raises no tenant set' do
         | 
| 5 | 
            +
                before do
         | 
| 6 | 
            +
                  allow(MensajeContacto).to receive(:new).and_raise(ActsAsTenant::Errors::NoTenantSet)
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                it 'shows the error' do
         | 
| 10 | 
            +
                  get '/contacto'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  expect(response).to have_http_status(:internal_server_error)
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
            end
         | 
| @@ -0,0 +1,60 @@ | |
| 1 | 
            +
            require 'rails_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe 'redirection' do
         | 
| 4 | 
            +
              let(:logged_user) { create :user }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              before do
         | 
| 7 | 
            +
                sign_in logged_user
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              context 'when switcher controller raises no tenant set' do
         | 
| 11 | 
            +
                # This is to prevent a redirect loop
         | 
| 12 | 
            +
                before do
         | 
| 13 | 
            +
                  allow_any_instance_of(User).to receive(:user_accounts).and_raise(ActsAsTenant::Errors::NoTenantSet)
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                it 'shows the error' do
         | 
| 17 | 
            +
                  get '/u/switcher'
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  expect(response).to have_http_status(:internal_server_error)
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              it do
         | 
| 24 | 
            +
                get '/u/cosas'
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                expect(response).to have_http_status(:ok)
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              context 'when has been removed from account' do
         | 
| 30 | 
            +
                let!(:other_account) { create :account }
         | 
| 31 | 
            +
                let!(:other_user_account) { logged_user.user_accounts.create(account: other_account) }
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                it 'redirects to switcher' do
         | 
| 34 | 
            +
                  get '/u/cosas'
         | 
| 35 | 
            +
                  expect(response).to redirect_to users_account_switcher_path
         | 
| 36 | 
            +
                  follow_redirect!
         | 
| 37 | 
            +
                  expect(response.body).to include 'Switcher'
         | 
| 38 | 
            +
                  post "/u/switcher/#{other_user_account.to_param}"
         | 
| 39 | 
            +
                  expect(response).to redirect_to(root_path)
         | 
| 40 | 
            +
                  follow_redirect!
         | 
| 41 | 
            +
                  expect(response.body).to include other_account.to_s
         | 
| 42 | 
            +
                  other_user_account.destroy!
         | 
| 43 | 
            +
                  get '/'
         | 
| 44 | 
            +
                  expect(response).to redirect_to users_account_switcher_path
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              context 'when belongs to other account' do
         | 
| 49 | 
            +
                before do
         | 
| 50 | 
            +
                  create :account, subdomain: 'other'
         | 
| 51 | 
            +
                  host! 'other.example.com'
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                it do
         | 
| 55 | 
            +
                  get '/u/cosas'
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  expect(response).to redirect_to new_user_session_path
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
            end
         | 
| @@ -12,7 +12,7 @@ describe 'Breadcrumbs' do | |
| 12 12 | 
             
                visit path
         | 
| 13 13 | 
             
              end
         | 
| 14 14 |  | 
| 15 | 
            -
              let(:path) { "/ | 
| 15 | 
            +
              let(:path) { "/a/cosas/#{cosa.id}" }
         | 
| 16 16 | 
             
              let(:cosa) { create :cosa }
         | 
| 17 17 | 
             
              let(:logged_user) { create :user, :developer }
         | 
| 18 18 | 
             
              let(:account) { logged_user.current_account }
         | 
| @@ -25,20 +25,20 @@ describe 'Breadcrumbs' do | |
| 25 25 | 
             
                it do
         | 
| 26 26 | 
             
                  visitar
         | 
| 27 27 |  | 
| 28 | 
            -
                  expect(page).to have_css('nav ol.breadcrumb li').exactly( | 
| 28 | 
            +
                  expect(page).to have_css('nav ol.breadcrumb li').exactly(3)
         | 
| 29 29 | 
             
                  expect(page).to have_css('nav ol.breadcrumb li a').exactly(1)
         | 
| 30 30 | 
             
                end
         | 
| 31 31 |  | 
| 32 32 | 
             
                context 'cuando es con nested' do
         | 
| 33 33 | 
             
                  let(:path) do
         | 
| 34 34 | 
             
                    hashid = cosa.categoria_de_cosa.hashid
         | 
| 35 | 
            -
                    "/ | 
| 35 | 
            +
                    "/a/categoria_de_cosas/#{hashid}/cosas/#{cosa.id}"
         | 
| 36 36 | 
             
                  end
         | 
| 37 37 |  | 
| 38 38 | 
             
                  it do
         | 
| 39 39 | 
             
                    visitar
         | 
| 40 40 |  | 
| 41 | 
            -
                    expect(page).to have_css('nav ol.breadcrumb li').exactly( | 
| 41 | 
            +
                    expect(page).to have_css('nav ol.breadcrumb li').exactly(4)
         | 
| 42 42 | 
             
                    expect(page).to have_css('nav ol.breadcrumb li a').exactly(1)
         | 
| 43 43 | 
             
                  end
         | 
| 44 44 | 
             
                end
         | 
| @@ -46,14 +46,14 @@ describe 'Breadcrumbs' do | |
| 46 46 | 
             
                context 'cuando es con nested y modal' do
         | 
| 47 47 | 
             
                  let(:path) do
         | 
| 48 48 | 
             
                    hashid = cosa.categoria_de_cosa.hashid
         | 
| 49 | 
            -
                    "/ | 
| 49 | 
            +
                    "/a/categoria_de_cosas/#{hashid}"
         | 
| 50 50 | 
             
                  end
         | 
| 51 51 |  | 
| 52 52 | 
             
                  it do
         | 
| 53 53 | 
             
                    visitar
         | 
| 54 54 | 
             
                    find('td span[title=Ver] a').click
         | 
| 55 55 |  | 
| 56 | 
            -
                    expect(page).to have_css('.modal nav ol.breadcrumb li').exactly( | 
| 56 | 
            +
                    expect(page).to have_css('.modal nav ol.breadcrumb li').exactly(4)
         | 
| 57 57 | 
             
                    expect(page).to have_no_css('.modal nav ol.breadcrumb li a')
         | 
| 58 58 | 
             
                  end
         | 
| 59 59 | 
             
                end
         | 
| @@ -12,7 +12,7 @@ describe 'Date selector' do | |
| 12 12 | 
             
                visit edit_admin_categoria_de_cosa_path(categoria_de_cosa)
         | 
| 13 13 | 
             
              end
         | 
| 14 14 |  | 
| 15 | 
            -
              let(:logged_user) { create :user }
         | 
| 15 | 
            +
              let(:logged_user) { create :user, :developer }
         | 
| 16 16 | 
             
              let(:account) { logged_user.current_account }
         | 
| 17 17 | 
             
              let(:categoria_de_cosa) { create :categoria_de_cosa, fecha: }
         | 
| 18 18 | 
             
              let(:fecha) { Date.new(2024, 8, 12) }
         | 
| @@ -19,7 +19,7 @@ describe 'Sign in' do | |
| 19 19 | 
             
                before do
         | 
| 20 20 | 
             
                  create_list :cosa, 5
         | 
| 21 21 | 
             
                  login_as user
         | 
| 22 | 
            -
                  visit '/ | 
| 22 | 
            +
                  visit '/a/cosas'
         | 
| 23 23 | 
             
                end
         | 
| 24 24 |  | 
| 25 25 | 
             
                it do
         | 
| @@ -40,12 +40,12 @@ describe 'Sign in' do | |
| 40 40 |  | 
| 41 41 | 
             
                before do
         | 
| 42 42 | 
             
                  login_as user
         | 
| 43 | 
            -
                  visit "/ | 
| 43 | 
            +
                  visit "/a/cosas/#{cosa.to_param}"
         | 
| 44 44 | 
             
                end
         | 
| 45 45 |  | 
| 46 46 | 
             
                it 'muestra el flash' do
         | 
| 47 47 | 
             
                  subject
         | 
| 48 | 
            -
                  expect(page).to have_current_path('/ | 
| 48 | 
            +
                  expect(page).to have_current_path('/a/cosas')
         | 
| 49 49 | 
             
                  expect(page).to have_text('Coso borrado')
         | 
| 50 50 | 
             
                end
         | 
| 51 51 | 
             
              end
         | 
| @@ -9,7 +9,7 @@ require 'rails_helper' | |
| 9 9 | 
             
            # DRIVER=selenium rspec
         | 
| 10 10 | 
             
            describe 'Modal windows' do
         | 
| 11 11 | 
             
              subject(:visitar) do
         | 
| 12 | 
            -
                visit '/ | 
| 12 | 
            +
                visit '/a/cosas'
         | 
| 13 13 | 
             
              end
         | 
| 14 14 |  | 
| 15 15 | 
             
              let(:logged_user) { create :user, :developer }
         | 
| @@ -38,7 +38,7 @@ describe 'Modal windows' do | |
| 38 38 | 
             
                let!(:cosa) { create :cosa, categoria_de_cosa: }
         | 
| 39 39 |  | 
| 40 40 | 
             
                it do
         | 
| 41 | 
            -
                  visit '/ | 
| 41 | 
            +
                  visit '/a/cosas/' + cosa.to_param
         | 
| 42 42 | 
             
                  click_on 'Ver categoría'
         | 
| 43 43 | 
             
                  expect(page).to have_css '.modal', text: categoria_de_cosa.nombre
         | 
| 44 44 | 
             
                end
         | 
| @@ -48,7 +48,7 @@ describe 'Modal windows' do | |
| 48 48 | 
             
                let!(:cosa) { create :cosa, categoria_de_cosa: }
         | 
| 49 49 |  | 
| 50 50 | 
             
                it do
         | 
| 51 | 
            -
                  visit '/ | 
| 51 | 
            +
                  visit '/a/cosas/' + cosa.to_param
         | 
| 52 52 | 
             
                  click_on 'Modificar'
         | 
| 53 53 | 
             
                  fill_in 'Nombre', with: ''
         | 
| 54 54 | 
             
                  find('.modal input[type=submit]').click
         | 
| @@ -63,7 +63,7 @@ describe 'Modal windows' do | |
| 63 63 | 
             
                before { create :cosa, categoria_de_cosa: }
         | 
| 64 64 |  | 
| 65 65 | 
             
                it do
         | 
| 66 | 
            -
                  visit '/ | 
| 66 | 
            +
                  visit '/a/cosas'
         | 
| 67 67 | 
             
                  find('span[title=Ver] a').click
         | 
| 68 68 | 
             
                  accept_confirm do
         | 
| 69 69 | 
             
                    find('.modal span[title=Eliminar] a').click
         | 
| @@ -77,7 +77,7 @@ describe 'Modal windows' do | |
| 77 77 | 
             
                  end
         | 
| 78 78 |  | 
| 79 79 | 
             
                  it do
         | 
| 80 | 
            -
                    visit '/ | 
| 80 | 
            +
                    visit '/a/cosas'
         | 
| 81 81 | 
             
                    find('span[title=Ver] a').click
         | 
| 82 82 | 
             
                    accept_confirm do
         | 
| 83 83 | 
             
                      find('.modal span[title=Eliminar] a').click
         | 
| @@ -17,9 +17,9 @@ describe 'Page sizes' do | |
| 17 17 |  | 
| 18 18 | 
             
              describe 'some case' do
         | 
| 19 19 | 
             
                it do
         | 
| 20 | 
            -
                  visit '/ | 
| 20 | 
            +
                  visit '/a/cosas?page_size=2'
         | 
| 21 21 | 
             
                  expect(page).to have_css('.page-item', count: 6)
         | 
| 22 | 
            -
                  visit '/ | 
| 22 | 
            +
                  visit '/a/cosas?page_size=5'
         | 
| 23 23 | 
             
                  expect(page).to have_css('.page-item', count: 4)
         | 
| 24 24 | 
             
                end
         | 
| 25 25 | 
             
              end
         | 
| @@ -34,8 +34,10 @@ describe 'Al Registrarse' do | |
| 34 34 | 
             
                    check 'user_accept_terms'
         | 
| 35 35 | 
             
                  end
         | 
| 36 36 |  | 
| 37 | 
            +
                  pending 'expect new account created also'
         | 
| 38 | 
            +
             | 
| 37 39 | 
             
                  it 'guarda el user' do
         | 
| 38 | 
            -
                    expect { subject }.to change(User, :count).by(1)
         | 
| 40 | 
            +
                    expect { subject }.to change(User.unscoped, :count).by(1)
         | 
| 39 41 | 
             
                    expect(page).to have_text('Te enviamos un correo electrónico con instrucciones')
         | 
| 40 42 | 
             
                  end
         | 
| 41 43 | 
             
                end
         | 
| @@ -57,8 +59,6 @@ describe 'Al Registrarse' do | |
| 57 59 | 
             
                  fill_in 'user_nombre', with: 'despues'
         | 
| 58 60 | 
             
                  fill_in 'user_current_password', with: password
         | 
| 59 61 | 
             
                  instance_exec('input[type=submit]', &find_scroll).click
         | 
| 60 | 
            -
                  # find('').click
         | 
| 61 | 
            -
                  sleep 1
         | 
| 62 62 | 
             
                end
         | 
| 63 63 |  | 
| 64 64 | 
             
                let(:password) { 'pass1234' }
         | 
| @@ -71,7 +71,7 @@ describe 'Al Registrarse' do | |
| 71 71 | 
             
                end
         | 
| 72 72 |  | 
| 73 73 | 
             
                it do
         | 
| 74 | 
            -
                   | 
| 74 | 
            +
                  subject
         | 
| 75 75 | 
             
                  expect(page).to have_text('Tu cuenta se ha actualizado')
         | 
| 76 76 | 
             
                end
         | 
| 77 77 | 
             
              end
         | 
| @@ -0,0 +1,55 @@ | |
| 1 | 
            +
            # Initially generated with PgRails::SystemSpecGenerator
         | 
| 2 | 
            +
            # https://github.com/martin-rosso/pg_rails
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'rails_helper'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # By default uses selenium_chrome_headless_iphone driver
         | 
| 7 | 
            +
            # run with DRIVER environment variable to override, eg:
         | 
| 8 | 
            +
            #
         | 
| 9 | 
            +
            # DRIVER=selenium rspec
         | 
| 10 | 
            +
            describe 'Tenants' do
         | 
| 11 | 
            +
              subject(:visitar) do
         | 
| 12 | 
            +
                visit '/u/cosas'
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              let(:logged_user) { create :user }
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              before do
         | 
| 18 | 
            +
                login_as logged_user
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              describe 'switcher' do
         | 
| 22 | 
            +
                it do
         | 
| 23 | 
            +
                  visitar
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  expect(page).to have_text 'No hay cosos que mostrar'
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                context 'when belongs to multiple accounts' do
         | 
| 29 | 
            +
                  let(:other_account) { create :account }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  before do
         | 
| 32 | 
            +
                    logged_user.user_accounts.create!(account: other_account)
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  it 'shows the switcher' do
         | 
| 36 | 
            +
                    visitar
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    expect(page).to have_text 'Switcher'
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  it 'switches to account' do
         | 
| 42 | 
            +
                    visitar
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    click_on other_account.to_s
         | 
| 45 | 
            +
                    expect(page).to have_text 'No hay categorías de cosas que mostrar'
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  it 'shows the profile form' do
         | 
| 49 | 
            +
                    visit '/users/edit'
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    expect(page).to have_text 'Editar Usuario'
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
            end
         | 
| @@ -5,6 +5,14 @@ | |
| 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>
         | 
| 14 | 
            +
                    <% end %>
         | 
| 15 | 
            +
                  <% end %>
         | 
| 8 16 | 
             
                  <hr>
         | 
| 9 17 | 
             
                <% end %>
         | 
| 10 18 | 
             
                <ul class="list-unstyled ps-0">
         | 
    
        data/pg_rails/lib/version.rb
    CHANGED
    
    
| @@ -31,7 +31,7 @@ class <%= class_name %>Policy < ApplicationPolicy | |
| 31 31 | 
             
              # end
         | 
| 32 32 |  | 
| 33 33 | 
             
              # def base_access_to_record?
         | 
| 34 | 
            -
              #   base_access_to_collection? && record.account ==  | 
| 34 | 
            +
              #   base_access_to_collection? && record.account == ActsAsTenant.current_tenant
         | 
| 35 35 | 
             
              # end
         | 
| 36 36 |  | 
| 37 37 | 
             
              # def base_access_to_collection?
         | 
| @@ -170,7 +170,6 @@ RSpec.describe <%= controller_class_name %>Controller do | |
| 170 170 | 
             
            <% else -%>
         | 
| 171 171 | 
             
                    post :create, params: { <%= nombre_tabla_completo_singular %>: valid_attributes }
         | 
| 172 172 | 
             
            <% end -%>
         | 
| 173 | 
            -
                    # FIXME: redirect to target object
         | 
| 174 173 | 
             
                    expect(response).to redirect_to([:<%= ns_prefix.first %>, <%= class_name %>.last])
         | 
| 175 174 | 
             
                  end
         | 
| 176 175 | 
             
                end
         | 
| @@ -219,7 +218,6 @@ RSpec.describe <%= controller_class_name %>Controller do | |
| 219 218 | 
             
            <% else -%>
         | 
| 220 219 | 
             
                    put :update, params: { id: <%= file_name %>.to_param, <%= nombre_tabla_completo_singular %>: valid_attributes }
         | 
| 221 220 | 
             
            <% end -%>
         | 
| 222 | 
            -
                    # FIXME: redirect to target object
         | 
| 223 221 | 
             
                    expect(response).to redirect_to([:<%= ns_prefix.first %>, <%= file_name %>])
         | 
| 224 222 | 
             
                  end
         | 
| 225 223 | 
             
                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. | 
| 4 | 
            +
              version: 7.5.0
         | 
| 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- | 
| 11 | 
            +
            date: 2024-09-10 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rails
         | 
| @@ -80,6 +80,20 @@ dependencies: | |
| 80 80 | 
             
                - - "~>"
         | 
| 81 81 | 
             
                  - !ruby/object:Gem::Version
         | 
| 82 82 | 
             
                    version: '5.0'
         | 
| 83 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 84 | 
            +
              name: acts_as_tenant
         | 
| 85 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 86 | 
            +
                requirements:
         | 
| 87 | 
            +
                - - "~>"
         | 
| 88 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 89 | 
            +
                    version: '1.0'
         | 
| 90 | 
            +
              type: :runtime
         | 
| 91 | 
            +
              prerelease: false
         | 
| 92 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 93 | 
            +
                requirements:
         | 
| 94 | 
            +
                - - "~>"
         | 
| 95 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 96 | 
            +
                    version: '1.0'
         | 
| 83 97 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 84 98 | 
             
              name: caxlsx_rails
         | 
| 85 99 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -670,6 +684,7 @@ files: | |
| 670 684 | 
             
            - pg_engine/app/controllers/pg_engine/require_sign_in.rb
         | 
| 671 685 | 
             
            - pg_engine/app/controllers/public/mensaje_contactos_controller.rb
         | 
| 672 686 | 
             
            - pg_engine/app/controllers/public/webhooks_controller.rb
         | 
| 687 | 
            +
            - pg_engine/app/controllers/users/account_switcher_controller.rb
         | 
| 673 688 | 
             
            - pg_engine/app/controllers/users/confirmations_controller.rb
         | 
| 674 689 | 
             
            - pg_engine/app/controllers/users/date_jumper_controller.rb
         | 
| 675 690 | 
             
            - pg_engine/app/controllers/users/notifications_controller.rb
         | 
| @@ -756,8 +771,10 @@ files: | |
| 756 771 | 
             
            - pg_engine/app/views/pg_engine/user_mailer/notification.text.slim
         | 
| 757 772 | 
             
            - pg_engine/app/views/public/mensaje_contactos/_gracias.html.slim
         | 
| 758 773 | 
             
            - pg_engine/app/views/public/mensaje_contactos/new.html.slim
         | 
| 774 | 
            +
            - pg_engine/app/views/users/account_switcher/list.html.slim
         | 
| 759 775 | 
             
            - pg_engine/config/initializers/action_mailer.rb
         | 
| 760 776 | 
             
            - pg_engine/config/initializers/active_admin.rb
         | 
| 777 | 
            +
            - pg_engine/config/initializers/acts_as_tenant.rb
         | 
| 761 778 | 
             
            - pg_engine/config/initializers/anycable.rb
         | 
| 762 779 | 
             
            - pg_engine/config/initializers/cable_ready.rb
         | 
| 763 780 | 
             
            - pg_engine/config/initializers/devise.rb
         | 
| @@ -789,6 +806,7 @@ files: | |
| 789 806 | 
             
            - pg_engine/db/migrate/20240611000219_create_noticed_tables.noticed.rb
         | 
| 790 807 | 
             
            - pg_engine/db/migrate/20240611000220_add_notifications_count_to_noticed_event.noticed.rb
         | 
| 791 808 | 
             
            - pg_engine/db/migrate/20240614130246_create_action_text_tables.action_text.rb
         | 
| 809 | 
            +
            - pg_engine/db/migrate/20240905154330_account_tenant_columns.rb
         | 
| 792 810 | 
             
            - pg_engine/db/seeds.rb
         | 
| 793 811 | 
             
            - pg_engine/lib/pg_engine.rb
         | 
| 794 812 | 
             
            - pg_engine/lib/pg_engine/configuracion.rb
         | 
| @@ -852,7 +870,9 @@ files: | |
| 852 870 | 
             
            - pg_engine/spec/pg_engine/pdf_preview_generator_spec.rb
         | 
| 853 871 | 
             
            - pg_engine/spec/requests/admin/eventos_spec.rb
         | 
| 854 872 | 
             
            - pg_engine/spec/requests/base_controller_requests_spec.rb
         | 
| 873 | 
            +
            - pg_engine/spec/requests/users/base_controller_spec.rb
         | 
| 855 874 | 
             
            - pg_engine/spec/requests/users/date_jumper_spec.rb
         | 
| 875 | 
            +
            - pg_engine/spec/requests/users/switcher_spec.rb
         | 
| 856 876 | 
             
            - pg_engine/spec/system/alerts_spec.rb
         | 
| 857 877 | 
             
            - pg_engine/spec/system/breadcrumbs_spec.rb
         | 
| 858 878 | 
             
            - pg_engine/spec/system/date_selector_spec.rb
         | 
| @@ -863,6 +883,7 @@ files: | |
| 863 883 | 
             
            - pg_engine/spec/system/page_sizes_spec.rb
         | 
| 864 884 | 
             
            - pg_engine/spec/system/send_mail_spec.rb
         | 
| 865 885 | 
             
            - pg_engine/spec/system/signup_spec.rb
         | 
| 886 | 
            +
            - pg_engine/spec/system/tenants_spec.rb
         | 
| 866 887 | 
             
            - pg_engine/spec/system/tooltips_spec.rb
         | 
| 867 888 | 
             
            - pg_layout/app/assets/stylesheets/animations.scss
         | 
| 868 889 | 
             
            - pg_layout/app/assets/stylesheets/sidebar.scss
         |