bullet_train-roles 0.1.5 → 0.1.8

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: 51bbbee558714e45bdff2dadf3735cf8a2fce88d7e7e3a8144880c245bb8e384
4
- data.tar.gz: 419402bc1f7560bc932c202275091456e4a68ddd271ddf7382df57b7f4b21b1f
3
+ metadata.gz: 4fafcbc375644791ab3480a2bee1e43f19074e3efa30809d4770a27e80d25634
4
+ data.tar.gz: fc145307e762f0abc11839dd2710c5b11ed2747a9b514f5a32d4707268d35a21
5
5
  SHA512:
6
- metadata.gz: 30bfee959c7c45e7dda23c7d4f71fa44a1efc9499e3bd5244e48e55895ff88e21fc26ade42def3591661c0aef1796762edae9a05625b1145822c5eb3a71cfc43
7
- data.tar.gz: 6da43045a530531c8910f4c456f7c5b7211ac90f9cce69d05fc7a7456fedb664d099a951d0c5fdd131f4daa8f0784ac36add7837bfcc7760ff5193c22191c21c
6
+ metadata.gz: cf85bf3d3df4a12751b7ac55fedf7917ec2634956e7df9c2a4d8a43e65000ff36b8740f1f0974b97e6cba4929831ef54159035a4dd4f5504fa8ef359cab95ed6
7
+ data.tar.gz: e34a82313a0291b967222780dde2e60d7ab3c14131e97270c1c1dd5c20073758e3d9347d4046c56fcc26ece2581347438e82eded64e067a19ba9fe3fdd2e42e0
data/.circleci/config.yml CHANGED
@@ -1,86 +1,124 @@
1
1
  version: 2.1
2
2
  orbs:
3
3
  ruby: circleci/ruby@0.1.2
4
-
4
+ browser-tools: circleci/browser-tools@1.1
5
5
  aliases:
6
6
  - &restore_bundler_cache
7
- name: Restore Bundler cache
8
- keys:
9
- - gem-cache-v1-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
10
- - gem-cache-v1-{{ .Branch }}-
11
- - gem-cache-v1-
7
+ name: Restore Bundler cache
8
+ keys:
9
+ - gem-cache-v1-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
10
+ - gem-cache-v1-{{ .Branch }}-
11
+ - gem-cache-v1-
12
12
  - &restore_yarn_cache
13
- name: Restore Yarn cache
14
- keys:
15
- - yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
16
- - yarn-packages-v1-{{ .Branch }}-
17
- - yarn-packages-
13
+ name: Restore Yarn cache
14
+ keys:
15
+ - yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
16
+ - yarn-packages-v1-{{ .Branch }}-
17
+ - yarn-packages-
18
18
  - &save_bundle_cache
19
- name: Save Bundle cache
20
- key: gem-cache-v1-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
21
- paths:
22
- - vendor/bundle
19
+ name: Save Bundle cache
20
+ key: gem-cache-v1-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
21
+ paths:
22
+ - vendor/bundle
23
23
  - &save_yarn_cache
24
- name: Save Yarn cache
25
- key: yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
26
- paths:
27
- - node_modules
28
-
24
+ name: Save Yarn cache
25
+ key: yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
26
+ paths:
27
+ - node_modules
28
+ - &ruby_node_browsers_docker_image
29
+ - image: cimg/ruby:3.1.2-browsers
30
+ environment:
31
+ PGHOST: localhost
32
+ PGUSER: untitled_application
33
+ RAILS_ENV: test
34
+ - &postgres_docker_image
35
+ - image: circleci/postgres
36
+ environment:
37
+ POSTGRES_HOST_AUTH_METHOD: trust
38
+ POSTGRES_DB: untitled_application_test
39
+ POSTGRES_USER: untitled_application
40
+ - &wait_for_docker
41
+ # We run this because the DB might not be available for a while due to a race condition.
42
+ run: dockerize -wait tcp://localhost:5432 -timeout 1m
29
43
  jobs:
