pg_rls 0.1.3 → 0.1.5

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: 0e0133ebb0867d0bfeeea122f6ddef47f861c6b17e2b8b65a07acdca4768c66a
4
- data.tar.gz: 5bd700b9dd72150b01e72086f07795772cbb3f3b512e7106dbf58b2850713414
3
+ metadata.gz: 96c51a563fc96608b2c952922f3f38475fe3dcd2a1822ee367a80b50997df72c
4
+ data.tar.gz: 1540d7bdc72fa8a2ea31eeeeadcb22ad06c5efc80b54440edc3a4ecdd6af155c
5
5
  SHA512:
6
- metadata.gz: af0c6529cd940354cbaf1432c7086e1ae336f0d160df036108820873f31699c580833b7b153956e1b599b26946de15e8bfd5eda2dc94e10fa8b0b757fc94bcf1
7
- data.tar.gz: 04feda60ca3f7fa0e98f096246db9ba2d4eecac158af08f719631e7f078b224e5dc33b660e92129a6eb70e217bb7e550fdf74843015b1df988272954d756192c
6
+ metadata.gz: '082c4cad7586ccf9f1c5aef6047489c52b86d4bd1b1dc3de0c4b2d7afec357d9b2463cdf753987c52657067372f5ac4fe271b874fabd383156519b34bebfca2f'
7
+ data.tar.gz: 9b46030589110529d4a2c6cd92590700cfd16fa139aa0e257431d43de19faf38f7d5e1bb8541c06253ec878dbbe4e9b92969cfcfa89df78bb47d0ba1cb206884
data/.rubocop.yml CHANGED
@@ -24,3 +24,6 @@ Security/MarshalLoad:
24
24
  Metrics/ModuleLength:
25
25
  Exclude:
26
26
  - 'lib/pg_rls.rb'
27
+ Naming/AccessorMethodName:
28
+ Exclude:
29
+ - 'lib/pg_rls/tenant.rb'
data/Gemfile.lock CHANGED
@@ -1,8 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pg_rls (0.1.1)
5
- bundler (~> 2.2)
4
+ pg_rls (0.1.5)
6
5
 
7
6
  GEM
8
7
  remote: https://rubygems.org/
@@ -132,6 +131,8 @@ GEM
132
131
  net-smtp (0.4.0)
133
132
  net-protocol
134
133
  nio4r (2.5.9)
134
+ nokogiri (1.15.4-arm64-darwin)
135
+ racc (~> 1.4)
135
136
  nokogiri (1.15.4-x86_64-linux)
136
137
  racc (~> 1.4)
137
138
  parallel (1.23.0)
@@ -266,6 +267,7 @@ GEM
266
267
  zeitwerk (2.6.12)
267
268
 
268
269
  PLATFORMS
270
+ arm64-darwin-22
269
271
  x86_64-linux
270
272
 
271
273
  DEPENDENCIES
@@ -284,4 +286,4 @@ RUBY VERSION
284
286
  ruby 3.2.2p53
285
287
 
286
288
  BUNDLED WITH
287
- 2.3.15
289
+ 2.4.22
@@ -16,6 +16,7 @@ module PgRls
16
16
  end
17
17
  super
18
18
  end
19
+ ENVIRONMENT_LINE = 'Rails.application.initialize!'
19
20
  ENVIRONMENT_PATH = 'config/environment.rb'
20
21
 
21
22
  APPLICATION_LINE = 'class Application < Rails::Application'
@@ -55,7 +56,9 @@ module PgRls
55
56
  def inject_include_to_environment
56
57
  return if environment_already_included?
57
58
 
