avo 4.3.8 → 4.3.9

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: 79364fd16b4d55af4c2ee6676ec4942ad7d7ad289bcf3fd300c47172acbb30ce
4
- data.tar.gz: f462864fcc13f206b4706a5454656f5aa278a48a5c3d839845c668e268a54029
3
+ metadata.gz: 2ca7f212d5e09898e6ec5b8aae81bdb7ccae9df016a6d9f48c162a45fae79426
4
+ data.tar.gz: 205fdca72016899639b593c92a3ce7f96a4822e62e178f8f0110db45f1175389
5
5
  SHA512:
6
- metadata.gz: 8008df30eb61a88c04529145fe63cbb678f00958c465b3726b8677f706f08a45dfb93cfcab3b2c9efe7948d108e376ca627463d2e73d7ff0ece74b8e7ef8c25b
7
- data.tar.gz: dab18f64782d3c6bffcac3927d4b1010c8a8ce42e95db1e6b12e3edf37b1394204f8d4af6638f013d20379ca2c52d1f7dd9f89f73aceca02afdad17e116b3b23
6
+ metadata.gz: 1f91977716121ccdb087fb910520f5d3a68de0f0f0625c8760014cbe31ab3f6852b26d54b106186209afd605b4ecf95172b5eb5f9ab87970837c3b4614adb7b0
7
+ data.tar.gz: f59463967527115900a1a1e751539ec68227bef01aef4230d03e362d9c0641faa3a51e3a16c3ccf97e980be416f234153fadf6c506a218163c60c5ab9e97af67
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (4.3.8)
4
+ avo (4.3.9)
5
5
  actionview (>= 6.1)
6
6
  active_link_to
7
7
  activerecord (>= 6.1)
@@ -71,7 +71,7 @@ module Avo
71
71
  def set_query
72
72
  # If the user selected all records, use the decrypted index query
73
73
  # Otherwise, find the records from the resource ids
74
- @query = if action_params[:fields]&.dig(:avo_selected_all) == "true"
74
+ @query = if selected_all?
75
75
  decrypted_index_query
76
76
  else
77
77
  find_records_from_resource_ids
@@ -252,8 +252,23 @@ module Avo
252
252
  end
253
253
  end
254
254
 
255
+ def selected_all?
256
+ action_params[:fields]&.dig(:avo_selected_all) == "true"
257
+ end
258
+
255
259
  def verify_authorization
256
- raise Avo::NotAuthorizedError.new unless @action.authorized?
260
+ raise Avo::NotAuthorizedError.new unless @action.authorized? && act_on_authorized?
261
+ end
262
+
263
+ # The Actions button asks `act_on?`, so the run asks it too, of every record it names: the one in
264
+ # the URL and the selected ids. With none, the model class stands in, as on the index. A select-all
265
+ # run is the index query the button already allowed, and is not loaded here to ask it row by row.
266
+ def act_on_authorized?
267
+ records = [@record, *(@query unless selected_all?)].compact
268
+
269
+ (records.presence || [@resource.model_class]).all? do |record|
270
+ @resource.authorization.authorize_action(:act_on, record:, raise_exception: false)
271
+ end
257
272
  end
258
273
  end
259
274
  end
@@ -245,16 +245,21 @@ module Avo
245
245
  Avo.configuration.locale = locale if locale
246
246
  end
247
247
 
248
+ # With nowhere to go back to, the refusal renders here: redirecting to the root loops when the
249
+ # home page is the one refused.
248
250
  def render_unauthorized(exception)
249
- flash[:notice] = t "avo.not_authorized"
250
-
251
- redirect_url = if request.referrer.blank? || (request.referrer == request.url)
252
- root_url
253
- else
254
- request.referrer
251
+ if request.referrer.present? && request.referrer != request.url
252
+ flash[:notice] = t "avo.not_authorized"
253
+ return redirect_to(request.referrer)
255
254
  end
256
255
 
257
- redirect_to(redirect_url)
256
+ respond_to do |format|
257
+ format.html do
258
+ Avo.error_manager.add t("avo.not_authorized")
259
+ render html: "", layout: "avo/application", status: :forbidden
260
+ end
261
+ format.any { head :forbidden }
262
+ end
258
263
  end
259
264
 
260
265
  def set_authorization
@@ -260,7 +260,7 @@ When an index spans multiple pages, checking "Select all" offers to select **eve
260
260
 
261
261
  - **`query` is always an array.** Even a single-record action gets `[record]`. Use `query.first` for the one-record case; don't call record methods on `query` directly. `records` is an alias.
262
262
  - **Records deleted after selection are omitted.** Another user may delete a checked record before the action request arrives. Avo drops that missing record and still passes every surviving selection to `handle`; action authors do not need to rescue `ActiveRecord::RecordNotFound` for this race. `query` can therefore come back **empty** when every selected record is gone — guard with `return error "No record selected" if query.blank?` if that matters.
263
- - **"My action doesn't show up" is usually the policy.** With Pundit, `act_on?` in the resource's policy gates action visibility (and `authorize` on the action gates it further). Check the policy first. See the **`avo-authorization`** skill.
263
+ - **"My action doesn't show up", or is refused, is usually the policy.** With Pundit, `act_on?` in the resource's policy gates the Actions dropdown and every run: Avo asks it of the record in the URL and of each selected record (of the model class when there are none, and for a "Select all" run), and one refusal refuses the whole run. An action started from an association panel shows under the parent's `act_on_<assoc>?`, but still runs only on children whose own `act_on?` allows it. `authorize` on the action gates it further. Check the policy first. See the **`avo-authorization`** skill.
264
264
  - **`view` is the view the action was started from.** In `authorize`, `visible`, the modal text blocks, `fields`, and `handle`, `view` (and `resource.view`) is `index`, `show`, or `edit` — the page the user opened the action from — both while the modal renders and while the action runs. It is never `new`; the modal is not a view. It arrives with the request and is checked against the route (`show` and `edit` need a record in the URL), so use it to adapt behavior (`reload_records if view.index?`), never as the only gate on who may run the action: gate people on `current_user`, and single-versus-bulk on `query.size` or `record`.
265
265
  - **Every field in `fields` renders in the modal.** `hide_on`/`show_on` marks are for resource views and are ignored here. A field with a form component (text, select, hidden...) renders as an input; a display-only field (badge, key/value) renders read-only, as on Show. The one mark that counts: a badge declared with `show_on: :forms` renders as a select. The modal focuses its first input; a field with `autofocus: true` takes the focus instead (avo-fields lists the fields that support it). Use it to show context next to the inputs.
266
266
  - **The modal is a NEW request.** Params from the Index/Show page that opened it are **not** available in `fields`/`handle`. To prefill from the triggering page, parse `request.referer`:
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "4.3.8" unless const_defined?(:VERSION)
2
+ VERSION = "4.3.9" unless const_defined?(:VERSION)
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: avo
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.8
4
+ version: 4.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Marin