pg_rls 0.1.3 → 0.1.5

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: 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