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 +4 -4
- data/.rubocop.yml +3 -0
- data/Gemfile.lock +5 -3
- data/lib/generators/pg_rls/install_generator.rb +5 -2
- data/lib/pg_rls/database/admin_statements.rb +28 -0
- data/lib/pg_rls/database/configurations.rb +11 -0
- data/lib/pg_rls/database/tasks/admin_database.rake +7 -119
- data/lib/pg_rls/errors/index.rb +0 -1
- data/lib/pg_rls/middleware/sidekiq/client.rb +3 -6
- data/lib/pg_rls/tenant.rb +11 -10
- data/lib/pg_rls/version.rb +1 -1
- data/lib/pg_rls.rb +37 -34
- metadata +6 -20
- data/lib/pg_rls/errors/admin_username.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96c51a563fc96608b2c952922f3f38475fe3dcd2a1822ee367a80b50997df72c
|
4
|
+
data.tar.gz: 1540d7bdc72fa8a2ea31eeeeadcb22ad06c5efc80b54440edc3a4ecdd6af155c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '082c4cad7586ccf9f1c5aef6047489c52b86d4bd1b1dc3de0c4b2d7afec357d9b2463cdf753987c52657067372f5ac4fe271b874fabd383156519b34bebfca2f'
|
7
|
+
data.tar.gz: 9b46030589110529d4a2c6cd92590700cfd16fa139aa0e257431d43de19faf38f7d5e1bb8541c06253ec878dbbe4e9b92969cfcfa89df78bb47d0ba1cb206884
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pg_rls (0.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.
|
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
|
-
|
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(
|
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
|
26
|
-
PgRls.
|
27
|
-
|
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
|
80
|
-
|
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.
|
88
|
-
|
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
|
data/lib/pg_rls/errors/index.rb
CHANGED
@@ -12,12 +12,9 @@ module PgRls
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def load_tenant_attribute!(msg)
|
15
|
-
if PgRls.admin_connection?
|
16
|
-
|
17
|
-
|
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
|
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
|
-
|
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
|
data/lib/pg_rls/version.rb
CHANGED
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
|
-
|
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 =
|
65
|
-
|
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
|
-
|
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.
|
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-
|
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
|
-
-
|
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.
|
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.
|