pg_rls 0.0.1.alpha → 0.0.1.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +10 -0
- data/README.md +12 -3
- data/Rakefile +9 -0
- data/lib/generators/pg_rls/active_record/active_record_generator.rb +61 -0
- data/lib/generators/pg_rls/active_record/templates/abstract_base_class.rb.tt +9 -0
- data/lib/generators/pg_rls/active_record/templates/init_migration.rb.tt +25 -0
- data/lib/generators/pg_rls/active_record/templates/init_model.rb.tt +29 -0
- data/lib/generators/pg_rls/active_record/templates/migration.rb.tt +17 -0
- data/lib/generators/pg_rls/active_record/templates/model.rb.tt +24 -0
- data/lib/generators/pg_rls/base.rb +36 -0
- data/lib/generators/pg_rls/install_generator.rb +75 -0
- data/lib/generators/pg_rls/pg_rls_generator.rb +12 -0
- data/lib/generators/pg_rls.rb +19 -0
- data/lib/generators/templates/README +19 -0
- data/lib/generators/templates/pg_rls.rb.tt +7 -0
- data/lib/pg_rls/multi_tenancy.rb +20 -0
- data/lib/pg_rls/schema/down_statements.rb +4 -4
- data/lib/pg_rls/schema/up_statements.rb +2 -2
- data/lib/pg_rls/secure_connection.rb +24 -0
- data/lib/pg_rls/{tenant/tenant.rb → tenant.rb} +4 -3
- data/lib/pg_rls/version.rb +1 -1
- data/lib/pg_rls.rb +10 -3
- metadata +32 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eff1edae4e2b864b6d1c50dbe73330ddd3092314fc0f0654ce631dd3f2381e73
|
4
|
+
data.tar.gz: f61c086a2319def269009a8acd4bb712457913cb23703d4f592486c1adc76161
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88eaa010df64b8ba78630841f3ac886c44dca7929e43016e2dcbe6b4000a06ad41d0606e94fe7457eb3c46fe0e3c341d2208bf6b5fd64553fcd9eedbaee59c7a
|
7
|
+
data.tar.gz: 70aef5056d562fb96a2189d580f3b3cc31b1efb4ef71433969f8896268cdf0286bc5450b9b855166e48580d12aed451d0771c672611c3a934f7f046be2ea8dc9
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -2,6 +2,7 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
pg_rls (0.0.1.alpha)
|
5
|
+
bundler (>= 2.2.10)
|
5
6
|
|
6
7
|
GEM
|
7
8
|
remote: https://rubygems.org/
|
@@ -136,6 +137,14 @@ GEM
|
|
136
137
|
rspec-mocks (3.10.2)
|
137
138
|
diff-lcs (>= 1.2.0, < 2.0)
|
138
139
|
rspec-support (~> 3.10.0)
|
140
|
+
rspec-rails (5.0.2)
|
141
|
+
actionpack (>= 5.2)
|
142
|
+
activesupport (>= 5.2)
|
143
|
+
railties (>= 5.2)
|
144
|
+
rspec-core (~> 3.10)
|
145
|
+
rspec-expectations (~> 3.10)
|
146
|
+
rspec-mocks (~> 3.10)
|
147
|
+
rspec-support (~> 3.10)
|
139
148
|
rspec-support (3.10.2)
|
140
149
|
rubocop (1.22.1)
|
141
150
|
parallel (~> 1.10)
|
@@ -173,6 +182,7 @@ DEPENDENCIES
|
|
173
182
|
rails (~> 6.1.4, >= 6.1.4.1)
|
174
183
|
rake
|
175
184
|
rspec
|
185
|
+
rspec-rails
|
176
186
|
rubocop
|
177
187
|
|
178
188
|
RUBY VERSION
|
data/README.md
CHANGED
@@ -22,8 +22,17 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
|
25
|
+
RUN `rails generate pg_rls:install company`
|
26
26
|
|
27
|
+
You can change company to anything you'd like like for example `tenant`
|
28
|
+
this will generate the model and inject all the required code
|
29
|
+
|
30
|
+
for any new model that required to be under rls you can generate it by writing
|
31
|
+
|
32
|
+
`rails generate pg_rls user`
|
33
|
+
and it will generate all the necesary information for you
|
34
|
+
|
35
|
+
enjoy the gem :)
|
27
36
|
## Development
|
28
37
|
|
29
38
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -32,7 +41,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
41
|
|
33
42
|
## Contributing
|
34
43
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
44
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/dandush03/pg_rls. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/dandush03/pg_rls/blob/master/CODE_OF_CONDUCT.md).
|
36
45
|
|
37
46
|
## License
|
38
47
|
|
@@ -40,4 +49,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
40
49
|
|
41
50
|
## Code of Conduct
|
42
51
|
|
43
|
-
Everyone interacting in the PgRls project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
52
|
+
Everyone interacting in the PgRls project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/dandush03/pg_rls/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
CHANGED
@@ -10,3 +10,12 @@ require 'rubocop/rake_task'
|
|
10
10
|
RuboCop::RakeTask.new
|
11
11
|
|
12
12
|
task default: %i[spec rubocop]
|
13
|
+
|
14
|
+
desc 'Generate documentation for PgRls.'
|
15
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'PgRls'
|
18
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
19
|
+
rdoc.rdoc_files.include('README.md')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators/active_record/model/model_generator'
|
4
|
+
require File.join(File.dirname(__FILE__), '../base')
|
5
|
+
|
6
|
+
module PgRls
|
7
|
+
module Generators
|
8
|
+
# Active Record Generator
|
9
|
+
class ActiveRecordGenerator < ::ActiveRecord::Generators::ModelGenerator
|
10
|
+
include ::PgRls::Base
|
11
|
+
|
12
|
+
source_root File.expand_path('./templates', __dir__)
|
13
|
+
|
14
|
+
hook_for :test_framework
|
15
|
+
|
16
|
+
def create_migration_file
|
17
|
+
migration_template migration_template_path, "#{migration_path}/#{file_sub_name}_#{table_name}.rb",
|
18
|
+
migration_version: migration_version
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_model_file
|
22
|
+
generate_abstract_class if database && !parent
|
23
|
+
template model_template_path, File.join('app/models', class_path, "#{file_name}.rb")
|
24
|
+
end
|
25
|
+
|
26
|
+
def migration_template_path
|
27
|
+
return 'init_migration.rb.tt' if installation_in_progress?
|
28
|
+
|
29
|
+
'migration.rb.tt'
|
30
|
+
end
|
31
|
+
|
32
|
+
def model_template_path
|
33
|
+
return 'init_model.rb.tt' if installation_in_progress?
|
34
|
+
|
35
|
+
'model.rb.tt'
|
36
|
+
end
|
37
|
+
|
38
|
+
def file_sub_name
|
39
|
+
return 'pg_rls_tenant_create' if installation_in_progress?
|
40
|
+
|
41
|
+
'pg_rls_create'
|
42
|
+
end
|
43
|
+
|
44
|
+
def installation_in_progress?
|
45
|
+
shell.base.class.name.include?('Install')
|
46
|
+
end
|
47
|
+
|
48
|
+
def migration_version
|
49
|
+
"[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
|
50
|
+
end
|
51
|
+
|
52
|
+
def migration_path
|
53
|
+
db_migrate_path
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def migration_action() = 'add'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class PgRlsTenantCreate<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
|
4
|
+
def up
|
5
|
+
create_rls_tenant_table :<%= table_name %>, id: :uuid do |t|
|
6
|
+
t.string :name
|
7
|
+
t.string :logo
|
8
|
+
|
9
|
+
t.string :identification
|
10
|
+
t.string :subdomain
|
11
|
+
t.string :domain
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
add_index :companies, :name, unique: true
|
17
|
+
add_index :companies, :identification, unique: true
|
18
|
+
add_index :companies, :domain, unique: true
|
19
|
+
add_index :companies, :subdomain, unique: true
|
20
|
+
end
|
21
|
+
|
22
|
+
def down
|
23
|
+
drop_rls_tenant_table :companies
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
<% module_namespacing do -%>
|
4
|
+
class <%= class_name %> < <%= parent_class_name.classify %>
|
5
|
+
def self.current
|
6
|
+
find_by_tenant_id(connection.execute("SELECT current_setting('rls.tenant_id')").getvalue(0, 0))
|
7
|
+
rescue ActiveRecord::StatementInvalid
|
8
|
+
'no tenant is selected'
|
9
|
+
end
|
10
|
+
<% attributes.select(&:reference?).each do |attribute| -%>
|
11
|
+
belongs_to :<%= attribute.name %><%= ", polymorphic: true" if attribute.polymorphic? %>
|
12
|
+
<% end -%>
|
13
|
+
<% attributes.select(&:rich_text?).each do |attribute| -%>
|
14
|
+
has_rich_text :<%= attribute.name %>
|
15
|
+
<% end -%>
|
16
|
+
<% attributes.select(&:attachment?).each do |attribute| -%>
|
17
|
+
has_one_attached :<%= attribute.name %>
|
18
|
+
<% end -%>
|
19
|
+
<% attributes.select(&:attachments?).each do |attribute| -%>
|
20
|
+
has_many_attached :<%= attribute.name %>
|
21
|
+
<% end -%>
|
22
|
+
<% attributes.select(&:token?).each do |attribute| -%>
|
23
|
+
has_secure_token<% if attribute.name != "token" %> :<%= attribute.name %><% end %>
|
24
|
+
<% end -%>
|
25
|
+
<% if attributes.any?(&:password_digest?) -%>
|
26
|
+
has_secure_password
|
27
|
+
<% end -%>
|
28
|
+
end
|
29
|
+
<% end -%>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class PgRlsCreate<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
|
4
|
+
def up
|
5
|
+
create_rls_table :<%= table_name %><%= primary_key_type %> do |t|
|
6
|
+
<% attributes.each do |attribute| -%>
|
7
|
+
t.<%= attribute.type %> :<%= attribute.name %>
|
8
|
+
<% end -%>
|
9
|
+
|
10
|
+
t.timestamps null: false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def down
|
15
|
+
drop_rls_table :<%= table_name %>
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
<% module_namespacing do -%>
|
4
|
+
class <%= class_name %> < <%= parent_class_name.classify %>
|
5
|
+
<% attributes.select(&:reference?).each do |attribute| -%>
|
6
|
+
belongs_to :<%= attribute.name %><%= ", polymorphic: true" if attribute.polymorphic? %>
|
7
|
+
<% end -%>
|
8
|
+
<% attributes.select(&:rich_text?).each do |attribute| -%>
|
9
|
+
has_rich_text :<%= attribute.name %>
|
10
|
+
<% end -%>
|
11
|
+
<% attributes.select(&:attachment?).each do |attribute| -%>
|
12
|
+
has_one_attached :<%= attribute.name %>
|
13
|
+
<% end -%>
|
14
|
+
<% attributes.select(&:attachments?).each do |attribute| -%>
|
15
|
+
has_many_attached :<%= attribute.name %>
|
16
|
+
<% end -%>
|
17
|
+
<% attributes.select(&:token?).each do |attribute| -%>
|
18
|
+
has_secure_token<% if attribute.name != "token" %> :<%= attribute.name %><% end %>
|
19
|
+
<% end -%>
|
20
|
+
<% if attributes.any?(&:password_digest?) -%>
|
21
|
+
has_secure_password
|
22
|
+
<% end -%>
|
23
|
+
end
|
24
|
+
<% end -%>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgRls
|
4
|
+
# Main Definition for Generator
|
5
|
+
module Base
|
6
|
+
protected
|
7
|
+
|
8
|
+
def nested_parent_name
|
9
|
+
@class_path.join('/')
|
10
|
+
end
|
11
|
+
|
12
|
+
def nested_parent_id
|
13
|
+
"#{nested_parent_name}_id"
|
14
|
+
end
|
15
|
+
|
16
|
+
def nested_parent_class_name
|
17
|
+
nested_parent_name.classify
|
18
|
+
end
|
19
|
+
|
20
|
+
def plural_nested_parent_name
|
21
|
+
nested_parent_name.pluralize
|
22
|
+
end
|
23
|
+
|
24
|
+
def class_path
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
|
28
|
+
def regular_class_path
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
|
32
|
+
def controller_class_path
|
33
|
+
[]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators/base'
|
4
|
+
require 'securerandom'
|
5
|
+
|
6
|
+
module PgRls
|
7
|
+
module Generators
|
8
|
+
MissingORMError = Class.new(Thor::Error)
|
9
|
+
# Installer Generator
|
10
|
+
class InstallGenerator < Rails::Generators::Base
|
11
|
+
APPLICATION_RECORD_LINE = 'class ApplicationRecord < ActiveRecord::Base'
|
12
|
+
APPLICATION_RECORD_PATH = 'app/models/application_record.rb'
|
13
|
+
APPLICATION_CONTROLLER_LINE = 'class ApplicationController < ActionController::Base'
|
14
|
+
APPLICATION_CONTROLLER_PATH = 'app/controllers/application_controller.rb'
|
15
|
+
source_root File.expand_path('../templates', __dir__)
|
16
|
+
|
17
|
+
desc 'Creates a PgRls initializer and copy locale files to your application.'
|
18
|
+
|
19
|
+
def orm_error_message
|
20
|
+
<<-ERROR.strip_heredoc
|
21
|
+
An ORM must be set to install PgRls in your application.
|
22
|
+
Be sure to have an ORM like Active Record or loaded in your
|
23
|
+
app or configure your own at `config/application.rb`.
|
24
|
+
config.generators do |g|
|
25
|
+
g.orm :your_orm_gem
|
26
|
+
end
|
27
|
+
ERROR
|
28
|
+
end
|
29
|
+
|
30
|
+
def copy_initializer
|
31
|
+
raise MissingORMError, orm_error_message unless options[:orm]
|
32
|
+
|
33
|
+
template 'pg_rls.rb.tt', 'config/initializers/pg_rls.rb'
|
34
|
+
|
35
|
+
inject_include_to_application_record
|
36
|
+
inject_include_to_application_controller
|
37
|
+
end
|
38
|
+
|
39
|
+
def inject_include_to_application_record
|
40
|
+
return if aplication_record_already_included?
|
41
|
+
|
42
|
+
gsub_file(APPLICATION_RECORD_PATH, /(#{Regexp.escape(APPLICATION_RECORD_LINE)})/mi) do |match|
|
43
|
+
"#{match}\n include PgRls::SecureConnection\n"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def inject_include_to_application_controller
|
48
|
+
return if aplication_controller_already_included?
|
49
|
+
|
50
|
+
gsub_file(APPLICATION_CONTROLLER_PATH, /(#{Regexp.escape(APPLICATION_CONTROLLER_LINE)})/mi) do |match|
|
51
|
+
"#{match}\n include PgRls::MultiTenancy\n"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def aplication_controller_already_included?
|
56
|
+
File.readlines(APPLICATION_CONTROLLER_PATH).grep(/include PgRls::MultiTenancy/).any?
|
57
|
+
end
|
58
|
+
|
59
|
+
def aplication_record_already_included?
|
60
|
+
File.readlines(APPLICATION_RECORD_PATH).grep(/include PgRls::SecureConnection/).any?
|
61
|
+
end
|
62
|
+
|
63
|
+
def initialize_error_text
|
64
|
+
<<-ERROR.strip_heredoc
|
65
|
+
ERROR
|
66
|
+
end
|
67
|
+
|
68
|
+
def show_readme
|
69
|
+
readme 'README' if behavior == :invoke
|
70
|
+
end
|
71
|
+
|
72
|
+
hook_for :orm, required: true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative File.join(File.dirname(__FILE__), 'active_record/active_record_generator')
|
4
|
+
|
5
|
+
module PgRls
|
6
|
+
module Generators
|
7
|
+
class PgRlsGenerator < ::Rails::Generators::NamedBase
|
8
|
+
# override ModelGenerator
|
9
|
+
hook_for :orm, required: true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators/named_base'
|
4
|
+
require 'rails/generators/active_model'
|
5
|
+
require 'rails/generators/active_record/migration'
|
6
|
+
require 'active_record'
|
7
|
+
|
8
|
+
module PgRls
|
9
|
+
module Generators # :nodoc:
|
10
|
+
class PgRlsGenerator < Rails::Generators::NamedBase # :nodoc:
|
11
|
+
include PgRls::Generators::Migration
|
12
|
+
|
13
|
+
# Set the current directory as base for the inherited generators.
|
14
|
+
def self.base_root
|
15
|
+
__dir__
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
README
|
2
|
+
===============================================================================
|
3
|
+
WARNING!!
|
4
|
+
|
5
|
+
Once you remove a tenant all of his data would be removed as well
|
6
|
+
|
7
|
+
PgRls::SecureConnection was included to your ApplicationRecord do not remove it
|
8
|
+
|
9
|
+
===============================================================================
|
10
|
+
|
11
|
+
to generate secure model run
|
12
|
+
|
13
|
+
rails g pg_rls model_name
|
14
|
+
|
15
|
+
or
|
16
|
+
|
17
|
+
rails generate pg_rls model_name
|
18
|
+
|
19
|
+
===============================================================================
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgRls
|
4
|
+
# Ensure Connection is with App_use
|
5
|
+
module MultiTenancy
|
6
|
+
def self.included(base)
|
7
|
+
base.class_eval do
|
8
|
+
before_action :switch_tenant
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def switch_tenant
|
15
|
+
Tenant.switch request.subdomain
|
16
|
+
rescue NoMethodError
|
17
|
+
redirect_to '/'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -4,8 +4,8 @@ module PgRls
|
|
4
4
|
module Schema
|
5
5
|
# Down Schema Statements
|
6
6
|
module DownStatements
|
7
|
-
def drop_rls_user
|
8
|
-
ActiveRecord::Migration.execute "DROP USER #{
|
7
|
+
def drop_rls_user
|
8
|
+
ActiveRecord::Migration.execute "DROP USER #{PgRls::SECURE_USERNAME};"
|
9
9
|
end
|
10
10
|
|
11
11
|
def drop_rls_blocking_function
|
@@ -37,9 +37,9 @@ module PgRls
|
|
37
37
|
SQL
|
38
38
|
end
|
39
39
|
|
40
|
-
def drop_rls_policy(table_name
|
40
|
+
def drop_rls_policy(table_name)
|
41
41
|
ActiveRecord::Migration.execute <<-SQL
|
42
|
-
DROP POLICY #{table_name}_#{
|
42
|
+
DROP POLICY #{table_name}_#{PgRls::SECURE_USERNAME} ON #{table_name};
|
43
43
|
ALTER TABLE #{table_name} DISABLE ROW LEVEL SECURITY;
|
44
44
|
SQL
|
45
45
|
end
|
@@ -4,7 +4,7 @@ module PgRls
|
|
4
4
|
module Schema
|
5
5
|
# Up Schema Statements
|
6
6
|
module UpStatements
|
7
|
-
def create_rls_user(name:
|
7
|
+
def create_rls_user(name: PgRls::SECURE_USERNAME, password: 'password')
|
8
8
|
PgRls.execute <<-SQL
|
9
9
|
DROP ROLE IF EXISTS #{name};
|
10
10
|
CREATE USER #{name} WITH PASSWORD '#{password}';
|
@@ -71,7 +71,7 @@ module PgRls
|
|
71
71
|
SQL
|
72
72
|
end
|
73
73
|
|
74
|
-
def create_rls_policy(table_name, user =
|
74
|
+
def create_rls_policy(table_name, user = PgRls::SECURE_USERNAME)
|
75
75
|
ActiveRecord::Migration.execute <<-SQL
|
76
76
|
ALTER TABLE #{table_name} ENABLE ROW LEVEL SECURITY;
|
77
77
|
CREATE POLICY #{table_name}_#{user}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgRls
|
4
|
+
# Ensure Connection is with App_use
|
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
|
13
|
+
|
14
|
+
def establish_secure_connection
|
15
|
+
return if secure_connection_established?
|
16
|
+
|
17
|
+
PgRls.establish_new_connection
|
18
|
+
end
|
19
|
+
|
20
|
+
def secure_connection_established?
|
21
|
+
PgRls.current_connection_username == PgRls::SECURE_USERNAME
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -6,10 +6,11 @@ module PgRls
|
|
6
6
|
class << self
|
7
7
|
SET_COMPANY_ID_SQL = 'SET rls.tenant_id = %s'
|
8
8
|
def switch(resource)
|
9
|
-
connection_adapter = PgRls.
|
9
|
+
connection_adapter = PgRls.connection_class
|
10
10
|
tenant = tenant_by_subdomain_uuid_or_tenant_id(resource)
|
11
|
-
connection_adapter.connection.execute(format(
|
12
|
-
|
11
|
+
connection_adapter.connection.execute(format(SET_COMPANY_ID_SQL,
|
12
|
+
connection_adapter.connection.quote(tenant.tenant_id)))
|
13
|
+
"RLS changed to '#{tenant}'"
|
13
14
|
rescue StandardError => e
|
14
15
|
puts 'connection was not made'
|
15
16
|
puts e
|
data/lib/pg_rls/version.rb
CHANGED
data/lib/pg_rls.rb
CHANGED
@@ -4,11 +4,14 @@ require 'active_record'
|
|
4
4
|
require 'forwardable'
|
5
5
|
require_relative 'pg_rls/version'
|
6
6
|
require_relative 'pg_rls/schema/statements'
|
7
|
-
require_relative 'pg_rls/tenant
|
7
|
+
require_relative 'pg_rls/tenant'
|
8
|
+
require_relative 'pg_rls/secure_connection'
|
9
|
+
require_relative 'pg_rls/multi_tenancy'
|
8
10
|
|
9
11
|
# PostgreSQL Row Level Security
|
10
12
|
module PgRls
|
11
13
|
class Error < StandardError; end
|
14
|
+
SECURE_USERNAME = 'app_user'
|
12
15
|
|
13
16
|
class << self
|
14
17
|
extend Forwardable
|
@@ -38,17 +41,21 @@ module PgRls
|
|
38
41
|
|
39
42
|
def establish_new_connection
|
40
43
|
connection_class.establish_connection(
|
41
|
-
|
44
|
+
**database_configuration
|
42
45
|
)
|
43
46
|
end
|
44
47
|
|
48
|
+
def current_connection_username
|
49
|
+
PgRls.connection_class.connection_db_config.configuration_hash[:username]
|
50
|
+
end
|
51
|
+
|
45
52
|
def execute(query)
|
46
53
|
@execute = ActiveRecord::Migration.execute(query)
|
47
54
|
end
|
48
55
|
|
49
56
|
def database_configuration
|
50
57
|
@database_configuration ||= database_connection_file[Rails.env].tap do |config|
|
51
|
-
config['username'] =
|
58
|
+
config['username'] = PgRls::SECURE_USERNAME
|
52
59
|
end
|
53
60
|
end
|
54
61
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_rls
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1.
|
4
|
+
version: 0.0.1.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Laloush
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-10-
|
12
|
-
dependencies:
|
11
|
+
date: 2021-10-10 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.10
|
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.10
|
13
27
|
description: Write a longer description or delete this line.
|
14
28
|
email:
|
15
29
|
- daniel.laloush@influitive.com
|
@@ -28,11 +42,25 @@ files:
|
|
28
42
|
- Rakefile
|
29
43
|
- bin/console
|
30
44
|
- bin/setup
|
45
|
+
- lib/generators/pg_rls.rb
|
46
|
+
- lib/generators/pg_rls/active_record/active_record_generator.rb
|
47
|
+
- lib/generators/pg_rls/active_record/templates/abstract_base_class.rb.tt
|
48
|
+
- lib/generators/pg_rls/active_record/templates/init_migration.rb.tt
|
49
|
+
- lib/generators/pg_rls/active_record/templates/init_model.rb.tt
|
50
|
+
- lib/generators/pg_rls/active_record/templates/migration.rb.tt
|
51
|
+
- lib/generators/pg_rls/active_record/templates/model.rb.tt
|
52
|
+
- lib/generators/pg_rls/base.rb
|
53
|
+
- lib/generators/pg_rls/install_generator.rb
|
54
|
+
- lib/generators/pg_rls/pg_rls_generator.rb
|
55
|
+
- lib/generators/templates/README
|
56
|
+
- lib/generators/templates/pg_rls.rb.tt
|
31
57
|
- lib/pg_rls.rb
|
58
|
+
- lib/pg_rls/multi_tenancy.rb
|
32
59
|
- lib/pg_rls/schema/down_statements.rb
|
33
60
|
- lib/pg_rls/schema/statements.rb
|
34
61
|
- lib/pg_rls/schema/up_statements.rb
|
35
|
-
- lib/pg_rls/
|
62
|
+
- lib/pg_rls/secure_connection.rb
|
63
|
+
- lib/pg_rls/tenant.rb
|
36
64
|
- lib/pg_rls/version.rb
|
37
65
|
homepage: https://github.com/Dandush03/pg_rls
|
38
66
|
licenses:
|