dynamican 0.1.9 → 1.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2919c67cd907ca110db119ff27da8eb0ab7dc7fef6d9911de9b2ed04fdd111e2
4
- data.tar.gz: 3e89dcbe20185469f70b2d066264f848be3c8ef92b0f9e18771a9b6bc23d69a3
3
+ metadata.gz: 57e35df3eaa7632f3e703de8ee81fa03205baf0f34678cc6f1cb7e4d1de30519
4
+ data.tar.gz: 6a0f272dba7e3c6fb4575c1b491cd4aa1b7c82c074a28cbde012e6233120d4bf
5
5
  SHA512:
6
- metadata.gz: f97e9268851d07d730e2d4cada589ed6c35ae57f8d127854d4199cd93b464dd1de342c6b9e674434be535a09ca9be8a52ad811d0fde348c846148b0c62494c3e
7
- data.tar.gz: 35b2f9fe8360a9cbd4e9627b9a4249ee6aca206d6a394f2a8909ea8b74e53605eb64cc04119d1c11ad0d871a06d85313c81d2e89c1faa6bba2d17b79714a0411
6
+ metadata.gz: a8302dc81c027a3256e4d943f2633c5d4a311dfebcc274c69c4f831607bd6ee68d4ab69615d8e66b2923e9fef1c472f16208855f07b30e5e5ac080300b78267a
7
+ data.tar.gz: '09ef56baf0b012223b1c562bfc1f57d2559bb9009ccb311322eab8750baa894c922f21f32b5e540a162e360e4b714b71a14f5ac764c52d6d7535f56b299c0f51'
data/README.md CHANGED
@@ -6,29 +6,21 @@ Inside your Gemfile put
6
6
 
7
7
  gem 'dynamican'
8
8
 
9
- and then run `bundle install`
9
+ and run `bundle install`, then you can launch the following command.
10
10
 
11
- In each model you want to have the feature, just put the following.
12
-
13
- include Dynamican::Model
14
-
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).
11
+ rails g dynamican_migration
16
12
 
17
- associations:
18
- role:
19
- class_name: 'Role'
20
- user:
21
- class_name: 'User'
13
+ This command will generate a migration file in your project, which you can run with
22
14
 
23
- Once this config file is created, you can launch the following command.
15
+ rails db:migrate
24
16
 
25
- rails generate dynamican_migration
17
+ In each model you want to have the feature, just put the following.
26
18
 
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.
19
+ include Dynamican::Model
28
20
 
29
21
  ### Using a model permissions on another model
30
22
 
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.
23
+ 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 Roles had another, the User could benefit from both. So i included the feature into both models and then decorated my User model like following.
32
24
 
33
25
  module Decorators
34
26
  module Models
@@ -36,16 +28,11 @@ I wanted to have the possibility to assign permissions both directly to my User
36
28
  module DynamicanOverrides
37
29
  def self.prepended(base)
38
30
  base.class_eval do
39
- has_many :user_permission_connectors, class_name: 'Dynamican::PermissionConnector'
40
- has_many :user_permissions, class_name: 'Dynamican::Permission', through: :user_permission_connectors, source: :permission
31
+ has_many :user_permissions, class_name: 'Dynamican::Permission', as: :permittable, inverse_of: :permittable, foreign_key: :permittable_id
41
32
  has_many :role_permissions, through: :roles, class_name: 'Dynamican::Permission', source: :permissions
42
33
  end
43
34
  end
44
35
 
45
- def permission_connectors
46
- Dynamican::PermissionConnector.where(id: user_permission_connectors.ids + roles.map(&:permission_connectors).flatten.map(&:id))
47
- end
48
-
49
36
  def permissions
50
37
  Dynamican::Permission.where(id: user_permissions.ids + role_permissions.ids)
51
38
  end
@@ -56,71 +43,84 @@ I wanted to have the possibility to assign permissions both directly to my User
56
43
  end
57
44
  end
58
45
 
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.
46
+ I personally have put this in `app/decorators/models/user/dynamican_overrides.rb` (rails needs to load the folder of course); you can make it work as you please but i recommend to keep it separate from the original User model.
62
47
 
63
48
  ## Usage
64
49
 
65
50
  Now the hard part: the real configuration.
66
51
 
67
- Create one `Dynamican::Permission` for each pair of action-object you need. For example i created CRUD permissions for my models. Let's say, for instance, you have the Order model.
52
+ Create one `Dynamican::Action` for each action you need. For example i created CRUD permissions.
68
53
 
