dynamican 0.1.7 → 0.1.9
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/README.md +32 -24
- data/dynamican.gemspec +2 -2
- data/lib/dynamican.rb +1 -0
- data/lib/generators/dynamican_migration_generator.rb +59 -0
- metadata +3 -3
- data/migrations/0.1.2/dynamican_create_database_structure.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2919c67cd907ca110db119ff27da8eb0ab7dc7fef6d9911de9b2ed04fdd111e2
|
4
|
+
data.tar.gz: 3e89dcbe20185469f70b2d066264f848be3c8ef92b0f9e18771a9b6bc23d69a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f97e9268851d07d730e2d4cada589ed6c35ae57f8d127854d4199cd93b464dd1de342c6b9e674434be535a09ca9be8a52ad811d0fde348c846148b0c62494c3e
|
7
|
+
data.tar.gz: 35b2f9fe8360a9cbd4e9627b9a4249ee6aca206d6a394f2a8909ea8b74e53605eb64cc04119d1c11ad0d871a06d85313c81d2e89c1faa6bba2d17b79714a0411
|
data/README.md
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
# Dynamican
|
2
|
-
Dynamican is a flexible gem
|
2
|
+
Dynamican is a flexible gem which introduces permissions on rails applications. It is very customizable because it stores all the rules inside the database and can be added to multiple models: for example you can add permissions to your Role and User models. With a couple of overrides you can also add permissions to both Role and User and allow user to use its roles permissions.
|
3
3
|
|
4
4
|
## Installation
|
5
5
|
Inside your Gemfile put
|
6
6
|
|
7
7
|
gem 'dynamican'
|
8
8
|
|
9
|
-
then run `bundle install`
|
9
|
+
and then run `bundle install`
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
In each model you want to have the feature, just put
|
11
|
+
In each model you want to have the feature, just put the following.
|
14
12
|
|
15
13
|
include Dynamican::Model
|
16
14
|
|
17
|
-
Create `config/dynamican.yml` file and compile it as follows for each of the models you included the code above into (let's say for instance you included Dynamican::Model into User and Role models)
|
15
|
+
Create `config/dynamican.yml` file in your project and compile it as follows for each of the models you included the code above into (let's say for instance you included Dynamican::Model into User and Role models).
|
18
16
|
|
19
17
|
associations:
|
20
18
|
role:
|
@@ -22,9 +20,15 @@ Create `config/dynamican.yml` file and compile it as follows for each of the mod
|
|
22
20
|
user:
|
23
21
|
class_name: 'User'
|
24
22
|
|
25
|
-
|
23
|
+
Once this config file is created, you can launch the following command.
|
24
|
+
|
25
|
+
rails generate dynamican_migration
|
26
|
+
|
27
|
+
This command will generate a migration file in your project. Inside this migration, the `permission_connectors` table will have a reference column for the models you configured in the config file. If you want to add the feature to a new model after your migrations are already run (and cannot be rollbacked) you need to create a new migration to add the corresponding columns in the `permission_connectors` table.
|
28
|
+
|
29
|
+
### Using a model permissions on another model
|
26
30
|
|
27
|
-
I wanted to have the possibility to assign permissions both directly to my User model and my Role model, so that if the User had one permission and one of its Role had another, the User could benefit from both. So i assigned the feature (as explained above) to both models and then decorated my User model like
|
31
|
+
I wanted to have the possibility to assign permissions both directly to my User model and my Role model, so that if the User had one permission and one of its Role had another, the User could benefit from both. So i assigned the feature (as explained above) to both models and then decorated my User model like following.
|
28
32
|
|
29
33
|
module Decorators
|
30
34
|
module Models
|
@@ -52,7 +56,9 @@ I wanted to have the possibility to assign permissions both directly to my User
|
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
55
|
-
I personally have put this in `app/decorators/models/user/dynamican_overrides.rb` (you need to load the folder if
|
59
|
+
I personally have put this in `app/decorators/models/user/dynamican_overrides.rb` (you need to make rails load the folder if); you can make it work as you please but i recommend to keep it separate from the original User model.
|
60
|
+
|
61
|
+
WARNING: if you have done this override, User `permissions` and `permission_connectors` methods are not relations anymore, so methods like `<<` and `create` won't work on them.
|
56
62
|
|
57
63
|
## Usage
|
58
64
|
|
@@ -65,25 +71,27 @@ Create one `Dynamican::Permission` for each pair of action-object you need. For
|
|
65
71
|
p3 = Dynamican::Permission.create(action: 'update', object_name: 'order')
|
66
72
|
p4 = Dynamican::Permission.create(action: 'delete', object_name: 'order')
|
67
73
|
|
68
|
-
To assign one of these permissions to your Role or User, you need to create a `Dynamican::PermissionConnector` like
|
74
|
+
To assign one of these permissions to your Role or User, you need to create a `Dynamican::PermissionConnector` like follows.
|
69
75
|
|
70
|
-
|
76
|
+
role.permission_connectors.create(permission: p1)
|
71
77
|
|
72
78
|
Or simply
|
73
79
|
|
74
|
-
|
80
|
+
role.permissions << p1
|
81
|
+
|
82
|
+
Now your Role is considered able to create orders and you can evaluate permissions with `can?` method.
|
75
83
|
|
76
|
-
|
84
|
+
role.can? :create, :order
|
77
85
|
|
78
|
-
user.can? :create, :order
|
79
86
|
# Returns true
|
80
87
|
|
81
|
-
|
88
|
+
role.can? :read, :order
|
89
|
+
|
82
90
|
# Returns false
|
83
91
|
|
84
92
|
You can pass as second argument (the object) a symbol, a string, the class itself and also the instance (instances are used for condition evaluations).
|
85
|
-
|
86
|
-
You can also create custom permissions which don't need an object, simply leaving the `object_name` empty. Let's say you want to give permission to a certain user to dance
|
93
|
+
If you pass an array of these elements, permissions for all single element will be evaluated. The `can?` method will return true only if permissions to all objects are evaluated positively.
|
94
|
+
You can also create custom permissions which don't need an object, simply leaving the `object_name` empty. Let's say you want to give permission to a certain user to dance.
|
87
95
|
|
88
96
|
p5 = Dynamican::Permission.create(action: 'dance')
|
89
97
|
|
@@ -96,23 +104,23 @@ Call the `can?` method without any second argument
|
|
96
104
|
# Returns true
|
97
105
|
|
98
106
|
|
99
|
-
|
107
|
+
### Conditions
|
100
108
|
|
101
|
-
You can link a `Dynamican::PermissionConnector` to as many conditions as you want.
|
109
|
+
You can link a `Dynamican::PermissionConnector` to as many conditions as you want. In order to evaluate its conditions, the `conditional` property of the permission_connector needs to be set as `true` (default to `false`)
|
102
110
|
|
103
|
-
Conditions are created like this
|
111
|
+
Conditions are created like this.
|
104
112
|
|
105
113
|
permission_connector.conditions.create(statement: '@user.orders.count < 5')
|
106
114
|
permission_connector.conditions.create(statement: '@object.field.present?')
|
107
115
|
|
108
|
-
You can store in conditions statements whatever conditions you like in plain ruby and the string will be evaulated. Inside the statements, object have to be called as instance variables. These instance variables need to be present and can be declared
|
116
|
+
You can store in conditions statements whatever conditions you like in plain ruby and the string will be evaulated. Inside the statements, object have to be called as instance variables. These instance variables indeed need to be present and can be declared in a few ways.
|
109
117
|
|
110
|
-
1. The model name of the instance you called `can?` from, like the user, will be defined automatically based on model name so if you call `user.can?` you will have `@user` variable defined.
|
118
|
+
1. The model name of the instance you called `can?` from, like the user, will be defined automatically based on model name, so if you call `user.can?` you will have `@user` variable defined.
|
111
119
|
2. The object you pass as second argument (which should match the `object_name` of your permission) will be defined as `@object`, so if you call `user.can? :read, @order` you will have `@object` variable defined containing your `@order`.
|
112
120
|
3. You can pass as third argument an hash of objects like this `user.can? :read, @order, time: Time.zone.now, whatever: @you_want` and you will have `@time` and `@whatever` variables defined.
|
113
121
|
|
114
|
-
WARNING: since the condition statement gets evaluated, i recommend not to allow anyone except project developers to create conditions to prevent malicious code from being executed.
|
122
|
+
WARNING: since the condition statement gets evaluated, i recommend not to allow anyone except project developers to create conditions, in order to prevent malicious code from being executed.
|
115
123
|
|
116
|
-
If one `Dynamican::PermissionConnector` is linked to many conditions, the model will be allowed to make that action only if all conditions are true. If you want to set alternative conditions, you should store the or conditions inside the same statement, like this:
|
124
|
+
If one `Dynamican::PermissionConnector` is linked to many conditions, the model will be allowed to make that action only if all conditions are true. If you want to set alternative conditions, you should store the `or` conditions inside the same condition statement, like this:
|
117
125
|
|
118
126
|
condition.statement = '@user.nice? || @user.polite?'
|
data/dynamican.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'dynamican'
|
3
|
-
s.version = '0.1.
|
4
|
-
s.date = '2020-04-
|
3
|
+
s.version = '0.1.9'
|
4
|
+
s.date = '2020-04-18'
|
5
5
|
s.summary = "Dynamic permissions"
|
6
6
|
s.description = "Dynamic and flexible database configurable permissions for your application"
|
7
7
|
s.authors = ["Valerio Bellaveglia"]
|
data/lib/dynamican.rb
CHANGED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
class DynamicanMigrationGenerator < Rails::Generators::Base
|
4
|
+
|
5
|
+
def create_migration_file
|
6
|
+
create_file "db/migrate/#{Time.zone.now.strftime("%Y%m%d%H%M%S")}_dynamican_migration.rb", migration_data
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def migration_data
|
12
|
+
<<MIGRATION
|
13
|
+
class DynamicanMigration < ActiveRecord::Migration[5.2]
|
14
|
+
# 0.1.2 Release
|
15
|
+
def change
|
16
|
+
unless table_exists? :permissions
|
17
|
+
create_table :conditions do |t|
|
18
|
+
t.string :description
|
19
|
+
t.string :statement
|
20
|
+
|
21
|
+
t.timestamps
|
22
|
+
end
|
23
|
+
|
24
|
+
create_table :permissions do |t|
|
25
|
+
t.string :action
|
26
|
+
t.string :object_name
|
27
|
+
|
28
|
+
t.timestamps
|
29
|
+
end
|
30
|
+
|
31
|
+
create_table :permission_connectors do |t|
|
32
|
+
#{create_migration_associations_data}
|
33
|
+
t.references :permission
|
34
|
+
t.boolean :conditional, default: false
|
35
|
+
|
36
|
+
t.timestamps
|
37
|
+
end
|
38
|
+
|
39
|
+
create_table :conditions_permission_connectors do |t|
|
40
|
+
t.bigint :condition_id
|
41
|
+
t.bigint :permission_connector_id
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
MIGRATION
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_migration_associations_data
|
50
|
+
migration_associations_data = ""
|
51
|
+
associations = Dynamican.configuration.associations.keys
|
52
|
+
|
53
|
+
associations.each do |association|
|
54
|
+
migration_associations_data += "t.references :#{association}#{"\n " unless association == associations.last}"
|
55
|
+
end
|
56
|
+
|
57
|
+
migration_associations_data
|
58
|
+
end
|
59
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamican
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Valerio Bellaveglia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-04-
|
11
|
+
date: 2020-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Dynamic and flexible database configurable permissions for your application
|
14
14
|
email:
|
@@ -23,10 +23,10 @@ files:
|
|
23
23
|
- lib/dynamican/configuration.rb
|
24
24
|
- lib/dynamican/evaluator.rb
|
25
25
|
- lib/dynamican/model.rb
|
26
|
+
- lib/generators/dynamican_migration_generator.rb
|
26
27
|
- lib/models/dynamican/condition.rb
|
27
28
|
- lib/models/dynamican/permission.rb
|
28
29
|
- lib/models/dynamican/permission_connector.rb
|
29
|
-
- migrations/0.1.2/dynamican_create_database_structure.rb
|
30
30
|
homepage: https://github.com/ValerioBellaveglia/Dynamican
|
31
31
|
licenses:
|
32
32
|
- MIT
|
@@ -1,31 +0,0 @@
|
|
1
|
-
class DynamicanCreateDatabaseStructure < ActiveRecord::Migration[5.2]
|
2
|
-
def change
|
3
|
-
create_table :conditions do |t|
|
4
|
-
t.string :description
|
5
|
-
t.string :statement
|
6
|
-
|
7
|
-
t.timestamps
|
8
|
-
end
|
9
|
-
|
10
|
-
create_table :permissions do |t|
|
11
|
-
t.string :action
|
12
|
-
t.string :object_name
|
13
|
-
|
14
|
-
t.timestamps
|
15
|
-
end
|
16
|
-
|
17
|
-
create_table :permission_connectors do |t|
|
18
|
-
t.references :user
|
19
|
-
t.references :role
|
20
|
-
t.references :permission
|
21
|
-
t.boolean :conditional, default: false
|
22
|
-
|
23
|
-
t.timestamps
|
24
|
-
end
|
25
|
-
|
26
|
-
create_table :conditions_permission_connectors do |t|
|
27
|
-
t.bigint :condition_id
|
28
|
-
t.bigint :permission_connector_id
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|