30
- 'Standard Ruby':
44
+ 'Local Minitest':
45
+ docker:
46
+ - <<: *ruby_node_browsers_docker_image
47
+ - <<: *postgres_docker_image
48
+ - image: circleci/redis
49
+ executor: ruby/default
50
+ steps:
51
+ - browser-tools/install-browser-tools
52
+ - checkout
53
+
54
+ # Install dependencies
55
+ - run: "bundle install"
56
+ - run: "bundle clean --force"
57
+ - run: "yarn install"
58
+ - *wait_for_docker
59
+ - run:
60
+ name: Run unit tests
61
+ command: bundle exec rails test
62
+
63
+ 'Local Standard Ruby':
31
64
  docker:
32
- # normal ruby image is also sufficient here but we are using node-browsers so that we can make use of caching and speed up the process since other jobs are also using the same image
33
- - image: circleci/ruby:3.0.2-node-browsers
65
+ - <<: *ruby_node_browsers_docker_image
34
66
  steps:
35
67
  - checkout
36
68
 
37
- # Restore dependency caches
38
- - restore_cache: *restore_bundler_cache
39
- - restore_cache: *restore_yarn_cache
69
+ # TODO Figure out how to make these work for `tmp/starter`
70
+ # # Restore dependency caches
71
+ # - restore_cache: *restore_bundler_cache
72
+ # - restore_cache: *restore_yarn_cache
40
73
 
41
74
  # Install dependencies
42
75
  - ruby/bundle-install
43
76
  - run: bundle clean --force
44
77
  - run: yarn install
45
78
 
46
- # Save dependency caches
47
- # We only do this as part of this job, because it's time consuming and we don't want it to slow down test runners.
48
- - save_cache: *save_bundle_cache
49
- - save_cache: *save_yarn_cache
79
+ # # Save dependency caches
80
+ # # We only do this as part of this job, because it's time consuming and we don't want it to slow down test runners.
81
+ # - save_cache: *save_bundle_cache
82
+ # - save_cache: *save_yarn_cache
50
83
 
51
84
  - run:
52
85
  name: Check Standard Ruby
53
86
  command: bundle exec standardrb
54
87
 
55
- 'Minitest':
88
+ 'Starter Repo Minitest':
56
89
  docker:
57
- - image: circleci/ruby:3.0.2-node-browsers
58
- environment:
59
- PGHOST: localhost
60
- PGUSER: bullet_train
61
- RAILS_ENV: test
62
- - image: circleci/postgres
63
- environment:
64
- POSTGRES_HOST_AUTH_METHOD: trust
65
- POSTGRES_DB: bullet_train_test
66
- POSTGRES_USER: bullet_train
90
+ - <<: *ruby_node_browsers_docker_image
91
+ - <<: *postgres_docker_image
92
+ - image: circleci/redis
67
93
  executor: ruby/default
68
94
  parallelism: 16
69
95
  steps:
96
+ - browser-tools/install-browser-tools
70
97
  - checkout
71
- - restore_cache: *restore_bundler_cache
72
- - restore_cache: *restore_yarn_cache
98
+ - run: "git clone https://github.com/bullet-train-co/bullet_train.git tmp/starter"
99
+
100
+ - run:
101
+ name: Link starter repository to the Ruby gem being tested.
102
+ command: "grep -v 'gem \"bullet_train-roles\"' tmp/starter/Gemfile > tmp/starter/Gemfile.tmp && mv tmp/starter/Gemfile.tmp tmp/starter/Gemfile && echo 'gem \"bullet_train-roles\", path: \"../..\"' >> tmp/starter/Gemfile"
103
+
104
+ # TODO Figure out how to make these work for `tmp/starter`
105
+ # - restore_cache: *restore_bundler_cache
106
+ # - restore_cache: *restore_yarn_cache
73
107
 
74
108
  # Install dependencies
75
- - ruby/bundle-install
76
- - run: bundle clean --force
109
+ - run: "cd tmp/starter && bundle install"
110
+ - run: "cd tmp/starter && bundle clean --force"
111
+ - run: "cd tmp/starter && bundle exec rake bt:link"
112
+ - run: "cd tmp/starter && yarn install"
113
+ - run: "cd tmp/starter && yarn build"
114
+ - run: "cd tmp/starter && yarn build:css"
77
115
 
