pg_rls 0.0.1.1 → 0.0.1.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4adb2a4dc970c7945eea48bae37f3fe6153607ac61bfe69e5190a4f1b0d3996b
4
- data.tar.gz: 6c223603207bb885e56b4e2340c0e737747418cfeca0fea9a0cda191385cc945
3
+ metadata.gz: fa0740a77d93fc9f87723797b3bca421e957a5661e4f82211762e21e9a29e53e
4
+ data.tar.gz: 47c18a7af64db89155056eaa370131134581f56769730865bf4c9e7781208ca2
5
5
  SHA512:
6
- metadata.gz: 58a6a9f87ad417a3ce1783211afe6189fec242f7488cb238d9ec416c71b960eac7263b1c90cb6afa03460ab0b393d7af510e40b6d5d78484d4e56a89ba742982
7
- data.tar.gz: bc5efaefc28e0b965ebeebc27151b96324399275f96a5ae473ea2336e220ff10f646490b35cbd3d7d5d92cefc55b88025502a8619bb32000ebb32bbbaefaf506
6
+ metadata.gz: c0cfdbfb358da830cabf1fae1406e52d208960331f9a871aef2829a9c18d7d5f31d0e6aa5c0d96942148bb6c64060faa875ec11dfe8dd0d9e2da4d14e41637b0
7
+ data.tar.gz: f420cf2bfc326cc3b8404f5059a9e1e6b398c377319939d196539be4e2aa4c43d88d27dfd579ca0ceea71cded49a78956687798a88b788a39c5076f2de88f970
data/README.md CHANGED
@@ -1,3 +1,10 @@
1
+ <!--
2
+ Title: PgRls Rails
3
+ Description: rails multitenancy with pg rls
4
+ Author: dandush03
5
+ -->
6
+ <meta name="google-site-verification" content="Mc1vBv8PRYPw_cdd3EiKhF2vlOeIEIk3VYhAg75ertI" />
7
+
1
8
  [![Contributors][contributors-shield]][contributors-url]
2
9
  [![Forks][forks-shield]][forks-url]
3
10
  [![Stargazers][stars-shield]][stars-url]
@@ -63,7 +70,7 @@ Or install it yourself with:
63
70
  ```bash
64
71
  rails generate pg_rls:install company #=> where company eq tenant model name
65
72
  ```
66
- You can change company to anything you'd like, for example `tenant`
73
+ You can change company to anything you'd like, for example, `tenant`
67
74
  This will generate the model and inject all the required code
68
75
 
69
76
  For any new model that needs to be under rls, you can generate it by writing
@@ -77,7 +84,28 @@ You can swtich to another tenant by using
77
84
  ```ruby
78
85
  PgRls::Tenant.switch :app #=> where app eq tenant name
79
86
  ```
87
+ Don't forget to update how you want `PgRls` to find your tenant, you can set multiple options by modifying `api/config/initializers/pg_rls.rb` `search_methods`
88
+
89
+ You can add the following configuration to your Database Config File to improve performance and remove `PgRls::SecureConnection` from `aplication_record.rb`
90
+
91
+ ```yml
92
+ # app/config/database.yml
93
+ <% def db_username
94
+ return PgRls::SECURE_USERNAME unless ENV['AS_DB_ADMIN']
95
+
96
+ Rails.application.credentials.dig(:database, :server_1, :username)
97
+ end %>
98
+
99
+ ...
100
+
101
+ development:
102
+ <<: *default
103
+ database: example_development
104
+ username: <%= db_username %> # Apply this to production and all env including tests
80
105
 
106
+ ...
107
+
108
+ ```
81
109
  ### Testing
82
110
 
83
111
  Many application uses some sort of database cleaner before running thair spec so on each test that we run we'll have an empty state. Usually, those gems clear our user configuration for the database. To solve this issue, we must implement the following:
@@ -90,8 +118,10 @@ Many application uses some sort of database cleaner before running thair spec so
90
118
 
91
119
  config.before(:suite) do
92
120
  # Create A Default Tenant and Grant Test User Credentials
