bullet_train-super_load_and_authorize_resource 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1a068f14f14c8f382a9d7b30d30dcf7ac89656d30f2b2e8279110e139a449f34
4
+ data.tar.gz: e80081fe8ea016f9418b072529a540b6282ff6c240b806871457f2f9189d23d7
5
+ SHA512:
6
+ metadata.gz: '09989eceabb20cdc3ca223acade617e01628ad8ff5d31b29f07ddbb4bc6f50b1f25d2a982ed1d21601f7d8cdbe475e143956f9d10045bcdbdf06effe1fde7bb2'
7
+ data.tar.gz: d5f772ee16dabfcbbb6c8908480462ae7e3a251af528767ee1bab4c91782aa132281902d3724edb20f1a9e07170396bac66e741d6f85d14ceea3a14a5ccdc6e9
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2022 Andrew Culver
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # BulletTrain::SuperLoadAndAuthorizeResource
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem "bullet_train-super_load_and_authorize_resource"
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install bullet_train-super_load_and_authorize_resource
22
+ ```
23
+
24
+ ## Contributing
25
+ Contribution directions go here.
26
+
27
+ ## License
28
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
@@ -0,0 +1,189 @@
1
+ module LoadsAndAuthorizesResource
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ def regex_to_remove_controller_namespace
6
+ raise "This is a template method that needs to be implemented by controllers including LoadsAndAuthorizesResource."
7
+ end
8
+
9
+ def load_team
10
+ # Sometimes `@team` has already been populated by earlier `before_action` steps.
11
+ @team ||= @child_object&.team || @parent_object&.team
12
+
13
+ # Update current attributes.
14
+ Current.team = @team
15
+
16
+ # If the currently loaded team is saved to the database, make that the user's new current team.
17
+ if @team.try(:persisted?)
18
+ if can? :show, @team
19
+ current_user.update_column(:current_team_id, @team.id)
20
+ end
21
+ end
22
+ end
23
+
24
+ def self.model_namespace_from_controller_namespace
25
+ controller_class_name = regex_to_remove_controller_namespace ? name.gsub(regex_to_remove_controller_namespace, "") : name
26
+ namespace = controller_class_name.split("::")
27
+ # Remove "::ThingsController"
28
+ namespace.pop
29
+ namespace
30
+ end
31
+
32
+ # this is one of the few pieces of 'magical' functionality that bullet train implements
33
+ # for you in your controllers beyond that is provided by the underlying gems that we've
34
+ # tied together. we've taken the liberty of doing this because it's heavily based on
35
+ # cancancan's `load_and_authorize_resource` method, which is awesome, but it also
36
+ # implements a lot of the options required to make that method work very well for our
37
+ # controllers in the account namespace, including our shallow nested routes.
38
+ #
39
+ # there are also some complications that were introduced into this method by our support
40
+ # for namespaced models and controllers. (we introduced this complexity in support of
41
+ # namespacing our `Oauth::` models and controllers.)
42
+ #
43
+ # to help you understand the code below, usually `through` is `team`
44
+ # and `model` is something like `project`.
45
+ def self.account_load_and_authorize_resource(model, options, old_options = {})
46
+ # options are now required, because you have to have at least a 'through' setting.
47
+
48
+ # we used to support calling this method with a signature like this:
49
+ #
50
+ # `account_load_and_authorize_resource [:oauth, :twitter_account], :team`
51
+ #
52
+ # however this abstraction was too short-sighted so we've updated this method to accept the exact same method
53
+ # signature as cancancan's original `load_and_authorize_resource` method.
54
+ if model.is_a?(Array)
55
+ raise "Bullet Train has depreciated this method of calling `account_load_and_authorize_resource`. Read the comments on this line of source for more details."
56
+ end
57
+
58
+ # this is providing backward compatibility for folks who are calling this method like this:
59
+ # account_load_and_authorize_resource :thing, through: :team, through_association: :scaffolding_things
60
+ # i'm going to deprecate this at some point.
61
+ if options.is_a?(Hash)
62
+ through = options[:through]
63
+ options.delete(:through)
64
+ else
65
+ through = options
66
+ options = old_options
67
+ end
68
+
69
+ # fetch the namespace of the controller. this should generally match the namespace of the model, except for the
70
+ # `account` part.
71
+ namespace = model_namespace_from_controller_namespace
72
+
73
+ tried = []
74
+ begin
75
+ # check whether the parent exists in the model namespace.
76
+ model_class_name = (namespace + [model.to_s.classify]).join("::")
77
+ model_class_name.constantize
78
+ rescue NameError
79
+ tried << model_class_name
80
+ if namespace.any?
81
+ namespace.pop
82
+ retry
83
+ else
84
+ raise "Oh no, it looks like your call to 'account_load_and_authorize_resource' is broken. We tried #{tried.join(" and ")}, but didn't find a valid class name."
85
+ end
86
+ end
87
+
88
+ # treat through as an array even if the user only specified one parent type.
89
+ through_as_symbols = through.is_a?(Array) ? through : [through]
90
+
91
+ through = []
92
+ through_class_names = []
93
+
94
+ through_as_symbols.each do |through_as_symbol|
95
+ # reflect on the belongs_to association of the child model to figure out the class names of the parents.
96
+ unless (association = model_class_name.constantize.reflect_on_association(through_as_symbol))
97
+ raise "Oh no, it looks like your call to 'account_load_and_authorize_resource' is broken. Tried to reflect on the `#{through_as_symbol}` association of #{model_class_name}, but didn't find one."
98
+ end
99
+
100
+ through_class_name = association.klass.name
101
+
102
+ begin
103
+ through << through_class_name.constantize
104
+ through_class_names << through_class_name
105
+ rescue NameError
106
+ raise "Oh no, it looks like your call to 'account_load_and_authorize_resource' is broken. We tried to load `#{through_class_name}}` (the class name defined for the `#{through_as_symbol}` association), but couldn't find it."
107
+ end
108
+ end
109
+
110
+ if through_as_symbols.count > 1 && !options[:polymorphic]
111
+ raise "When a resource can be loaded through multiple parents, please specify the 'polymorphic' option to tell us what that controller calls the parent, e.g. `polymorphic: :imageable`."
112
+ end
113
+
114
+ # this provides the support we need for shallow nested resources, which
115
+ # helps keep our routes tidy even after many levels of nesting. most people
116
+ # i talk to don't actually know about this feature in rails, but it's
117
+ # actually the recommended approach in the rails routing documentation.
118
+ #
119
+ # also, similar to `load_and_authorize_resource`, people can pass in additional
120
+ # actions for which the resource should be loaded, but because we're making
121
+ # separate calls to `load_and_authorize_resource` for member and collection
122
+ # actions, we ask controllers to specify these actions separately, e.g.:
123
+ # `account_load_and_authorize_resource :invitation, :team, member_actions: [:accept, :promote]`
124
+ collection_actions = options[:collection_actions] || []
125
+ member_actions = options[:member_actions] || []
126
+
127
+ # this option is native to cancancan and allows you to skip account_load_and_authorize_resource
128
+ # for a specific action that would otherwise run it (e.g. see invitations#show.)
129
+ except_actions = options[:except] || []
130
+
131
+ collection_actions = ([:index, :new, :create, :reorder] + collection_actions) - except_actions
132
+ member_actions = ([:show, :edit, :update, :destroy] + member_actions) - except_actions
133
+
134
+ options.delete(:collection_actions)
135
+ options.delete(:member_actions)
136
+
137
+ # NOTE: because we're using prepend for all of these, these are written in backwards order
138
+ # of how they'll be executed during a request!
139
+
140
+ # 4. finally, load the team and parent resource if we can.
141
+ prepend_before_action :load_team
142
+
143
+ # x. this and the thing below it are only here to make a sortable concern possible.
144
+ prepend_before_action only: member_actions do
145
+ instance_variable_name = options[:polymorphic] || through_as_symbols[0]
146
+ eval "@child_object = @#{model}"
147
+ eval "@parent_object = @#{instance_variable_name}"
148
+ end
149
+
150
+ prepend_before_action only: collection_actions do
151
+ instance_variable_name = options[:polymorphic] || through_as_symbols[0]
152
+ eval "@parent_object = @#{instance_variable_name}"
153
+ if options[:through_association].present?
154
+ eval "@child_collection = :#{options[:through_association]}"
155
+ else
156
+ eval "@child_collection = :#{model.to_s.pluralize}"
157
+ end
158
+ end
159
+
160
+ prepend_before_action only: member_actions do
161
+ instance_variable_name = options[:polymorphic] || through_as_symbols[0]
162
+ possible_sources_of_parent = through_as_symbols.map { |tas| "@#{model}.#{tas}" }.join(" || ")
163
+ eval_string = "@#{instance_variable_name} ||= " + possible_sources_of_parent
164
+ eval eval_string
165
+ end
166
+
167
+ if options[:polymorphic]
168
+ prepend_before_action only: collection_actions do
169
+ possible_sources_of_parent = through_as_symbols.map { |tas| "@#{tas}" }.join(" || ")
170
+ eval "@#{options[:polymorphic]} ||= #{possible_sources_of_parent}"
171
+ end
172
+ end
173
+
174
+ # 3. on action resource, we have a specific id for the child resource, so load it directly.
175
+ load_and_authorize_resource model, options.merge(class: model_class_name, only: member_actions, prepend: true, shallow: true)
176
+
177
+ # 2. only load the child resource through the parent resource for collection actions.
178
+ load_and_authorize_resource model, options.merge(class: model_class_name, through: through_as_symbols, only: collection_actions, prepend: true, shallow: true)
179
+
180
+ # 1. load the parent resource for collection actions only. (we're using shallow routes.)
181
+ # since a controller can have multiple potential parents, we have to run this as a loop on every possible
182
+ # parent. (the vast majority of controllers only have one parent.)
183
+
184
+ through_class_names.each_with_index do |through_class_name, index|
185
+ load_and_authorize_resource through_as_symbols[index], options.merge(class: through_class_name, only: collection_actions, prepend: true, shallow: true)
186
+ end
187
+ end
188
+ end
189
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Rails.application.routes.draw do
2
+ end
@@ -0,0 +1,6 @@
1
+ module BulletTrain
2
+ module SuperLoadAndAuthorizeResource
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module BulletTrain
2
+ module SuperLoadAndAuthorizeResource
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ require "bullet_train/super_load_and_authorize_resource/version"
2
+ require "bullet_train/super_load_and_authorize_resource/engine"
3
+
4
+ module BulletTrain
5
+ module SuperLoadAndAuthorizeResource
6
+ # Your code goes here...
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :bullet_train_super_load_and_authorize_resource do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bullet_train-super_load_and_authorize_resource
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Culver
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-01-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 7.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 7.0.0
27
+ description: Bullet Train Super Load And Authorize Resource
28
+ email:
29
+ - andrew.culver@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - MIT-LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - app/assets/config/bullet_train_super_load_and_authorize_resource_manifest.js
38
+ - app/controllers/concerns/loads_and_authorizes_resource.rb
39
+ - config/routes.rb
40
+ - lib/bullet_train/super_load_and_authorize_resource.rb
41
+ - lib/bullet_train/super_load_and_authorize_resource/engine.rb
42
+ - lib/bullet_train/super_load_and_authorize_resource/version.rb
43
+ - lib/tasks/bullet_train/super_load_and_authorize_resource_tasks.rake
44
+ homepage: https://github.com/bullet-train-co/bullet_train-super_load_and_authorize_resource
45
+ licenses:
46
+ - MIT
47
+ metadata:
48
+ homepage_uri: https://github.com/bullet-train-co/bullet_train-super_load_and_authorize_resource
49
+ source_code_uri: https://github.com/bullet-train-co/bullet_train-super_load_and_authorize_resource
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubygems_version: 3.2.22
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: Bullet Train Super Load And Authorize Resource
69
+ test_files: []