69
- p1 = Dynamican::Permission.create(action: 'create', object_name: 'order')
70
- p2 = Dynamican::Permission.create(action: 'read', object_name: 'order')
71
- p3 = Dynamican::Permission.create(action: 'update', object_name: 'order')
72
- p4 = Dynamican::Permission.create(action: 'delete', object_name: 'order')
54
+ a1 = Dynamican::Action.create(name: 'create')
55
+ a2 = Dynamican::Action.create(name: 'read')
56
+ a3 = Dynamican::Action.create(name: 'update')
57
+ a4 = Dynamican::Action.create(name: 'delete')
73
58
 
74
- To assign one of these permissions to your Role or User, you need to create a `Dynamican::PermissionConnector` like follows.
59
+ Then create one `Dynamican::Item` for each resource you want your permittables to have permissions to act on. This is not mandatory for every permission though: you can also set a permission to do a general action, like `login`. Right now i'm trying to setup permissions for my permittable (Role model) to act on Order model.
75
60
 
76
- role.permission_connectors.create(permission: p1)
61
+ i1 = Dynamican::Item.create(name: 'Order')
77
62
 
78
- Or simply
63
+ NOTE: conventionally, the name should be PascalCase, so there is a `before_validation` hook that classifies the name you are setting.
79
64
 
80
- role.permissions << p1
65
+ Create one `Dynamican::Permission` for each action you want your `role` instance to have permissions for.
81
66
 
82
- Now your Role is considered able to create orders and you can evaluate permissions with `can?` method.
67
+ p1 = Dynamican::Permission.create(action: a1, items: [i1], permittable: role)
68
+ p2 = Dynamican::Permission.create(action: a2, items: [i1], permittable: role)
69
+ p3 = Dynamican::Permission.create(action: a3, items: [i1], permittable: role)
70
+ p4 = Dynamican::Permission.create(action: a4, items: [i1], permittable: role)
83
71
 
84
- role.can? :create, :order
72
+ Now your Role is considered able to create, read, update and destroy orders; you can evaluate permissions with `can?` method.
85
73
 
86
- # Returns true
74
+ role.can? :create, :order
87
75
 
88
- role.can? :read, :order
76
+ # true
89
77
 
90
- # Returns false
78
+ role.can? :else, :order
91
79
 
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).
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.
80
+ # false
95
81
 
96
- p5 = Dynamican::Permission.create(action: 'dance')
82
+ You can pass as second argument (the item) a symbol, a string, the class itself and also the instance (instances are required for condition evaluations).
83
+ 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 items are evaluated positively.
84
+ You can also create custom permissions which don't need an item, (item is not required for permission creation). Let's say you want to give permission to a certain `user` to dance.
97
85
 
98
- user.permissions << p5
86
+ action_dance = Dynamican::Action.create(name: 'dance')
87
+ p5 = Dynamican::Permission.create(action: action_dance, permittable: user)
99
88
 
100
89
  Call the `can?` method without any second argument
101
90
 
102
91
  user.can? :dance
103
92
 
104
- # Returns true
93
+ # true
105
94
 
106
95
 
107
96
  ### Conditions
108
97
 
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`)
98
+ You can link a `Dynamican::Permission` to as many conditions as you want. A permission having at least one condition linked to is considered conditional (Permission class have `conditional` and `unconditional` scopes)
110
99
 
111
100
  Conditions are created like this.
112
101
 
113
- permission_connector.conditions.create(statement: '@user.orders.count < 5')
114
- permission_connector.conditions.create(statement: '@object.field.present?')
102
+ permission.conditions.create(statement: '@user.orders.count < 5')
103
+ permission.conditions.create(statement: '@item.field.present?')
115
104
 
116
105
  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.
117
106
 
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.
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`.
107
+ 1. The model name of the instance you called `can?` from, like the user, will be defined automatically based both on a fixed name and on model name, so if you call `user.can?` you will have `@subject` variable (this is fixed) and `@user` variable defined because user is of class `User` (namespaces get cut out, so `Something::User` still turne into `@user`).
108
+ 2. The same thing happens with the item: it will be defined both as `@item` and as the name of its class, so if you call `user.can? :read, @order` you will have `@item` and `@order` variable defined containing your `@order` object.
120
109
  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.
121
110
 
122
111
  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.
123
112
 
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:
113
+ If one `Dynamican::Permission` 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:
125
114
 
126
115
  condition.statement = '@user.nice? || @user.polite?'