93
- PgRls::Test::PreparedDatabase.grant_user_credentials
121
+ PgRls::Database::Prepared.grant_user_credentials
122
+ # Create the tenant which in this example is company and we are using FactoryBot
94
123
  FactoryBot.create(:company, subdomain: 'app')
124
+ # In this default case our initializer is set to search by subdomain so will use it
95
125
  PgRls::Tenant.switch :app
96
126
  end
97
127
 
@@ -11,34 +11,86 @@ module PgRls
11
11
 
12
12
  source_root File.expand_path('./templates', __dir__)
13
13
 
14
- def create_migration_file
15
- migration_template migration_template_path, "#{migration_path}/#{file_sub_name}_#{table_name}.rb",
14
+ def check_class_collision; end
15
+
16
+ def create_migration_file; end
17
+
18
+ def migration_exist?
19
+ @migration_exist ||= Dir.glob("#{migration_path}/*create_#{table_name}.rb").present?
20
+ end
21
+
22
+ def create_tenant_migration_file
23
+ return if migration_exist?
24
+
25
+ migration_template create_migration_template_path,
26
+ "#{migration_path}/#{create_file_sub_name}_#{table_name}.rb",
27
+ migration_version: migration_version
28
+ end
29
+
30
+ def convert_tenant_migration_file
31
+ return unless migration_exist?
32
+
33
+ migration_template convert_migration_template_path,
34
+ "#{migration_path}/#{convert_file_sub_name}_#{table_name}.rb",
35
+ migration_version: migration_version
36
+
37
+ return if installation_in_progress?
38
+
39
+ migration_template 'convert_migration_backport.rb.tt',
40
+ "#{migration_path}/pg_rls_backport_#{table_name}.rb",
16
41
  migration_version: migration_version
17
42
  end
18
43
 
19
44
  def create_model_file
45
+ return if migration_exist?
46
+
20
47
  generate_abstract_class if database && !parent
