pg_rls 0.1.3 → 0.1.4

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: 1bead0b6e11e78f3aebe2c843c8cceaa178664bad5755f4f6858893f0232979c
4
+ data.tar.gz: c91f321f93c5d79aebccf09413f98580cc64104a32e350f874dce1c170c1c6a8
5
5
  SHA512:
6
- metadata.gz: af0c6529cd940354cbaf1432c7086e1ae336f0d160df036108820873f31699c580833b7b153956e1b599b26946de15e8bfd5eda2dc94e10fa8b0b757fc94bcf1
7
- data.tar.gz: 04feda60ca3f7fa0e98f096246db9ba2d4eecac158af08f719631e7f078b224e5dc33b660e92129a6eb70e217bb7e550fdf74843015b1df988272954d756192c
6
+ metadata.gz: 3baca7c6f170a2ffe07538413374230163d6a907372186bfe3bbab61b5fe8f7eb32402bd4781ef6f0a35b0f8f80e6b6dd2df1115f807810955a606b899f13eb9
7
+ data.tar.gz: '00866118e32d11bacc622119a0bbd02880c1f231b59fed3f65b58b176b29b96f0a38469b4071ebc3f4d32c3261a5090153683bc48512a556f48f4edbf72d09b3'
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.4)
6
5
 
7
6
  GEM
8
7
  remote: https://rubygems.org/
@@ -284,4 +283,4 @@ RUBY VERSION
284
283
  ruby 3.2.2p53
285
284
 
286
285
  BUNDLED WITH
287
- 2.3.15
286
+ 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
@@ -23,130 +23,19 @@ namespace :db do
23
23
  include PgRls::Schema::UpStatements
24
24
 
25
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
26
+ PgRls.instance_variable_set(:@as_db_admin, true)
27
+ create_rls_user
77
28
  end
78
29
 
79
30
  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
31
+ PgRls.instance_variable_set(:@as_db_admin, true)
32
+ Rake::Task['db:abort_if_pending_migrations:original'].invoke
83
33
  end
84
34
 
85
35
  namespace :test do
86
36
  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
37
+ PgRls.instance_variable_set(:@as_db_admin, true)
38
+ create_rls_user
150
39
  end
151
40
  end
152
41
  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'
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.4'
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.4
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-13 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.22
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