116
+
117
+ ### Permission scopes
118
+
119
+ You can apply the scope `for_action(action_name)` to Permission to find permissions bound to a specific action.
120
+ There is a `for_item(item_name)` scope, which turns to string and then classifies automatically the argument to match it with the classified item name. The scope filters all Permission records that have an item with the specified name in its items list.
121
+ There is also a `without_item` scope to filter records that are not linked to any item.
122
+ As mentioned before, you can also use `conditional` and `unconditional` scopes to find objects with or without any condition attached.
123
+
124
+ ### Controller usage
125
+
126
+ Your controllers now all have the `authorize!` method, which accepts one or two arguments: the first is the action, and the second (optional) is the item (or list of items) you want to check permissions for. As you can see, the usage is similar to the `can?` method. The reason is that is actually calls that method on the instance of `@current_user` and, whether permissions are evaluated as false, it raises an exception which is rescued by an `unauthorized` response rendered.
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.9'
4
- s.date = '2020-04-18'
3
+ s.version = '1.0.2'
4
+ s.date = '2021-06-30'
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
@@ -1,7 +1,8 @@
1
- require 'dynamican/configuration'
1
+ require 'dynamican/authorization'
2
2
  require 'dynamican/evaluator'
3
3
  require 'dynamican/model'
4
- require 'models/dynamican/condition'
5
- require 'models/dynamican/permission_connector'
6
4
  require 'models/dynamican/permission'
7
- require 'generators/create_dynamican_migration'
5
+ require 'models/dynamican/action'
6
+ require 'models/dynamican/item'
7
+ require 'models/dynamican/condition'
8
+ require 'generators/dynamican_migration_generator'
@@ -0,0 +1,25 @@
1
+ module Dynamican
2
+ module Authorization
3
+ extend ActiveSupport::Concern
4
+
5
+ class UnauthorizedResource < StandardError; end
6
+
7
+ included do
8
+ rescue_from UnauthorizedResource, with: :unauthorized
9
+ end
10
+
11
+ def authorize!(action, item = nil)
12
+ raise UnauthorizedResource unless @current_user.can? action, item
13
+ end
14
+
15
+ def unauthorized
16
+ render status: :unauthorized
17
+ end
18
+ end
19
+ end
20
+
21
+ if defined? ActiveSupport
22
+ ActiveSupport.on_load(:action_controller) do
23
+ include Dynamican::Authorization
24
+ end
25
+ end
@@ -1,43 +1,46 @@
1
1
  module Dynamican
2
2
  class Evaluator
3
- attr_reader :subject, :action, :object, :object_name, :conditions_instances
3
+ attr_reader :subject, :action, :item, :item_name, :conditions_instances
4
4
 
5
- def initialize(subject, action, object, conditions_instances = {})
5
+ def initialize(subject, action, item, conditions_instances = {})
6
6
  @subject = subject
7
7
  @action = action
8
- @object = object
9
- @object_name = calculate_object_name
8
+ @item = item
9
+ @item_name = calculate_item_name
10
10
  @conditions_instances = conditions_instances
11
11
  end
12
12
 
13
13
  def evaluate
14
14
  set_instance_variables
15
15
 
16
- matching_connectors = subject.permission_connectors.for_action(action).for_object(object_name)
17
- matching_conditions_statements = matching_connectors.conditional.map(&:conditions).flatten.map(&:statement)
16
+ matching_permissions = item.present? ? subject.permissions.for_action(action).for_item(item_name) : subject.permissions.for_action(action).without_item
17
+ matching_permissions_statements = matching_permissions.conditional.map(&:conditions).flatten.map(&:statement)
18
18
 
19
- matching_connectors.unconditional.any? ||
20
- matching_conditions_statements.any? && matching_conditions_statements.map { |statement| eval statement }.all?
19
+ matching_permissions.unconditional.any? ||
20
+ matching_permissions_statements.any? && matching_permissions_statements.map { |statement| eval statement }.all?
21
21
  end
22
22
 
23
23
  private
24
24
 
25
25
  def set_instance_variables
26
- instance_variable_set("@#{subject.model_name.element}", subject)
26
+ instance_variable_set("@#{subject.class.name.demodulize.underscore}", subject)
27
+ instance_variable_set("@#{item.class.name.demodulize.underscore}", item)
27
28
 
28
- conditions_instances.each do |instance_name, instance_object|
29
- instance_variable_set("@#{instance_name}", instance_object)
29
+ conditions_instances.each do |instance_name, instance_item|
30
+ instance_variable_set("@#{instance_name}", instance_item)
30
31
  end
31
32
  end
32
33
 
33
- def calculate_object_name
34
- if object.class.in? [Symbol, String, Class]
35
- object.to_s.downcase
36
- elsif object.is_a?(NilClass)
37
- nil
34
+ def calculate_item_name
35
+ class_name = if item.class.in? [Symbol, String, Class]
36
+ item.to_s.classify
38
37
  else
