bullet_train-roles 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f03a796a2c17954ad4c25e313caea68ba0b60b7e8901e7c1acf83d869e100592
4
- data.tar.gz: 131e6518cefb00c6ea280d4ac4bf492961cb6f45b6d0ef3d695b66de9366d906
3
+ metadata.gz: 51bbbee558714e45bdff2dadf3735cf8a2fce88d7e7e3a8144880c245bb8e384
4
+ data.tar.gz: 419402bc1f7560bc932c202275091456e4a68ddd271ddf7382df57b7f4b21b1f
5
5
  SHA512:
6
- metadata.gz: 7df53d71fb2d393e84a30a5efb1fa9f351781653b40e1cc31e5cf565d4432228b3a78b6924d021908c5d463695dfdeb0dff834a0f1c63a26438774e8159f4438
7
- data.tar.gz: 56a0c8b76f5105959d828db3f619c863cc917fd3caf1e8dc838151268da68da1bce455ebd3378f68dfa7bf78d804d673df311f6351cfd0a47a2b4f43a6c68c07
6
+ metadata.gz: 30bfee959c7c45e7dda23c7d4f71fa44a1efc9499e3bd5244e48e55895ff88e21fc26ade42def3591661c0aef1796762edae9a05625b1145822c5eb3a71cfc43
7
+ data.tar.gz: 6da43045a530531c8910f4c456f7c5b7211ac90f9cce69d05fc7a7456fedb664d099a951d0c5fdd131f4daa8f0784ac36add7837bfcc7760ff5193c22191c21c
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Roles
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.5"
5
5
  end
data/lib/models/role.rb CHANGED
@@ -21,17 +21,12 @@ class Role < ActiveYaml::Base
21
21
 
22
22
  def self.includes(role_or_key)
23
23
  role_key = role_or_key.is_a?(Role) ? role_or_key.key : role_or_key
24
-
25
24
  role = Role.find_by_key(role_key)
26
-
27
25
  return Role.all.select(&:assignable?) if role.default?
28
-
29
26
  result = []
30
-
31
27
  all.each do |role|
32
28
  result << role if role.includes.include?(role_key)
33
29
  end
34
-
35
30
  result
36
31
  end
37
32
 
@@ -49,6 +44,10 @@ class Role < ActiveYaml::Base
49
44
  key
50
45
  end
51
46
 
47
+ def to_s
48
+ key
49
+ end
50
+
52
51
  def included_by
53
52
  Role.includes(self)
54
53
  end
@@ -69,20 +68,15 @@ class Role < ActiveYaml::Base
69
68
 
70
69
  def included_roles
71
70
  default_roles = []
72
-
73
71
  default_roles << Role.default unless default?
74
-
75
72
  (default_roles + includes.map { |included_key| Role.find_by_key(included_key) }).uniq.compact
76
73
  end
77
74
 
78
75
  def manageable_by?(role_or_roles)
79
76
  return true if default?
80
-
81
77
  roles = role_or_roles.is_a?(Array) ? role_or_roles : [role_or_roles]
82
-
83
78
  roles.each do |role|
84
79
  return true if role.manageable_roles.include?(key)
85
-
86
80
  role.included_roles.each do |included_role|
87
81
  return true if manageable_by?([included_role])
88
82
  end
@@ -151,42 +145,38 @@ class Role < ActiveYaml::Base
151
145
 
152
146
  def actions
153
147
  return @actions if @actions
154
-
155
148
  actions = (@ability_data["actions"] if @ability_data.is_a?(Hash)) || @ability_data
156
-
157
149
  actions = [actions] unless actions.is_a?(Array)
158
-
159
150
  @actions = actions.map!(&:to_sym)
160
151
  end
161
152
 
162
153
  def possible_parent_associations
163
154
  ary = @parent.to_s.split("::").map(&:underscore)
164
-
165
155
  possibilities = []
166
156
  current = nil
167
-
168
157
  until ary.empty?
169
158
  current = "#{ary.pop}#{"_" unless current.nil?}#{current}"
170
159
  possibilities << current
171
160
  end
172
-
173
161
  possibilities.map(&:to_sym)
174
162
  end
175
163
 
176
164
  def condition
177
165
  return @condition if @condition
178
-
179
166
  return nil unless @parent_ids
180
-
181
167
  if @model == @parent
182
168
  return @condition = {id: @parent_ids}
183
169
  end
184
-
185
- parent_association = possible_parent_associations.find { |association| @model.method_defined? association }
186
-
170
+ parent_association = possible_parent_associations.find { |association| @model.method_defined?(association) || @model.method_defined?("#{association}_id") }
187
171
  return nil unless parent_association.present?
188
-
189
- @condition = {parent_association => {id: @parent_ids}}
172
+ # If possible, use the team_id attribute because it saves us having to join all the way back to the sorce parent model
173
+ # In some scenarios this may be quicker, or if the parent model is in a different database shard, it may not even
174
+ # be possible to do the join
175
+ if @model.method_defined?("#{parent_association}_id")
176
+ @condition = {"#{parent_association}_id".to_sym => @parent_ids}
177
+ else
178
+ @condition = {parent_association => {id: @parent_ids}}
179
+ end
190
180
  end