58
- prepend_to_file(ENVIRONMENT_PATH, "\nrequire_relative 'initializers/pg_rls'\n")
59
+ gsub_file(ENVIRONMENT_PATH, /(#{Regexp.escape(ENVIRONMENT_LINE)})/mio) do |match|
60
+ "require_relative 'initializers/pg_rls'\n#{match}"
61
+ end
59
62
  end
60
63
 
61
64
  def inject_include_to_application
@@ -83,7 +86,7 @@ module PgRls
83
86
  end
84
87
 
85
88
  def environment_already_included?
86
- File.readlines(ENVIRONMENT_PATH).grep(/require_relative 'initializers\/pg_rls'/).any?
89
+ File.readlines(ENVIRONMENT_PATH).grep(%r{require_relative 'initializers/pg_rls'}).any?
87
90
  end
88
91
 
89
92
  def initialize_error_text
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgRls
4
+ module Admin
5
+ module ActiveRecord
6
+ module Migrator
7
+ def initialize(*args)
8
+ PgRls.instance_variable_set(:@as_db_admin, true)
9
+ super
10
+ end
11
+ end
12
+
13
+ module Tasks
14
+ module DatabaseTasks
15
+ def resolve_configuration(configuration)
16
+ PgRls.instance_variable_set(:@as_db_admin, true) unless PgRls.as_db_admin?
17
+ super
18
+ end
19
+
20
+ def migration_class
21
+ PgRls.instance_variable_set(:@as_db_admin, true) unless PgRls.as_db_admin?
22
+ super
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -13,6 +13,8 @@ module ActiveRecord
13
13
  end
14
14
 
15
15
  def configuration_hash
16
+ reset_pg_rls_configuration if db_changed?
17
+
16
18
  return admin_configuration_hash if PgRls.as_db_admin?
17
19
 
18
20
  rls_configuration_hash
@@ -28,6 +30,15 @@ module ActiveRecord
28
30
  config[:password] = PgRls.password
29
31
  end.freeze
30
32
  end
33
+
34
+ def db_changed?
35
+ admin_configuration_hash[:database] != @configuration_hash[:database]
36
+ end
37
+
38
+ def reset_pg_rls_configuration
39
+ @rls_configuration_hash = nil
40
+ @admin_configuration_hash = nil
41
+ end
31
42
  end
32
43
  end
33
44
  end
@@ -22,131 +22,19 @@ end
22
22
  namespace :db do
23
23
  include PgRls::Schema::UpStatements
24
24
 
25
- override_task grant_usage: :load_config do
26
- PgRls.admin_tasks_execute do
27
- create_rls_user
28
- end
29
- end
30
-
31
- override_task create: :load_config do
32
- PgRls.admin_tasks_execute do
33
- Rake::Task['db:create:original'].invoke
34
- end
35
- end
36
-
37
- override_task drop: :load_config do
38
- PgRls.admin_tasks_execute do
39
- Rake::Task['db:drop:original'].invoke
40
- end
41
- end
42
-
43
- override_task migrate: :load_config do
44
- PgRls.admin_tasks_execute do
45
- Rake::Task['db:migrate:original'].invoke
46
- end
47
- end
48
-
49
- override_task rollback: :load_config do
50
- PgRls.admin_tasks_execute do
51
- Rake::Task['db:rollback:original'].invoke
52
- end
53
- end
54
-
55
- override_task prepare: :load_config do
56
- PgRls.admin_tasks_execute do
57
- Rake::Task['db:prepare:original'].invoke
58
- end
59
- end
60
-
61
- override_task setup: :load_config do
62
- PgRls.admin_tasks_execute do
63
- Rake::Task['db:setup:original'].invoke
64
- end
65
- end
66
-
67
- override_task prepare: :load_config do
68
- PgRls.admin_tasks_execute do
69
- Rake::Task['db:reset:original'].invoke
70
- end
71
- end
72
-
73
- override_task purge: :load_config do
74
- PgRls.admin_tasks_execute do
75
- Rake::Task['db:purge:original'].invoke
76
- end
25
+ override_task :load_config do
26
+ PgRls.instance_variable_set(:@as_db_admin, true)
27
+ Rake::Task['db:load_config:original'].invoke
77
28
  end
78
29
 
79
- override_task abort_if_pending_migrations: :load_config do
80
- PgRls.admin_tasks_execute do
81
- Rake::Task['db:abort_if_pending_migrations:original'].invoke
82
- end
30
+ override_task grant_usage: :load_config do
31
+ create_rls_user
83
32
  end
84
33
 
85
34
  namespace :test do
86
35
  override_task grant_usage: :load_config do
87
- PgRls.admin_tasks_execute do
88
- create_rls_user
89
- end
90
- end
91
-
92
- override_task create: :load_config do
93
- PgRls.admin_tasks_execute do
94
- Rake::Task['db:test:create:original'].invoke
95
- end
96
- end
97
-
98
- override_task drop: :load_config do
99
- PgRls.admin_tasks_execute do
100
- Rake::Task['db:test:drop:original'].invoke
101
- end
102
- end
103
-
104
- override_task prepare: :load_config do
105
- PgRls.admin_tasks_execute do
106
- Rake::Task['db:test:prepare:original'].invoke
107
- end
108
- end
109
-
110
- override_task setup: :load_config do
111
- PgRls.admin_tasks_execute do
112
- Rake::Task['db:test:setup:original'].invoke
113
- end
114
- end
115
-
116
- override_task purge: :load_config do
117
- PgRls.admin_tasks_execute do
118
- Rake::Task['db:test:purge:original'].invoke
119
- end
120
- end
121
-
122
- override_task load_schema: :load_config do
123
- PgRls.admin_tasks_execute do
124
- Rake::Task['db:test:load_schema:original'].invoke
125
- end
126
- end
127
- end
128
-
129
- namespace :environment do
130
- override_task set: :load_config do
131
- PgRls.admin_tasks_execute do
132
- Rake::Task['db:environment:set:original'].invoke
133
- end
134
- end
135
- end
136
-
137
- namespace :schema do
138
- override_task load: :load_config do
139
- PgRls.admin_tasks_execute do
140
- Rake::Task['db:schema:load:original'].invoke
141
- Rake::Task['db:grant_usage'].invoke
142
- Rake::Task['db:test:grant_usage'].invoke
143
- end
144
- end
145
-
146
- override_task dump: :load_config do
147
- PgRls.admin_tasks_execute do
148
- Rake::Task['db:schema:dump:original'].invoke
149
- end
36
+ PgRls.instance_variable_set(:@as_db_admin, true)
37
+ create_rls_user
150
38
  end
151
39
  end
152
40
  end
@@ -2,4 +2,3 @@
2
2
 
3
3
  require_relative 'rake_only_error'
4
4
  require_relative 'tenant_not_found'
5
- require_relative 'admin_username'
@@ -12,12 +12,9 @@ module PgRls
12
12
  end
13
13
 
14
14
  def load_tenant_attribute!(msg)
15
- if PgRls.admin_connection?
16
- msg['admin'] = true
17
- else
18
- tenant = PgRls::Tenant.fetch!
19
- msg['pg_rls'] = tenant.id
20
- end
15
+ return msg['admin'] = true if PgRls.admin_connection?
16
+
17
+ msg['pg_rls'] ||= PgRls::Tenant.fetch&.id
21
18
  end
22
19
  end
23
20
  end
data/lib/pg_rls/tenant.rb CHANGED
@@ -14,12 +14,11 @@ module PgRls
14
14
  tenant = switch_tenant!(resource)
15
15
 
16
16
  "RLS changed to '#{tenant.id}'"
17
- rescue StandardError => e
17
+ rescue StandardError
18
18
  Rails.logger.info('connection was not made')
19
19
  raise PgRls::Errors::TenantNotFound
20
20
  end
21
21
 
22
-
23
22
  def with_tenant!(resource)
24
23
  PgRls.main_model.connection_pool.with_connection do
25
24
  tenant = switch_tenant!(resource)
@@ -54,6 +53,15 @@ module PgRls
54
53
  nil
55
54
  end
56
55
 
56
+ def set_rls!(tenant_id)
57
+ PgRls.execute_rls_in_shards do |connection_class|
58
+ connection_class.transaction do
59
+ connection_class.connection.execute(format('SET rls.tenant_id = %s',
60
+ connection_class.connection.quote(tenant_id)))
61
+ end
62
+ end
63
+ end
64
+
57
65
  private
58
66
 
59
67
  def switch_tenant!(resource)
@@ -63,12 +71,7 @@ module PgRls
63
71
 
64
72
  tenant = find_tenant(resource)
65
73
 
66
- PgRls.execute_rls_in_shards do |connection_class|
67
- connection_class.transaction do
68
- connection_class.connection.execute(format('SET rls.tenant_id = %s',
69
- connection_class.connection.quote(tenant.tenant_id)))
70
- end
71
- end
74
+ set_rls!(tenant.tenant_id)
72
75
 
73
76
  tenant
74
77
  rescue NoMethodError
@@ -76,8 +79,6 @@ module PgRls
76
79
  end
77
80
 
78
81
  def find_tenant(resource)
79
- raise PgRls::Errors::AdminUsername if PgRls.admin_connection?
80
-
81
82
  reset_rls!
82
83
 
83
84
  tenant = nil
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgRls
4
- VERSION = '0.1.3'
4
+ VERSION = '0.1.5'
5
5
  end
data/lib/pg_rls.rb CHANGED
@@ -6,27 +6,24 @@ require_relative 'pg_rls/version'
6
6
  require_relative 'pg_rls/database/prepared'
7
7
  require_relative 'pg_rls/schema/statements'
8
8
  require_relative 'pg_rls/database/configurations'
9
+ require_relative 'pg_rls/database/admin_statements'
9
10
  require_relative 'pg_rls/tenant'
10
11
  require_relative 'pg_rls/multi_tenancy'
11
12
  require_relative 'pg_rls/railtie' if defined?(Rails)
12
13
  require_relative 'pg_rls/errors/index'
13
14
 
15
+ ActiveRecord::Migrator.prepend PgRls::Admin::ActiveRecord::Migrator
16
+ ActiveRecord::Tasks::DatabaseTasks.prepend PgRls::Admin::ActiveRecord::Tasks::DatabaseTasks
17
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.include PgRls::Schema::Statements
14
18
  # PostgreSQL Row Level Security
15
19
  module PgRls
16
20
  class Error < StandardError; end
17
- SECURE_USERNAME = 'app_user'
18
-
19
21
  class << self
20
22
  extend Forwardable
21
23
 
22
24
  WRITER_METHODS = %i[table_name class_name search_methods].freeze
23
- READER_METHODS = %i[
24
- connection_class execute table_name class_name search_methods
25
- ].freeze
26
- DELEGATORS_METHODS = %i[
27
- connection_class execute table_name search_methods
28
- class_name main_model
29
- ].freeze
25
+ READER_METHODS = %i[connection_class execute table_name class_name search_methods].freeze
26
+ DELEGATORS_METHODS = %i[connection_class execute table_name search_methods class_name main_model].freeze
30
27
 
31
28
  attr_writer(*WRITER_METHODS)
32
29
  attr_reader(*READER_METHODS)
@@ -34,7 +31,6 @@ module PgRls
34
31
  def_delegators(*DELEGATORS_METHODS)
35
32
 
36
33
  def setup
37
- ActiveRecord::ConnectionAdapters::AbstractAdapter.include PgRls::Schema::Statements
38
34
  ActiveRecord::Base.ignored_columns += %w[tenant_id]
39
35
 
40
36
  yield self
@@ -44,32 +40,11 @@ module PgRls
44
40
  @connection_class ||= ActiveRecord::Base
45
41
  end
46
42
 
47
- def rake_tasks?
48
- Rake.application.top_level_tasks.present? || ARGV.any? { |arg| arg =~ /rake|dsl/ }
49
- rescue NoMethodError
50
- false
51
- end
52
-
53
- def admin_tasks_execute
54
- raise PgRls::Errors::RakeOnlyError unless rake_tasks?
55
-
56
- self.as_db_admin = true
57
-
58
- yield
59
- ensure
60
- self.as_db_admin = false
61
- end
62
-
63
43
  def admin_execute(query = nil, &)
64
- current_tenant = PgRls::Tenant.fetch
65
- establish_new_connection!(admin: true)
66
-
67
- return ensure_block_execution(&) if block_given?
68
-
69
- execute(query)
44
+ current_tenant, reset_rls_connection = establish_admin_connection
45
+ execute_query_or_block(query, &)
70
46
  ensure
71
- establish_new_connection!
72
- PgRls::Tenant.switch(current_tenant) if current_tenant.present?
47
+ reset_connection_if_needed(current_tenant, reset_rls_connection)
73
48
  end
74
49
 
75
50
  def establish_new_connection!(admin: false)
@@ -142,9 +117,37 @@ module PgRls
142
117
  establish_new_connection!(admin: true) if reset_connection
143
118
  end
144
119
 
120
+ def establish_admin_connection
121
+ reset_rls_connection = false
122
+ current_tenant = nil
123
+
124
+ unless admin_connection?
125
+ reset_rls_connection = true
126
+ current_tenant = PgRls::Tenant.fetch
127
+ establish_new_connection!(admin: true)
128
+ end
129
+
130
+ [current_tenant, reset_rls_connection]
131
+ end
132
+
145
133
  def ensure_block_execution(*, **)
146
134
  yield(*, **).presence
147
135
  end
136
+
137
+ def execute_query_or_block(query = nil, &)
138
+ if block_given?
139
+ ensure_block_execution(&)
140
+ else
141
+ execute(query)
142
+ end
143
+ end
144
+
145
+ def reset_connection_if_needed(current_tenant, reset_rls_connection)
146
+ return unless reset_rls_connection
147
+
148
+ establish_new_connection!
149
+ PgRls::Tenant.switch(current_tenant) if current_tenant.present?
150
+ end
148
151
  end
149
152
 
150
153
  mattr_accessor :table_name
metadata CHANGED
@@ -1,34 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_rls
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Laloush
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-02 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.2'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2.2'
11
+ date: 2023-11-29 00:00:00.000000000 Z
12
+ dependencies: []
27
13
  description: |2
28
14
  This gem will help you to integrate PostgreSQL RLS to help you develop a great multitenancy application
29
15
  checkout the repository at https://github.com/Dandush03/pg_rls
30
16
  email:
31
- - daniel.laloush@influitive.com
17
+ - d.laloush@outlook.com
32
18
  executables: []
33
19
  extensions: []
34
20
  extra_rdoc_files: []
@@ -61,10 +47,10 @@ files:
61
47
  - lib/generators/templates/pg_rls.rb.tt
62
48
  - lib/pg_rls.rb
63
49
  - lib/pg_rls/Rakefile
50
+ - lib/pg_rls/database/admin_statements.rb
64
51
  - lib/pg_rls/database/configurations.rb
65
52
  - lib/pg_rls/database/prepared.rb
66
53
  - lib/pg_rls/database/tasks/admin_database.rake
67
- - lib/pg_rls/errors/admin_username.rb
68
54
  - lib/pg_rls/errors/index.rb
69
55
  - lib/pg_rls/errors/rake_only_error.rb
70
56
  - lib/pg_rls/errors/tenant_not_found.rb
@@ -100,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
86
  - !ruby/object:Gem::Version
101
87
  version: '0'
102
88
  requirements: []
103
- rubygems_version: 3.3.7
89
+ rubygems_version: 3.4.21
104
90
  signing_key:
105
91
  specification_version: 4
106
92
  summary: Write a short summary, because RubyGems requires one.
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module PgRls
4
- module Errors
5
- class AdminUsername < StandardError
6
- def initialize(msg = nil)
7
- msg ||= 'Cannot set or reset tenant for admin user'
8
- super(msg)
9
- end
10
- end
11
- end
12
- end