pg_rls 0.0.1.4.3 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 05d5356859c19958958aaf0c3160e2bafc66a5b3464b542b4087e8684b70dd7c
4
- data.tar.gz: 2e53e808f31b07293ea6b1071f8e237be72d483964df2d4313c1215973a07fcd
3
+ metadata.gz: 6ee45b6831bde44dff2a29fa6dd8e832e1e55970833bbbd52a9a30982f6b987a
4
+ data.tar.gz: 83013597d4b42fb6b808c8c1b7e90c58eeb3e8dc231923523a01e6454b52507d
5
5
  SHA512:
6
- metadata.gz: b4535bef8f1ed1595cd2639a2db3168c3c0d67b5f94db461bead0d1c00e94fec492e4dbf6a8481baa3f76e102946ec95ab6eed5f2930ecd010feb5d90c1f9da5
7
- data.tar.gz: 2c14bc491065d684f962a122923fbbba7e40766a02fc870c91d15655ba7a204a1aaec7656e45ae6f11cc2245a56b8327e861dba721a92fc06bb7a62660216952
6
+ metadata.gz: fae8b1317628ddc17c19753eab39937bfc237cda1c0df9b60a9c91bbe58e5203316e305fbe3175d803531e09fc9e43b0e63941cd2153aa9a363a4d4f35e0d308
7
+ data.tar.gz: a42e6f8ebc4a93739ab3475a9d436748f1c63fc2e4878011a37d9bb46db17fff79bf66bfb4f374f5cabf8496d93bcac024a285687f19bca5f19f3717fd65f05e
data/README.md CHANGED
@@ -91,7 +91,7 @@ You can add the following configuration to your Database Config File to improve
91
91
  ```yml
92
92
  # app/config/database.yml
93
93
  <% def db_username
94
- return PgRls::SECURE_USERNAME unless ENV['AS_DB_ADMIN']
94
+ return PgRls.username unless ENV['AS_DB_ADMIN']
95
95
 
96
96
  Rails.application.credentials.dig(:database, :server_1, :username)
97
97
  end %>
@@ -108,6 +108,8 @@ development:
108
108
  ```
109
109
  ### Testing
110
110
 
111
+ If you are getting `PG::InsufficientPrivilege: ERROR: permission denied ` you can override does permistion by running `RAILS_ENV=test rake db:grant_usage`
112
+
111
113
  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:
112
114
 