191
181
  end
192
182
  end
data/lib/roles/permit.rb CHANGED
@@ -8,23 +8,18 @@ module Roles
8
8
 
9
9
  # When changing permissions during development, you may also want to do this on each request:
10
10
  # User.update_all ability_cache: nil if Rails.env.development?
11
-
12
11
  output = []
13
12
  added_roles = Set.new
14
-
15
13
  user.send(through).map(&:roles).flatten.uniq.each do |role|
16
14
  unless added_roles.include?(role)
17
15
  output << "########### ROLE: #{role.key}"
18
-
19
16
  output += add_abilities_for(role, user, through, parent)
20
-
21
17
  added_roles << role
22
18
  end
23
19
 
24
20
  role.included_roles.each do |included_role|
25
21
  unless added_roles.include?(included_role)
26
22
  output << "############# INCLUDED ROLE: #{included_role.key}"
27
-
28
23
  output += add_abilities_for(included_role, user, through, parent)
29
24
  end
30
25
  end
@@ -40,17 +35,14 @@ module Roles
40
35
 
41
36
  def add_abilities_for(role, user, through, parent)
42
37
  output = []
43
-
44
38
  role.ability_generator(user, through, parent) do |ag|
45
39
  if ag.valid?
46
40
  output << "can #{ag.actions}, #{ag.model}, #{ag.condition}"
47
-
48
41
  can(ag.actions, ag.model, ag.condition)
49
42
  else
50
43
  output << "# #{ag.model} does not respond to #{parent} so we're not going to add an ability for the #{through} context"
51
44
  end
52
45
  end
53
-
54
46
  output
55
47
  end
56
48
  end
data/lib/roles/support.rb CHANGED
@@ -13,16 +13,13 @@ module Roles
13
13
 
14
14
  def assignable_roles
15
15
  return Role.assignable if @allowed_roles.nil?
16
-
17
16
  Role.assignable.select { |role| @allowed_roles.include?(role.key.to_sym) }
18
17
  end
19
18
 
20
19
  # Note default_role is an ActiveRecord core class method so we need to use something else here
21
20
  def default_roles
22
21
  default_role = Role.default
23
-
24
22
  return [default_role] if @allowed_roles.nil?
25
-
26
23
  @allowed_roles.include?(default_role.key.to_sym) ? [default_role] : []
27
24
  end
28
25
  end
@@ -30,11 +27,7 @@ module Roles
30
27
  included do
31
28
  validate :validate_roles
32
29
 
33
- # This query will return records that have a role "included" in a different role they have.
34
- # For example, if you do with_roles(editor) it will return admin users if the admin role includes the editor role
35
- scope :with_roles, ->(roles) { where("#{table_name}.role_ids ?| array[:keys]", keys: roles.map(&:key_plus_included_by_keys).flatten.uniq.map(&:to_s)) }
36
-
37
- # This query will return roles that include the given role. See with_roles above for details
30
+ # This query will return roles that include the given role. See self.with_roles below for details
38
31
  scope :with_role, ->(role) { role.nil? ? all : with_roles([role]) }
39
32
  scope :viewers, -> { where("#{table_name}.role_ids = ?", [].to_json) }
40
33
  scope :editors, -> { with_role(Role.find_by_key("editor")) }
@@ -43,6 +36,26 @@ module Roles
43
36
  after_save :invalidate_cache
44
37
  after_destroy :invalidate_cache
45
38
 
39
+ # This query will return records that have a role "included" in a different role they have.
40
+ # For example, if you do with_roles(editor) it will return admin users if the admin role includes the editor role
41
+ def self.with_roles(roles)
42
+ # Mysql and postgres have different syntax for searching json or jsonb columns so we need different queries depending on the database
43
+ ActiveRecord::Base.connection.adapter_name.downcase.include?("mysql") ? with_roles_mysql(roles) : with_roles_postgres(roles)
44
+ end
45
+
46
+ def self.with_roles_mysql(roles)
47
+ queries = []
48
+ roles.map(&:key_plus_included_by_keys).flatten.uniq.map(&:to_s).each do |role|
49
+ queries << "JSON_CONTAINS(#{table_name}.role_ids, '\"#{role}\"')"
50
+ end
51
+ query = queries.join(" OR ")
52
+ where(query)
53
+ end
54
+
55
+ def self.with_roles_postgres(roles)
56
+ where("#{table_name}.role_ids ?| array[:keys]", keys: roles.map(&:key_plus_included_by_keys).flatten.uniq.map(&:to_s))
57
+ end
58
+
46
59
  def validate_roles
47
60
  self.role_ids = role_ids&.select(&:present?) || []
48
61
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet_train-roles
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Prabin Poudel
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-02-10 00:00:00.000000000 Z
12
+ date: 2022-02-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: byebug