rbac_rls 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +53 -0
- data/Rakefile +8 -0
- data/app/assets/config/rbac_rls_manifest.js +2 -0
- data/app/assets/javascripts/rbac_rls/application.js +1 -0
- data/app/assets/stylesheets/rbac_rls/application.css.scss +16 -0
- data/app/controllers/concerns/connection_rls_user_concern.rb +31 -0
- data/app/controllers/rbac_rls/application_controller.rb +3 -0
- data/app/controllers/rbac_rls/groups_controller.rb +94 -0
- data/app/controllers/rbac_rls/home_controller.rb +5 -0
- data/app/controllers/rbac_rls/permissions_controller.rb +69 -0
- data/app/controllers/rbac_rls/roles_controller.rb +61 -0
- data/app/helpers/rbac_rls/application_helper.rb +4 -0
- data/app/helpers/rbac_rls/groups_helper.rb +4 -0
- data/app/helpers/rbac_rls/permissions_helper.rb +41 -0
- data/app/helpers/rbac_rls/roles_helper.rb +4 -0
- data/app/jobs/rbac_rls/application_job.rb +4 -0
- data/app/mailers/rbac_rls/application_mailer.rb +6 -0
- data/app/models/concerns/connection_rls_concern.rb +19 -0
- data/app/models/rbac_rls/application_record.rb +3 -0
- data/app/models/rbac_rls/group.rb +14 -0
- data/app/models/rbac_rls/group_permission.rb +20 -0
- data/app/models/rbac_rls/group_user.rb +7 -0
- data/app/models/rbac_rls/permission.rb +68 -0
- data/app/models/rbac_rls/role.rb +10 -0
- data/app/models/rbac_rls/role_permission.rb +6 -0
- data/app/models/rbac_rls/user_role.rb +7 -0
- data/app/views/layouts/rbac_rls/application.html.erb +55 -0
- data/app/views/rbac_rls/groups/_form.html.erb +97 -0
- data/app/views/rbac_rls/groups/_group.html.erb +12 -0
- data/app/views/rbac_rls/groups/_group_permission_fields.html.erb +18 -0
- data/app/views/rbac_rls/groups/_group_user_fields.html.erb +9 -0
- data/app/views/rbac_rls/groups/edit.html.erb +10 -0
- data/app/views/rbac_rls/groups/index.html.erb +14 -0
- data/app/views/rbac_rls/groups/new.html.erb +9 -0
- data/app/views/rbac_rls/groups/show.html.erb +10 -0
- data/app/views/rbac_rls/home/_link_to_home_page.html.erb +3 -0
- data/app/views/rbac_rls/home/index.html.erb +28 -0
- data/app/views/rbac_rls/permissions/_form.html.erb +78 -0
- data/app/views/rbac_rls/permissions/_permission.html.erb +54 -0
- data/app/views/rbac_rls/permissions/_role_permission_fields.html.erb +9 -0
- data/app/views/rbac_rls/permissions/edit.html.erb +7 -0
- data/app/views/rbac_rls/permissions/index.html.erb +18 -0
- data/app/views/rbac_rls/permissions/new.html.erb +9 -0
- data/app/views/rbac_rls/permissions/show.html.erb +10 -0
- data/app/views/rbac_rls/roles/_form.html.erb +42 -0
- data/app/views/rbac_rls/roles/_role.html.erb +2 -0
- data/app/views/rbac_rls/roles/_user_role_fields.html.erb +9 -0
- data/app/views/rbac_rls/roles/edit.html.erb +9 -0
- data/app/views/rbac_rls/roles/index.html.erb +19 -0
- data/app/views/rbac_rls/roles/new.html.erb +8 -0
- data/app/views/rbac_rls/roles/show.html.erb +12 -0
- data/config/assets.rb +12 -0
- data/config/importmap.rb +9 -0
- data/config/routes.rb +14 -0
- data/config/setup.rb +0 -0
- data/db/migrate/20220411125339_create_rbac_rls_roles.rb +9 -0
- data/db/migrate/20220411125613_create_rbac_rls_user_roles.rb +9 -0
- data/db/migrate/20220411133054_create_rbac_rls_permissions.rb +18 -0
- data/db/migrate/20220425212731_create_role_permissions.rb +9 -0
- data/db/migrate/20220912104712_create_rbac_rls_groups.rb +10 -0
- data/db/migrate/20220912104929_create_rbac_rls_group_permissions.rb +12 -0
- data/db/migrate/20220914004802_create_rbac_rls_group_users.rb +10 -0
- data/db/migrate/20220914004803_create_basic_permissions_for_application_acess.rb +18 -0
- data/lib/generators/generator_helpers.rb +8 -0
- data/lib/generators/rbac_rls/custom_migration_generator.rb +78 -0
- data/lib/generators/rbac_rls/group_permission_generator.rb +57 -0
- data/lib/generators/rbac_rls/templates/group_permission_migration.rb +83 -0
- data/lib/generators/rbac_rls/templates/rls_migration.rb +81 -0
- data/lib/generators/rbac_rls/templates/rls_migration.rb.erb +64 -0
- data/lib/generators/rbac_rls/templates/rls_migration2.rb.erb +80 -0
- data/lib/rbac_rls/engine.rb +21 -0
- data/lib/rbac_rls/version.rb +3 -0
- data/lib/rbac_rls.rb +6 -0
- data/lib/tasks/rbac_rls_tasks.rake +4 -0
- metadata +192 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3bc52fa4bdbbc44cf0d4b6ede8d4d142458a169baed9767a30c1f6549a827520
|
4
|
+
data.tar.gz: d289b6293db261f8643b702a70c0f8d9affd094385a898e299f1e7b7d6966c25
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6a7d8a952d7bbb5af6eedee3338ffd0ff76e71384eb82a2c7e0010f58855519cccb653e6b28e5ec29358b0c4a5f700d9663dfe0a372097d1fb2040ea60a5ff9c
|
7
|
+
data.tar.gz: ae99e701a1bce22e40993385b0f0644a6c49f2aa8e496cf7ed57cd4808133eb8d3ffeb15f70768389728321ddcd741184716a992f35e45dd0cad3aad9fa8528f
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2022 FilipeBeserraMaia
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# RbacRls
|
2
|
+
Short description and motivation.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
How to use my plugin.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem "rbac_rls"
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
```bash
|
21
|
+
$ gem install rbac_rls
|
22
|
+
```
|
23
|
+
And then add in your manifest.js:
|
24
|
+
```bash
|
25
|
+
//= link rbac_rls/application.css
|
26
|
+
//= link rbac_rls/application.js
|
27
|
+
```
|
28
|
+
And then add in your application_record.rb and application_controller.rb:
|
29
|
+
```bash
|
30
|
+
include ConnectionRls
|
31
|
+
include ConnectionRlsUser
|
32
|
+
```
|
33
|
+
|
34
|
+
And then run this command:
|
35
|
+
```bash
|
36
|
+
rake rbac_rls:install:migrations
|
37
|
+
```
|
38
|
+
|
39
|
+
And then run this command:
|
40
|
+
```bash
|
41
|
+
rake db:migrate
|
42
|
+
```
|
43
|
+
And then run this command:
|
44
|
+
```bash
|
45
|
+
yarn install
|
46
|
+
```
|
47
|
+
|
48
|
+
|
49
|
+
## Contributing
|
50
|
+
Contribution directions go here.
|
51
|
+
|
52
|
+
## License
|
53
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
// = require vanilla_nested
|
@@ -0,0 +1,16 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
16
|
+
@import "bootstrap";
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ConnectionRlsUserConcern
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
around_action :with_user_id
|
6
|
+
rescue_from ::PG::InsufficientPrivilege, with: :rls_error
|
7
|
+
|
8
|
+
def with_user_id
|
9
|
+
if current_user.present?
|
10
|
+
ApplicationRecord.with_user_id(current_user.id) do
|
11
|
+
yield
|
12
|
+
end
|
13
|
+
else
|
14
|
+
yield
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def rls_error(exception)
|
19
|
+
respond_to do |format|
|
20
|
+
format.json { render json: { error: exception.message }.to_json, status: 500 }
|
21
|
+
format.html { redirect_to request.referrer, notice: exception.message }
|
22
|
+
format.js { render :nothing => true, :status => 404, notice: exception.message }
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class_methods do
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module RbacRls
|
2
|
+
class GroupsController < ApplicationController
|
3
|
+
include ConnectionRlsUserConcern
|
4
|
+
before_action :set_group, only: %i[ show edit update destroy ]
|
5
|
+
|
6
|
+
# GET /groups
|
7
|
+
def index
|
8
|
+
@groups = Group.all
|
9
|
+
end
|
10
|
+
|
11
|
+
# GET /groups/1
|
12
|
+
def show
|
13
|
+
end
|
14
|
+
|
15
|
+
# GET /groups/new
|
16
|
+
def new
|
17
|
+
@group = Group.new
|
18
|
+
@group.group_permissions.build()
|
19
|
+
end
|
20
|
+
|
21
|
+
# GET /groups/1/edit
|
22
|
+
def edit
|
23
|
+
end
|
24
|
+
|
25
|
+
# POST /groups
|
26
|
+
def create
|
27
|
+
@group = Group.new(group_params)
|
28
|
+
|
29
|
+
if @group.save
|
30
|
+
redirect_to @group, notice: "Group was successfully created."
|
31
|
+
else
|
32
|
+
render :new, status: :unprocessable_entity
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# PATCH/PUT /groups/1
|
37
|
+
def update
|
38
|
+
if @group.update(group_params)
|
39
|
+
redirect_to @group, notice: "Group was successfully updated."
|
40
|
+
else
|
41
|
+
render :edit, status: :unprocessable_entity
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# DELETE /groups/1
|
46
|
+
def destroy
|
47
|
+
@group.destroy
|
48
|
+
redirect_to groups_url, notice: "Group was successfully destroyed."
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_options_select
|
52
|
+
@permission = Permission.find_by(id: params[:permission_object_id])
|
53
|
+
|
54
|
+
if @permission.present?
|
55
|
+
attrs = @permission.table_name.singularize.camelize.constantize.new.attributes.keys
|
56
|
+
if params[:target_select].to_s.to_sym == :table_key_id
|
57
|
+
|
58
|
+
@collection = [attrs, attrs].transpose.to_h if params[:target_select].to_s.to_sym == :table_key_id
|
59
|
+
|
60
|
+
elsif params[:target_select].to_s.to_sym == :table_value_id
|
61
|
+
elements = @permission.table_name.singularize.camelize.constantize.all.map(¶ms[:permission_id].to_s.to_sym)
|
62
|
+
@collection = [elements, elements].transpose.to_h
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
render json: @collection.to_h.as_json
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# Use callbacks to share common setup or constraints between actions.
|
72
|
+
def set_group
|
73
|
+
@group = Group.find(params[:id])
|
74
|
+
end
|
75
|
+
|
76
|
+
# Only allow a list of trusted parameters through.
|
77
|
+
def group_params
|
78
|
+
params.require(:group).permit(:name, :comments, group_permissions_attributes: [:id,
|
79
|
+
:group_id,
|
80
|
+
:permission_id,
|
81
|
+
:table_key,
|
82
|
+
:table_value,
|
83
|
+
:_destroy],
|
84
|
+
group_users_attributes: [
|
85
|
+
:id,
|
86
|
+
:group_id,
|
87
|
+
:user_id,
|
88
|
+
:_destroy
|
89
|
+
]
|
90
|
+
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module RbacRls
|
2
|
+
class PermissionsController < RbacRls::ApplicationController
|
3
|
+
before_action :set_permission, only: %i[ show edit update destroy ]
|
4
|
+
|
5
|
+
# GET /permissions
|
6
|
+
def index
|
7
|
+
@permissions = Permission.all
|
8
|
+
end
|
9
|
+
|
10
|
+
# GET /permissions/1
|
11
|
+
def show
|
12
|
+
end
|
13
|
+
|
14
|
+
# GET /permissions/new
|
15
|
+
def new
|
16
|
+
@permission = Permission.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# GET /permissions/1/edit
|
20
|
+
def edit
|
21
|
+
end
|
22
|
+
|
23
|
+
# POST /permissions
|
24
|
+
def create
|
25
|
+
@permission = Permission.new(permission_params)
|
26
|
+
|
27
|
+
if @permission.save
|
28
|
+
|
29
|
+
redirect_to @permission, notice: "Permission was successfully created."
|
30
|
+
else
|
31
|
+
render :new, status: :unprocessable_entity
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# PATCH/PUT /permissions/1
|
36
|
+
def update
|
37
|
+
if @permission.update(permission_params)
|
38
|
+
redirect_to @permission, notice: "Permission was successfully updated."
|
39
|
+
else
|
40
|
+
render :edit, status: :unprocessable_entity
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# DELETE /permissions/1
|
45
|
+
def destroy
|
46
|
+
@permission.destroy
|
47
|
+
redirect_to permissions_url, notice: "Permission was successfully destroyed."
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Use callbacks to share common setup or constraints between actions.
|
53
|
+
def set_permission
|
54
|
+
@permission = Permission.find(params[:id])
|
55
|
+
end
|
56
|
+
|
57
|
+
# Only allow a list of trusted parameters through.
|
58
|
+
def permission_params
|
59
|
+
params.require(:permission).permit(:name, :table_name, :read, :write, :change, :remove, :permission_id,
|
60
|
+
:owner_read, :owner_change, :owner_remove,
|
61
|
+
role_permissions_attributes: [:id,
|
62
|
+
:role_id,
|
63
|
+
:permission_id,
|
64
|
+
:_destroy]
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module RbacRls
|
2
|
+
class RolesController < RbacRls::ApplicationController
|
3
|
+
before_action :set_role, only: %i[ show edit update destroy ]
|
4
|
+
|
5
|
+
# GET /roles
|
6
|
+
def index
|
7
|
+
@roles = Role.all
|
8
|
+
end
|
9
|
+
|
10
|
+
# GET /roles/1
|
11
|
+
def show
|
12
|
+
end
|
13
|
+
|
14
|
+
# GET /roles/new
|
15
|
+
def new
|
16
|
+
@role = RbacRls::Role.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# GET /roles/1/edit
|
20
|
+
def edit
|
21
|
+
end
|
22
|
+
|
23
|
+
# POST /roles
|
24
|
+
def create
|
25
|
+
@role = Role.new(role_params)
|
26
|
+
|
27
|
+
if @role.save
|
28
|
+
redirect_to @role, notice: "Role was successfully created."
|
29
|
+
else
|
30
|
+
render :new, status: :unprocessable_entity
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# PATCH/PUT /roles/1
|
35
|
+
def update
|
36
|
+
if @role.update(role_params)
|
37
|
+
redirect_to @role, notice: "Role was successfully updated."
|
38
|
+
else
|
39
|
+
render :edit, status: :unprocessable_entity
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# DELETE /roles/1
|
44
|
+
def destroy
|
45
|
+
@role.destroy
|
46
|
+
redirect_to roles_url, notice: "Role was successfully destroyed."
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
# Use callbacks to share common setup or constraints between actions.
|
52
|
+
def set_role
|
53
|
+
@role = Role.find(params[:id])
|
54
|
+
end
|
55
|
+
|
56
|
+
# Only allow a list of trusted parameters through.
|
57
|
+
def role_params
|
58
|
+
params.require(:role).permit(:name, :comments, user_roles_attributes: [:id, :_destroy, :user_id])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module RbacRls
|
2
|
+
module PermissionsHelper
|
3
|
+
|
4
|
+
def permission_options_for_select(form)
|
5
|
+
c = RbacRls::Permission.all
|
6
|
+
options_for_select(c.collect { |p| [p.name, p.id] }, form.object.permission_id)
|
7
|
+
end
|
8
|
+
|
9
|
+
def table_selected_key_options_for_select(form)
|
10
|
+
return options_for_select({}, nil) if form.object.permission_id.nil?
|
11
|
+
c = RbacRls::GroupPermission.all
|
12
|
+
options_for_select(c.collect { |p| [p.table_key, p.table_key] }, form.object.table_key)
|
13
|
+
end
|
14
|
+
|
15
|
+
def table_selected_value_options_for_select(form)
|
16
|
+
return options_for_select({}, nil) if form.object.permission_id.nil?
|
17
|
+
c = RbacRls::GroupPermission.all
|
18
|
+
options_for_select(c.collect { |p| [p.table_value, p.table_value] }, form.object.table_value)
|
19
|
+
end
|
20
|
+
|
21
|
+
def role_options_for_select(form)
|
22
|
+
c = RbacRls::Role.all
|
23
|
+
options_for_select(c.collect { |p| [p.name, p.id] }, form.object.role_id)
|
24
|
+
end
|
25
|
+
|
26
|
+
def permission_options_for_select(form)
|
27
|
+
c = RbacRls::Permission.all
|
28
|
+
options_for_select(c.collect { |p| [p.name, p.id] }, form.object.permission_id)
|
29
|
+
end
|
30
|
+
|
31
|
+
def user_options_for_select(form)
|
32
|
+
c = User.all
|
33
|
+
options_for_select(c.collect { |p| [p.email, p.id] }, form.object.user_id)
|
34
|
+
end
|
35
|
+
|
36
|
+
def table_name_options_for_select(form)
|
37
|
+
c = RbacRls::Permission.all_tables
|
38
|
+
options_for_select(c.collect { |t| [t, t] }, form.object.table_name)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ConnectionRlsConcern
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
SET_USER_ID_SQL = 'SET rls.user_id = %s'.freeze
|
6
|
+
RESET_USER_ID_SQL = 'RESET rls.user_id'.freeze
|
7
|
+
end
|
8
|
+
|
9
|
+
class_methods do
|
10
|
+
def with_user_id(user_id, &block)
|
11
|
+
begin
|
12
|
+
connection.execute format(SET_USER_ID_SQL, connection.quote(user_id))
|
13
|
+
block.call
|
14
|
+
ensure
|
15
|
+
connection.execute RESET_USER_ID_SQL
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class RbacRls::Group < ApplicationRecord
|
2
|
+
|
3
|
+
self.table_name = :groups
|
4
|
+
has_many :group_permissions, :class_name => 'RbacRls::GroupPermission'
|
5
|
+
has_many :group_users, :class_name => 'RbacRls::GroupUser'
|
6
|
+
accepts_nested_attributes_for :group_permissions, reject_if: :all_blank, allow_destroy: true
|
7
|
+
accepts_nested_attributes_for :group_users, reject_if: :all_blank, allow_destroy: true
|
8
|
+
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RbacRls
|
2
|
+
class GroupPermission < ApplicationRecord
|
3
|
+
self.table_name = :group_permissions
|
4
|
+
belongs_to :permission
|
5
|
+
belongs_to :group
|
6
|
+
after_save :create_group_rls_policy
|
7
|
+
|
8
|
+
#rails generate rbac_rls:group_permission table_name description:table_key 'produto':table_value
|
9
|
+
def create_group_rls_policy
|
10
|
+
cmd = ""
|
11
|
+
if self.permission.table_name.present? and self.table_key.present? and self.table_value.present?
|
12
|
+
cmd = "rails generate rbac_rls:group_permission #{self.permission.table_name} '#{self.table_key}':table_key '#{self.table_value}':table_value"
|
13
|
+
end
|
14
|
+
if cmd.present?
|
15
|
+
system(cmd)
|
16
|
+
system('rake db:migrate RAILS_ENV=migrations')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class RbacRls::Permission < ApplicationRecord
|
2
|
+
|
3
|
+
self.table_name = :permissions
|
4
|
+
belongs_to :permission, :class_name => 'RbacRls::Permission', optional: true
|
5
|
+
has_many :role_permissions, :class_name => 'RbacRls::RolePermission'
|
6
|
+
accepts_nested_attributes_for :role_permissions, reject_if: :all_blank, allow_destroy: true
|
7
|
+
|
8
|
+
#validations
|
9
|
+
validate :validate_self_relationship, if: Proc.new { |obj| obj.permission.present? }
|
10
|
+
validates_uniqueness_of :name, message: "This permission already exists"
|
11
|
+
validates_presence_of :table_name
|
12
|
+
before_validation :set_permission_name
|
13
|
+
after_commit :create_rls_policy
|
14
|
+
|
15
|
+
def self.all_tables(schema = :public)
|
16
|
+
|
17
|
+
sql = "SELECT table_name FROM information_schema.tables #{where_schema(schema)} "
|
18
|
+
result = ActiveRecord::Base.connection.select_all(sql)
|
19
|
+
tables = result.map { |k| k['table_name'] }
|
20
|
+
tables
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.where_schema(schema_name = nil)
|
24
|
+
schema_name.present? ? "WHERE table_schema = '#{schema_name}'" : ''
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def validate_self_relationship
|
30
|
+
self.errors.add(:permission, "cannot add self relationship with the same record") if self.id == self.permission_id
|
31
|
+
end
|
32
|
+
|
33
|
+
#@example rails generate rbac_rls:custom_migration transictions insert:role update:role select:all delete:user
|
34
|
+
def create_rls_policy
|
35
|
+
type_policies = ->() do
|
36
|
+
cmd = ""
|
37
|
+
cmd += " select:role " if read.present?
|
38
|
+
cmd += " insert:role " if write.present?
|
39
|
+
cmd += " update:role " if change.present?
|
40
|
+
cmd += " delete:role " if remove.present?
|
41
|
+
cmd
|
42
|
+
end
|
43
|
+
type_options = -> () do
|
44
|
+
cmd = ""
|
45
|
+
cmd += " --permission_identifier #{self.id} " if self.id.present?
|
46
|
+
cmd
|
47
|
+
end
|
48
|
+
|
49
|
+
if (type_policies.===).present? and (type_options.===).present? &&
|
50
|
+
RbacRls::Permission.all.map(&:table_name).exclude?(table_name)
|
51
|
+
|
52
|
+
cmd = "rails generate rbac_rls:custom_migration #{table_name} #{type_policies.===} #{type_options.===}"
|
53
|
+
system(cmd)
|
54
|
+
system('rake db:migrate RAILS_ENV=migrations')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def set_permission_name
|
59
|
+
self.name = self.table_name.to_s if self.table_name.present?
|
60
|
+
self.name += "_rd" if self.read
|
61
|
+
self.name += "_wt" if self.write
|
62
|
+
self.name += "_cg" if self.change
|
63
|
+
self.name += "_rv" if self.remove
|
64
|
+
end
|
65
|
+
|
66
|
+
def has_role_permission?() end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class RbacRls::Role < ApplicationRecord
|
2
|
+
self.table_name = :roles
|
3
|
+
|
4
|
+
# has_many :permissions, :class_name => 'RbacRls::Permission'
|
5
|
+
|
6
|
+
has_many :user_roles, :class_name => 'RbacRls::UserRole'
|
7
|
+
accepts_nested_attributes_for :user_roles, reject_if: :all_blank, allow_destroy: true
|
8
|
+
|
9
|
+
end
|
10
|
+
|