bullet_train-roles 0.1.4 → 0.1.5

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: 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