78
- # We run this because the DB might not be available for a while due to a race condition.
79
- - run: dockerize -wait tcp://localhost:5432 -timeout 1m
116
+ - *wait_for_docker
80
117
 
81
118
  - run:
82
119
  name: Run tests with Knapsack Pro
83
120
  command: |
121
+ cd tmp/starter
84
122
  export RAILS_ENV=test
85
123
  bundle exec rails "knapsack_pro:queue:minitest[--verbose]"
86
124
  environment:
@@ -102,9 +140,48 @@ jobs:
102
140
  # - store_test_results:
103
141
  # path: test/reports
104
142
 
143
+ 'Starter Repo Minitest for Super Scaffolding':
144
+ docker:
145
+ - <<: *ruby_node_browsers_docker_image
146
+ - <<: *postgres_docker_image
147
+ - image: circleci/redis
148
+ executor: ruby/default
149
+ steps:
150
+ - browser-tools/install-browser-tools
151
+ - checkout
152
+ - run: "git clone https://github.com/bullet-train-co/bullet_train.git tmp/starter"
153
+
154
+ - run:
155
+ name: Link starter repository to the Ruby gem being tested.
156
+ command: "grep -v 'gem \"bullet_train-roles\"' tmp/starter/Gemfile > tmp/starter/Gemfile.tmp && mv tmp/starter/Gemfile.tmp tmp/starter/Gemfile && echo 'gem \"bullet_train-roles\", path: \"../..\"' >> tmp/starter/Gemfile"
157
+
158
+ # TODO Figure out how to make these work for `tmp/starter`
159
+ # # Restore dependency caches
160
+ # - restore_cache: *restore_bundler_cache
161
+ # - restore_cache: *restore_yarn_cache
162
+
163
+ # Install dependencies
164
+ - run: "cd tmp/starter && bundle install"
165
+ - run: "cd tmp/starter && bundle clean --force"
166
+ - run: "cd tmp/starter && bundle exec rake bt:link"
167
+ - run: "cd tmp/starter && yarn install"
168
+ - run: "cd tmp/starter && yarn build"
169
+ - run: "cd tmp/starter && yarn build:css"
170
+
171
+ - *wait_for_docker
172
+
173
+ - run:
174
+ name: 'Setup Super Scaffolding System Test'
175
+ command: "cd tmp/starter && bundle exec test/bin/setup-super-scaffolding-system-test"
176
+ - run:
177
+ name: 'Run Super Scaffolding Test'
178
+ command: "cd tmp/starter && bundle exec rails test test/system/super_scaffolding_test.rb"
179
+
105
180
  workflows:
106
181
  version: 2
107
182
  build:
108
183
  jobs:
109
- - 'Standard Ruby'
110
- - 'Minitest'
184
+ - 'Local Minitest'
185
+ - 'Local Standard Ruby'
186
+ - 'Starter Repo Minitest'
187
+ - 'Starter Repo Minitest for Super Scaffolding'
data/Gemfile.lock CHANGED
@@ -9,7 +9,7 @@ GIT
9
9
  PATH
10
10
  remote: .
11
11
  specs:
12
- bullet_train-roles (0.1.4)
12
+ bullet_train-roles (0.1.8)
13
13
  active_hash
14
14
  activesupport
15
15
  cancancan
@@ -79,7 +79,7 @@ GEM
79
79
  ast (2.4.2)
80
80
  builder (3.2.4)
81
81
  byebug (11.1.3)
82
- cancancan (3.3.0)
82
+ cancancan (3.4.0)
83
83
  concurrent-ruby (1.1.9)
84
84
  crass (1.0.6)
85
85
  erubi (1.10.0)
@@ -106,6 +106,8 @@ GEM
106
106
  nio4r (2.5.8)
107
107
  nokogiri (1.12.5-arm64-darwin)
108
108
  racc (~> 1.4)
109
+ nokogiri (1.12.5-x86_64-darwin)
110
+ racc (~> 1.4)
109
111
  parallel (1.21.0)
110
112
  parser (3.0.3.2)
111
113
  ast (~> 2.4.1)
@@ -174,6 +176,7 @@ GEM
174
176
  PLATFORMS
175
177
  arm64-darwin-20
176
178
  arm64-darwin-21
179
+ x86_64-darwin-21
177
180
 
