Module: PgRls

Extended by:
Forwardable
Defined in:
lib/pg_rls.rb,
lib/pg_rls/tenant.rb,
lib/pg_rls/railtie.rb,
lib/pg_rls/version.rb,
lib/generators/pg_rls.rb,
lib/pg_rls/middleware.rb,
lib/pg_rls/multi_tenancy.rb,
lib/generators/pg_rls/base.rb,
lib/pg_rls/database/prepared.rb,
lib/pg_rls/schema/statements.rb,
lib/pg_rls/middleware/sidekiq.rb,
lib/pg_rls/schema/up_statements.rb,
lib/pg_rls/errors/admin_username.rb,
lib/pg_rls/errors/rake_only_error.rb,
lib/pg_rls/schema/down_statements.rb,
lib/pg_rls/errors/tenant_not_found.rb,
lib/pg_rls/middleware/sidekiq/client.rb,
lib/pg_rls/middleware/sidekiq/server.rb,
lib/generators/pg_rls/pg_rls_generator.rb,
lib/generators/pg_rls/install_generator.rb,
lib/pg_rls/middleware/set_reset_connection.rb,
lib/pg_rls/middleware/set_reset_connection.rb,
lib/generators/pg_rls/active_record/active_record_generator.rb

Overview

:nocov:

Defined Under Namespace

Modules: Base, Database, Errors, Generators, Middleware, MultiTenancy, Schema, Tenant Classes: Error, FrozenConfiguration, Railtie

Constant Summary collapse

SECURE_USERNAME =
'app_user'
WRITER_METHODS =
%i[table_name class_name search_methods].freeze
READER_METHODS =
%i[
  connection_class execute table_name class_name search_methods
].freeze
DELEGATORS_METHODS =
%i[
  connection_class execute table_name search_methods
  class_name main_model
].freeze
VERSION =
'0.1.3'
@@table_name =
'companies'
@@class_name =
'Company'
@@username =
'app_user'
@@password =
'password'
@@test_inline_tenant =
false
@@search_methods =
%i[subdomain id tenant_id]

Class Method Summary collapse

Class Method Details

.admin_connection?Boolean

Returns:

  • (Boolean)


128
129
130
# File 'lib/pg_rls.rb', line 128

def admin_connection?
  current_db_username != username
end

.admin_execute(query = nil) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/pg_rls.rb', line 63

def admin_execute(query = nil, &)
  current_tenant = PgRls::Tenant.fetch
  establish_new_connection!(admin: true)

  return ensure_block_execution(&) if block_given?

  execute(query)
ensure
  establish_new_connection!
  PgRls::Tenant.switch(current_tenant) if current_tenant.present?
end

.admin_tasks_executeObject



53
54
55
56
57
58
59
60
61
# File 'lib/pg_rls.rb', line 53

def admin_tasks_execute
  raise PgRls::Errors::RakeOnlyError unless rake_tasks?

  self.as_db_admin = true

  yield
ensure
  self.as_db_admin = false
end

.as_db_admin?Boolean

Returns:

  • (Boolean)


124
125
126
# File 'lib/pg_rls.rb', line 124

def as_db_admin?
  @as_db_admin || false
end

.connection_classObject



43
44
45
# File 'lib/pg_rls.rb', line 43

def connection_class
  @connection_class ||= ActiveRecord::Base
end

.current_db_usernameObject



120
121
122
# File 'lib/pg_rls.rb', line 120

def current_db_username
  ActiveRecord::Base.connection_db_config.configuration_hash[:username]
end

.establish_new_connection!(admin: false) ⇒ Object



75
76
77
78
79
80
81
82
# File 'lib/pg_rls.rb', line 75

def establish_new_connection!(admin: false)
  self.as_db_admin = admin

  execute_rls_in_shards do |connection_class, pool|
    connection_class.remove_connection
    connection_class.establish_connection(pool.db_config)
  end
end

.execute_rls_in_shardsObject



105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/pg_rls.rb', line 105

def execute_rls_in_shards
  connection_pool_list = PgRls.connection_class.connection_handler.connection_pool_list
  result = []

  connection_pool_list.each do |pool|
    pool.connection.transaction do
      Rails.logger.info("Executing in #{pool.connection.connection_class}")

      result << yield(pool.connection.connection_class, pool)
    end
  end

  result
end

.main_modelObject



84
85
86
# File 'lib/pg_rls.rb', line 84

def main_model
  class_name.to_s.camelize.constantize
end

.on_each_tenantObject



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/pg_rls.rb', line 88

def on_each_tenant(&)
  with_rls_connection do
    result = []

    main_model.find_each do |tenant|
      allowed_search_fields = search_methods.map(&:to_s).intersection(main_model.column_names)
      Tenant.switch tenant.send(allowed_search_fields.first)

      result << { tenant:, result: ensure_block_execution(tenant, &) }
    end

    PgRls::Tenant.reset_rls!

    result
  end
end

.rake_tasks?Boolean

Returns:

  • (Boolean)


47
48
49
50
51
# File 'lib/pg_rls.rb', line 47

def rake_tasks?
  Rake.application.top_level_tasks.present? || ARGV.any? { |arg| arg =~ /rake|dsl/ }
rescue NoMethodError
  false
end

.session_key_prefixObject



30
31
32
# File 'lib/pg_rls/middleware/set_reset_connection.rb', line 30

def self.session_key_prefix
  @session_key_prefix ||= @session_key_prefix || @session_store_server[:key_prefix]
end

.session_key_prefix=(val) ⇒ Object

Raises:

  • (Errors::FrozenConfiguration)


34
35
36
37
38
# File 'lib/pg_rls/middleware/set_reset_connection.rb', line 34

def self.session_key_prefix=(val)
  raise Errors::FrozenConfiguration unless @sessions.nil?

  @session_key_prefix = val
end

.session_prefixObject



10
11
12
13
14
15
16
# File 'lib/pg_rls/middleware/set_reset_connection.rb', line 10

def self.session_prefix
  @session_prefix ||= begin
    store_default_warden_key = @session_store_default_warden_key || '2'

    "#{session_key_prefix}:#{store_default_warden_key}::"
  end
end

.session_store_default_warden_key=(val) ⇒ Object

Raises:

  • (Errors::FrozenConfiguration)


24
25
26
27
28
# File 'lib/pg_rls/middleware/set_reset_connection.rb', line 24

def self.session_store_default_warden_key=(val)
  raise Errors::FrozenConfiguration unless @sessions.nil?

  @session_store_default_warden_key = val
end

.session_store_server=(opts = {}) ⇒ Object

Raises:

  • (Errors::FrozenConfiguration)


18
19
20
21
22
# File 'lib/pg_rls/middleware/set_reset_connection.rb', line 18

def self.session_store_server=(opts = {})
  raise Errors::FrozenConfiguration unless @sessions.nil?

  @session_store_server = opts.deep_symbolize_keys
end

.sessionsObject



6
7
8
# File 'lib/pg_rls/middleware/set_reset_connection.rb', line 6

def self.sessions
  @sessions ||= Redis.new(@session_store_server)
end

.setup {|_self| ... } ⇒ Object

Yields:

  • (_self)

Yield Parameters:

  • _self (PgRls)

    the object that the method was called on



36
37
38
39
40
41
# File 'lib/pg_rls.rb', line 36

def setup
  ActiveRecord::ConnectionAdapters::AbstractAdapter.include PgRls::Schema::Statements
  ActiveRecord::Base.ignored_columns += %w[tenant_id]

  yield self
end