Module: Karst::Access::PrincipalSourceSelection
- Defined in:
- lib/karst/access/principal_source_selection.rb
Overview
The local, machine-scoped record of which ambiguous Devise model(s) a developer has explicitly told Karst to test (see Karst::Access::SelectedPrincipalSources for how this is turned back into runnable Karst::Access::PrincipalSource objects, revalidated against Karst::Identity::DeviseSupport's own current metadata on every read).
Deliberately data, never code: an entry is a bare model name and nothing else -- never a scope, a class, or any executable Ruby. Karst never constantizes a stored name; it is only ever compared, as a string, against what Devise.mappings currently reports. This is the same never-trust-the-file posture Karst::Access::PopulationApprovals uses for candidate populations, applied one layer earlier: to which models Karst may consider at all, not what it may sample from within one already-known model.
Stored under the host application's tmp/ (tmp/karst/) for the same
reason approved populations are: machine-local, disposable,
git-ignored, reset by deleting the file, and consulted only in
development/test (see Karst::Access::ApprovedPopulations.local_environment?,
reused as-is by Karst::Access::SelectedPrincipalSources -- this is the
same local-preference mechanism, not a parallel one).
Every read fails closed, exactly like PopulationApprovals: a file that is unreadable, is not JSON, is not the expected document shape, carries an unknown schema version, or holds a single entry that is not a plausible constant name selects nothing at all.
Constant Summary collapse
- SCHEMA_VERSION =
1- RELATIVE_PATH =
File.join("tmp", "karst", "principal_source_selection.json")
- MODEL_NAME =
Matched only against Karst::Identity::DeviseSupport.mappings' own model names -- a stored name is never constantized and never used to look up an arbitrary constant.
/\A[A-Z][A-Za-z0-9_]*(?:::[A-Z][A-Za-z0-9_]*)*\z/- MAX_ENTRIES =
A generous bound no realistic application approaches -- exists only so a corrupted or maliciously grown document cannot turn every principal source resolution into unbounded work.
50- Record =
Value.define(:model_names, :error) do def selected?(model_name) model_names.include?(model_name.to_s) end end
Class Method Summary collapse
-
.display_path ⇒ Object
The path as a developer should see it: relative to the application root, since that is where they will go looking for (or delete) it.
- .load ⇒ Object
- .path ⇒ Object
-
.replace(model_names) ⇒ Object
Replaces the whole selection with
model_names, atomically: callers always submit the complete set they intend to keep, so deselecting a model is simply selecting a smaller set, and a partially written file can never be observed.
Class Method Details
.display_path ⇒ Object
The path as a developer should see it: relative to the application root, since that is where they will go looking for (or delete) it.
64 65 66 |
# File 'lib/karst/access/principal_source_selection.rb', line 64 def display_path RELATIVE_PATH end |
.load ⇒ Object
68 69 70 71 72 73 74 75 76 77 |
# File 'lib/karst/access/principal_source_selection.rb', line 68 def load document = JSON.parse(File.read(path)) parse(document) rescue Errno::ENOENT empty rescue JSON::ParserError failed("could not be read as JSON") rescue StandardError => e failed("could not be read (#{e.class})") end |
.path ⇒ Object
58 59 60 |
# File 'lib/karst/access/principal_source_selection.rb', line 58 def path File.join(root, RELATIVE_PATH) end |
.replace(model_names) ⇒ Object
Replaces the whole selection with model_names, atomically:
callers always submit the complete set they intend to keep, so
deselecting a model is simply selecting a smaller set, and a
partially written file can never be observed.
83 84 85 86 87 88 89 90 |
# File 'lib/karst/access/principal_source_selection.rb', line 83 def replace(model_names) normalized = normalize(model_names) write(normalized) Record.new(model_names: normalized, error: nil) rescue StandardError => e Record.new(model_names: normalized || [].freeze, error: "selection could not be saved (#{e.class})") end |