178
181
  DEPENDENCIES
179
182
  active_hash!
data/README.md CHANGED
@@ -68,7 +68,7 @@ editor:
68
68
  manageable_roles:
69
69
  - editor
70
70
  models:
71
- Project: manage
71
+ Project: crud
72
72
 
73
73
  billing:
74
74
  manageable_roles:
@@ -98,7 +98,8 @@ The following things are true given the example configuration above:
98
98
  - By default, users on a team are read-only participants.
99
99
  - Users with the `editor` role:
100
100
  - can give other users the `editor` role.
101
- - can modify project details.
101
+ - can perform crud actions on project (create, read, update and destroy).
102
+ - cannot perform any custom controller actions the projects controller responds to
102
103
  - Users with the `billing` role:
103
104
  - can give other users the `billing` role.
104
105
  - can create and update billing subscriptions.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Roles
4
- VERSION = "0.1.5"
4
+ VERSION = "0.1.8"
5
5
  end
data/lib/models/role.rb CHANGED
@@ -89,9 +89,9 @@ class Role < ActiveYaml::Base
89
89
  !default?
90
90
  end
91
91
 
92
- def ability_generator(user, through, parent)
92
+ def ability_generator(user, through, parent, intermediary)
93
93
  models.each do |model_name, _|
94
- ag = AbilityGenerator.new(self, model_name, user, through, parent)
94
+ ag = AbilityGenerator.new(self, model_name, user, through, parent, intermediary)
95
95
  yield(ag)
96
96
  end
97
97
  end
@@ -125,7 +125,7 @@ class Role < ActiveYaml::Base
125
125
  class AbilityGenerator
126
126
  attr_reader :model
127
127
 
128
- def initialize(role, model_name, user, through, parent_name)
128
+ def initialize(role, model_name, user, through, parent_name, intermediary = nil)
129
129
  begin
130
130
  @model = model_name.constantize
131
131
  rescue NameError
@@ -137,6 +137,8 @@ class Role < ActiveYaml::Base
137
137
  @through = through
138
138
  @parent = user.send(through).reflect_on_association(parent_name)&.klass
139
139
  @parent_ids = user.parent_ids_for(@role, @through, parent_name) if @parent
140
+ @intermediary = intermediary
141
+ @intermediary_class = @model.reflect_on_association(intermediary)&.class_name&.constantize if @intermediary.present?
140
142
  end
141
143
 
142
144
  def valid?
@@ -145,9 +147,16 @@ class Role < ActiveYaml::Base
145
147
 
146
148
  def actions
147
149
  return @actions if @actions
148
- actions = (@ability_data["actions"] if @ability_data.is_a?(Hash)) || @ability_data
149
- actions = [actions] unless actions.is_a?(Array)
150
- @actions = actions.map!(&:to_sym)
150
+ @actions = (@ability_data["actions"] if @ability_data.is_a?(Hash)) || @ability_data
151
+ # crud is a special value that we substitute for the 4 crud actions
152
+ # This is instead of :manage which covers all 4 actions _and_ any extra actions the controller may respond to
153
+ @actions = crud_actions if @actions.to_s.downcase == "crud"
154
+ @actions = [actions] unless actions.is_a?(Array)
155
+ @actions.map!(&:to_sym)
156
+ end
157
+
158
+ def crud_actions
159
+ [:create, :read, :update, :destroy]
151
160
  end
152
161
 
153
162
  def possible_parent_associations
@@ -167,15 +176,18 @@ class Role < ActiveYaml::Base
167
176
  if @model == @parent
168
177
  return @condition = {id: @parent_ids}
169
178
  end
170
- parent_association = possible_parent_associations.find { |association| @model.method_defined?(association) || @model.method_defined?("#{association}_id") }
179
+ parent_association = possible_parent_associations.find { |association| @model.reflect_on_association(association) || @intermediary_class&.reflect_on_association(association) }
171
180
  return nil unless parent_association.present?
172
- # If possible, use the team_id attribute because it saves us having to join all the way back to the sorce parent model
181
+ # If possible, use the team_id attribute because it saves us having to join all the way back to the source parent model
173
182
  # In some scenarios this may be quicker, or if the parent model is in a different database shard, it may not even