39
- object.class.to_s.downcase
38
+ item.class.name.demodulize
40
39
  end
40
+
41
+ given_item_name = item.class.try(:dynamican_item_name)
42
+
43
+ given_item_name || class_name
41
44
  end
42
45
  end
43
46
  end
@@ -3,15 +3,14 @@ module Dynamican
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- has_many :permission_connectors, class_name: 'Dynamican::PermissionConnector'
7
- has_many :permissions, class_name: 'Dynamican::Permission', through: :permission_connectors, source: :permission
6
+ has_many :permissions, class_name: 'Dynamican::Permission', as: :permittable, dependent: :destroy
8
7
  end
9
8
 
10
- def can?(action, object = nil, conditions_instances = {})
11
- if object.respond_to? :each
12
- object.all? { |single_object| can? action, single_object }
9
+ def can?(action, item = nil, conditions_instances = {})
10
+ if item.respond_to? :each
11
+ item.all? { |single_item| can? action, single_item }
13
12
  else
14
- Dynamican::Evaluator.new(self, action, object, conditions_instances).evaluate
13
+ Dynamican::Evaluator.new(self, action, item, conditions_instances).evaluate
15
14
  end
16
15
  end
17
16
  end
@@ -11,49 +11,43 @@ class DynamicanMigrationGenerator < Rails::Generators::Base
11
11
  def migration_data
12
12
  <<MIGRATION
13
13
  class DynamicanMigration < ActiveRecord::Migration[5.2]
14
- # 0.1.2 Release
15
14
  def change
16
15
  unless table_exists? :permissions
17
- create_table :conditions do |t|
18
- t.string :description
19
- t.string :statement
16
+ create_table :permissions do |t|
17
+ t.bigint :permittable_id
18
+ t.string :permittable_type
19
+ t.bigint :action_id
20
20
 
21
21
  t.timestamps
22
22
  end
23
23
 
24
- create_table :permissions do |t|
25
- t.string :action
26
- t.string :object_name
24
+ create_table :actions do |t|
25
+ t.string :name
27
26
 
28
27
  t.timestamps
29
28
  end
30
29
 
31
- create_table :permission_connectors do |t|
32
- #{create_migration_associations_data}
33
- t.references :permission
34
- t.boolean :conditional, default: false
30
+ create_table :items do |t|
31
+ t.string :name
35
32
 
36
33
  t.timestamps
37
34
  end
38
35
 
39
- create_table :conditions_permission_connectors do |t|
40
- t.bigint :condition_id
41
- t.bigint :permission_connector_id
36
+ create_table :conditions do |t|
37
+ t.bigint :permission_id
38
+ t.string :statement
39
+ t.string :description
40
+
41
+ t.timestamps
42
+ end
43
+
44
+ create_table :items_permissions do |t|
45
+ t.bigint :item_id
46
+ t.bigint :permission_id
42
47
  end
43
48
  end
44
49
  end
45
50
  end
46
51
  MIGRATION
47
52
  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
53
  end
@@ -0,0 +1,9 @@
1
+ module Dynamican
2
+ class Action < ActiveRecord::Base
3
+ has_many :permissions, class_name: 'Dynamican::Permission', inverse_of: :action, foreign_key: :action_id, dependent: :destroy
4
+
5
+ validates :name, presence: true, uniqueness: true
6
+
7
+ attr_readonly :name
8
+ end
9
+ end
@@ -1,5 +1,7 @@
1
1
  module Dynamican
2
2
  class Condition < ActiveRecord::Base
3
- has_and_belongs_to_many :permission_connectors, class_name: 'Dynamican::PermissionConnector', foreign_key: :condition_id
3
+ belongs_to :permission, class_name: 'Dynamican::Permission', inverse_of: :conditions, foreign_key: :permission_id
4
+
5
+ validates_presence_of :statement
4
6
  end
5
7
  end
@@ -0,0 +1,15 @@
1
+ module Dynamican
2
+ class Item < ActiveRecord::Base
3
+ has_and_belongs_to_many :permissions, class_name: 'Dynamican::Permission', inverse_of: :items, foreign_key: :item_id, dependent: :destroy
4
+
5
+ validates :name, presence: true, uniqueness: true
6
+
7
+ attr_readonly :name
8
+
9
+ before_validation :classify_name
10
+
11
+ def classify_name
12
+ self.name = self.name.classify
13
+ end
14
+ end
15
+ end
@@ -1,10 +1,14 @@
1
1
  module Dynamican