21
- template model_template_path, File.join('app/models', class_path, "#{file_name}.rb")
48
+
49
+ template model_template_path, model_file
50
+ end
51
+
52
+ def inject_method_to_model
53
+ return unless installation_in_progress?
54
+
55
+ gsub_file(model_file, /Class #{class_name} < #{parent_class_name.classify}/mi) do |match|
56
+ "#{match}\n def self.current\n PgRls::Tenant.fetch\n end\n"
57
+ end
58
+ end
59
+
60
+ def model_file
61
+ File.join('app/models', class_path, "#{file_name}.rb")
22
62
  end
23
63
 
24
- def migration_template_path
64
+ def create_migration_template_path
25
65
  return 'init_migration.rb.tt' if installation_in_progress?
26
66
 
27
67
  'migration.rb.tt'
28
68
  end
29
69
 
70
+ def convert_migration_template_path
71
+ return 'init_convert_migration.rb.tt' if installation_in_progress?
72
+
73
+ 'convert_migration.rb.tt'
74
+ end
75
+
30
76
  def model_template_path
31
77
  return 'init_model.rb.tt' if installation_in_progress?
32
78
 
33
79
  'model.rb.tt'
34
80
  end
35
81
 
36
- def file_sub_name
37
- return 'pg_rls_tenant_create' if installation_in_progress?
82
+ def create_file_sub_name
83
+ return 'pg_rls_create_tenant' if installation_in_progress?
38
84
 
39
85
  'pg_rls_create'
40
86
  end
41
87
 
88
+ def convert_file_sub_name
89
+ return 'pg_rls_convert_tenant' if installation_in_progress?
90
+
91
+ 'pg_rls_convert'
92
+ end
93
+
42
94
  def installation_in_progress?
43
95
  shell.base.class.name.include?('Install')
44
96
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PgRlsConvert<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
4
+ def up
5
+ convert_to_rls_table :<%= table_name %>
6
+ end
7
+
8
+ def down
9
+ revert_rls_table :<%= table_name %>
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PgRlsBackport<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
4
+ def up
5
+ # Suggested Code:
6
+ # PgRls.all_tenants do |tenant|
7
+ # tenant.<%= table_name %>.in_batches(of: 100) do |<%= table_name %>|
8
+ # <%= table_name %>.each { |<%= table_name.singularize %>| <%= table_name.singularize %>.update_attribute('tenant_id', tenant.tenant_id) }
9
+ # end
10
+ # end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PgRlsConvertTenant<%= PgRls.table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
4
+ def up
5
+ convert_to_rls_tenant_table :<%= table_name %>
6
+ end
7
+
8
+ def down
9
+ revert_rls_tenant_table :<%= table_name %>
10
+ end
11
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class PgRlsTenantCreate<%= PgRls.table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
3
+ class PgRlsCreateTenant<%= PgRls.table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
4
4
  def up
5
5
  create_rls_tenant_table :<%= table_name %>, id: :uuid do |t|
6
6
  t.string :name
@@ -8,4 +8,5 @@ PgRls.setup do |config|
8
8
  # Do not remove this value after initialization
9
9
  config.class_name = :<%= PgRls.class_name %>
10
10
  config.table_name = :<%= PgRls.table_name %>
11
+ config.search_methods = <%= PgRls.search_methods %>
11
12
  end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../pg_rls'
4
+
5
+ path = File.expand_path(__dir__)
6
+ Dir.glob("#{path}/database/tasks/**/*.rake").each { |f| import f }
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgRls
4
+ module Database
5
+ # Prepare database for test unit
6
+ module Prepared
7
+ class << self
8
+ def grant_user_credentials(name: PgRls::SECURE_USERNAME, password: 'password')
9
+ return unless Rails.env.test? || PgRls.default_connection?
10
+
11
+ PgRls.admin_execute <<-SQL
12
+ DO
13
+ $do$
14
+ BEGIN
15
+ IF NOT EXISTS (
16
+ SELECT FROM pg_catalog.pg_roles AS r
17
+ WHERE r.rolname = '#{name}') THEN
18
+
19
+ CREATE USER #{name} WITH PASSWORD '#{password}';
20
+ END IF;
21
+ END
22
+ $do$;
23
+ GRANT USAGE ON SCHEMA public TO #{name};
24
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public
25
+ GRANT SELECT, INSERT, UPDATE, DELETE
26
+ ON TABLES TO #{name};
27
+ GRANT SELECT, INSERT, UPDATE, DELETE
28
+ ON ALL TABLES IN SCHEMA public
29
+ TO #{name};
30
+ GRANT USAGE, SELECT
31
+ ON ALL SEQUENCES IN SCHEMA public
32
+ TO #{name};
33
+ SQL
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ # OVERIDE RAILS TASK
4
+ Rake::TaskManager.class_eval do
5
+ def alias_task(fq_name)
6
+ new_name = "#{fq_name}:original"
7
+ @tasks[new_name] = @tasks.delete(fq_name)
8
+ end
9
+ end
10
+
11
+ def alias_task(fq_name)
12
+ Rake.application.alias_task(fq_name)
13
+ end
14
+
15
+ def override_task(*args, &block)
16
+ name, _params, _deps = Rake.application.resolve_args(args.dup)
17
+ fq_name = Rake.application.instance_variable_get(:@scope).to_a.reverse.push(name).join(':')
18
+ alias_task(fq_name)
19
+ Rake::Task.define_task(*args, &block)
20
+ end
21
+
22
+ namespace :db do
23
+ override_task create: :load_config do
24
+ system('AS_DB_ADMIN=true rake db:create:original')
25
+ end
26
+
27
+ override_task drop: :load_config do
28
+ system('AS_DB_ADMIN=true rake db:drop:original')
29
+ end
30
+
31
+ override_task migrate: :load_config do
32
+ system('AS_DB_ADMIN=true rake db:migrate:original')
33
+ end
34
+
35
+ override_task rollback: :load_config do
36
+ system('AS_DB_ADMIN=true rake db:rollback:original')
37
+ end
38
+
39
+ override_task prepare: :load_config do
40
+ system('AS_DB_ADMIN=true rake db:prepare:original')
41
+ end
42
+
43
+ override_task setup: :load_config do
44
+ system('AS_DB_ADMIN=true rake db:setup:original')
45
+ end
46
+
47
+ override_task prepare: :load_config do
48
+ system('AS_DB_ADMIN=true rake db:reset:original')
49
+ end
50
+
51
+ override_task purge: :load_config do
52
+ system('AS_DB_ADMIN=true rake db:purge:original')
53
+ end
54
+
55
+ override_task abort_if_pending_migrations: :load_config do
56
+ system('AS_DB_ADMIN=true rake db:abort_if_pending_migrations:original')
57
+ end
58
+
59
+ override_task seed: :load_config do
60
+ system('AS_DB_ADMIN=true rake db:seed:original')
61
+ end
62
+
63
+ namespace :test do
64
+ override_task create: :load_config do
65
+ system('AS_DB_ADMIN=true rake db:test:create:original')
66
+ end
67
+
68
+ override_task drop: :load_config do
69
+ system('AS_DB_ADMIN=true rake db:test:drop:original')
70
+ end
71
+
72
+ override_task prepare: :load_config do
73
+ system('AS_DB_ADMIN=true rake db:test:prepare:original')
74
+ end
75
+
76
+ override_task setup: :load_config do
77
+ system('AS_DB_ADMIN=true rake db:test:setup:original')
78
+ end
79
+
80
+ override_task purge: :load_config do
81
+ system('AS_DB_ADMIN=true rake db:test:purge:original')
82
+ end
83
+
84
+ override_task load_schema: :load_config do
85
+ system('AS_DB_ADMIN=true rake db:test:load_schema:original')
86
+ end
87
+ end
88
+
89
+ namespace :enviroment do
90
+ override_task set: :load_config do
91
+ system('AS_DB_ADMIN=true rake db:enviroment:set:original')
92
+ end
93
+ end
94
+
95
+ namespace :schema do
96
+ override_task load: :load_config do
97
+ system('AS_DB_ADMIN=true rake db:schema:load:original')
98
+ PgRls.admin_execute do
99
+ PgRls.execute <<-SQL
100
+ DROP ROLE IF EXISTS #{PgRls::SECURE_USERNAME};
101
+ CREATE USER #{PgRls::SECURE_USERNAME} WITH PASSWORD '#{PgRls.database_configuration['password']}';
102
+ GRANT ALL PRIVILEGES ON TABLE schema_migrations TO #{PgRls::SECURE_USERNAME};
103
+ GRANT USAGE ON SCHEMA public TO #{PgRls::SECURE_USERNAME};
104
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public
105
+ GRANT SELECT, INSERT, UPDATE, DELETE
106
+ ON TABLES TO #{PgRls::SECURE_USERNAME};
107
+ GRANT SELECT, INSERT, UPDATE, DELETE
108
+ ON ALL TABLES IN SCHEMA public
109
+ TO #{PgRls::SECURE_USERNAME};
110
+ GRANT USAGE, SELECT
111
+ ON ALL SEQUENCES IN SCHEMA public
112
+ TO #{PgRls::SECURE_USERNAME};
113
+ SQL
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../pg_rls'
4
+ require 'rails'
5
+
6
+ module PgRls
7
+ # Extend Rails Railties
8
+ class Railtie < Rails::Railtie
9
+ railtie_name :my_gem
10
+
11
+ rake_tasks do
12
+ path = File.dirname(__FILE__)
13
+ Dir.glob("#{path}/database/tasks/**/*.rake").each { |f| load f }
14
+ end
15
+ end
16
+ end
@@ -5,7 +5,13 @@ module PgRls
5
5
  # Down Schema Statements
6
6
  module DownStatements
7
7
  def drop_rls_user
8
- ActiveRecord::Migration.execute "DROP USER #{PgRls::SECURE_USERNAME};"
8
+ ActiveRecord::Migration.execute <<~SQL
9
+ DROP OWNED BY #{PgRls::SECURE_USERNAME};
10
+ REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM #{PgRls::SECURE_USERNAME};
11
+ REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM #{PgRls::SECURE_USERNAME};
12
+ REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public FROM #{PgRls::SECURE_USERNAME};
13
+ DROP USER #{PgRls::SECURE_USERNAME};
14
+ SQL
9
15
  end
10
16
 
11
17
  def drop_rls_blocking_function
@@ -27,11 +27,11 @@ module PgRls
27
27
  end
28
28
 
29
29
  def drop_rls_tenant_table(table_name)
30
- drop_rls_user
31
30
  drop_rls_setter_function
32
31
  detach_blocking_function(table_name)
33
32
  drop_table(table_name)
34
33
  drop_rls_blocking_function
34
+ drop_rls_user
35
35
  end
36
36
 
37
37
  def drop_rls_table(table_name)
@@ -39,6 +39,34 @@ module PgRls
39
39
  drop_rls_policy(table_name)
40
40
  drop_table(table_name)
41
41
  end
42
+
43
+ def convert_to_rls_tenant_table(table_name, **_options)
44
+ create_rls_user(password: PgRls.database_configuration['password'])
45
+ create_rls_setter_function
46
+ create_rls_blocking_function
47
+ add_rls_column_to_tenant_table(table_name)
48
+ append_blocking_function(table_name)
49
+ end
50
+
51
+ def revert_rls_tenant_table(table_name)
52
+ drop_rls_setter_function
53
+ detach_blocking_function(table_name)
54
+ drop_rls_blocking_function
55
+ drop_rls_user
56
+ drop_rls_column(table_name)
57
+ end
58
+
59
+ def convert_to_rls_table(table_name)
60
+ add_rls_column(table_name)
61
+ create_rls_policy(table_name)
62
+ append_trigger_function(table_name)
63
+ end
64
+
65
+ def revert_rls_table(table_name)
66
+ detach_trigger_function(table_name)
67
+ drop_rls_policy(table_name)
68
+ drop_rls_column(table_name)
69
+ end
42
70
  end
43
71
  end
44
72
  end
@@ -9,9 +9,16 @@ module PgRls
9
9
  DROP ROLE IF EXISTS #{name};
10
10
  CREATE USER #{name} WITH PASSWORD '#{password}';
11
11
  GRANT ALL PRIVILEGES ON TABLE schema_migrations TO #{name};
12
+ GRANT USAGE ON SCHEMA public TO #{name};
12
13
  ALTER DEFAULT PRIVILEGES IN SCHEMA public
13
14
  GRANT SELECT, INSERT, UPDATE, DELETE
14
15
  ON TABLES TO #{name};
16
+ GRANT SELECT, INSERT, UPDATE, DELETE
17
+ ON ALL TABLES IN SCHEMA public
18
+ TO #{name};
19
+ GRANT USAGE, SELECT
20
+ ON ALL SEQUENCES IN SCHEMA public
21
+ TO #{name};
15
22
  SQL
16
23
  end
17
24
 
@@ -12,6 +12,8 @@ module PgRls
12
12
  private
13
13
 
14
14
  def establish_secure_connection
15
+ return if PgRls.default_connection?
16
+
15
17
  return if secure_connection_established?
16
18
 
17
19
  PgRls.establish_new_connection
data/lib/pg_rls/tenant.rb CHANGED
@@ -6,21 +6,19 @@ module PgRls
6
6
  class << self
7
7
  def switch(resource)
8
8
  connection_adapter = PgRls.connection_class
9
- tenant = tenant_by_subdomain_uuid_or_tenant_id(resource)
9
+ find_tenant(resource)
10
10
  connection_adapter.connection.execute(format('SET rls.tenant_id = %s',
11
11
  connection_adapter.connection.quote(tenant.tenant_id)))
12
- "RLS changed to '#{tenant.name}'"
12
+ "RLS changed to '#{tenant.send(@method)}'"
13
13
  rescue StandardError => e
14
14
  puts 'connection was not made'
15
- puts e
15
+ puts @error || e
16
16
  end
17
17
 
18
- def tenant
19
- PgRls.class_name.to_s.camelize.constantize
20
- end
18
+ attr_reader :tenant
21
19
 
22
20
  def fetch
23
- tenant.find_by_tenant_id(
21
+ @fetch ||= tenant.find_by_tenant_id(
24
22
  PgRls.connection_class.connection.execute(
25
23
  "SELECT current_setting('rls.tenant_id')"
26
24
  ).getvalue(0, 0)
@@ -29,8 +27,15 @@ module PgRls
29
27
  'no tenant is selected'
30
28
  end
31
29
 
32
- def tenant_by_subdomain_uuid_or_tenant_id(resource)
33
- tenant.find_by_subdomain(resource) || tenant.find_by_id(resource) || tenant.find_by_tenant_id(resource)
30
+ def find_tenant(resource)
31
+ @tenant = nil
32
+
33
+ PgRls.search_methods.each do |method|
34
+ @method = method
35
+ @tenant ||= PgRls.main_model.send("find_by_#{method}", resource)
36
+ rescue NoMethodError => e
37
+ @error = e
38
+ end
34
39
  end
35
40
  end
36
41
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgRls
4
- VERSION = '0.0.1.1'
4
+ VERSION = '0.0.1.4.1'
5
5
  end
data/lib/pg_rls.rb CHANGED
@@ -3,11 +3,12 @@
3
3
  require 'active_record'
4
4
  require 'forwardable'
5
5
  require_relative 'pg_rls/version'
6
- require_relative 'pg_rls/test/prepared_database'
6
+ require_relative 'pg_rls/database/prepared'
7
7
  require_relative 'pg_rls/schema/statements'
8
8
  require_relative 'pg_rls/tenant'
9
9
  require_relative 'pg_rls/secure_connection'
10
10
  require_relative 'pg_rls/multi_tenancy'
11
+ require_relative 'pg_rls/railtie' if defined?(Rails)
11
12
 
12
13
  # PostgreSQL Row Level Security
13
14
  module PgRls
@@ -17,12 +18,13 @@ module PgRls
17
18
  class << self
18
19
  extend Forwardable
19
20
 
20
- WRITER_METHODS = %i[table_name class_name].freeze
21
+ WRITER_METHODS = %i[table_name class_name search_methods establish_default_connection].freeze
21
22
  READER_METHODS = %i[
22
- connection_class database_configuration execute table_name class_name
23
+ connection_class database_configuration execute table_name class_name search_methods establish_default_connection
23
24
  ].freeze
24
25
  DELEGATORS_METHODS = %i[
25
- connection_class database_configuration execute table_name class_name
26
+ connection_class database_configuration execute table_name search_methods
27
+ class_name all_tenants main_model establish_default_connection
26
28
  ].freeze
27
29
 
28
30
  attr_writer(*WRITER_METHODS)
@@ -50,17 +52,50 @@ module PgRls
50
52
  )
51
53
  end
52
54
 
55
+ def admin_execute(query = nil)
56
+ self.establish_default_connection = true
57
+ establish_new_connection
58
+ return yield if block_given?
59
+
60
+ execute(query)
61
+ ensure
62
+ self.establish_default_connection = false
63
+ establish_new_connection
64
+ end
65
+
66
+ def establish_default_connection=(value)
67
+ ENV['AS_DB_ADMIN'] = value.to_s
68
+ @default_connection = value
69
+ end
70
+
71
+ def default_connection?
72
+ @default_connection
73
+ end
74
+
75
+ def main_model
76
+ class_name.to_s.camelize.constantize
77
+ end
78
+
79
+ def all_tenants
80
+ main_model.all.each do |tenant|
81
+ allowed_search_fields = search_methods.map(&:to_s).intersection(main_model.column_names)
82
+ Tenant.switch tenant.send(allowed_search_fields.first)
83
+
84
+ yield(tenant) if block_given?
85
+ end
86
+ end
87
+
53
88
  def current_connection_username
54
- PgRls.connection_class.connection_db_config.configuration_hash[:username]
89
+ connection_class.connection_db_config.configuration_hash[:username]
55
90
  end
56
91
 
57
92
  def execute(query)
58
- @execute = ActiveRecord::Migration.execute(query)
93
+ ActiveRecord::Migration.execute(query)
59
94
  end
60
95
 
61
96
  def database_configuration
62
- @database_configuration ||= database_connection_file[Rails.env].tap do |config|
63
- config['username'] = PgRls::SECURE_USERNAME
97
+ database_connection_file[Rails.env].tap do |config|
98
+ config['username'] = PgRls::SECURE_USERNAME unless default_connection?
64
99
  end
65
100
  end
66
101
  end
@@ -69,4 +104,7 @@ module PgRls
69
104
 
70
105
  mattr_accessor :class_name
71
106
  @@class_name = 'Company'
107
+
108
+ mattr_accessor :search_methods
109
+ @@search_methods = %i[subdomain id tenant_id]
72
110
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_rls
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.1
4
+ version: 0.0.1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Laloush
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-30 00:00:00.000000000 Z
11
+ date: 2022-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -47,6 +47,9 @@ files:
47
47
  - lib/generators/pg_rls.rb
48
48
  - lib/generators/pg_rls/active_record/active_record_generator.rb
49
49
  - lib/generators/pg_rls/active_record/templates/abstract_base_class.rb.tt
50
+ - lib/generators/pg_rls/active_record/templates/convert_migration.rb.tt
51
+ - lib/generators/pg_rls/active_record/templates/convert_migration_backport.rb.tt
52
+ - lib/generators/pg_rls/active_record/templates/init_convert_migration.rb.tt
50
53
  - lib/generators/pg_rls/active_record/templates/init_migration.rb.tt
51
54
  - lib/generators/pg_rls/active_record/templates/init_model.rb.tt
52
55
  - lib/generators/pg_rls/active_record/templates/migration.rb.tt
@@ -57,18 +60,22 @@ files:
57
60
  - lib/generators/templates/README
58
61
  - lib/generators/templates/pg_rls.rb.tt
59
62
  - lib/pg_rls.rb
63
+ - lib/pg_rls/Rakefile
64
+ - lib/pg_rls/database/prepared.rb
65
+ - lib/pg_rls/database/tasks/admin_database.rake
60
66
  - lib/pg_rls/multi_tenancy.rb
67
+ - lib/pg_rls/railtie.rb
61
68
  - lib/pg_rls/schema/down_statements.rb
62
69
  - lib/pg_rls/schema/statements.rb
63
70
  - lib/pg_rls/schema/up_statements.rb
64
71
  - lib/pg_rls/secure_connection.rb
65
72
  - lib/pg_rls/tenant.rb
66
- - lib/pg_rls/test/prepared_database.rb
67
73
  - lib/pg_rls/version.rb
68
74
  homepage: https://github.com/Dandush03/pg_rls
69
75
  licenses:
70
76
  - MIT
71
- metadata: {}
77
+ metadata:
78
+ rubygems_mfa_required: 'true'
72
79
  post_install_message:
73
80
  rdoc_options: []
74
81
  require_paths:
@@ -84,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
91
  - !ruby/object:Gem::Version
85
92
  version: '0'
86
93
  requirements: []
87
- rubygems_version: 3.2.27
94
+ rubygems_version: 3.3.3
88
95
  signing_key:
89
96
  specification_version: 4
90
97
  summary: Write a short summary, because RubyGems requires one.
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module PgRls
4
- module Test
5
- # Prepare database for test unit
6
- module PreparedDatabase
7
- class << self
8
- def grant_user_credentials(name: PgRls::SECURE_USERNAME)
9
- return unless Rails.env.test?
10
-
11
- PgRls.execute <<-SQL
12
- GRANT USAGE, SELECT
13
- ON ALL SEQUENCES IN SCHEMA public
14
- TO #{name};
15
- GRANT SELECT, INSERT, UPDATE, DELETE
16
- ON ALL TABLES IN SCHEMA public
17
- TO #{name};
18
- SQL
19
- end
20
- end
21
- end
22
- end
23
- end