174
183
  # be possible to do the join
175
- if @model.method_defined?("#{parent_association}_id")
176
- @condition = {"#{parent_association}_id".to_sym => @parent_ids}
184
+ parent_with_id = "#{parent_association}_id"
185
+ @condition = if @model.column_names.include?(parent_with_id)
186
+ {parent_with_id.to_sym => @parent_ids}
187
+ elsif @intermediary.present? && @model.reflect_on_association(@intermediary)
188
+ {@intermediary.to_sym => {parent_with_id.to_sym => @parent_ids}}
177
189
  else
178
- @condition = {parent_association => {id: @parent_ids}}
190
+ {parent_association => {id: @parent_ids}}
179
191
  end
180
192
  end
181
193
  end
data/lib/roles/permit.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Roles
4
4
  module Permit
5
- def permit(user, through:, parent:, debug: false)
5
+ def permit(user, through:, parent:, debug: false, intermediary: nil)
6
6
  # Without this, you need to restart the server each time you make changes to the config/models/role.yml file
7
7
  Role.reload(true) if Rails.env.development?
8
8
 
@@ -13,14 +13,14 @@ module Roles
13
13
  user.send(through).map(&:roles).flatten.uniq.each do |role|
14
14
  unless added_roles.include?(role)
15
15
  output << "########### ROLE: #{role.key}"
16
- output += add_abilities_for(role, user, through, parent)
16
+ output += add_abilities_for(role, user, through, parent, intermediary)
17
17
  added_roles << role
18
18
  end
19
19
 
20
20
  role.included_roles.each do |included_role|
21
21
  unless added_roles.include?(included_role)
22
22
  output << "############# INCLUDED ROLE: #{included_role.key}"
23
- output += add_abilities_for(included_role, user, through, parent)
23
+ output += add_abilities_for(included_role, user, through, parent, intermediary)
24
24
  end
25
25
  end
26
26
  end
@@ -33,9 +33,9 @@ module Roles
33
33
  end
34
34
  end
35
35
 
36
- def add_abilities_for(role, user, through, parent)
36
+ def add_abilities_for(role, user, through, parent, intermediary)
37
37
  output = []
38
- role.ability_generator(user, through, parent) do |ag|
38
+ role.ability_generator(user, through, parent, intermediary) do |ag|
39
39
  if ag.valid?
40
40
  output << "can #{ag.actions}, #{ag.model}, #{ag.condition}"
41
41
  can(ag.actions, ag.model, ag.condition)
data/lib/roles/support.rb CHANGED
@@ -71,7 +71,7 @@ module Roles
71
71
  end
72
72
 
73
73
  def roles=(roles)
74
- self.role_ids = roles.map(&:key)
74
+ update(role_ids: roles.map(&:key))
75
75
  end
76
76
 
77
77
  def assignable_roles
data/lib/roles/user.rb CHANGED
@@ -10,16 +10,19 @@ module Roles
10
10
  def parent_ids_for(role, through, parent)
11
11
  parent_id_column = "#{parent}_id"
12
12
  key = "#{role.key}_#{through}_#{parent_id_column}s"
13
+
14
+ @_parent_ids_for_cache ||= {}
15
+ return @_parent_ids_for_cache[key] if @_parent_ids_for_cache[key]
16
+
13
17
  # TODO Maybe we should make ability caching a default feature of the gem?
14
18
  # If we do that, we would just make it check whether `ability_cache` exists.
15
19
  # return ability_cache[key] if ability_cache && ability_cache[key]
16
20
  role = nil if role.default?
17
- value = send(through).with_role(role).distinct.pluck(parent_id_column)
21
+ @_parent_ids_for_cache[key] = send(through).with_role(role).distinct.pluck(parent_id_column)
18
22
  # TODO Maybe we should make ability caching a default feature of the gem?
19
23
  # current_cache = ability_cache || {}
20
24
  # current_cache[key] = value
21
25
  # update_column :ability_cache, current_cache
22
- value
23
26
  end
24
27
  end
25
28
  end
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.5
4
+ version: 0.1.8
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-11 00:00:00.000000000 Z
12
+ date: 2022-07-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: byebug