2
2
  class Permission < ActiveRecord::Base
3
- has_many :permission_connectors, class_name: 'Dynamican::PermissionConnector', inverse_of: :permission, foreign_key: :permission_id
3
+ belongs_to :permittable, polymorphic: true
4
+ belongs_to :action, class_name: 'Dynamican::Action', inverse_of: :permissions, foreign_key: :action_id
5
+ has_and_belongs_to_many :items, class_name: 'Dynamican::Item', inverse_of: :permissions, foreign_key: :permission_id
6
+ has_many :conditions, class_name: 'Dynamican::Condition', inverse_of: :permission, foreign_key: :permission_id
4
7
 
5
- validates_presence_of :action
6
-
7
- scope :for_action, -> (actions) { where(action: actions) }
8
- scope :for_object, -> (object_names) { where(object_name: object_names) }
8
+ scope :for_action, -> (action_name) { joins(:action).where(actions: { name: action_name }) }
9
+ scope :for_item, -> (item_name) { joins(:items).where(items: { name: item_name.to_s.classify }) }
10
+ scope :without_item, -> { left_outer_joins(:items).where(items: { id: nil }) }
11
+ scope :conditional, -> { joins(:conditions) }
12
+ scope :unconditional, -> { left_outer_joins(:conditions).where(conditions: { id: nil }) }
9
13
  end
10
14
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamican
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Valerio Bellaveglia
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-18 00:00:00.000000000 Z
11
+ date: 2021-06-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Dynamic and flexible database configurable permissions for your application
14
- email:
14
+ email:
15
15
  executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
@@ -20,18 +20,19 @@ files:
20
20
  - README.md
21
21
  - dynamican.gemspec
22
22
  - lib/dynamican.rb
23
- - lib/dynamican/configuration.rb
23
+ - lib/dynamican/authorization.rb
24
24
  - lib/dynamican/evaluator.rb
25
25
  - lib/dynamican/model.rb
26
26
  - lib/generators/dynamican_migration_generator.rb
27
+ - lib/models/dynamican/action.rb
27
28
  - lib/models/dynamican/condition.rb
29
+ - lib/models/dynamican/item.rb
28
30
  - lib/models/dynamican/permission.rb
29
- - lib/models/dynamican/permission_connector.rb
30
31
  homepage: https://github.com/ValerioBellaveglia/Dynamican
31
32
  licenses:
32
33
  - MIT
33
34
  metadata: {}
34
- post_install_message:
35
+ post_install_message:
35
36
  rdoc_options: []
36
37
  require_paths:
37
38
  - lib
@@ -46,8 +47,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
46
47
  - !ruby/object:Gem::Version
47
48
  version: '0'
48
49
  requirements: []
49
- rubygems_version: 3.0.2
50
- signing_key:
50
+ rubygems_version: 3.2.3
51
+ signing_key:
51
52
  specification_version: 4
52
53
  summary: Dynamic permissions
53
54
  test_files: []
@@ -1,17 +0,0 @@
1
- module Dynamican
2
- def self.configuration
3
- @configuration ||= Configuration.new(configuration_hash)
4
- end
5
-
6
- def self.configuration_hash
7
- @configuration_hash ||= HashWithIndifferentAccess.new(YAML.load_file('config/dynamican.yml'))
8
- end
9
-
10
- class Configuration
11
- attr_accessor :associations
12
-
13
- def initialize(configuration_hash)
14
- @associations = configuration_hash[:associations]
15
- end
16
- end
17
- end
@@ -1,14 +0,0 @@
1
- module Dynamican
2
- class PermissionConnector < ActiveRecord::Base
3
- Dynamican.configuration.associations.each do |association_name, association_options|
4
- belongs_to association_name.to_sym, class_name: association_options[:class_name], inverse_of: association_options[:inverse_of], foreign_key: "#{association_name}_id".to_sym, optional: true
5
- end
6
- has_and_belongs_to_many :conditions, class_name: 'Dynamican::Condition', inverse_of: :permission_connectors, foreign_key: :permission_connector_id
7
- belongs_to :permission, class_name: 'Dynamican::Permission', inverse_of: :permission_connectors, foreign_key: :permission_id
8
-
9
- scope :conditional, -> { where(conditional: true) }
10
- scope :unconditional, -> { where(conditional: false) }
11
- scope :for_action, -> (action) { joins(:permission).where(permissions: { action: action }) }
12
- scope :for_object, -> (object_name) { joins(:permission).where(permissions: { object_name: object_name }) }
13
- end
14
- end