janela 0.6.0 → 0.7.0
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 +4 -4
- data/CHANGELOG.md +18 -0
- data/README.md +27 -8
- data/UPGRADING.md +104 -0
- data/app/controllers/janela/application_controller.rb +3 -2
- data/app/helpers/janela/frames_helper.rb +4 -2
- data/app/jobs/janela/snapshot_job.rb +47 -6
- data/app/models/janela/snapshot.rb +11 -2
- data/db/migrate/20260921000001_add_owner_to_janela_snapshots.rb +9 -0
- data/docs/decisions/009-snapshots.md +1 -1
- data/docs/decisions/032-janela-will-not-read-a-model-it-cannot-scope.md +156 -0
- data/docs/decisions/033-a-snapshot-is-told-who-owns-it.md +151 -0
- data/docs/decisions/034-janela-will-not-freeze-a-scope-the-host-has-not-named.md +238 -0
- data/docs/decisions/INDEX.md +9 -6
- data/docs/multi-tenancy.md +87 -18
- data/lib/janela/doctor.rb +58 -7
- data/lib/janela/version.rb +1 -1
- data/lib/janela.rb +27 -0
- metadata +20 -8
data/lib/janela.rb
CHANGED
|
@@ -20,6 +20,10 @@ module Janela
|
|
|
20
20
|
# Something the request asked for is not allowed here: a renderer, a
|
|
21
21
|
# granularity, a limit or a filter. Rendered as 400.
|
|
22
22
|
class BadRequest < Error; end
|
|
23
|
+
# The host has not said what may be read. Not rendered as anything: it is a
|
|
24
|
+
# setup mistake rather than a data condition, and dressing it as a 404 would
|
|
25
|
+
# hide the one line that fixes it (ADR 032).
|
|
26
|
+
class Unscoped < Error; end
|
|
23
27
|
|
|
24
28
|
# Janela's controllers inherit from the host's, so the host's authentication
|
|
25
29
|
# and authorisation apply to dashboards with no configuration.
|
|
@@ -37,6 +41,29 @@ module Janela
|
|
|
37
41
|
# is for (ADR 021).
|
|
38
42
|
mattr_accessor :silenced_checks, default: []
|
|
39
43
|
|
|
44
|
+
# What the host permits to be read, asked of its controller and never
|
|
45
|
+
# assumed. Janela refuses rather than reading everything, because a
|
|
46
|
+
# dashboard that quietly totals rows its reader may not see is the worst
|
|
47
|
+
# thing this library can do (ADR 032).
|
|
48
|
+
#
|
|
49
|
+
# Asked of the controller and never of self, because a helper runs on the
|
|
50
|
+
# view and a view cannot see a private controller method: when there were
|
|
51
|
+
# two copies of this question they disagreed about whether a host had
|
|
52
|
+
# answered it (#46). One copy, for that reason.
|
|
53
|
+
def self.scope(controller, model)
|
|
54
|
+
unless controller.respond_to?(:policy_scope, true)
|
|
55
|
+
raise Unscoped, "#{controller.class} defines no policy_scope, so Janela has not been " \
|
|
56
|
+
"told what may be read of #{model.name}. Define it on " \
|
|
57
|
+
"#{Janela.parent_controller}, returning the rows this visitor may see:\n\n" \
|
|
58
|
+
" private def policy_scope(model) = model.all\n\n" \
|
|
59
|
+
"That line says every visitor may read every row of every model on a " \
|
|
60
|
+
"dashboard. If that is not true here, return something narrower. " \
|
|
61
|
+
"UPGRADING.md has the steps and docs/multi-tenancy.md has the wiring."
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
controller.send(:policy_scope, model)
|
|
65
|
+
end
|
|
66
|
+
|
|
40
67
|
# A model that declares a janela block is addressable over HTTP, and so is a
|
|
41
68
|
# subclass of one, keyed by the route key that appears in pane URLs (orders,
|
|
42
69
|
# sales_orders). Names are stored rather than classes so a reloaded model
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: janela
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jay Killeen
|
|
@@ -136,6 +136,7 @@ files:
|
|
|
136
136
|
- db/migrate/20260915000001_create_janela_snapshots.rb
|
|
137
137
|
- db/migrate/20260916000001_create_janela_frames.rb
|
|
138
138
|
- db/migrate/20260916000002_create_janela_panes.rb
|
|
139
|
+
- db/migrate/20260921000001_add_owner_to_janela_snapshots.rb
|
|
139
140
|
- docs/decisions/001-built-to-be-forked.md
|
|
140
141
|
- docs/decisions/002-measures-and-dimensions-over-ransack.md
|
|
141
142
|
- docs/decisions/003-cross-filtering-with-turbo-frames.md
|
|
@@ -167,6 +168,9 @@ files:
|
|
|
167
168
|
- docs/decisions/029-a-panes-frame-is-identified-by-who-it-is.md
|
|
168
169
|
- docs/decisions/030-a-panes-src-belongs-to-turbo.md
|
|
169
170
|
- docs/decisions/031-a-subclass-inherits-the-dashboard.md
|
|
171
|
+
- docs/decisions/032-janela-will-not-read-a-model-it-cannot-scope.md
|
|
172
|
+
- docs/decisions/033-a-snapshot-is-told-who-owns-it.md
|
|
173
|
+
- docs/decisions/034-janela-will-not-freeze-a-scope-the-host-has-not-named.md
|
|
170
174
|
- docs/decisions/INDEX.md
|
|
171
175
|
- docs/multi-tenancy.md
|
|
172
176
|
- docs/naming.md
|
|
@@ -190,14 +194,22 @@ metadata:
|
|
|
190
194
|
bug_tracker_uri: https://github.com/retail-tasker/janela/issues
|
|
191
195
|
rubygems_mfa_required: 'true'
|
|
192
196
|
post_install_message: |
|
|
193
|
-
Janela 0.
|
|
194
|
-
|
|
195
|
-
that declares a janela block. Every named subclass of one is now
|
|
196
|
-
registered and addressable on its own route key, and Janela.definitions
|
|
197
|
-
returns one entry per subclass where a form offering a choice of model
|
|
198
|
-
previously showed one.
|
|
197
|
+
Janela 0.7.0 stops guessing what may be read. Two things now refuse
|
|
198
|
+
rather than defaulting to every row, and both are quick to answer.
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
1. If your ApplicationController defines no policy_scope, every pane
|
|
201
|
+
raises Janela::Unscoped instead of totalling every row. Pundit
|
|
202
|
+
hosts and anyone following docs/multi-tenancy.md: nothing to do.
|
|
203
|
+
Everyone else writes one line (ADR 032).
|
|
204
|
+
|
|
205
|
+
2. If you schedule Janela::SnapshotJob, it now needs to be told what
|
|
206
|
+
rows to freeze: pass scope: :model_default, or subclass it and
|
|
207
|
+
override scope_for. A job already on your queue was serialised
|
|
208
|
+
without that argument and will raise when it performs, so drain it
|
|
209
|
+
or re-enqueue (ADR 034).
|
|
210
|
+
|
|
211
|
+
If you use snapshots, there is also a migration: janela_snapshots
|
|
212
|
+
gains a nullable owner (ADR 033).
|
|
201
213
|
|
|
202
214
|
Steps: UPGRADING.md in this gem, or
|
|
203
215
|
https://github.com/retail-tasker/janela/blob/main/UPGRADING.md
|