113
115
  ```ruby
@@ -117,8 +119,6 @@ Many application uses some sort of database cleaner before running thair spec so
117
119
  # some database cleaning strategy
118
120
 
119
121
  config.before(:suite) do
120
- # Create A Default Tenant and Grant Test User Credentials
121
- PgRls::Database::Prepared.grant_user_credentials
122
122
  # Create the tenant which in this example is company and we are using FactoryBot
123
123
  FactoryBot.create(:company, subdomain: 'app')
124
124
  # In this default case our initializer is set to search by subdomain so will use it
@@ -147,7 +147,7 @@ Everyone interacting in the PgRls project's codebases, issue trackers, chat room
147
147
 
148
148
  ## Note
149
149
  Currently we only support subdomain as a searcher but will soon integrate slug/domain and cookies support
150
-
150
+ we recommed the use of ``
151
151
  ## Show your support
152
152
 
153
153
  Give a ⭐️ if you like this project!
data/Rakefile CHANGED
@@ -2,11 +2,10 @@
2
2
 
3
3
  require 'bundler/gem_tasks'
4
4
  require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
5
6
 
6
7
  RSpec::Core::RakeTask.new(:spec)
7
8
 
8
- require 'rubocop/rake_task'
9
-
10
9
  RuboCop::RakeTask.new
11
10
 
12
11
  task default: %i[spec rubocop]
@@ -20,19 +20,25 @@ module PgRls
20
20
  end
21
21
 
22
22
  def create_tenant_migration_file
23
- migration_template(create_migration_template_path,
24
- "#{migration_path}/#{create_file_sub_name}_#{table_name}.rb",
25
- migration_version: migration_version) if creating?
23
+ if creating?
24
+ migration_template(create_migration_template_path,
25
+ "#{migration_path}/#{create_file_sub_name}_#{table_name}.rb",
26
+ migration_version: migration_version)
27
+ end
26
28
  end
27
29
 
28
30
  def convert_tenant_migration_file
29
- migration_template(convert_migration_template_path,
30
- "#{migration_path}/#{convert_file_sub_name}_#{table_name}.rb",
31
- migration_version: migration_version) unless creating?
31
+ unless creating?
32
+ migration_template(convert_migration_template_path,
33
+ "#{migration_path}/#{convert_file_sub_name}_#{table_name}.rb",
34
+ migration_version: migration_version)
35
+ end
32
36
 
33
- migration_template('convert_migration_backport.rb.tt',
34
- "#{migration_path}/pg_rls_backport_#{table_name}.rb",
35
- migration_version: migration_version) if installation_in_progress?
37
+ if installation_in_progress?
38
+ migration_template('convert_migration_backport.rb.tt',
39
+ "#{migration_path}/pg_rls_backport_#{table_name}.rb",
40
+ migration_version: migration_version)
41
+ end
36
42
  end
37
43
 
38
44
  def create_model_file
@@ -103,7 +109,7 @@ module PgRls
103
109
 
104
110
  protected
105
111
 
106
- def migration_action() = 'add'
112
+ def migration_action = 'add'
107
113
  end
108
114
  end
109
115
  end
@@ -16,8 +16,12 @@ module PgRls
16
16
  end
17
17
  super
18
18
  end
19
+ APPLICATION_LINE = 'class Application < Rails::Application'
20
+ APPLICATION_PATH = 'config/application.rb'
21
+
19
22
  APPLICATION_RECORD_LINE = 'class ApplicationRecord < ActiveRecord::Base'
20
23
  APPLICATION_RECORD_PATH = 'app/models/application_record.rb'
24
+
21
25
  APPLICATION_CONTROLLER_LINE = 'class ApplicationController < ActionController::Base'
22
26
  APPLICATION_CONTROLLER_PATH = 'app/controllers/application_controller.rb'
23
27
 
@@ -41,11 +45,20 @@ module PgRls
41
45
  def copy_initializer
42
46
  raise MissingORMError, orm_error_message unless options[:orm]
43
47
 
48
+ inject_include_to_application
44
49
  inject_include_to_application_record
45
50
  inject_include_to_application_controller
46
51
  template 'pg_rls.rb.tt', 'config/initializers/pg_rls.rb'
47
52
  end
48
53
 
54
+ def inject_include_to_application
55
+ return if aplication_already_included?
56
+
57
+ gsub_file(APPLICATION_PATH, /(#{Regexp.escape(APPLICATION_LINE)})/mi) do |match|
58
+ "#{match}\n config.active_record.schema_format = :sql\n"
59
+ end
60
+ end
61
+
49
62
  def inject_include_to_application_record
50
63
  return if aplication_record_already_included?
51
64
 
@@ -70,6 +83,10 @@ module PgRls
70
83
  File.readlines(APPLICATION_RECORD_PATH).grep(/include PgRls::SecureConnection/).any?
71
84
  end
72
85
 
86
+ def aplication_already_included?
87
+ File.readlines(APPLICATION_PATH).grep(/config.active_record.schema_format = :sql/).any?
88
+ end
89
+
73
90
  def initialize_error_text
74
91
  <<-ERROR.strip_heredoc
75
92
  ERROR
@@ -2,10 +2,15 @@ README
2
2
  ===============================================================================
3
3
  WARNING!!
4
4
 
5
+ PgRls required that ActiveRecord format migration as SQL
6
+
5
7
  Once you remove a tenant all of his data would be removed as well
6
8
 
7
9
  PgRls::SecureConnection was included to your ApplicationRecord do not remove it
8
10
 
11
+ If you're setting a custom user, make sure to regenerate the structure.sql since
12
+ Postgresql policies are created on each user
13
+
9
14
  ===============================================================================
10
15
 
11
16
  to generate secure model run
@@ -9,4 +9,14 @@ PgRls.setup do |config|
9
9
  config.class_name = :<%= PgRls.class_name %>
10
10
  config.table_name = :<%= PgRls.table_name %>
11
11
  config.search_methods = <%= PgRls.search_methods %>
12
+
13
+ ##
14
+ ## Uncomment this lines if you have a custome user per enviroment
15
+ ## don't forget to grant the required privilange in order for it to run
16
+ ##
17
+ ## Remember that PgRls is adding triggers that would set the RLS to the default user
18
+ ## make sure you recreate the structure.sql on each enviroment
19
+ ##
20
+ # config.username = Rails.application.credentials.dig(:database, :username)
21
+ # config.password = Rails.application.credentials.dig(:database, :password)
12
22
  end
data/lib/pg_rls/Rakefile CHANGED
@@ -3,4 +3,5 @@
3
3
  require_relative '../pg_rls'
4
4
 
5
5
  path = File.expand_path(__dir__)
6
+
6
7
  Dir.glob("#{path}/database/tasks/**/*.rake").each { |f| import f }
@@ -5,31 +5,33 @@ module PgRls
5
5
  # Prepare database for test unit
6
6
  module Prepared
7
7
  class << self
8
- def grant_user_credentials(name: PgRls::SECURE_USERNAME, password: 'password')
9
- return unless Rails.env.test? || PgRls.default_connection?
10
-
8
+ def grant_user_credentials(name: PgRls.username, password: PgRls.password, schema: 'public')
11
9
  PgRls.admin_execute <<-SQL
12
10
  DO
13
11
  $do$
14
12
  BEGIN
15
13
  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
14
+ SELECT table_catalog, table_schema, table_name, privilege_type
15
+ FROM information_schema.table_privileges#{' '}
16
+ WHERE grantee = '#{name}'
17
+ ) THEN
18
+ GRANT ALL PRIVILEGES ON TABLE schema_migrations TO #{name};
19
+ GRANT USAGE ON SCHEMA #{schema} TO #{name};
20
+ ALTER DEFAULT PRIVILEGES IN SCHEMA #{schema}
21
+ GRANT USAGE, SELECT
22
+ ON SEQUENCES TO #{name};
23
+ ALTER DEFAULT PRIVILEGES IN SCHEMA #{schema}
24
+ GRANT SELECT, INSERT, UPDATE, DELETE
25
+ ON TABLES TO #{name};
26
+ GRANT SELECT, INSERT, UPDATE, DELETE
27
+ ON ALL TABLES IN SCHEMA #{schema}
28
+ TO #{name};
29
+ GRANT USAGE, SELECT
30
+ ON ALL SEQUENCES IN SCHEMA #{schema}
31
+ TO #{name};
32
+ END IF;
33
+ END;
22
34
  $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
35
  SQL
34
36
  end
35
37
  end
@@ -20,97 +20,155 @@ def override_task(*args, &block)
20
20
  end
21
21
 
22
22
  namespace :db do
23
+ include PgRls::Schema::UpStatements
24
+
25
+ def admin_connection
26
+ PgRls.as_db_admin = true
27
+ PgRls.establish_new_connection
28
+
29
+ yield
30
+ ensure
31
+ PgRls.as_db_admin = false
32
+ ActiveRecord::Base.connection.disconnect!
33
+ PgRls.establish_new_connection
34
+ end
35
+
36
+ override_task grant_usage: :load_config do
37
+ admin_connection do
38
+ create_rls_user
39
+ end
40
+ end
41
+
23
42
  override_task create: :load_config do
24
- system('AS_DB_ADMIN=true rake db:create:original')
43
+ admin_connection do
44
+ Rake::Task['db:create:original'].invoke
45
+ end
25
46
  end
26
47
 
27
48
  override_task drop: :load_config do
28
- system('AS_DB_ADMIN=true rake db:drop:original')
49
+ admin_connection do
50
+ Rake::Task['db:drop:original'].invoke
51
+ end
29
52
  end
30
53
 
31
54
  override_task migrate: :load_config do
32
- system('AS_DB_ADMIN=true rake db:migrate:original')
55
+ admin_connection do
56
+ Rake::Task['db:migrate:original'].invoke
57
+ end
33
58
  end
34
59
 
35
60
  override_task rollback: :load_config do
36
- system('AS_DB_ADMIN=true rake db:rollback:original')
61
+ admin_connection do
62
+ Rake::Task['db:rollback:original'].invoke
63
+ end
37
64
  end
38
65
 
39
66
  override_task prepare: :load_config do
40
- system('AS_DB_ADMIN=true rake db:prepare:original')
67
+ admin_connection do
68
+ Rake::Task['db:prepare:original'].invoke
69
+ end
41
70
  end
42
71
 
43
72
  override_task setup: :load_config do
44
- system('AS_DB_ADMIN=true rake db:setup:original')
73
+ admin_connection do
74
+ Rake::Task['db:setup:original'].invoke
75
+ end
45
76
  end
46
77
 
47
78
  override_task prepare: :load_config do
48
- system('AS_DB_ADMIN=true rake db:reset:original')
79
+ admin_connection do
80
+ Rake::Task['db:reset:original'].invoke
81
+ end
49
82
  end
50
83
 
51
84
  override_task purge: :load_config do
52
- system('AS_DB_ADMIN=true rake db:purge:original')
85
+ admin_connection do
86
+ Rake::Task['db:purge:original'].invoke
87
+ end
53
88
  end
54
89
 
55
90
  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')
91
+ admin_connection do
92
+ Rake::Task['db:abort_if_pending_migrations:original'].invoke
93
+ end
61
94
  end
62
95
 
63
96
  namespace :test do
97
+ def admin_connection_test_db
98
+ Rails.env = 'test'
99
+ PgRls.as_db_admin = true
100
+ PgRls.establish_new_connection
101
+
102
+ yield
103
+ ensure
104
+ PgRls.as_db_admin = false
105
+ ActiveRecord::Base.connection.disconnect!
106
+ PgRls.establish_new_connection
107
+ end
108
+
109
+ override_task grant_usage: :load_config do
110
+ admin_connection_test_db do
111
+ create_rls_user
112
+ end
113
+ end
114
+
64
115
  override_task create: :load_config do
65
- system('AS_DB_ADMIN=true rake db:test:create:original')
116
+ admin_connection_test_db do
117
+ Rake::Task['db:test:create:original'].invoke
118
+ end
66
119
  end
67
120
 
68
121
  override_task drop: :load_config do
69
- system('AS_DB_ADMIN=true rake db:test:drop:original')
122
+ admin_connection_test_db do
123
+ Rake::Task['db:test:drop:original'].invoke
124
+ end
70
125
  end
71
126
 
72
127
  override_task prepare: :load_config do
73
- system('AS_DB_ADMIN=true rake db:test:prepare:original')
128
+ admin_connection_test_db do
129
+ Rake::Task['db:test:prepare:original'].invoke
130
+ end
74
131
  end
75
132
 
76
133
  override_task setup: :load_config do
77
- system('AS_DB_ADMIN=true rake db:test:setup:original')
134
+ admin_connection_test_db do
135
+ Rake::Task['db:test:setup:original'].invoke
136
+ end
78
137
  end
79
138
 
80
139
  override_task purge: :load_config do
81
- system('AS_DB_ADMIN=true rake db:test:purge:original')
140
+ admin_connection_test_db do
141
+ Rake::Task['db:test:purge:original'].invoke
142
+ end
82
143
  end
83
144
 
84
145
  override_task load_schema: :load_config do
85
- system('AS_DB_ADMIN=true rake db:test:load_schema:original')
146
+ admin_connection_test_db do
147
+ Rake::Task['db:test:load_schema:original'].invoke
148
+ end
86
149
  end
87
150
  end
88
151
 
89
152
  namespace :enviroment do
90
153
  override_task set: :load_config do
91
- system('AS_DB_ADMIN=true rake db:enviroment:set:original')
154
+ admin_connection do
155
+ Rake::Task['db:enviroment:set:original'].invoke
156
+ end
92
157
  end
93
158
  end
94
159
 
95
160
  namespace :schema do
96
161
  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
162
+ admin_connection do
163
+ Rake::Task['db:schema:load:original'].invoke
164
+ Rake::Task['db:grant_usage'].invoke
165
+ Rake::Task['db:test:grant_usage'].invoke
166
+ end
167
+ end
168
+
169
+ override_task dump: :load_config do
170
+ admin_connection do
171
+ Rake::Task['db:schema:dump:original'].invoke
114
172
  end
115
173
  end
116
174
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PgRls
2
4
  module Errors
3
5
  class TenantNotFound < StandardError
@@ -12,9 +12,17 @@ module PgRls
12
12
  private
13
13
 
14
14
  def switch_tenant
15
- Tenant.switch request.subdomain
15
+ Tenant.switch!(request.subdomain)
16
+ session[:_tenant] = request.subdomain
17
+ rescue PgRls::Errors::TenantNotFound, ActiveRecord::RecordNotFound
18
+ Tenant.switch(session[:_tenant])
16
19
  rescue NoMethodError
20
+ session[:tenant] = nil
17
21
  redirect_to '/'
18
22
  end
23
+
24
+ def tenant_match_session_cookies?
25
+ session[:_tenant] == request.subdomain
26
+ end
19
27
  end
20
28
  end
@@ -6,11 +6,11 @@ module PgRls
6
6
  module DownStatements
7
7
  def drop_rls_user
8
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};
9
+ DROP OWNED BY #{PgRls.username};
10
+ REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM #{PgRls.username};
11
+ REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM #{PgRls.username};
12
+ REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public FROM #{PgRls.username};
13
+ DROP USER #{PgRls.username};
14
14
  SQL
15
15
  end
16
16
 
@@ -45,7 +45,7 @@ module PgRls
45
45
 
46
46
  def drop_rls_policy(table_name)
47
47
  ActiveRecord::Migration.execute <<-SQL
48
- DROP POLICY #{table_name}_#{PgRls::SECURE_USERNAME} ON #{table_name};
48
+ DROP POLICY #{table_name}_#{PgRls.username} ON #{table_name};
49
49
  ALTER TABLE #{table_name} DISABLE ROW LEVEL SECURITY;
50
50
  SQL
51
51
  end
@@ -11,7 +11,7 @@ module PgRls
11
11
  include DownStatements
12
12
 
13
13
  def create_rls_tenant_table(table_name, **options, &block)
14
- create_rls_user(password: PgRls.database_default_configuration[:password])
14
+ create_rls_user
15
15
  create_rls_setter_function
16
16
  create_rls_blocking_function
17
17
  create_table(table_name, **options, &block)
@@ -41,7 +41,7 @@ module PgRls
41
41
  end
42
42
 
43
43
  def convert_to_rls_tenant_table(table_name, **_options)
44
- create_rls_user(password: PgRls.database_default_configuration[:password])
44
+ create_rls_user
45
45
  create_rls_setter_function
46
46
  create_rls_blocking_function
47
47
  add_rls_column_to_tenant_table(table_name)
@@ -4,29 +4,32 @@ module PgRls
4
4
  module Schema
5
5
  # Up Schema Statements
6
6
  module UpStatements
7
- def create_rls_user(name: PgRls::SECURE_USERNAME, password: 'password')
7
+ def create_rls_user(name: PgRls.username, password: PgRls.password, schema: 'public')
8
8
  PgRls.execute <<-SQL
9
9
  DO
10
10
  $do$
11
11
  BEGIN
12
12
  IF NOT EXISTS (
13
- SELECT FROM pg_catalog.pg_roles -- SELECT list can be empty for this
14
- WHERE rolname = '#{name}') THEN
13
+ SELECT FROM pg_catalog.pg_roles -- SELECT list can be empty for this
14
+ WHERE rolname = '#{name}') THEN
15
15
 
16
- CREATE USER #{name} WITH PASSWORD '#{password}';
17
- GRANT ALL PRIVILEGES ON TABLE schema_migrations TO #{name};
18
- GRANT USAGE ON SCHEMA public TO #{name};
19
- ALTER DEFAULT PRIVILEGES IN SCHEMA public
20
- GRANT SELECT, INSERT, UPDATE, DELETE
21
- ON TABLES TO #{name};
22
- GRANT SELECT, INSERT, UPDATE, DELETE
23
- ON ALL TABLES IN SCHEMA public
24
- TO #{name};
25
- GRANT USAGE, SELECT
26
- ON ALL SEQUENCES IN SCHEMA public
27
- TO #{name};
16
+ CREATE USER #{name} WITH PASSWORD '#{password}';
28
17
  END IF;
29
- END
18
+ GRANT ALL PRIVILEGES ON TABLE schema_migrations TO #{name};
19
+ GRANT USAGE ON SCHEMA #{schema} TO #{name};
20
+ ALTER DEFAULT PRIVILEGES IN SCHEMA #{schema}
21
+ GRANT USAGE, SELECT
22
+ ON SEQUENCES TO #{name};
23
+ ALTER DEFAULT PRIVILEGES IN SCHEMA #{schema}
24
+ GRANT SELECT, INSERT, UPDATE, DELETE
25
+ ON TABLES TO #{name};
26
+ GRANT SELECT, INSERT, UPDATE, DELETE
27
+ ON ALL TABLES IN SCHEMA #{schema}
28
+ TO #{name};
29
+ GRANT USAGE, SELECT
30
+ ON ALL SEQUENCES IN SCHEMA #{schema}
31
+ TO #{name};
32
+ END;
30
33
  $do$;
31
34
  SQL
32
35
  end
@@ -87,7 +90,7 @@ module PgRls
87
90
  SQL
88
91
  end
89
92
 
90
- def create_rls_policy(table_name, user = PgRls::SECURE_USERNAME)
93
+ def create_rls_policy(table_name, user = PgRls.username)
91
94
  ActiveRecord::Migration.execute <<-SQL
92
95
  ALTER TABLE #{table_name} ENABLE ROW LEVEL SECURITY;
93
96
  CREATE POLICY #{table_name}_#{user}
@@ -3,24 +3,23 @@
3
3
  module PgRls
4
4
  # Ensure Connection is with App_use
5
5
  module SecureConnection
6
- def self.included(base)
7
- base.class_eval do
8
- after_initialize :establish_secure_connection
9
- end
10
- end
11
-
12
- private
6
+ def self.establish_secure_connection
7
+ return if secure_connection_established?
13
8
 
14
- def establish_secure_connection
15
9
  return if PgRls.default_connection?
16
10
 
17
- return if secure_connection_established?
18
-
19
11
  PgRls.establish_new_connection
20
12
  end
21
13
 
22
- def secure_connection_established?
23
- PgRls.current_connection_username == PgRls::SECURE_USERNAME
14
+ def self.secure_connection_established?
15
+ PgRls.current_connection_username == PgRls.username
16
+ end
17
+
18
+ def self.included(_base)
19
+ establish_secure_connection
20
+ # base.class_eval do
21
+ # after_initialize :establish_secure_connection
22
+ # end
24
23
  end
25
24
  end
26
25
  end
data/lib/pg_rls/tenant.rb CHANGED
@@ -4,19 +4,21 @@ module PgRls
4
4
  # Tenant Controller
5
5
  module Tenant
6
6
  class << self
7
+ attr_reader :tenant
8
+
7
9
  def switch(resource)
8
- @fetch = nil
9
- connection_adapter = PgRls.connection_class
10
- find_tenant(resource)
11
- connection_adapter.connection.execute(format('SET rls.tenant_id = %s',
12
- connection_adapter.connection.quote(tenant.tenant_id)))
13
- "RLS changed to '#{tenant.send(@method)}'"
10
+ switch_tenant!(resource)
14
11
  rescue StandardError => e
15
12
  puts 'connection was not made'
16
- puts @error || e
13
+ puts e
17
14
  end
18
15
 
19
- attr_reader :tenant
16
+ def switch!(resource)
17
+ switch_tenant!(resource)
18
+ rescue StandardError => e
19
+ puts 'connection was not made'
20
+ raise e
21
+ end
20
22
 
21
23
  def fetch
22
24
  @fetch ||= PgRls.main_model.find_by_tenant_id(
@@ -28,16 +30,28 @@ module PgRls
28
30
  'no tenant is selected'
29
31
  end
30
32
 
33
+ private
34
+
35
+ def switch_tenant!(resource)
36
+ @fetch = nil
37
+ connection_adapter = PgRls.connection_class
38
+ find_tenant(resource)
39
+
40
+ raise PgRls::Errors::TenantNotFound unless tenant.present?
41
+
42
+ connection_adapter.connection.execute(format('SET rls.tenant_id = %s',
43
+ connection_adapter.connection.quote(tenant.tenant_id)))
44
+ "RLS changed to '#{tenant.send(@method)}'"
45
+ end
46
+
31
47
  def find_tenant(resource)
32
48
  @tenant = nil
33
49
 
34
50
  PgRls.search_methods.each do |method|
35
51
  @method = method
36
52
  @tenant ||= PgRls.main_model.send("find_by_#{method}!", resource)
37
- rescue NoMethodError => e
53
+ rescue NoMethodError, ActiveRecord::RecordNotFound => e
38
54
  @error = e
39
- rescue ActiveRecord::RecordNotFound
40
- raise PgRls::Errors::TenantNotFound
41
55
  end
42
56
  end
43
57
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgRls
4
- VERSION = '0.0.1.4.3'
4
+ VERSION = '0.0.2'
5
5
  end
data/lib/pg_rls.rb CHANGED
@@ -14,7 +14,7 @@ require_relative 'pg_rls/errors/tenant_not_found'
14
14
  # PostgreSQL Row Level Security
15
15
  module PgRls
16
16
  class Error < StandardError; end
17
- SECURE_USERNAME = "#{Rails.env}_app_user".freeze
17
+ SECURE_USERNAME = 'app_user'
18
18
 
19
19
  class << self
20
20
  extend Forwardable
@@ -32,7 +32,7 @@ module PgRls
32
32
  attr_reader(*READER_METHODS)
33
33
 
34
34
  def_delegators(*DELEGATORS_METHODS)
35
- # Your code goes here...
35
+
36
36
  def setup
37
37
  yield self
38
38
  end
@@ -54,13 +54,13 @@ module PgRls
54
54
  end
55
55
 
56
56
  def admin_execute(query = nil)
57
- self.establish_default_connection = true
57
+ self.as_db_admin = true
58
58
  establish_new_connection
59
59
  return yield if block_given?
60
60
 
61
61
  execute(query)
62
62
  ensure
63
- self.establish_default_connection = false
63
+ self.as_db_admin = false
64
64
  establish_new_connection
65
65
  end
66
66
 
@@ -70,7 +70,7 @@ module PgRls
70
70
  end
71
71
 
72
72
  def default_connection?
73
- @default_connection
73
+ as_db_admin
74
74
  end
75
75
 
76
76
  def main_model
@@ -96,20 +96,46 @@ module PgRls
96
96
 
97
97
  def database_default_configuration
98
98
  connection_class.connection.pool.db_config.configuration_hash
99
+ rescue ActiveRecord::NoDatabaseError
100
+ connection_class.connection_db_config.configuration_hash
101
+ end
102
+
103
+ def database_admin_configuration
104
+ enviroment_db_configuration = database_connection_file[Rails.env]
105
+
106
+ return enviroment_db_configuration if enviroment_db_configuration['username'].present?
107
+
108
+ enviroment_db_configuration.first.last
99
109
  end
100
110
 
101
111
  def database_configuration
112
+ return database_admin_configuration if default_connection?
113
+
102
114
  current_configuration = database_default_configuration.deep_dup
103
- current_configuration.tap { |config| config[:username] = PgRls::SECURE_USERNAME unless default_connection? }
115
+ current_configuration.tap do |config|
116
+ config[:username] = PgRls.username
117
+ config[:password] = PgRls.password
118
+ end
119
+
104
120
  current_configuration.freeze
105
121
  end
106
122
  end
123
+
124
+ mattr_accessor :as_db_admin
125
+ @@as_db_admin = false
126
+
107
127
  mattr_accessor :table_name
108
128
  @@table_name = 'companies'
109
129
 
110
130
  mattr_accessor :class_name
111
131
  @@class_name = 'Company'
112
132
 
133
+ mattr_accessor :username
134
+ @@username = 'app_user'
135
+
136
+ mattr_accessor :password
137
+ @@password = 'password'
138
+
113
139
  mattr_accessor :search_methods
114
140
  @@search_methods = %i[subdomain id tenant_id]
115
141
  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.4.3
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Laloush
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-05-17 00:00:00.000000000 Z
11
+ date: 2022-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -92,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
94
  requirements: []
95
- rubygems_version: 3.3.7
95
+ rubygems_version: 3.3.15
96
96
  signing_key:
97
97
  specification_version: 4
98
98
  summary: Write a short summary, because RubyGems requires one.